help-smalltalk
[Top][All Lists]
Advanced

[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);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]