[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Help-smalltalk] Searching directories
From: |
Mike Anderson |
Subject: |
[Help-smalltalk] Searching directories |
Date: |
Wed, 10 Aug 2005 09:42:45 +0000 |
User-agent: |
Mozilla Thunderbird 0.7.3 (X11/20040803) |
Hello all,
I came accross this page by Why The Lucky Stiff:
http://whytheluckystiff.net/articles/wearingRubySlippersToWork.html
and, thinking about the Smalltalk equivalent, I wanted to write:
(Directory name: '.') allFilesMatching: '*.php' do:
[ :f |
f linesDo:
[ :l |
l =~ '<search string>' ifMatched:
[ :m | Transcript << f name << ' : ' << l ; nl ] ] ].
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.
Unfortunately, #allFilesMatching:do: isn't as easy to implement as you
might think. The most fundamental problem is that there's no way to
prevent it following symlinks, because there's no way (that I can see)
to test a file to see whether it is a symlink.
I hope there's nothing too controversial about cint.diff. I've made
st_mode a long, because that seems to be how it is declared, but I'm not
sure it is strictly necessary. The most confusing thing is that my_lstat
appears in the list of functions at the bottom, #ifdef'd out - I'm
wondering if that means that there's something I'm missing?
I've not made a diff for changes.st, because there's a few of them, and
you might not want them all.
Now there's another problem, which is that there is a file in the
directory tree that I've been testing this on named: '#1.st#', and that
causes things to go horribly wrong when in VFSHandler >> #for:
The solution for this, I think is to test the filename to see if it
exists first, and only if it doesn't, to start processing virtual file
paths, but that won't work if there's a virtual file path hanging off a
file with a # in its name (eg. file#file#vfs/vfs/vfs), so I thought I'd
canvas opinions.
Mike
Directory methodsFor: 'accessing'!
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.
!
!
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
isSymLink ]) ifFalse:
[ f allFilesMatching: aPattern do:
aBlock ] ]
ifFalse:
[ (aPattern match: name) ifTrue:
[ aBlock value: (self at: name)] ] ].
!
!
Directory class methodsFor: 'enumerating'!
allFilesMatching: aPattern do: aBlock
(self name: (self working))
allFilesMatching: aPattern do: aBlock
!
!
File methodsFor: 'testing'!
isSymLink
^vfsHandler isSymLink
!
!
Stream methodsFor: 'enumerating'!
linesDo: aBlock
[ self atEnd ]
whileFalse:
[ aBlock value: self nextLine ].
!
!
VFS.RealFileHandler methodsFor: 'testing'!
isSymLink
| lstat |
lstat := CStatStruct new.
lstat addToBeFinalized.
self lstatOn: self realFileName into: lstat.
^(lstat stMode value bitAnd: 8r120000) = 8r120000 "S_IFLNK"
!
!
--- smalltalk-2.1g-orig/libgst/cint.c 2003-12-11 13:22:59.000000000 +0000
+++ smalltalk-2.1g/libgst/cint.c 2005-08-09 20:57:26.000000000 +0000
@@ -135,7 +135,7 @@
typedef struct gst_stat
{
- unsigned short st_mode; /* protection */
+ unsigned long st_mode; /* protection */
long st_size; /* total size, in bytes */
long st_aTime; /* time of last access */
long st_mTime; /* time of last modification */
@@ -196,8 +196,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_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);
@@ -292,6 +292,18 @@
return (old);
}
+void fill_gst_stat(struct stat *in, gst_stat *out)
+{
+ out->st_mode = in -> st_mode;
+ out->st_size = in -> st_size;
+ out->st_aTime =
+ _gst_adjust_time_zone (in -> st_atime) - 86400 * 10959;
+ out->st_mTime =
+ _gst_adjust_time_zone (in -> st_mtime) - 86400 * 10959;
+ out->st_cTime =
+ _gst_adjust_time_zone (in -> st_ctime) - 86400 * 10959;
+}
+
int
my_stat (const char *name,
gst_stat * out)
@@ -299,18 +311,27 @@
int result;
static struct stat statOut;
- result = stat (name, &statOut);
+ result = stat (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 * 10959;
- out->st_mTime =
- _gst_adjust_time_zone (statOut.st_mtime) - 86400 * 10959;
- out->st_cTime =
- _gst_adjust_time_zone (statOut.st_ctime) - 86400 * 10959;
+ fill_gst_stat(&statOut, out);
+ }
+ 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;
+ fill_gst_stat(&statOut, out);
}
return (result);
}
@@ -462,9 +483,7 @@
_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);
- [Help-smalltalk] Searching directories,
Mike Anderson <=