Contents of /trunk/mkinitrd-magellan/busybox/libbb/parse_mode.c
Parent Directory | Revision Log
Revision 984 -
(show annotations)
(download)
Sun May 30 11:32:42 2010 UTC (14 years, 4 months ago) by niro
File MIME type: text/plain
File size: 3433 byte(s)
Sun May 30 11:32:42 2010 UTC (14 years, 4 months ago) by niro
File MIME type: text/plain
File size: 3433 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 | /* vi: set sw=4 ts=4: */ |
2 | /* |
3 | * parse_mode implementation for busybox |
4 | * |
5 | * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org> |
6 | * |
7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
8 | */ |
9 | |
10 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/chmod.html */ |
11 | |
12 | #include "libbb.h" |
13 | |
14 | /* This function is used from NOFORK applets. It must not allocate anything */ |
15 | |
16 | #define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) |
17 | |
18 | int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode) |
19 | { |
20 | static const mode_t who_mask[] = { |
21 | S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */ |
22 | S_ISUID | S_IRWXU, /* u */ |
23 | S_ISGID | S_IRWXG, /* g */ |
24 | S_IRWXO /* o */ |
25 | }; |
26 | static const mode_t perm_mask[] = { |
27 | S_IRUSR | S_IRGRP | S_IROTH, /* r */ |
28 | S_IWUSR | S_IWGRP | S_IWOTH, /* w */ |
29 | S_IXUSR | S_IXGRP | S_IXOTH, /* x */ |
30 | S_IXUSR | S_IXGRP | S_IXOTH, /* X -- special -- see below */ |
31 | S_ISUID | S_ISGID, /* s */ |
32 | S_ISVTX /* t */ |
33 | }; |
34 | static const char who_chars[] ALIGN1 = "augo"; |
35 | static const char perm_chars[] ALIGN1 = "rwxXst"; |
36 | |
37 | const char *p; |
38 | mode_t wholist; |
39 | mode_t permlist; |
40 | mode_t new_mode; |
41 | char op; |
42 | |
43 | if ((unsigned char)(*s - '0') < 8) { |
44 | unsigned long tmp; |
45 | char *e; |
46 | |
47 | tmp = strtoul(s, &e, 8); |
48 | if (*e || (tmp > 07777U)) { /* Check range and trailing chars. */ |
49 | return 0; |
50 | } |
51 | *current_mode = tmp; |
52 | return 1; |
53 | } |
54 | |
55 | new_mode = *current_mode; |
56 | |
57 | /* Note: we allow empty clauses, and hence empty modes. |
58 | * We treat an empty mode as no change to perms. */ |
59 | |
60 | while (*s) { /* Process clauses. */ |
61 | if (*s == ',') { /* We allow empty clauses. */ |
62 | ++s; |
63 | continue; |
64 | } |
65 | |
66 | /* Get a wholist. */ |
67 | wholist = 0; |
68 | WHO_LIST: |
69 | p = who_chars; |
70 | do { |
71 | if (*p == *s) { |
72 | wholist |= who_mask[(int)(p-who_chars)]; |
73 | if (!*++s) { |
74 | return 0; |
75 | } |
76 | goto WHO_LIST; |
77 | } |
78 | } while (*++p); |
79 | |
80 | do { /* Process action list. */ |
81 | if ((*s != '+') && (*s != '-')) { |
82 | if (*s != '=') { |
83 | return 0; |
84 | } |
85 | /* Since op is '=', clear all bits corresponding to the |
86 | * wholist, or all file bits if wholist is empty. */ |
87 | permlist = ~FILEMODEBITS; |
88 | if (wholist) { |
89 | permlist = ~wholist; |
90 | } |
91 | new_mode &= permlist; |
92 | } |
93 | op = *s++; |
94 | |
95 | /* Check for permcopy. */ |
96 | p = who_chars + 1; /* Skip 'a' entry. */ |
97 | do { |
98 | if (*p == *s) { |
99 | int i = 0; |
100 | permlist = who_mask[(int)(p-who_chars)] |
101 | & (S_IRWXU | S_IRWXG | S_IRWXO) |
102 | & new_mode; |
103 | do { |
104 | if (permlist & perm_mask[i]) { |
105 | permlist |= perm_mask[i]; |
106 | } |
107 | } while (++i < 3); |
108 | ++s; |
109 | goto GOT_ACTION; |
110 | } |
111 | } while (*++p); |
112 | |
113 | /* It was not a permcopy, so get a permlist. */ |
114 | permlist = 0; |
115 | PERM_LIST: |
116 | p = perm_chars; |
117 | do { |
118 | if (*p == *s) { |
119 | if ((*p != 'X') |
120 | || (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH)) |
121 | ) { |
122 | permlist |= perm_mask[(int)(p-perm_chars)]; |
123 | } |
124 | if (!*++s) { |
125 | break; |
126 | } |
127 | goto PERM_LIST; |
128 | } |
129 | } while (*++p); |
130 | GOT_ACTION: |
131 | if (permlist) { /* The permlist was nonempty. */ |
132 | mode_t tmp = wholist; |
133 | if (!wholist) { |
134 | mode_t u_mask = umask(0); |
135 | umask(u_mask); |
136 | tmp = ~u_mask; |
137 | } |
138 | permlist &= tmp; |
139 | if (op == '-') { |
140 | new_mode &= ~permlist; |
141 | } else { |
142 | new_mode |= permlist; |
143 | } |
144 | } |
145 | } while (*s && (*s != ',')); |
146 | } |
147 | |
148 | *current_mode = new_mode; |
149 | return 1; |
150 | } |