class: DirectoryStream
authorca
Mon, 12 Jan 2015 14:55:30 +0100
changeset 17287 04ef8ce2c146
parent 17286 a7170033e17f
child 17288 eb5098cf2493
class: DirectoryStream reading filenames with fileInfo
DirectoryStream.st
--- a/DirectoryStream.st	Mon Jan 12 14:54:50 2015 +0100
+++ b/DirectoryStream.st	Mon Jan 12 14:55:30 2015 +0100
@@ -11,6 +11,8 @@
 "
 "{ Package: 'stx:libbasic' }"
 
+"{ NameSpace: Smalltalk }"
+
 FileStream subclass:#DirectoryStream
 	instanceVariableNames:'dirPointer readAheadEntry'
 	classVariableNames:''
@@ -507,89 +509,29 @@
 !
 
 nextLine
-    "return the next filename as a string"
-
-    |prevEntry nextEntry isUnix error|
-%{
-#ifdef HAS_OPENDIR
-    DIR *d;
-    DIRENT_STRUCT *dp;
-    OBJ dirP;
-
-    if (__INST(hitEOF) != true && (dirP = __INST(dirPointer)) != nil) {
-        __INST(lastErrorNumber) = nil;
-        d = (DIR *)__FILEVal(dirP);
+    "return the next filename as a string or nil"
+    |linkInfo|
 
-        __BEGIN_INTERRUPTABLE__
-        do {
-            do {
-                __threadErrno = 0;
-                dp = readdir(d);
-                /*
-                 * for compatibility with ST-80,
-                 * skip entries for '.' and '..'.
-                 * If wanted, these must be added synthetically.
-                 */
-            } while (dp && ((strcmp(dp->d_name, ".")==0) || (strcmp(dp->d_name, "..")==0)));
-        } while ((dp == NULL) && (__threadErrno == EINTR));
-        __END_INTERRUPTABLE__
+    linkInfo := self nextLinkInfo.
+    linkInfo notNil ifTrue:[^ linkInfo sourcePath].
+    ^ nil
+!
+
+nextLinkInfo
+    "return the next FileStatusInfo or nil"
 
-        if (dp != NULL) {
-            nextEntry = __MKSTRING((char *)(dp->d_name));
-        } else {
-            if (__threadErrno) {
-                error = __mkSmallInteger(__threadErrno);
-            } else {
-                __INST(hitEOF) = true;
-            }
-       }
-    }
-#else /* no HAS_OPENDIR */
-# ifdef WIN32
-    HANDLE d;
-    WIN32_FIND_DATAW data;
-    OBJ dirP;
-    int rslt;
-
-    if (__INST(hitEOF) != true && (dirP = __INST(dirPointer)) != nil) {
-        __INST(lastErrorNumber) = nil;
-        d = __HANDLEVal(dirP);
-
-        do {
-            __threadErrno = 0;
-            rslt = STX_API_NOINT_CALL2( "FindNextFileW", FindNextFileW, d, &data );
-        } while ((rslt < 0) && (__threadErrno == EINTR));
+    |nextResult resultInfo|
 
-        if (rslt > 0) {
-            nextEntry = __MKU16STRING( data.cFileName );
-        } else {
-           __INST(hitEOF) = true;
-        }
-    }
-# endif /* WIN32 */
-#endif /* HAS_OPENDIR */
-
-#ifdef unix
-    isUnix = true;
-#endif
-
-%}.
-    error notNil ifTrue:[
-        lastErrorNumber := error.
-        self ioError:error.
-        ^ self.    
+    hitEOF ifFalse:[
+	nextResult := OperatingSystem nextLinkInfoFrom:self dirPointer:dirPointer.
+	nextResult isNil ifTrue:[
+	    hitEOF := true.
+	].
     ].
-    nextEntry notNil ifTrue:[
-        isUnix == true ifTrue:[
-            nextEntry := OperatingSystem decodePath:nextEntry.
-        ] ifFalse:[
-            nextEntry := nextEntry asSingleByteStringIfPossible.
-        ]
-    ].
-    prevEntry := readAheadEntry.
-    readAheadEntry := nextEntry.
-    prevEntry isNil ifTrue:[^ self pastEndRead].
-    ^ prevEntry
+    resultInfo := readAheadEntry.
+    resultInfo isNil ifTrue:[^ self pastEndRead].
+    readAheadEntry := nextResult.
+    ^ resultInfo
 ! !
 
 !DirectoryStream protectedMethodsFor:'instance release'!
@@ -601,7 +543,7 @@
 
     dp := dirPointer.
     dp isNil ifTrue:[
-        ^ self errorNotOpen.
+	^ self errorNotOpen.
     ].
     dirPointer := nil.
 %{
@@ -620,10 +562,11 @@
 openForReading
     "open the file for readonly"
 
-    |ok entry encodedPathName error|
+    |ok encodedPathName error fileSize osPathname osModTime osCrtTime osAccTime osFileAttributes |
 
     encodedPathName := OperatingSystem encodePath:pathName.
     mode := #readonly.
+
 %{
 #ifdef HAS_OPENDIR
     DIR *d;
@@ -631,114 +574,131 @@
 
     ok = false;
     if (__INST(dirPointer) == nil) {
-        if (__isStringLike(encodedPathName)) {
-            __BEGIN_INTERRUPTABLE__
-            __threadErrno = 0;
-            do {
-                d = opendir((char *) __stringVal(encodedPathName));
-            } while ((d == NULL) && (__threadErrno == EINTR));
-            __END_INTERRUPTABLE__
+	if (__isStringLike(encodedPathName)) {
+	    __BEGIN_INTERRUPTABLE__
+	    __threadErrno = 0;
+	    do {
+		d = opendir((char *) __stringVal(encodedPathName));
+	    } while ((d == NULL) && (__threadErrno == EINTR));
+	    __END_INTERRUPTABLE__
 
-            if (d == NULL) {
-                error = __mkSmallInteger(__threadErrno);
-            } else {
-                dp = __MKEXTERNALADDRESS(d); __INST(dirPointer) = dp; __STORE(self, dp);
-                ok = true;
-            }
-        }
+	    if (d == NULL) {
+		error = __mkSmallInteger(__threadErrno);
+	    } else {
+		dp = __MKEXTERNALADDRESS(d); __INST(dirPointer) = dp; __STORE(self, dp);
+		ok = true;
+	    }
+	}
     }
 #else
-# ifdef WIN32
+#ifdef WIN32
     HANDLE d;
     OBJ path, dp;
     union {
-        char pattern[MAXPATHLEN];
-        wchar_t wpattern[MAXPATHLEN];
+	char pattern[MAXPATHLEN];
+	wchar_t wpattern[MAXPATHLEN];
     } uP;
     union {
-        WIN32_FIND_DATAA data;
-        WIN32_FIND_DATAW wdata;
+	WIN32_FIND_DATAA data;
+	WIN32_FIND_DATAW wdata;
     } uD;
 
     ok = false;
     if (__INST(dirPointer) == nil) {
-        path = __INST(pathName);
-        if (__isStringLike(path)) {
-            int l = __stringSize(path);
+	path = __INST(pathName);
+	if (__isStringLike(path)) {
+	    int l = __stringSize(path);
+
+	    if (l < (MAXPATHLEN-4)) {
+		strncpy(uP.pattern, __stringVal(path), l);
+		strcpy(uP.pattern+l, "\\*");
 
-            if (l < (MAXPATHLEN-4)) {
-                strncpy(uP.pattern, __stringVal(path), l);
-                strcpy(uP.pattern+l, "\\*");
+		do {
+		    __threadErrno = 0;
+		    d = STX_API_NOINT_CALL2( "FindFirstFileA", FindFirstFileA, uP.pattern, &uD.data );
+		} while ((d < 0) && (__threadErrno == EINTR));
 
-                do {
-                    __threadErrno = 0;
-                    d = STX_API_NOINT_CALL2( "FindFirstFileA", FindFirstFileA, uP.pattern, &uD.data );
-                } while ((d < 0) && (__threadErrno == EINTR));
+		if (d == INVALID_HANDLE_VALUE) {
+		    error = __mkSmallInteger(GetLastError());
+		} else {
+		    dp = __MKEXTERNALADDRESS(d); __INST(dirPointer) = dp; __STORE(self, dp);
+
+		    fileSize   = __MKLARGEINT64(1, uD.data.nFileSizeLow, uD.data.nFileSizeHigh );
+		    osPathname = __MKSTRING( uD.data.cFileName );
+		    osFileAttributes = __mkSmallInteger( uD.data.dwFileAttributes );
 
-                if (d == INVALID_HANDLE_VALUE) {
-                    error = __mkSmallInteger(GetLastError());
-                } else {
-                    dp = __MKEXTERNALADDRESS(d); __INST(dirPointer) = dp; __STORE(self, dp);
-                    entry = __MKSTRING( uD.data.cFileName );
-                    ok = true;
-                }
-            }
-        }
-        else if (__isUnicode16String(path)) {
-            int l = __unicode16StringSize(path);
-            int i;
+		    osCrtTime = FileTimeToOsTime(&uD.data.ftCreationTime);
+		    osAccTime = FileTimeToOsTime(&uD.data.ftLastAccessTime);
+		    osModTime = FileTimeToOsTime(&uD.data.ftLastWriteTime);
+		    ok = true;
+		}
+	    }
+	}
+	else if (__isUnicode16String(path)) {
+	    int l = __unicode16StringSize(path);
+	    int i;
+
+	    if (l < (MAXPATHLEN-4)) {
+		for (i=0; i<l; i++) {
+		    uP.wpattern[i] = __unicode16StringVal(path)[i];
+		}
+		uP.wpattern[i++] = '\\';
+		uP.wpattern[i++] = '*';
+		uP.wpattern[i] = 0;
 
-            if (l < (MAXPATHLEN-4)) {
-                for (i=0; i<l; i++) {
-                    uP.wpattern[i] = __unicode16StringVal(path)[i];
-                }
-                uP.wpattern[i++] = '\\';
-                uP.wpattern[i++] = '*';
-                uP.wpattern[i] = 0;
+		do {
+		    __threadErrno = 0;
+		    d = STX_API_NOINT_CALL2( "FindFirstFileW", FindFirstFileW, uP.wpattern, &uD.wdata );
+		} while ((d < 0) && (__threadErrno == EINTR));
+
+		if (d == INVALID_HANDLE_VALUE) {
+		    error = __mkSmallInteger(GetLastError());
+		} else {
+		    dp = __MKEXTERNALADDRESS(d); __INST(dirPointer) = dp; __STORE(self, dp);
 
-                do {
-                    __threadErrno = 0;
-                    d = STX_API_NOINT_CALL2( "FindFirstFileW", FindFirstFileW, uP.wpattern, &uD.wdata );
-                } while ((d < 0) && (__threadErrno == EINTR));
+		    fileSize   = __MKLARGEINT64(1, uD.wdata.nFileSizeLow, uD.wdata.nFileSizeHigh );
+		    osPathname = __MKU16STRING( uD.wdata.cFileName );
+		    osFileAttributes = __mkSmallInteger( uD.data.dwFileAttributes );
 
-                if (d == INVALID_HANDLE_VALUE) {
-                    error = __mkSmallInteger(GetLastError());
-                } else {
-                    dp = __MKEXTERNALADDRESS(d); __INST(dirPointer) = dp; __STORE(self, dp);
-                    entry = __MKU16STRING( uD.wdata.cFileName );
-                    ok = true;
-                }
-            }
-        }
+		    osCrtTime = FileTimeToOsTime(&uD.wdata.ftCreationTime);
+		    osAccTime = FileTimeToOsTime(&uD.wdata.ftLastAccessTime);
+		    osModTime = FileTimeToOsTime(&uD.wdata.ftLastWriteTime);
+		    ok = true;
+		}
+	    }
+	}
     }
-# endif
+#endif
 #endif
 %}.
-    ok isNil ifTrue:[
-        "
-         opendir not avalable - use slower pipe
-        "
-        ^ PipeStream readingFrom:('cd ' , pathName , '; ls -a')
+
+    ok == true ifTrue:[
+	Lobby register:self.
+	osPathname isNil ifTrue:[ "UNIX: doesnot provide the first entry"
+	    StreamError handle:[:ex |
+		self close.
+		ex reject.
+	    ] do:[
+		self nextLinkInfo. "read 1st entry into readAheadEntry buffer"
+	    ].
+	] ifFalse:[
+	    readAheadEntry := OperatingSystem
+		linkInfoFor:osPathname
+		fileSize:fileSize
+		fileAttributes:osFileAttributes
+		osCrtTime:osCrtTime
+		osAccTime:osAccTime
+		osModTime:osModTime
+	].
+
+	^ self
     ].
 
-    (ok == true) ifTrue:[
-        Lobby register:self.
-        entry isNil ifTrue:[
-            StreamError handle:[:ex |
-                self close.
-                ex reject.
-            ] do:[
-                self nextLine. "read 1st entry into readAheadEntry buffer"
-            ].        
-        ] ifFalse:[
-            readAheadEntry := entry.
-        ].
-        ^ self
+    ok notNil ifTrue:[
+	dirPointer notNil ifTrue:[^ self errorAlreadyOpen].
     ].
-    dirPointer notNil ifTrue:[^ self errorAlreadyOpen].
     error notNil ifTrue:[
-        lastErrorNumber := error.
-        ^ self openError:error.
+	^ self openError:(lastErrorNumber := error).
     ].
     ^ nil
 !
@@ -789,10 +749,10 @@
 !DirectoryStream class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/DirectoryStream.st,v 1.82 2014-11-18 20:16:37 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/DirectoryStream.st,v 1.83 2015-01-12 13:55:30 ca Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/DirectoryStream.st,v 1.82 2014-11-18 20:16:37 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/DirectoryStream.st,v 1.83 2015-01-12 13:55:30 ca Exp $'
 ! !