From f3d05ffd0ac4226f9064be5c71606ab9b7d12d92 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Mon, 6 Jan 2020 13:08:38 -0800 Subject: [PATCH] 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. --- chmod.1 | 4 +++- chmod.c | 6 +++--- libutil/mode.c | 6 +++++- 3 files changed, 11 insertions(+), 5 deletions(-) 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; }