--- 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 $'
! !