... 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 |
Free forum by Nabble | Edit this page |