[PATCH] add File>>#owner:/#group:/#owner:group:

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] add File>>#owner:/#group:/#owner:group:

Paolo Bonzini-2
... 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.  */
 

_______________________________________________
help-smalltalk mailing list
[hidden email]
http://lists.gnu.org/mailman/listinfo/help-smalltalk