getLinkTarget is now done lazyly.
authorClaus Gittinger <cg@exept.de>
Wed, 07 Feb 2007 10:50:22 +0100
changeset 10373 92efacf8b050
parent 10372 44ba935b47ba
child 10374 71de61c77770
getLinkTarget is now done lazyly.
Win32OperatingSystem.st
--- a/Win32OperatingSystem.st	Mon Feb 05 16:40:19 2007 +0100
+++ b/Win32OperatingSystem.st	Wed Feb 07 10:50:22 2007 +0100
@@ -3622,71 +3622,72 @@
     IPersistFile *ppf;
 
     if (! __isString(aPathName)) {
-	console_fprintf(stderr, "invalid argument\n");
-	goto error;
+        console_fprintf(stderr, "invalid argument\n");
+        goto error;
     }
 
     hres = CoInitialize(NULL);
     if (! SUCCEEDED(hres)) {
-	console_fprintf(stderr, "Could not open the COM library\n");
-	goto error;
+        console_fprintf(stderr, "Could not open the COM library\n");
+        goto error;
     }
 
     hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
-			    &IID_IShellLink, (LPVOID *)&psl);
+                            &IID_IShellLink, (LPVOID *)&psl);
     if (SUCCEEDED(hres)) {
-	hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf);
-
-	if (SUCCEEDED(hres)) {
-	    WORD wsz[MAX_PATH];
-
-	    MultiByteToWideChar(CP_ACP, 0, __stringVal(aPathName), -1, wsz, MAX_PATH);
-
-	    hres = ppf->lpVtbl->Load(ppf, wsz, STGM_READ);
-	    if (SUCCEEDED(hres)) {
+        hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf);
+
+        if (SUCCEEDED(hres)) {
+            WORD wsz[MAX_PATH];
+
+            MultiByteToWideChar(CP_ACP, 0, __stringVal(aPathName), -1, wsz, MAX_PATH);
+
+            hres = ppf->lpVtbl->Load(ppf, wsz, STGM_READ);
+            if (SUCCEEDED(hres)) {
 #if 0
-		hres = psl->lpVtbl->Resolve(psl, 0, SLR_ANY_MATCH|SLR_NO_UI);
-#endif
-		if (SUCCEEDED(hres)) {
-		    hres = psl->lpVtbl->GetPath(psl, szGotPath, MAX_PATH,
-				(WIN32_FIND_DATA *)&wfd, 0 /* SLGP_SHORTPATH */ );
-		    if (!SUCCEEDED(hres)) {
-			console_fprintf(stderr, "GetPath failed!\n");
-		    } else {
+                hres = psl->lpVtbl->Resolve(psl, 0, SLR_ANY_MATCH|SLR_NO_UI);
+#endif
+                if (SUCCEEDED(hres)) {
+                    hres = psl->lpVtbl->GetPath(psl, szGotPath, MAX_PATH,
+                                (WIN32_FIND_DATA *)&wfd, 0 /* SLGP_SHORTPATH */ );
+                    if (!SUCCEEDED(hres)) {
+                        console_fprintf(stderr, "GetPath failed!\n");
+                    } else {
 #if 0
-			console_printf("This points to %s\n", wfd.cFileName); console_fflush(stdout);
-			console_printf("Path is %s\n", szGotPath); console_fflush(stdout);
-			if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-			    console_printf("This is a directory\n"); console_fflush(stdout);
-			}
-#endif
-			resolvedPath = __MKSTRING(szGotPath);
+                        console_printf("This points to %s\n", wfd.cFileName); console_fflush(stdout);
+                        console_printf("Path is %s\n", szGotPath); console_fflush(stdout);
+                        if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+                            console_printf("This is a directory\n"); console_fflush(stdout);
+                        }
+#endif
+                        resolvedPath = __MKSTRING(szGotPath);
 #if 0
-			hres = psl->lpVtbl->GetWorkingDirectory(psl, szGotPath, MAX_PATH);
-			if (!SUCCEEDED(hres)) {
-			    console_fprintf(stderr, "GetWorkingDirectory failed!\n");
-			} else {
-			    console_printf("In Directory %s\n", szGotPath);
-			}
-#endif
-		    }
-		}
-	    } else {
-	       console_fprintf(stderr, "IPersistFile Load Error\n");
-	    }
-	    ppf->lpVtbl->Release(ppf);
-	} else {
-	    console_fprintf(stderr, "QueryInterface Error\n");
-	}
-	psl->lpVtbl->Release(psl);
+                        hres = psl->lpVtbl->GetWorkingDirectory(psl, szGotPath, MAX_PATH);
+                        if (!SUCCEEDED(hres)) {
+                            console_fprintf(stderr, "GetWorkingDirectory failed!\n");
+                        } else {
+                            console_printf("In Directory %s\n", szGotPath);
+                        }
+#endif
+                    }
+                }
+            } else {
+               console_fprintf(stderr, "IPersistFile Load Error\n");
+            }
+            ppf->lpVtbl->Release(ppf);
+        } else {
+            console_fprintf(stderr, "QueryInterface Error\n");
+        }
+        psl->lpVtbl->Release(psl);
     } else {
-	console_fprintf(stderr, "CoCreateInstance Error - hres = %08x\n", hres);
+        console_fprintf(stderr, "CoCreateInstance Error - hres = %08x\n", hres);
     }
 error: ;
 %}.
     resolvedPath notNil ifTrue:[^ resolvedPath ].
 
