FileStream.st
changeset 11812 fae9f7c22dbd
parent 11454 b451c165163a
child 11813 9ccd2b0ca724
--- a/FileStream.st	Tue Jul 28 12:32:54 2009 +0200
+++ b/FileStream.st	Tue Jul 28 13:32:44 2009 +0200
@@ -1011,11 +1011,11 @@
 
 %{
     HFILE f;
-    HFILE fopen();
+
     int pass = 0;
 
 retry:
-    if (__isNonNilObject(pathName) && __isString(openmode))
+    if (__isNonNilObject(pathName) && (__isStringLike(openmode) || __isArray(openmode)))
 #ifdef __VMS__
       if (__qClass(pathName)==String) {
         do {
@@ -1140,49 +1140,131 @@
 #else /* not VMS */
 
 # ifdef WIN32
-
-      if (__qClass(pathName)==String) {
-        {
-            char _aPathName[MAXPATHLEN];
-            char _openMode[64];
+    {
+          DWORD share = 0, access = 0, create = 0, attr = 0;
+          int numAttrib, i;
+          OBJ *ap;
+          char * __openmode;
+          HANDLE handle;
 
-            strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
-            strncpy(_openMode, __stringVal(openmode), sizeof(_openMode)-1); _openMode[sizeof(_openMode)-1] = '\0';
-            do {
-                __threadErrno = 0;
-                f = STX_C_CALL2( "fopen", fopen, _aPathName, _openMode);
-                if (__threadErrno == EINTR) {
-                    f = NULL;
-                }
-            } while ((f == NULL) && (__threadErrno == EINTR));
-        }
-      } else if (__qClass(pathName)==Unicode16String) {
-        {
-            wchar_t _aPathName[MAXPATHLEN+1];
-            wchar_t _openMode[64];
-            int i, l;
+          if (__isStringLike(openmode)) {
+              share = FILE_SHARE_READ|FILE_SHARE_WRITE;
+              __openmode = __stringVal(openmode);
+              if (strcmp(__openmode, "rb") == 0) {
+                  access = GENERIC_READ;
+                  create = OPEN_EXISTING;
+              } else if (strcmp(__openmode, "rb+") == 0) {
+                  access = GENERIC_READ | GENERIC_WRITE;
+                  create = OPEN_ALWAYS;
+              } else if (strcmp(__openmode, "wb") == 0) {
+                  access = GENERIC_WRITE;
+                  create = CREATE_ALWAYS;
+              } else if (strcmp(__openmode, "wb+") == 0) {
+                  access = GENERIC_READ | GENERIC_WRITE;
+                  create = CREATE_ALWAYS;
+              } else if (strcmp(__openmode, "ab") == 0) {
+                  access = FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
+                                STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
+                  create = OPEN_ALWAYS;
+              } else if (strcmp(__openmode, "ab+") == 0) {
+                  access = GENERIC_READ |FILE_APPEND_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|
+                                STANDARD_RIGHTS_WRITE|SYNCHRONIZE;
+                  create = OPEN_ALWAYS;
+              } else {
+                  console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
+              }
+          } else if (__isArrayLike(openmode)) {
+              ap = __ArrayInstPtr(attributeSpec)->a_element;
+              numAttrib = __arraySize(attributeSpec);
+              __openmode = "rb+";
+
+              for (i=0; i<numAttrib; i++) {
+                  OBJ attrSym = ap[i];
+
+                  if (attrSym == @symbol(FILE_SHARE_READ)) {
+                      share |= FILE_SHARE_READ;
+                  } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
+                      share |= FILE_SHARE_WRITE;
+
+                  } else if (attrSym == @symbol(GENERIC_READ)) {
+                      access |= GENERIC_READ;
+                  } else if (attrSym == @symbol(GENERIC_WRITE)) {
+                      access |= GENERIC_WRITE;
+
+                  } else if (attrSym == @symbol(CREATE_NEW)) {
+                      create |= CREATE_NEW;
+                  } else if (attrSym == @symbol(CREATE_ALWAYS)) {
+                      create |= CREATE_ALWAYS;
+                  } else if (attrSym == @symbol(OPEN_EXISTING)) {
+                      create |= OPEN_EXISTING;
+                  } else if (attrSym == @symbol(OPEN_ALWAYS)) {
+                      create |= OPEN_ALWAYS;
+                  } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
+                      create |= TRUNCATE_EXISTING;
 
-            l = __unicode16StringSize(pathName);
-            if (l > MAXPATHLEN) l = MAXPATHLEN;
-            for (i=0; i<l; i++) {
-                _aPathName[i] = __unicode16StringVal(pathName)[i];
-            }
-            _aPathName[i] = 0;
+                  } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
+                      attr |= FILE_ATTRIBUTE_HIDDEN;
+                  } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
+                      attr |= FILE_ATTRIBUTE_READONLY;
+                  } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
+                      attr |= FILE_FLAG_WRITE_THROUGH;
+                  } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
+                      attr |= FILE_FLAG_SEQUENTIAL_SCAN;
+                  } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
+                      attr |= FILE_FLAG_DELETE_ON_CLOSE;
+                  } else {
+                      console_fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
+                  }
+              }
+          } else {
+              f = NULL;
+//              argumentError = @symbol(badAttributeSpec);
+              goto badArgument;
+          }
+          if (create == 0) {
+              f = NULL;
+//              argumentError = @symbol(missingCreateMode);
+              goto badArgument;
+          }
+          if (attr == 0) {
+              attr = FILE_ATTRIBUTE_NORMAL;
+          }
+
+          if (__isString(pathName)) {
+                char _aPathName[MAXPATHLEN];
 
-            l = __stringSize(openmode);
-            if (l > 64) l = 64;
-            for (i=0; i<l; i++) {
-                _openMode[i] = ((unsigned char *)__stringVal(openmode))[i];
-            }
-            _openMode[i] = 0;
-            do {
-                __threadErrno = 0;
-                f = STX_C_CALL2( "_wfopen", _wfopen, _aPathName, _openMode);
-                if (__threadErrno == EINTR) {
-                    f = NULL;
+                strncpy(_aPathName, __stringVal(pathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
+                do {
+                    __threadErrno = 0;
+                    handle = STX_API_CALL7( "CreateFileA", CreateFileA, _aPathName, access, share, 0 /* sa */, create, attr, 0 /* hTempl */);
+                    if (__threadErrno == EINTR) {
+                        handle = INVALID_HANDLE_VALUE;
+                    }
+                } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
+          } else if (__isUnicode16String(pathName)) {
+                wchar_t _aPathName[MAXPATHLEN+1];
+                int i, l;
+
+                l = __unicode16StringSize(pathName);
+                if (l > MAXPATHLEN) l = MAXPATHLEN;
+                for (i=0; i<l; i++) {
+                    _aPathName[i] = __unicode16StringVal(pathName)[i];
                 }
-            } while ((f == NULL) && (__threadErrno == EINTR));
-        }
+                _aPathName[i] = 0;
+
+                do {
+                    __threadErrno = 0;
+                    handle = STX_API_CALL7( "CreateFileW", CreateFileW, _aPathName, access, share, 0 /* sa */, create, attr, 0 /* hTempl */);
+                    if (__threadErrno == EINTR) {
+                        handle = INVALID_HANDLE_VALUE;
+                    }
+                } while ((handle == INVALID_HANDLE_VALUE) && (__threadErrno == EINTR));
+          }
+          if (handle != INVALID_HANDLE_VALUE) {
+              f = fdopen(_open_osfhandle((long)handle, O_BINARY), __openmode);
+          } else {
+              f = NULL;
+          }
       }
 # else /* not WIN32 */
 
@@ -1218,7 +1300,8 @@
             __SSEND0(@global(ObjectMemory), @symbol(finalize), 0);
             goto retry;
         }
-    getOutOfHere: ;
+    badArgument:
+    getOutOfHere:
         __INST(lastErrorNumber) = __mkSmallInteger(__threadErrno);
         __INST(position) = nil;
     } else {
@@ -1252,7 +1335,7 @@
 # endif
 #else /* not VMS */
         __INST(canPosition) = true;
-#endif /* poor VMS */
+#endif /* not VMS */
 
         if (@global(FileOpenTrace) == true) {
             console_fprintf(stderr, "fopen %s [FileStream] -> %x\n", __stringVal(pathName), f);
@@ -1558,7 +1641,7 @@
 !FileStream class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.131 2009-01-14 20:01:21 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/FileStream.st,v 1.132 2009-07-28 11:32:44 stefan Exp $'
 ! !
 
 FileStream initialize!