help-smalltalk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-smalltalk] [PATCH] add File>>#owner:/#group:/#owner:group:


From: Paolo Bonzini
Subject: [Help-smalltalk] [PATCH] add File>>#owner:/#group:/#owner:group:
Date: Wed, 07 Jan 2009 12:27:30 +0100
User-agent: Thunderbird 2.0.0.18 (Macintosh/20081105)

... and also adds some more methods to RecursiveFileWrapper so that you
can change the owner/group/mode/times of an entire directory with
something like

  (File name: 'pp') all group: 'wheel'

HTH,

Paolo
diff --git a/configure.ac b/configure.ac
index 0c5a4dc..d3d2979 100644
--- a/configure.ac
+++ b/configure.ac
@@ -299,7 +299,8 @@ AC_REPLACE_FUNCS(putenv strdup strerror strsignal mkstemp 
getpagesize \
 AC_CHECK_FUNCS_ONCE(gethostname memcpy memmove sighold uname usleep lstat \
        grantpt popen getrusage gettimeofday fork strchr utimes utime readlink \
        sigsetmask alarm select mprotect madvise waitpid \
-       setsid spawnl nanosleep pread pwrite _NSGetExecutablePath)
+       setsid spawnl nanosleep pread pwrite _NSGetExecutablePath \
+       chown getgrnam getpwnam endgrent endpwent setgroupent setpassent)
 
 GST_FUNC_LRINT
 GST_FUNC_STRTOUL
diff --git a/kernel/File.st b/kernel/File.st
index 705fa8a..e74dfe2 100644
--- a/kernel/File.st
+++ b/kernel/File.st
@@ -85,6 +85,18 @@ FilePath subclass: File [
        ^true
     ]
 
+    File class >> setTimeFor: fileName atime: atimeSec mtime: mtimeSec [
+       <category: 'private-C call-outs'>
+       <cCall: 'utime' returning: #int args: #(#string #int #int)>
+       
+    ]
+
+    File class >> setOwnerFor: fileName owner: ownerString group: groupString [
+       <category: 'private-C call-outs'>
+       <cCall: 'chown' returning: #int args: #(#string #string #string)>
+       
+    ]
+
     File class >> path: aString [
        "Answer a new file with the given path.  The path is not validated until
         some of the fields of the newly created objects are accessed"
@@ -471,6 +483,17 @@ FilePath subclass: File [
        ^File isAbsolute: self asString
     ]
     
+    owner: ownerString group: groupString [
+       "Set the receiver's owner and group to be ownerString and groupString."
+
+       <category: 'file operations'>
+       self class 
+           setOwnerFor: self asString
+           owner: ownerString
+           group: groupString.
+       File checkError
+    ]
+
     lastAccessTime: accessDateTime lastModifyTime: modifyDateTime [
        "Set the receiver's timestamps to be accessDateTime and modifyDateTime."
 
diff --git a/kernel/FilePath.st b/kernel/FilePath.st
index c2dc833..aec3b92 100644
--- a/kernel/FilePath.st
+++ b/kernel/FilePath.st
@@ -317,6 +317,28 @@ size and timestamps.'>
        self subclassResponsibility
     ]
 
+    owner: ownerString group: groupString [
+       "Set the owner and group of the file identified by the receiver to be
+        aString."
+
+       <category: 'accessing'>
+       self subclassResponsibility
+    ]
+
+    group: aString [
+       "Set the group of the file identified by the receiver to be aString."
+
+       <category: 'accessing'>
+       self owner: nil group: aString
+    ]
+
+    owner: aString [
+       "Set the owner of the file identified by the receiver to be aString."
+
+       <category: 'accessing'>
+       self owner: aString group: nil
+    ]
+
     lastAccessTime: aDateTime [
        "Update the last access time of the file corresponding to the receiver,
         to be aDateTime."
diff --git a/kernel/VFS.st b/kernel/VFS.st
index 1168355..9a01b02 100644
--- a/kernel/VFS.st
+++ b/kernel/VFS.st
@@ -192,6 +192,13 @@ virtual files that refer to a real file on disk.'>
         ^self file isSymbolicLink
     ]
 
+    owner: ownerString group: groupString [
+       "Set the receiver's owner and group to be ownerString and groupString."
+
+        <category: 'accessing'>
+        self file owner: ownerString group: groupString
+    ]
+
     lastAccessTime: accessDateTime lastModifyTime: modifyDateTime [
         "Update the timestamps of the file corresponding to the receiver, to be
          accessDateTime and modifyDateTime."
@@ -406,6 +413,57 @@ VFS.FileWrapper subclass: RecursiveFileWrapper [
        <category: 'testing'>
        ^self file isFileSystemPath
     ]
+
+    lastAccessTime: accessDateTime lastModifyTime: modifyDateTime [
+       "Update the timestamps of all files in the tree to be
+        accessDateTime and modifyDateTime."
+
+        <category: 'accessing'>
+       self isDirectory ifFalse: [
+           ^super lastAccessTime: accessDateTime lastModifyTime: 
modifyDateTime ].
+        self do: [ :each |
+           each file lastAccessTime: accessDateTime lastModifyTime: 
modifyDateTime ]
+    ]
+
+    owner: ownerString group: groupString [
+       "Set the owner and group for all files and directories in the tree."
+
+        <category: 'accessing'>
+       self isDirectory ifFalse: [
+           ^super owner: ownerString group: groupString ].
+       "These special calls cache the uid and gid to avoid repeated lookups."
+       [
+           File setOwnerFor: nil owner: ownerString group: groupString.
+            self do: [ :each | each file owner: ownerString group: groupString 
]
+       ] ensure: [ File setOwnerFor: nil owner: nil group: nil ]
+    ]
+
+    mode: anInteger [
+       "Set the mode to be anInteger for all files in the tree.  Directory
+        modes are left unchanged."
+
+        <category: 'accessing'>
+       self isDirectory ifFalse: [ ^super mode: anInteger ].
+
+       self do: [ :each |
+           each isDirectory ifFalse: [ each file mode: anInteger ] ]
+    ]
+
+    fileMode: fMode directoryMode: dMode [
+       "Set the mode to be fMode for all files in the tree, and dMode for
+        all directories in the tree."
+
+        <category: 'accessing'>
+       self isDirectory ifFalse: [ ^super mode: fMode ].
+
+       super mode: dMode.
+       self isDirectory ifTrue: [
+           self do: [ :each |
+               each file
+                   mode: (each isDirectory
+                               ifTrue: [ dMode ]
+                               ifFalse: [ fMode ]) ] ]
+    ]
 ]
 
 ]
