introduce and use bb_basename()
[oweals/busybox.git] / libbb / parse_mode.c
index 356d95db6f5505afc3d5de2f995883e5d98c4a70..a31bd4bfd604cc950d50661fda58a79affed260e 100644 (file)
@@ -9,49 +9,42 @@
 
 /* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */
 
-#include <stdlib.h>
-#include <assert.h>
-#include <sys/stat.h>
 #include "libbb.h"
 
-#define FILEMODEBITS    (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
+/* This function is used from NOFORK applets. It must not allocate anything */
+
+#define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
 
 int bb_parse_mode(const char *s, mode_t *current_mode)
 {
        static const mode_t who_mask[] = {
                S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */
-               S_ISUID | S_IRWXU,              /* u */
-               S_ISGID | S_IRWXG,              /* g */
-               S_IRWXO                                 /* o */
+               S_ISUID | S_IRWXU,           /* u */
+               S_ISGID | S_IRWXG,           /* g */
+               S_IRWXO                      /* o */
        };
-
        static const mode_t perm_mask[] = {
                S_IRUSR | S_IRGRP | S_IROTH, /* r */
                S_IWUSR | S_IWGRP | S_IWOTH, /* w */
                S_IXUSR | S_IXGRP | S_IXOTH, /* x */
                S_IXUSR | S_IXGRP | S_IXOTH, /* X -- special -- see below */
-               S_ISUID | S_ISGID,              /* s */
-               S_ISVTX                                 /* t */
+               S_ISUID | S_ISGID,           /* s */
+               S_ISVTX                      /* t */
        };
-
        static const char who_chars[] = "augo";
        static const char perm_chars[] = "rwxXst";
 
        const char *p;
-
        mode_t wholist;
        mode_t permlist;
-       mode_t mask;
        mode_t new_mode;
        char op;
 
-       assert(s);
-
        if (((unsigned int)(*s - '0')) < 8) {
                unsigned long tmp;
                char *e;
 
-               tmp = strtol(s, &e, 8);
+               tmp = strtoul(s, &e, 8);
                if (*e || (tmp > 07777U)) { /* Check range and trailing chars. */
                        return 0;
                }
@@ -59,16 +52,12 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
                return 1;
        }
 
-       mask = umask(0);
-       umask(mask);
-
        new_mode = *current_mode;
 
-       /* Note: We allow empty clauses, and hence empty modes.
+       /* Note: we allow empty clauses, and hence empty modes.
         * We treat an empty mode as no change to perms. */
 
        while (*s) {    /* Process clauses. */
-
                if (*s == ',') {        /* We allow empty clauses. */
                        ++s;
                        continue;
@@ -76,8 +65,7 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
 
                /* Get a wholist. */
                wholist = 0;
-
-       WHO_LIST:
+ WHO_LIST:
                p = who_chars;
                do {
                        if (*p == *s) {
@@ -95,7 +83,7 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
                                        return 0;
                                }
                                /* Since op is '=', clear all bits corresponding to the
-                                * wholist, of all file bits if wholist is empty. */
+                                * wholist, or all file bits if wholist is empty. */
                                permlist = ~FILEMODEBITS;
                                if (wholist) {
                                        permlist = ~wholist;
@@ -124,13 +112,12 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
 
                        /* It was not a permcopy, so get a permlist. */
                        permlist = 0;
-
-               PERM_LIST:
+ PERM_LIST:
                        p = perm_chars;
                        do {
                                if (*p == *s) {
                                        if ((*p != 'X')
-                                               || (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH))
+                                        || (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH))
                                        ) {
                                                permlist |= perm_mask[(int)(p-perm_chars)];
                                        }
@@ -140,15 +127,15 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
                                        goto PERM_LIST;
                                }
                        } while (*++p);
-
-               GOT_ACTION:
+ GOT_ACTION:
                        if (permlist) { /* The permlist was nonempty. */
-                               mode_t tmp = ~mask;
-                               if (wholist) {
-                                       tmp = wholist;
+                               mode_t tmp = wholist;
+                               if (!wholist) {
+                                       mode_t u_mask = umask(0);
+                                       umask(u_mask);
+                                       tmp = ~u_mask;
                                }
                                permlist &= tmp;
-
                                if (op == '-') {
                                        new_mode &= ~permlist;
                                } else {
@@ -159,6 +146,5 @@ int bb_parse_mode(const char *s, mode_t *current_mode)
        }
 
        *current_mode = new_mode;
-
        return 1;
 }