hush: fix umask: umask(022) was setting umask(755)
authorDenys Vlasenko <vda.linux@googlemail.com>
Wed, 7 Oct 2015 14:56:20 +0000 (16:56 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Wed, 7 Oct 2015 14:56:20 +0000 (16:56 +0200)
Based on the patch by Rich Felker <dalias@libc.org>

function                                             old     new   delta
builtin_umask                                        121     161     +40
umaskcmd                                             318     279     -39

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c
shell/hush.c

index b34dcc1497bcc6bf025984d90ba4f789b0c2ed9a..2669157bcae1aed3e5502690db8b08a52c328a24 100644 (file)
@@ -12814,7 +12814,7 @@ readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
 }
 
 static int FAST_FUNC
-umaskcmd(int argc UNUSED_PARAM, char **argv)
+umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
 {
        static const char permuser[3] ALIGN1 = "ugo";
        static const char permmode[3] ALIGN1 = "rwx";
@@ -12824,9 +12824,6 @@ umaskcmd(int argc UNUSED_PARAM, char **argv)
                S_IROTH, S_IWOTH, S_IXOTH
        };
 
-       /* TODO: use bb_parse_mode() instead */
-
-       char *ap;
        mode_t mask;
        int i;
        int symbolic_mode = 0;
@@ -12840,8 +12837,7 @@ umaskcmd(int argc UNUSED_PARAM, char **argv)
        umask(mask);
        INT_ON;
 
-       ap = *argptr;
-       if (ap == NULL) {
+       if (*argptr == NULL) {
                if (symbolic_mode) {
                        char buf[18];
                        char *p = buf;
@@ -12858,27 +12854,23 @@ umaskcmd(int argc UNUSED_PARAM, char **argv)
                                }
                                *p++ = ',';
                        }
-                       *--p = 0;
+                       *--p = '\0';
                        puts(buf);
                } else {
                        out1fmt("%.4o\n", mask);
                }
        } else {
-               if (isdigit((unsigned char) *ap)) {
-                       mask = 0;
-                       do {
-                               if (*ap >= '8' || *ap < '0')
-                                       ash_msg_and_raise_error(msg_illnum, argv[1]);
-                               mask = (mask << 3) + (*ap - '0');
-                       } while (*++ap != '\0');
-                       umask(mask);
-               } else {
-                       mask = ~mask & 0777;
-                       if (!bb_parse_mode(ap, &mask)) {
-                               ash_msg_and_raise_error("illegal mode: %s", ap);
-                       }
-                       umask(~mask & 0777);
-               }
+               char *modestr = *argptr;
+                /* numeric umasks are taken as-is */
+                /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
+               if (!isdigit(modestr[0]))
+                       mask ^= 0777;
+               if (!bb_parse_mode(modestr, &mask) || (unsigned)mask > 0777) {
+                       ash_msg_and_raise_error("illegal mode: %s", modestr);
+               }
+               if (!isdigit(modestr[0]))
+                       mask ^= 0777;
+               umask(mask);
        }
        return 0;
 }
index 752080a64b34611af430ba5716d9184a22663954..8b8d5fc8b5a3e0816946a175a846273ba3958866 100644 (file)
@@ -8970,10 +8970,14 @@ static int FAST_FUNC builtin_umask(char **argv)
        if (argv[0]) {
                mode_t old_mask = mask;
 
-               mask ^= 0777;
+               /* numeric umasks are taken as-is */
+               /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */
+               if (!isdigit(argv[0][0]))
+                       mask ^= 0777;
                rc = bb_parse_mode(argv[0], &mask);
-               mask ^= 0777;
-               if (rc == 0) {
+               if (!isdigit(argv[0][0]))
+                       mask ^= 0777;
+               if (rc == 0 || (unsigned)mask > 0777) {
                        mask = old_mask;
                        /* bash messages:
                         * bash: umask: 'q': invalid symbolic mode operator