-    self primitiveFailed.
+    "/ self primitiveFailed.
+    ^ nil.
 
     "
      OperatingSystem getLinkTarget:'C:\Dokumente und Einstellungen\cg\Favoriten\Incoming.lnk'
@@ -3694,7 +3695,7 @@
     "
 
     "Created: / 07-11-2006 / 10:52:44 / cg"
-    "Modified: / 08-11-2006 / 12:20:33 / cg"
+    "Modified: / 07-02-2007 / 10:37:48 / cg"
 !
 
 linkFile:oldPath to:newPath
@@ -4416,16 +4417,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.
@@ -4439,8 +4440,10 @@
 
     info := self linkInfoOf:aPathName.
     (info notNil and:[info isSymbolicLink]) ifTrue:[
-	target := info path.
-	^ self linkInfoOf:target.
+        target := info path.
+        target notNil ifTrue:[
+            ^ self linkInfoOf:target.
+        ]
     ].
     ^ info
 
@@ -4451,7 +4454,7 @@
     (OperatingSystem infoOf:'/') accessed
    "
 
-    "Modified: / 07-11-2006 / 16:27:02 / cg"
+    "Modified: / 07-02-2007 / 10:37:14 / cg"
 !
 
 isDirectory:aPathName
@@ -4719,16 +4722,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.
@@ -4754,145 +4757,147 @@
     unsigned INT ino;
 
     if (__isString(aPathName)) {
-	HANDLE hFile;
-	FILETIME tempFileTime;
-	SYSTEMTIME creationTime;
-	SYSTEMTIME accessTime;
-	SYSTEMTIME modificationTime;
-	int modeBits = 0;
-	WIN32_FIND_DATA findStruct;
+        HANDLE hFile;
+        FILETIME tempFileTime;
+        SYSTEMTIME creationTime;
+        SYSTEMTIME accessTime;
+        SYSTEMTIME modificationTime;
+        int modeBits = 0;
+        WIN32_FIND_DATA findStruct;
 
 #ifdef DO_WRAP_CALLS
-	{
-	    char _aPathName[MAXPATHLEN];
-
-	    strncpy(_aPathName, __stringVal(aPathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
-	    do {
-		__threadErrno = 0;
-		hFile = STX_API_CALL2( "FindFirstFile", FindFirstFile, _aPathName, &findStruct);
-	    } while ((hFile < 0) && (__threadErrno == EINTR));
-	}
-#else
-	hFile = FindFirstFile(__stringVal(aPathName), &findStruct);
-	if (hFile < 0) {
-	    __threadErrno = __WIN32_ERR(GetLastError());
-	}
-#endif
-	if (! hFile || (hFile == (HANDLE)(-1)) || (hFile == INVALID_HANDLE_VALUE)) {
-	    @global(LastErrorNumber) = __mkSmallInteger(__threadErrno);
-	} else {
-	    FindClose(hFile);
-
-	    id = __mkSmallInteger(0);   /* could get it by opening ... */
-	    size = __MKLARGEINT64(1, findStruct.nFileSizeLow, findStruct.nFileSizeHigh);
-
-	    if (findStruct.cFileName[0] != '\0') {
-		bcopy(findStruct.cFileName, fileNameBuffer, MAX_PATH);
-		fileNameBuffer[MAX_PATH] = '\0';
-		fileName = __MKSTRING(fileNameBuffer);             /* FULL name */
-	    }
-
-	    if (findStruct.cAlternateFileName[0] != '\0') {
-		bcopy(findStruct.cAlternateFileName, alternativeFileNameBuffer, 14);
-		alternativeFileNameBuffer[14] = '\0';
-		alternativeName = __MKSTRING(alternativeFileNameBuffer); /* DOS name */
-	    }
-
-	    /*
-	     * simulate access bits
-	     */
-	    if (findStruct.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
-		modeBits = 0444;
-	    } else {
-		modeBits = 0666;
-	    }
-
-	    if (findStruct.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(&findStruct.ftCreationTime, &tempFileTime);
-	    FileTimeToSystemTime(&tempFileTime, &creationTime);
-	    FileTimeToLocalFileTime(&findStruct.ftLastAccessTime, &tempFileTime);
-	    FileTimeToSystemTime(&tempFileTime, &accessTime);
-	    FileTimeToLocalFileTime(&findStruct.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);
-	}
+        {
+            char _aPathName[MAXPATHLEN];
+
+            strncpy(_aPathName, __stringVal(aPathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0';
+            do {
+                __threadErrno = 0;
+                hFile = STX_API_CALL2( "FindFirstFile", FindFirstFile, _aPathName, &findStruct);
+            } while ((hFile < 0) && (__threadErrno == EINTR));
+        }
+#else
+        hFile = FindFirstFile(__stringVal(aPathName), &findStruct);
+        if (hFile < 0) {
+            __threadErrno = __WIN32_ERR(GetLastError());
+        }
+#endif
+        if (! hFile || (hFile == (HANDLE)(-1)) || (hFile == INVALID_HANDLE_VALUE)) {
+            @global(LastErrorNumber) = __mkSmallInteger(__threadErrno);
+        } else {
+            FindClose(hFile);
+
+            id = __mkSmallInteger(0);   /* could get it by opening ... */
+            size = __MKLARGEINT64(1, findStruct.nFileSizeLow, findStruct.nFileSizeHigh);
+
+            if (findStruct.cFileName[0] != '\0') {
+                bcopy(findStruct.cFileName, fileNameBuffer, MAX_PATH);
+                fileNameBuffer[MAX_PATH] = '\0';
+                fileName = __MKSTRING(fileNameBuffer);             /* FULL name */
+            }
+
+            if (findStruct.cAlternateFileName[0] != '\0') {
+                bcopy(findStruct.cAlternateFileName, alternativeFileNameBuffer, 14);
+                alternativeFileNameBuffer[14] = '\0';
+                alternativeName = __MKSTRING(alternativeFileNameBuffer); /* DOS name */
+            }
+
+            /*
+             * simulate access bits
+             */
+            if (findStruct.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+                modeBits = 0444;
+            } else {
+                modeBits = 0666;
+            }
+
+            if (findStruct.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(&findStruct.ftCreationTime, &tempFileTime);
+            FileTimeToSystemTime(&tempFileTime, &creationTime);
+            FileTimeToLocalFileTime(&findStruct.ftLastAccessTime, &tempFileTime);
+            FileTimeToSystemTime(&tempFileTime, &accessTime);
+            FileTimeToLocalFileTime(&findStruct.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);
+        }
     }
 %}.
     (aPathName endsWith:'.lnk') ifTrue:[
-	type := #symbolicLink.
-	path := self getLinkTarget:aPathName.
+        type := #symbolicLink.
+        path := nil.    
+        "/ 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
-	    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
+            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.
-	].
-
-	info := FileStatusInfo
-		    type:type
-		    mode:mode
-		    uid:uid
-		    gid:gid
-		    size:size
-		    id:id
-		    accessed:atime
-		    modified:mtime
-		    created:ctime
-		    path:path
-		    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.
+        ].
+
+        info := FileStatusInfo
+                    type:type
+                    mode:mode
+                    uid:uid
+                    gid:gid
+                    size:size
+                    id:id
+                    accessed:atime
+                    modified:mtime
+                    created:ctime
+                    path:path
+                    fullName:fileName
+                    alternativeName:alternativeName.
+        ^ info
    ].
    ^ nil
 
@@ -4904,7 +4909,7 @@
      OperatingSystem linkInfoOf:'C:\Dokumente und Einstellungen\cg\Favoriten\Incoming.lnk'
    "
 
-    "Modified: / 08-11-2006 / 12:20:13 / cg"
+    "Modified: / 07-02-2007 / 10:30:14 / cg"
 !
 
 mimeTypeForSuffix:aFileSuffix
@@ -9675,8 +9680,16 @@
 path
     "for symbolic links only: return the path where the symbolic link points to"
 
+    "/ access lazily...
+    path isNil ifTrue:[
+        type == #symbolicLink ifTrue:[
+            path := OperatingSystem getLinkTarget:fullName.
+        ]
+    ].
+
     ^ path
 
+    "Modified: / 07-02-2007 / 10:31:56 / cg"
 !
 
 recordAttributes
@@ -12745,7 +12758,7 @@
 !Win32OperatingSystem class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.264 2007-01-26 13:34:10 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.265 2007-02-07 09:50:22 cg Exp $'
 ! !
 
 Win32OperatingSystem initialize!