Win32OperatingSystem.st
changeset 11779 73c3f28d8960
parent 11767 057b2c8eba6f
child 11800 bfd3073ef9d2
--- a/Win32OperatingSystem.st	Sat Jun 20 11:16:54 2009 +0200
+++ b/Win32OperatingSystem.st	Mon Jun 22 16:52:12 2009 +0200
@@ -5279,69 +5279,72 @@
 
 isWritable:aPathName
     "return true, if the given file is writable.
-     For symbolic links, the pointed-to-file is checked."
+     For symbolic links, the pointed-to-file is checked.
+
+     In Windows, files can possibly be created in and deleted from directories marked as
+     read only. See http://support.microsoft.com/kb/326549. So we always return true
+     for directories."
 
 %{
     int ret;
 
     if (__isString(aPathName)) {
 #ifdef DO_WRAP_CALLS
-	char _aPathName[MAXPATHLEN];
-
-	strncpy(_aPathName, __stringVal(aPathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
-	do {
-	    __threadErrno = 0;
-	    ret = STX_API_CALL1( "GetFileAttributes", GetFileAttributes, _aPathName);
-	} while ((ret < 0) && (__threadErrno == EINTR));
-#else
-	ret = GetFileAttributes((char *) __stringVal(aPathName));
-	if (ret < 0) {
-	    __threadErrno = __WIN32_ERR(GetLastError());
-	}
-#endif
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(__threadErrno);
-	    RETURN ( false );
-	}
-	RETURN ( (ret & FILE_ATTRIBUTE_READONLY) ? false : true);
-    }
-    if (__isUnicode16String(aPathName)) {
-	int ret;
-
-	/*
-	 * under windows, all files are readable ...
-	 * so, only check for the files existence here.
-	 */
-	wchar_t _wPathName[MAXPATHLEN+1];
-	int i, l;
-
-	l = __unicode16StringSize(aPathName);
-	if (l > MAXPATHLEN) l = MAXPATHLEN;
-	for (i=0; i<l; i++) {
-	    _wPathName[i] = __unicode16StringVal(aPathName)[i];
-	}
-	_wPathName[i] = 0;
+        char _aPathName[MAXPATHLEN];
+
+        strncpy(_aPathName, __stringVal(aPathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
+        do {
+            __threadErrno = 0;
+            ret = STX_API_CALL1( "GetFileAttributes", GetFileAttributes, _aPathName);
+        } while ((ret < 0) && (__threadErrno == EINTR));
+#else
+        ret = GetFileAttributes((char *) __stringVal(aPathName));
+        if (ret < 0) {
+            __threadErrno = __WIN32_ERR(GetLastError());
+        }
+#endif
+    } else if (__isUnicode16String(aPathName)) {
+        /*
+         * under windows, all files are readable ...
+         * so, only check for the files existence here.
+         */
+        wchar_t _wPathName[MAXPATHLEN+1];
+        int i, l;
+
+        l = __unicode16StringSize(aPathName);
+        if (l > MAXPATHLEN) l = MAXPATHLEN;
+        for (i=0; i<l; i++) {
+            _wPathName[i] = __unicode16StringVal(aPathName)[i];
+        }
+        _wPathName[i] = 0;
 #ifdef DO_WRAP_CALLS
-	do {
-	    __threadErrno = 0;
-	    ret = STX_API_CALL1( "GetFileAttributesW", GetFileAttributesW, _wPathName);
-	} while ((ret < 0) && (__threadErrno == EINTR));
-#else
-	ret = GetFileAttributesW(_wPathName);
-	if (ret < 0) {
-	    __threadErrno = __WIN32_ERR(GetLastError());
-	}
-#endif
-	if (ret < 0) {
-	    @global(LastErrorNumber) = __mkSmallInteger(__threadErrno);
-	    RETURN (false);
-	}
-	RETURN ( (ret & FILE_ATTRIBUTE_READONLY) ? false : true);
-    }
+        do {
+            __threadErrno = 0;
+            ret = STX_API_CALL1( "GetFileAttributesW", GetFileAttributesW, _wPathName);
+        } while ((ret < 0) && (__threadErrno == EINTR));
+#else
+        ret = GetFileAttributesW(_wPathName);
+        if (ret < 0) {
+            __threadErrno = __WIN32_ERR(GetLastError());
+        }
+#endif
+    } else {
+        goto fail;
+    }
+
+    if (ret < 0) {
+        @global(LastErrorNumber) = __mkSmallInteger(__threadErrno);
+        RETURN (false);
+    }
+    RETURN ( (ret & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) ? false : true);
+
+fail:;
 %}.
     ^ self primitiveFailed
 
     "
+     self isWritable:'c:\windows'
+     self isWritable:'c:\Dokumente und Einstellungen\stefan\Eigene Dateien'
      self isWritable:'.'
      self isWritable:'.' asUnicode16String
     "
@@ -5351,16 +5354,16 @@
     "return some object filled with info for the file 'aPathName';
      the info (for which corresponding access methods are understood by
      the returned object) is:
-	 type            - a symbol giving the files type
-	 mode            - numeric access mode
-	 uid             - owners user id
-	 gid             - owners group id
-	 size            - files size
-	 id              - files number (i.e. inode number)
-	 accessed        - last access time (as Timestamp)
-	 modified        - last modification time (as Timestamp)
-	 statusChanged   - last status change time (as Timestamp)
-	 alternativeName - (windows only:) the MSDOS name of the file
+         type            - a symbol giving the files type
+         mode            - numeric access mode
+         uid             - owners user id
+         gid             - owners group id
+         size            - files size
+         id              - files number (i.e. inode number)
+         accessed        - last access time (as Timestamp)
+         modified        - last modification time (as Timestamp)
+         statusChanged   - last status change time (as Timestamp)
+         alternativeName - (windows only:) the MSDOS name of the file
 
      Some of the fields may be returned as nil on systems which do not provide
      all of the information.
@@ -5392,165 +5395,165 @@
     wchar_t _aPathName[MAX_PATH+1];
 
     if (__isString(aPathName)) {
-	int i;
-	int l = __stringSize(aPathName);
-	if (l > MAX_PATH) l = MAX_PATH;
-
-	for (i=0; i<l; i++) {
-	    _aPathName[i] = __stringVal(aPathName)[i];
-	}
-	_aPathName[i] = 0;
+        int i;
+        int l = __stringSize(aPathName);
+        if (l > MAX_PATH) l = MAX_PATH;
+
+        for (i=0; i<l; i++) {
+            _aPathName[i] = __stringVal(aPathName)[i];
+        }
+        _aPathName[i] = 0;
     } else if (__isUnicode16String(aPathName)) {
-	int i;
-	int l = __unicode16StringSize(aPathName);
-	if (l > MAX_PATH) l = MAX_PATH;
-
-	for (i=0; i<l; i++) {
-	    _aPathName[i] = __unicode16StringVal(aPathName)[i];
-	}
-	_aPathName[i] = 0;
+        int i;
+        int l = __unicode16StringSize(aPathName);
+        if (l > MAX_PATH) l = MAX_PATH;
+
+        for (i=0; i<l; i++) {
+            _aPathName[i] = __unicode16StringVal(aPathName)[i];
+        }
+        _aPathName[i] = 0;
     } else
-	goto badArgument;
+        goto badArgument;
 
 #ifdef DO_WRAP_CALLS
     {
-	do {
-	    __threadErrno = 0;
-	    hFile = STX_API_CALL2( "FindFirstFileW", FindFirstFileW, _aPathName, &findStructW);
-	} while ((hFile < 0) && (__threadErrno == EINTR));
+        do {
+            __threadErrno = 0;
+            hFile = STX_API_CALL2( "FindFirstFileW", FindFirstFileW, _aPathName, &findStructW);
+        } while ((hFile < 0) && (__threadErrno == EINTR));
     }
 #else
     hFile = FindFirstFileW(_aPathName, &findStructW);
     if (hFile < 0) {
-	__threadErrno = __WIN32_ERR(GetLastError());
+        __threadErrno = __WIN32_ERR(GetLastError());
     }
 #endif
 
     if (! hFile || (hFile == (HANDLE)(-1)) || (hFile == INVALID_HANDLE_VALUE)) {
-	@global(LastErrorNumber) = __mkSmallInteger(__threadErrno);
+        @global(LastErrorNumber) = __mkSmallInteger(__threadErrno);
     } else {
-	FindClose(hFile);
-
-	id = __mkSmallInteger(0);   /* could get it by opening ... */
-	size = __MKLARGEINT64(1, findStructW.nFileSizeLow, findStructW.nFileSizeHigh);
-
-	if (findStructW.cFileName[0] != '\0') {
-	    bcopy(findStructW.cFileName, fileNameBuffer, MAX_PATH*sizeof(wchar_t));
-	    fileNameBuffer[MAX_PATH] = '\0';
-	    fileName = __MKU16STRING(fileNameBuffer);             /* FULL name */
-	}
-
-	if (findStructW.cAlternateFileName[0] != '\0') {
-	    bcopy(findStructW.cAlternateFileName, alternativeFileNameBuffer, 14*sizeof(wchar_t));
-	    alternativeFileNameBuffer[14] = '\0';
-	    alternativeName = __MKU16STRING(alternativeFileNameBuffer); /* DOS name */
-	}
-
-	/*
-	 * simulate access bits
-	 */
-	if (findStructW.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
-	    modeBits = 0444;
-	} else {
-	    modeBits = 0666;
-	}
-
-	if (findStructW.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-	    type = @symbol(directory);
-	    modeBits |= 0111;   /* executable */
-	} else {
-	    type = @symbol(regular);
-	}
-
-	mode = __mkSmallInteger(modeBits);
-
-	/*
-	 * sigh - convert from stupid time to useful time
-	 */
-	FileTimeToLocalFileTime(&findStructW.ftCreationTime, &tempFileTime);
-	FileTimeToSystemTime(&tempFileTime, &creationTime);
-
-	FileTimeToLocalFileTime(&findStructW.ftLastAccessTime, &tempFileTime);
-	FileTimeToSystemTime(&tempFileTime, &accessTime);
-
-	FileTimeToLocalFileTime(&findStructW.ftLastWriteTime, &tempFileTime);
-	FileTimeToSystemTime(&tempFileTime, &modificationTime);
-
-	aYr  = __mkSmallInteger(accessTime.wYear);
-	aMon = __mkSmallInteger(accessTime.wMonth);
-	aDay = __mkSmallInteger(accessTime.wDay);
-	aHr  = __mkSmallInteger(accessTime.wHour);
-	aMin = __mkSmallInteger(accessTime.wMinute);
-	aSec = __mkSmallInteger(accessTime.wSecond);
-	aMS  = __mkSmallInteger(accessTime.wMilliseconds);
-
-	mYr  = __mkSmallInteger(modificationTime.wYear);
-	mMon = __mkSmallInteger(modificationTime.wMonth);
-	mDay = __mkSmallInteger(modificationTime.wDay);
-	mHr  = __mkSmallInteger(modificationTime.wHour);
-	mMin = __mkSmallInteger(modificationTime.wMinute);
-	mSec = __mkSmallInteger(modificationTime.wSecond);
-	mMS  = __mkSmallInteger(modificationTime.wMilliseconds);
-
-	cYr  = __mkSmallInteger(creationTime.wYear);
-	cMon = __mkSmallInteger(creationTime.wMonth);
-	cDay = __mkSmallInteger(creationTime.wDay);
-	cHr  = __mkSmallInteger(creationTime.wHour);
-	cMin = __mkSmallInteger(creationTime.wMinute);
-	cSec = __mkSmallInteger(creationTime.wSecond);
-	cMS  = __mkSmallInteger(creationTime.wMilliseconds);
+        FindClose(hFile);
+
+        id = __mkSmallInteger(0);   /* could get it by opening ... */
+        size = __MKLARGEINT64(1, findStructW.nFileSizeLow, findStructW.nFileSizeHigh);
+
+        if (findStructW.cFileName[0] != '\0') {
+            bcopy(findStructW.cFileName, fileNameBuffer, MAX_PATH*sizeof(wchar_t));
+            fileNameBuffer[MAX_PATH] = '\0';
+            fileName = __MKU16STRING(fileNameBuffer);             /* FULL name */
+        }
+
+        if (findStructW.cAlternateFileName[0] != '\0') {
+            bcopy(findStructW.cAlternateFileName, alternativeFileNameBuffer, 14*sizeof(wchar_t));
+            alternativeFileNameBuffer[14] = '\0';
+            alternativeName = __MKU16STRING(alternativeFileNameBuffer); /* DOS name */
+        }
+
+        /*
+         * simulate access bits
+         */
+        if (findStructW.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+            modeBits = 0444;
+        } else {
+            modeBits = 0666;
+        }
+
+        if (findStructW.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+            type = @symbol(directory);
+            modeBits = 0777;   /* executable and WRITABLE - why? please refer to #isWritable: */
+        } else {
+            type = @symbol(regular);
+        }
+
+        mode = __mkSmallInteger(modeBits);
+
+        /*
+         * sigh - convert from stupid time to useful time
+         */
+        FileTimeToLocalFileTime(&findStructW.ftCreationTime, &tempFileTime);
+        FileTimeToSystemTime(&tempFileTime, &creationTime);
+
+        FileTimeToLocalFileTime(&findStructW.ftLastAccessTime, &tempFileTime);
+        FileTimeToSystemTime(&tempFileTime, &accessTime);
+
+        FileTimeToLocalFileTime(&findStructW.ftLastWriteTime, &tempFileTime);
+        FileTimeToSystemTime(&tempFileTime, &modificationTime);
+
+        aYr  = __mkSmallInteger(accessTime.wYear);
+        aMon = __mkSmallInteger(accessTime.wMonth);
+        aDay = __mkSmallInteger(accessTime.wDay);
+        aHr  = __mkSmallInteger(accessTime.wHour);
+        aMin = __mkSmallInteger(accessTime.wMinute);
+        aSec = __mkSmallInteger(accessTime.wSecond);
+        aMS  = __mkSmallInteger(accessTime.wMilliseconds);
+
+        mYr  = __mkSmallInteger(modificationTime.wYear);
+        mMon = __mkSmallInteger(modificationTime.wMonth);
+        mDay = __mkSmallInteger(modificationTime.wDay);
+        mHr  = __mkSmallInteger(modificationTime.wHour);
+        mMin = __mkSmallInteger(modificationTime.wMinute);
+        mSec = __mkSmallInteger(modificationTime.wSecond);
+        mMS  = __mkSmallInteger(modificationTime.wMilliseconds);
+
+        cYr  = __mkSmallInteger(creationTime.wYear);
+        cMon = __mkSmallInteger(creationTime.wMonth);
+        cDay = __mkSmallInteger(creationTime.wDay);
+        cHr  = __mkSmallInteger(creationTime.wHour);
+        cMin = __mkSmallInteger(creationTime.wMinute);
+        cSec = __mkSmallInteger(creationTime.wSecond);
+        cMS  = __mkSmallInteger(creationTime.wMilliseconds);
     }
 
   badArgument: ;
 %}.
     (aPathName endsWith:'.lnk') ifTrue:[
-	type := #symbolicLink.
-	"/ now done lazyly in FileStatusInfo, when the path is accessed
-	"/ path := self getLinkTarget:aPathName.
+        type := #symbolicLink.
+        "/ now done lazyly in FileStatusInfo, when the path is accessed
+        "/ path := self getLinkTarget:aPathName.
     ].
 
     mode isNil ifTrue:[
-	(self isDirectory:aPathName) ifTrue:[
-	    "/ the code above fails for root directories (these do not exist).
-	    "/ simulate here
-	    mode := 8r777.
-	    type := #directory.
-	    uid := gid := 0.
-	    size := 0.
-	    id := 0.
-	    atime := mtime := ctime := Timestamp now.
-	].
+        (self isDirectory:aPathName) ifTrue:[
+            "/ the code above fails for root directories (these do not exist).
+            "/ simulate here
+            mode := 8r777.
+            type := #directory.
+            uid := gid := 0.
+            size := 0.
+            id := 0.
+            atime := mtime := ctime := Timestamp now.
+        ].
     ].
     mode notNil ifTrue:[
-	atime isNil ifTrue:[
-	    atime := Timestamp day:aDay month:aMon year:aYr hour:aHr minutes:aMin seconds:aSec milliseconds:aMS.
-	].
-	mtime isNil ifTrue:[
-	    mtime := Timestamp day:mDay month:mMon year:mYr hour:mHr minutes:mMin seconds:mSec milliseconds:mMS.
-	].
-	ctime isNil ifTrue:[
-	    ctime := Timestamp day:cDay month:cMon year:cYr hour:cHr minutes:cMin seconds:cSec milliseconds:cMS.
-	].
-	fileName notNil ifTrue:[
-	    fileName := fileName asSingleByteStringIfPossible
-	].
-	alternativeName notNil ifTrue:[
-	    alternativeName := alternativeName asSingleByteStringIfPossible
-	].
-	info := FileStatusInfo
-		    type:type
-		    mode:mode
-		    uid:uid
-		    gid:gid
-		    size:size
-		    id:id
-		    accessed:atime
-		    modified:mtime
-		    created:ctime
-		    sourcePath:aPathName
-		    fullName:fileName
-		    alternativeName:alternativeName.
-	^ info
+        atime isNil ifTrue:[
+            atime := Timestamp day:aDay month:aMon year:aYr hour:aHr minutes:aMin seconds:aSec milliseconds:aMS.
+        ].
+        mtime isNil ifTrue:[
+            mtime := Timestamp day:mDay month:mMon year:mYr hour:mHr minutes:mMin seconds:mSec milliseconds:mMS.
+        ].
+        ctime isNil ifTrue:[
+            ctime := Timestamp day:cDay month:cMon year:cYr hour:cHr minutes:cMin seconds:cSec milliseconds:cMS.
+        ].
+        fileName notNil ifTrue:[
+            fileName := fileName asSingleByteStringIfPossible
+        ].
+        alternativeName notNil ifTrue:[
+            alternativeName := alternativeName asSingleByteStringIfPossible
+        ].
+        info := FileStatusInfo
+                    type:type
+                    mode:mode
+                    uid:uid
+                    gid:gid
+                    size:size
+                    id:id
+                    accessed:atime
+                    modified:mtime
+                    created:ctime
+                    sourcePath:aPathName
+                    fullName:fileName
+                    alternativeName:alternativeName.
+        ^ info
    ].
    ^ nil
 
@@ -5563,27 +5566,6 @@
    "
 
     "Modified: / 07-02-2007 / 10:30:14 / cg"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 !
 
 mimeTypeForSuffix:aFileSuffix
@@ -16132,7 +16114,7 @@
 !Win32OperatingSystem class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.368 2009-06-12 16:27:00 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.369 2009-06-22 14:52:12 stefan Exp $'
 ! !
 
 Win32OperatingSystem initialize!