aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/lib.c21
-rwxr-xr-xtests/chmod.test1
2 files changed, 11 insertions, 11 deletions
diff --git a/lib/lib.c b/lib/lib.c
index 3129e3e3..dfa4499f 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -976,22 +976,19 @@ mode_t string_to_mode(char *modestr, mode_t mode)
}
// Repeated "hows" are allowed; something like "a=r+w+s" is valid.
- do {
- if (!(dohow = *str) || !strchr(hows, *str)) goto barf;
+ for (;;) {
+ if (-1 == stridx(hows, dohow = *str)) goto barf;
while (*++str && (s = strchr(whats, *str))) dowhat |= 1<<(s-whats);
// Convert X to x for directory or if already executable somewhere
if ((dowhat&32) && (S_ISDIR(mode) || (mode&0111))) dowhat |= 1;
// Copy mode from another category?
- if (!dowhat && *str && (s = strchr(whys, *str))) {
- dowhat = (mode>>(3*(s-whys)))&7;
+ if (!dowhat && -1 != (i = stridx(whys, *str))) {
+ dowhat = (mode>>(3*i))&7;
str++;
}
- // Are we ready to do a thing yet?
- if (*str && (str[1] != ',' && !strchr(hows, *str))) goto barf;
-
// 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++) {
@@ -1015,12 +1012,14 @@ mode_t string_to_mode(char *modestr, mode_t mode)
if (bit && dohow != '-') mode |= where;
}
}
- } while (*str);
-
- if (!*str) break;
+ if (!*str) return mode|extrabits;
+ if (*str == ',') {
+ str++;
+ break;
+ }
+ }
}
- return mode|extrabits;
barf:
error_exit("bad mode '%s'", modestr);
}
diff --git a/tests/chmod.test b/tests/chmod.test
index 3f5673d7..9adca60f 100755
--- a/tests/chmod.test
+++ b/tests/chmod.test
@@ -96,6 +96,7 @@ chtest +x "drwxr-xr-x\n-rwxr-xr-x\n"
chtest -r "d-wx--x--x\n--w-------\n"
chtest -w "dr-xr-xr-x\n-r--r--r--\n"
chtest -x "drw-r--r--\n-rw-r--r--\n"
+chtest a-w,a+x "dr-xr-xr-x\n-r-xr-xr-x\n"
# macOS doesn't allow +s in /tmp
touch s-supported