1
2
3
4
5
6
7
8
9#include "libbb.h"
10
11
12
13
14
15#define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
16
17int FAST_FUNC bb_parse_mode(const char *s, unsigned current_mode)
18{
19 static const mode_t who_mask[] = {
20 S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO,
21 S_ISUID | S_IRWXU,
22 S_ISGID | S_IRWXG,
23 S_IRWXO
24 };
25 static const mode_t perm_mask[] = {
26 S_IRUSR | S_IRGRP | S_IROTH,
27 S_IWUSR | S_IWGRP | S_IWOTH,
28 S_IXUSR | S_IXGRP | S_IXOTH,
29 S_IXUSR | S_IXGRP | S_IXOTH,
30 S_ISUID | S_ISGID,
31 S_ISVTX
32 };
33 static const char who_chars[] ALIGN1 = "augo";
34 static const char perm_chars[] ALIGN1 = "rwxXst";
35
36 const char *p;
37 mode_t wholist;
38 mode_t permlist;
39 mode_t new_mode;
40 char op;
41
42 if ((unsigned char)(*s - '0') < 8) {
43 unsigned long tmp;
44 char *e;
45
46 tmp = strtoul(s, &e, 8);
47 if (*e || (tmp > 07777U)) {
48 return -1;
49 }
50 return tmp;
51 }
52
53 new_mode = current_mode;
54
55
56
57
58 while (*s) {
59 if (*s == ',') {
60 ++s;
61 continue;
62 }
63
64
65 wholist = 0;
66 WHO_LIST:
67 p = who_chars;
68 do {
69 if (*p == *s) {
70 wholist |= who_mask[(int)(p-who_chars)];
71 if (!*++s) {
72 return -1;
73 }
74 goto WHO_LIST;
75 }
76 } while (*++p);
77
78 do {
79 if ((*s != '+') && (*s != '-')) {
80 if (*s != '=') {
81 return -1;
82 }
83
84
85 permlist = ~FILEMODEBITS;
86 if (wholist) {
87 permlist = ~wholist;
88 }
89 new_mode &= permlist;
90 }
91 op = *s++;
92
93
94 p = who_chars + 1;
95 do {
96 if (*p == *s) {
97 int i = 0;
98 permlist = who_mask[(int)(p-who_chars)]
99 & (S_IRWXU | S_IRWXG | S_IRWXO)
100 & new_mode;
101 do {
102 if (permlist & perm_mask[i]) {
103 permlist |= perm_mask[i];
104 }
105 } while (++i < 3);
106 ++s;
107 goto GOT_ACTION;
108 }
109 } while (*++p);
110
111
112 permlist = 0;
113 PERM_LIST:
114 p = perm_chars;
115 do {
116 if (*p == *s) {
117 if ((*p != 'X')
118 || (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH))
119 ) {
120 permlist |= perm_mask[(int)(p-perm_chars)];
121 }
122 if (!*++s) {
123 break;
124 }
125 goto PERM_LIST;
126 }
127 } while (*++p);
128 GOT_ACTION:
129 if (permlist) {
130 mode_t tmp = wholist;
131 if (!wholist) {
132 mode_t u_mask = umask(0);
133 umask(u_mask);
134 tmp = ~u_mask;
135 }
136 permlist &= tmp;
137 if (op == '-') {
138 new_mode &= ~permlist;
139 } else {
140 new_mode |= permlist;
141 }
142 }
143 } while (*s && (*s != ','));
144 }
145
146 return new_mode;
147}
148