From a2c4a53e155cae1e47a2d955aee285d249592d63 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Wed, 29 May 2024 11:22:08 -0500 Subject: [PATCH] Fix chmod g+rX-ws and similar, plus in-passing cleanups. --- lib/lib.c | 13 ++++++------- lib/lib.h | 4 ++-- tests/chmod.test | 2 ++ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/lib.c b/lib/lib.c index 9561848a..dc578804 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -950,11 +950,11 @@ void list_signals(void) } // premute mode bits based on posix mode strings. -mode_t string_to_mode(char *modestr, mode_t mode) +unsigned string_to_mode(char *modestr, unsigned mode) { char *whos = "ogua", *hows = "=+-", *whats = "xwrstX", *whys = "ogu", *s, *str = modestr; - mode_t extrabits = mode & ~(07777); + unsigned extrabits = mode & ~(07777), bit; // Handle octal mode if (isdigit(*str)) { @@ -966,9 +966,7 @@ mode_t string_to_mode(char *modestr, mode_t mode) // Gaze into the bin of permission... for (;;) { - int i, j, dowho, dohow, dowhat, amask; - - dowho = dohow = dowhat = amask = 0; + int i, j, dowho = 0, dohow = 0, dowhat, amask = 0; // Find the who, how, and what stanzas, in that order while (*str && (s = strchr(whos, *str))) { @@ -984,6 +982,7 @@ mode_t string_to_mode(char *modestr, mode_t mode) // Repeated "hows" are allowed; something like "a=r+w+s" is valid. for (;;) { if (-1 == stridx(hows, dohow = *str)) goto barf; + dowhat = 0; while (*++str && (s = strchr(whats, *str))) dowhat |= 1<<(s-whats); // Convert X to x for directory or if already executable somewhere @@ -998,12 +997,12 @@ mode_t string_to_mode(char *modestr, mode_t mode) // Loop through what=xwrs and who=ogu to apply bits to the mode. for (i=0; i<4; i++) { for (j=0; j<3; j++) { - mode_t bit = 0; int where = 1<<((3*i)+j); if (amask & where) continue; // Figure out new value at this location + bit = 0; if (i == 3) { // suid and sticky if (!j) bit = dowhat&16; // o+s = t but a+s doesn't set t, hence t @@ -1031,7 +1030,7 @@ barf: } // Format access mode into a drwxrwxrwx string -void mode_to_string(mode_t mode, char *buf) +void mode_to_string(unsigned mode, char *buf) { char c, d; int i, bit; diff --git a/lib/lib.h b/lib/lib.h index 5bc21f01..cca70789 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -410,8 +410,8 @@ void exit_signal(int signal); void sigatexit(void *handler); void list_signals(void); -mode_t string_to_mode(char *mode_str, mode_t base); -void mode_to_string(mode_t mode, char *buf); +unsigned string_to_mode(char *mode_str, mode_t base); +void mode_to_string(unsigned mode, char *buf); char *getbasename(char *name); char *fileunderdir(char *file, char *dir); void *mepcpy(void *from, void *to, unsigned long len); diff --git a/tests/chmod.test b/tests/chmod.test index 97c9e939..8c4f5e63 100755 --- a/tests/chmod.test +++ b/tests/chmod.test @@ -114,6 +114,8 @@ SKIP=0 chtest +t "drwxr-xr-t\n-rw-r--r-T\n" chtest a=r+w+x "drwxrwxrwx\n-rwxrwxrwx\n" +chtest u+rwX-s,g+rX-ws,o+rX-wt "drwxr-xr-x\n-rw-r--r--\n" +chtest u+rwX,u-s,g+rX,g-ws,o+rX,o-wt "drwxr-xr-x\n-rw-r--r--\n" # (chtest starts off with a directory that's +x...) testing "+X" \ -- 2.39.2