Change 5109da9b3e6a898c8e0ad647303a1b375e3d97d3 caused test.test to call chmod with mode `u+s+s` which passes on the host (where you have a toybox test but a GNU chmod) but fails on Android where chmod is toybox too.
Add the missing loop to string_to_mode(), which means this will also affect other toys, but that seems like a feature (and, for example, GNU mkdir also accepts a mode like `a=r+w+x`). --- lib/lib.c | 76 +++++++++++++++++++++++++----------------------- tests/chmod.test | 1 + 2 files changed, 41 insertions(+), 36 deletions(-)
From da730f8d8e0555dd4dc5645b2b4f4b15e5542937 Mon Sep 17 00:00:00 2001 From: Elliott Hughes <e...@google.com> Date: Thu, 3 Dec 2020 14:48:16 -0800 Subject: [PATCH] chmod: support complex modes. Change 5109da9b3e6a898c8e0ad647303a1b375e3d97d3 caused test.test to call chmod with mode `u+s+s` which passes on the host (where you have a toybox test but a GNU chmod) but fails on Android where chmod is toybox too. Add the missing loop to string_to_mode(), which means this will also affect other toys, but that seems like a feature (and, for example, GNU mkdir also accepts a mode like `a=r+w+x`). --- lib/lib.c | 76 +++++++++++++++++++++++++----------------------- tests/chmod.test | 1 + 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/lib/lib.c b/lib/lib.c index c4e70dfe..ebf85ce0 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -970,48 +970,52 @@ mode_t string_to_mode(char *modestr, mode_t mode) umask(amask = umask(0)); } - if (!*str || !(s = strchr(hows, *str))) goto barf; - if (!(dohow = *(str++))) goto barf; + // Repeated "hows" are allowed; something like "a=r+w+s" is valid. + if (!*str) goto barf; + while (*str) { + if (!strchr(hows, *str)) goto barf; + if (!(dohow = *(str++))) goto barf; + + while (*str && (s = strchr(whats, *str))) { + dowhat |= 1<<(s-whats); + str++; + } - while (*str && (s = strchr(whats, *str))) { - dowhat |= 1<<(s-whats); - str++; - } + // Convert X to x for directory or if already executable somewhere + if ((dowhat&32) && (S_ISDIR(mode) || (mode&0111))) dowhat |= 1; - // 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; + str++; + } - // Copy mode from another category? - if (!dowhat && *str && (s = strchr(whys, *str))) { - dowhat = (mode>>(3*(s-whys)))&7; - str++; - } + // Are we ready to do a thing yet? + if (*str && (str[1] != ',' && !strchr(hows, *str))) goto barf; - // Are we ready to do a thing yet? - if (*str && *(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++) { - mode_t bit = 0; - int where = 1<<((3*i)+j); - - if (amask & where) continue; - - // Figure out new value at this location - if (i == 3) { - // suid and sticky - if (!j) bit = dowhat&16; // o+s = t - else if ((dowhat&8) && (dowho&(8|(1<<j)))) bit++; - } else { - if (!(dowho&(8|(1<<i)))) continue; - else if (dowhat&(1<<j)) bit++; - } + // 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; - // When selection active, modify bit + // Figure out new value at this location + if (i == 3) { + // suid and sticky + if (!j) bit = dowhat&16; // o+s = t + else if ((dowhat&8) && (dowho&(8|(1<<j)))) bit++; + } else { + if (!(dowho&(8|(1<<i)))) continue; + else if (dowhat&(1<<j)) bit++; + } - if (dohow == '=' || (bit && dohow == '-')) mode &= ~where; - if (bit && dohow != '-') mode |= where; + // When selection active, modify bit + + if (dohow == '=' || (bit && dohow == '-')) mode &= ~where; + if (bit && dohow != '-') mode |= where; + } } } diff --git a/tests/chmod.test b/tests/chmod.test index 9dcf796e..2c8c6b91 100755 --- a/tests/chmod.test +++ b/tests/chmod.test @@ -112,6 +112,7 @@ chtest u+s "drwsr-xr-x\n-rwSr--r--\n" chtest +s "drwsr-sr-x\n-rwSr-Sr--\n" chtest o+s "drwxr-xr-x\n-rw-r--r--\n" chtest +t "drwxr-xr-t\n-rw-r--r-T\n" +chtest a=r+w+x "drwxrwxrwx\n-rwxrwxrwx\n" mkdir foo ln -s bar foo/baz -- 2.29.2.576.ga3fc446d84-goog
_______________________________________________ Toybox mailing list Toybox@lists.landley.net http://lists.landley.net/listinfo.cgi/toybox-landley.net