[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-smalltalk] Searching directories
From: |
Paolo Bonzini |
Subject: |
Re: [Help-smalltalk] Searching directories |
Date: |
Thu, 11 Aug 2005 18:06:18 +0200 |
User-agent: |
Mozilla Thunderbird 0.9 (Macintosh/20041103) |
OK, so we don't have Directory >> #allFilesMatching:do:, or File >>
#linesDo:, but it looks pretty promising. If I was typing this a lot,
I would probably want something like File >> #grep: as well.
Mike, thanks for providing as usual good insights and good code.
I've modified a bit your code to optimize #isSymbolicLink, but otherwise
it is the same. I do an lstat, and then follow with a stat if it is a
symbolic link. It is possible to optimize it further, I'll look at this
after I've been able to test the code as it is (I must rush out).
I attach my patch, it should appear in the arch repository tomorrow.
Paolo
* looking for address@hidden/smalltalk--devo--2.2--patch-47 to compare with
* auto-adding address@hidden/smalltalk--devo--2.2--patch-47 to greedy revision
library /Users/bonzinip/Archives/revlib
* found immediate ancestor revision in library
(address@hidden/smalltalk--devo--2.2--patch-46)
* patching for this revision (address@hidden/smalltalk--devo--2.2--patch-47)
* comparing to address@hidden/smalltalk--devo--2.2--patch-47
M kernel/Directory.st
M kernel/Stream.st
M kernel/VFS.st
M libgst/cint.c
* modified files
--- orig/kernel/Directory.st
+++ mod/kernel/Directory.st
@@ -140,6 +140,11 @@ working: dirName
self checkError
!
+allFilesMatching: aPattern do: aBlock
+ (self name: (self working))
+ allFilesMatching: aPattern do: aBlock
+!
+
create: dirName
"Create a directory named dirName."
^(VFS.VFSHandler for: (File pathFor: dirName))
@@ -149,12 +154,24 @@ create: dirName
!Directory methodsFor: 'accessing'!
-at: aName
- "Answer a File object for a file named `aName' residing in the directory
- represented by the receiver."
+fileAt: aName
+ "Answer a File object for a file named `aName' residing in the
+ directory represented by the receiver."
^File on: (vfsHandler at: aName)
!
+
+at: aName
+ "Answer a File or Directory object as appropriate for a file named
+ 'aName' in the directory represented by the receiver."
+ | f |
+ f := vfsHandler at: aName.
+ ^((f exists and: [f isDirectory])
+ ifTrue: [ Directory ]
+ ifFalse: [ File ])
+ on: f
+!
+
directoryAt: aName
"Answer a Directory object for a file named `aName' residing in the
directory represented by the receiver."
@@ -182,6 +199,22 @@ nameAt: aName
!Directory methodsFor: 'enumerating'!
+allFilesMatching: aPattern do: aBlock
+ "Evaluate aBlock on the File objects that match aPattern (according to
+ String>>#match:) in the directory named by the receiver. Recursively
+ descend into directories."
+
+ self do: [ :name || f |
+ f := self at: name.
+ f isDirectory
+ ifTrue: [
+ ((#('.' '..') includes: name) or: [ f isSymbolicLink ])
+ ifFalse: [ f allFilesMatching: aPattern do: aBlock ] ]
+ ifFalse: [
+ (aPattern match: name)
+ ifTrue: [ aBlock value: f ] ] ]
+!
+
contents
"Answer an Array with the names of the files in the directory
represented by the receiver."
--- orig/kernel/Stream.st
+++ mod/kernel/Stream.st
@@ -225,6 +225,13 @@ isExternalStream
!Stream methodsFor: 'enumerating'!
+linesDo: aBlock
+ "Evaluate aBlock once for every line in the receiver (assuming the
+ receiver is streaming on Characters)."
+ [self atEnd] whileFalse:
+ [aBlock value: self nextLine].
+!
+
do: aBlock
"Evaluate aBlock once for every object in the receiver"
[self atEnd] whileFalse:
--- orig/kernel/VFS.st
+++ mod/kernel/VFS.st
@@ -46,7 +46,7 @@ delegate to the appropriate handler, whi
actually accessing or ``molding'''' the filesystem.'!
VFSHandler subclass: #RealFileHandler
- instanceVariableNames: 'stat'
+ instanceVariableNames: 'stat isSymbolicLink'
classVariableNames: 'Epoch'
poolDictionaries: ''
category: 'Streams-Files'
@@ -124,6 +124,9 @@ CStruct
"opendir and closedir needed to test for directories"
!VFSHandler methodsFor: 'C call-outs'!
+lstatOn: fileName into: statStruct
+ <cCall: 'lstat' returning: #int args: #(#string #cObject)>!
+
statOn: fileName into: statStruct
<cCall: 'stat' returning: #int args: #(#string #cObject)>!
@@ -321,6 +324,11 @@ exists
^true
!
+isSymbolicLink
+ "Answer whether the file is a symbolic link."
+ ^false
+!
+
isDirectory
"Answer whether a file with the name contained in the receiver does exist
and identifies a directory."
@@ -416,6 +424,12 @@ size
^self stat stSize value
!
+isSymbolicLink
+ "Answer whether the file is a symbolic link."
+ self stat.
+ ^isSymbolicLink
+!
+
lastAccessTime
"Answer the last access time of the file identified by the receiver"
^self getDateAndTime: self stat stAtime value
@@ -449,8 +463,12 @@ refresh
stat := CStatStruct new.
stat addToBeFinalized
].
- self statOn: self realFileName into: stat.
- File checkError
+ self lstatOn: self realFileName into: stat.
+ File checkError.
+ isSymbolicLink := (stat stMode value bitAnd: 8r120000) = 8r120000.
"S_IFLNK"
+ isSymbolicLink ifTrue: [
+ self statOn: self realFileName into: stat.
+ File checkError ]
! !
--- orig/libgst/cint.c
+++ mod/libgst/cint.c
@@ -198,6 +198,8 @@ static int get_errno (void);
/* Encapsulate binary incompatibilities between various C libraries. */
static int my_stat (const char *name,
gst_stat * out);
+static int my_lstat (const char *name,
+ gst_stat * out);
static int my_putenv (const char *str);
static int my_chdir (const char *str);
static DIR *my_opendir (const char *str);
@@ -312,6 +314,26 @@ my_stat (const char *name,
return (result);
}
+int
+my_lstat (const char *name,
+ gst_stat * out)
+{
+ int result;
+ static struct stat statOut;
+
+ result = lstat (name, &statOut);
+ if (!result)
+ {
+ errno = 0;
+ out->st_mode = statOut.st_mode;
+ out->st_size = statOut.st_size;
+ out->st_aTime = _gst_adjust_time_zone (statOut.st_atime) - 86400 * 10957;
+ out->st_mTime = _gst_adjust_time_zone (statOut.st_mtime) - 86400 * 10957;
+ out->st_cTime = _gst_adjust_time_zone (statOut.st_ctime) - 86400 * 10957;
+ }
+ return (result);
+}
+
int
my_putenv (const char *str)
{
@@ -459,9 +485,7 @@ _gst_init_cfuncs (void)
_gst_define_cfunc ("errno", get_errno);
_gst_define_cfunc ("strerror", strerror);
_gst_define_cfunc ("stat", my_stat);
-#if 0
_gst_define_cfunc ("lstat", my_lstat);
-#endif
_gst_define_cfunc ("opendir", my_opendir);
_gst_define_cfunc ("closedir", closedir);