diff --git a/libgst/cint.c b/libgst/cint.c
index f5e8451..cc0e947 100644
--- a/libgst/cint.c
+++ b/libgst/cint.c
@@ -59,6 +59,13 @@
 #include "ffi.h"
 #include <ltdl.h>
 
+#ifdef HAVE_GETGRNAM
+#include <grp.h>
+#endif
+#ifdef HAVE_GETPWNAM
+#include <pwd.h>
+#endif
+
 typedef struct cparam
 {
   union {
@@ -186,6 +193,7 @@ static int my_lstat (const char *name,
                     OOP out);
 static int my_putenv (const char *str);
 static int my_chdir (const char *str);
+static int my_chown (const char *file, const char *owner, const char *group);
 static int my_symlink (const char* oldpath, const char* newpath);
 static char *my_mkdtemp (char* template);
 static int my_mkdir (const char* name, int mode);
@@ -543,6 +551,7 @@ _gst_init_cfuncs (void)
   _gst_define_cfunc ("lstat_obj", my_lstat);
   _gst_define_cfunc ("utime", _gst_set_file_access_times);
   _gst_define_cfunc ("chmod", chmod);
+  _gst_define_cfunc ("chown", my_chown);
 
   _gst_define_cfunc ("opendir", my_opendir);
   _gst_define_cfunc ("closedir", closedir);
@@ -1382,6 +1391,104 @@ _gst_set_errno(int errnum)
 }
 
 
+int
+my_chown (const char *file, const char *user, const char *group)
+{
+#if defined HAVE_CHOWN && defined HAVE_GETGRNAM && defined HAVE_GETPWNAM
+  static char *save_user, *save_group;
+  static uid_t save_uid;
+  static gid_t save_gid;
+  static int recursive_depth;
+
+  uid_t uid, gid;
+  if (!file && !user && !group)
+    {
+      recursive_depth--;
+      if (recursive_depth == 0)
+       {
+#if defined HAVE_SETGROUPENT && defined HAVE_ENDGRENT
+         endgrent ();
+#endif
+#if defined HAVE_SETPASSENT && defined HAVE_ENDPWENT
+         endpwent ();
+#endif
+       }
+
+      free (save_user);
+      free (save_group);
+      save_user = save_group = NULL;
+      return 0;
+    }
+
+  if (!file)
+    {
+      recursive_depth++;
+      if (recursive_depth == 1)
+       {
+#if defined HAVE_SETGROUPENT && defined HAVE_ENDGRENT
+         setgroupent (1);
+#endif
+#if defined HAVE_SETPASSENT && defined HAVE_ENDPWENT
+         setpassent (1);
+#endif
+       }
+    }
+
+  if (!user)
+    uid = -1;
+  else if (save_user && !strcmp (save_user, user))
+    uid = save_uid;
+  else
+    {
+      struct passwd *pw;
+      pw = getpwnam (user);
+      if (!pw)
+       {
+         errno = EINVAL;
+         return -1;
+       }
+
+      uid = pw->pw_uid;
+      if (recursive_depth)
+       {
+         if (save_user)
+           free (save_user);
+          save_user = strdup (user);
+         save_uid = uid;
+       }
+    }
+
+  if (!group)
+    gid = -1;
+  else if (save_group && !strcmp (save_group, group))
+    gid = save_gid;
+  else
+    {
+      struct group *gr;
+      gr = getgrnam (group);
+      if (!gr)
+       {
+         errno = EINVAL;
+         return -1;
+       }
+
+      gid = gr->gr_gid;
+      if (recursive_depth)
+       {
+         if (save_group)
+           free (save_group);
+          save_group = strdup (group);
+         save_gid = gid;
+       }
+    }
+
+  if (!file)
+    return 0;
+  else
+    return chown (file, uid, gid);
+#endif
+}
+
 /* TODO: check if this can be changed to an extern declaration and/or
    an AC_CHECK_DECLS test.  */
 

reply via email to

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