commit f3d05ffd0ac4226f9064be5c71606ab9b7d12d92
Author: Michael Forney <[email protected]>
AuthorDate: Mon Jan 6 13:08:38 2020 -0800
Commit: Michael Forney <[email protected]>
CommitDate: Mon Jan 6 13:47:26 2020 -0800
chmod: Implement X perm symbol
Instead of clearing the format bits before calling parsemode, leave
them in so we can differentiate between directories and other files,
then clear the format bits in the result.
diff --git a/chmod.1 b/chmod.1
index 4805ce0..fa4131d 100644
--- a/chmod.1
+++ b/chmod.1
@@ -47,7 +47,7 @@ If
.Ar mode
is
.Em symbolic
-"[ugoa]*[+-=][rwxst]*"
+"[ugoa]*[+-=][rwxXst]*"
.Bl -tag -width Ds
.It u|g|o|a
owner | group | other (non-group) | everyone
@@ -55,6 +55,8 @@ owner | group | other (non-group) | everyone
add | remove | set
.It r|w|x|s|t
read | write | execute | setuid and setgid | sticky
+.It X
+execute, if directory or at least one execute bit is already set
.El
.Sh OPTIONS
.Bl -tag -width Ds
diff --git a/chmod.c b/chmod.c
index 2a0085d..512a7ea 100644
--- a/chmod.c
+++ b/chmod.c
@@ -13,7 +13,7 @@ chmodr(const char *path, struct stat *st, void *data, struct
recursor *r)
{
mode_t m;
- m = parsemode(modestr, st->st_mode & ~S_IFMT, mask);
+ m = parsemode(modestr, st->st_mode, mask);
if (chmod(path, m) < 0) {
weprintf("chmod %s:", path);
ret = 1;
@@ -50,8 +50,8 @@ main(int argc, char *argv[])
case 'P':
r.follow = (*argv)[i];
break;
- case 'r': case 'w': case 'x': case 's': case 't':
- /* -[rwxst] are valid modes, so we're done */
+ case 'r': case 'w': case 'x': case 'X': case 's': case
't':
+ /* -[rwxXst] are valid modes, so we're done */
if (i == 1)
goto done;
/* fallthrough */
diff --git a/libutil/mode.c b/libutil/mode.c
index 5ba8eb1..b3632ad 100644
--- a/libutil/mode.c
+++ b/libutil/mode.c
@@ -113,6 +113,10 @@ next:
case 'x':
perm |= S_IXUSR|S_IXGRP|S_IXOTH;
break;
+ case 'X':
+ if (S_ISDIR(mode) || mode &
(S_IXUSR|S_IXGRP|S_IXOTH))
+ perm |= S_IXUSR|S_IXGRP|S_IXOTH;
+ break;
case 's':
perm |= S_ISUID|S_ISGID;
break;
@@ -144,5 +148,5 @@ apply:
goto next;
}
}
- return mode;
+ return mode & ~S_IFMT;
}