The supplied patch adds R, W, S and T flags to chmod. (see documentation
patch for description of functionality).
(nb - this patch is licensed under the GPL version 2 or any later version)
Thanks,
Jonathan.
--- chmod.1.old Sun Apr 29 09:29:42 2001
+++ chmod.1 Thu Nov 22 16:59:17 2001
@@ -35,14 +35,17 @@
existing permissions of each file; `-' causes them to be removed; and
`=' causes them to be the only permissions that the file has.
.PP
-The letters `rwxXstugo' select the new permissions for the affected
+The letters `rwxstRWXSTugo' select the new permissions for the affected
users: read (r), write (w), execute (or access for directories) (x),
-execute only if the file is a directory or already has execute
-permission for some user (X), set user or group ID on execution (s),
-save program text on swap device (t), the permissions that the user
-who owns the file currently has for it (u), the permissions that other
-users in the file's group have for it (g), and the permissions that
-other users not in the file's group have for it (o).
+set user or group ID on execution (s), save program text on swap
+device (t), read only if already has read permission for some user (R),
+write only if already has write permission for some user (W), execute
+only if the file is a directory or already has execute permission for
+some user (X), setgid if the file is a directory (S), sticky if the
+file is a directory (T), the permissions that the user who owns the
+file currently has for it (u), the permissions that other users in the
+file's group have for it (g), and the permissions that other users not
+in the file's group have for it (o).
.PP
A numeric mode is from one to four octal digits (0-7), derived by
adding up the bits with values 4, 2, and 1. Any omitted digits are
--- chmod.c.old Sun Nov 19 16:56:33 2000
+++ chmod.c Tue Oct 9 19:55:48 2001
@@ -323,11 +323,16 @@
case 0:
break;
case 'r':
+ /* We can't do case 'R' here because it conflicts with Recursive
+ however chmod -R isn't ever going to be a sensible thing to do */
case 'w':
+ case 'W':
case 'x':
case 'X':
case 's':
+ case 'S':
case 't':
+ case 'T':
case 'u':
case 'g':
case 'o':
--- modechange.c.old Sun Jan 7 09:20:33 2001
+++ modechange.c Tue Oct 9 19:57:10 2001
@@ -304,10 +304,16 @@
for (++mode_string;; ++mode_string)
switch (*mode_string)
{
+ case 'R':
+ change->flags |= MODE_R_IF_ANY_R;
+ /* Fall through. */
case 'r':
change->value |= ((S_IRUSR | S_IRGRP | S_IROTH)
& affected_masked);
break;
+ case 'W':
+ change->flags |= MODE_W_IF_ANY_W;
+ /* Fall through. */
case 'w':
change->value |= ((S_IWUSR | S_IWGRP | S_IWOTH)
& affected_masked);
@@ -318,11 +324,17 @@
case 'x':
change->value |= ((S_IXUSR | S_IXGRP | S_IXOTH)
& affected_masked);
- break;
- case 's':
+ break;
+ case 'S':
+ change->flags |= (MODE_ISGID_IF_DIR | MODE_ISUID_IF_DIR);
+ /* Fall through. */
+ case 's':
/* Set the setuid/gid bits if `u' or `g' is selected. */
change->value |= (S_ISUID | S_ISGID) & affected_masked;
break;
+ case 'T':
+ change->flags |= MODE_ISVTX_IF_DIR;
+ /* Fall through. */
case 't':
/* Set the "save text image" bit if `o' is selected. */
change->value |= S_ISVTX & affected_masked;
@@ -435,15 +447,47 @@
value &= changes->affected;
}
else
- {
+ {
value = changes->value;
- /* If `X', do not affect the execute bits if the file is not a
- directory and no execute bits are already set. */
- if ((changes->flags & MODE_X_IF_ANY_X)
- && !S_ISDIR (oldmode)
- && (newmode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
- /* Clear the execute bits. */
- value &= ~ (S_IXUSR | S_IXGRP | S_IXOTH);
+
+ if (!S_ISDIR (oldmode)) {
+ /* If `X', do not affect the execute bits if the file is not a
+ directory and no execute bits are already set. */
+ if ((changes->flags & MODE_X_IF_ANY_X)
+ && (newmode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
+ value &= ~ (S_IXUSR | S_IXGRP | S_IXOTH);
+
+ /* If `S', do not affect the setgid bit if the file is not a
+ directory. */
+ if (changes->flags & MODE_ISGID_IF_DIR)
+ /* Reset the ISGID bit. */
+ value = (value & ~S_ISGID) | (oldmode & S_ISGID);
+
+ /* If `T', do not affect the sticky bit if the file is not a
+ directory. */
+ if (changes->flags & MODE_ISVTX_IF_DIR)
+ /* Reset the ISVTX bit. */
+ value = (value & ~S_ISVTX) | (oldmode & S_ISVTX);
+ }
+
+ /* If `S', do not affect the setuid bit ever */
+ if (changes->flags & MODE_ISUID_IF_DIR)
+ /* Reset the ISUID bit. */
+ value = (value & ~S_ISUID) | (oldmode & S_ISUID);
+
+ /* If `W', do not affect the write bits if no
+ write bits are already set. */
+ if ((changes->flags & MODE_W_IF_ANY_W)
+ && (newmode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0)
+ /* Clear the write bits. */
+ value &= ~ (S_IWUSR | S_IWGRP | S_IWOTH);
+
+ /* If `R', do not affect the write bits if no
+ read bits are already set. */
+ if ((changes->flags & MODE_R_IF_ANY_R)
+ && (newmode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0)
+ /* Clear the read bits. */
+ value &= ~ (S_IRUSR | S_IRGRP | S_IROTH);
}
switch (changes->op)
--- modechange.h.old Mon Aug 7 18:01:58 2000
+++ modechange.h Tue Oct 9 19:57:10 2001
@@ -26,14 +26,22 @@
# include <sys/types.h>
-/* Affect the execute bits only if at least one execute bit is set already,
- or if the file is a directory. */
+/* Affect the <foo> bits only if at least one <foo> bit is set already */
+/* X also works if the file is a directory regardless */
# define MODE_X_IF_ANY_X 01
+# define MODE_W_IF_ANY_W 02
+# define MODE_R_IF_ANY_R 04
+
+/* Affect the <foo> bits if the file is a directory. ISUID affects nothing,
+ but is needed because of the overloading of the S flag */
+# define MODE_ISVTX_IF_DIR 010
+# define MODE_ISGID_IF_DIR 020
+# define MODE_ISUID_IF_DIR 040
/* If set, copy some existing permissions for u, g, or o onto the other two.
Which of u, g, or o is copied is determined by which bits are set in the
`value' field. */
-# define MODE_COPY_EXISTING 02
+# define MODE_COPY_EXISTING 0100
struct mode_change
{