Annotation of /trunk/mkinitrd-magellan/busybox/libbb/parse_mode.c
Parent Directory | Revision Log
Revision 984 -
(hide annotations)
(download)
Sun May 30 11:32:42 2010 UTC (13 years, 11 months ago) by niro
File MIME type: text/plain
File size: 3433 byte(s)
Sun May 30 11:32:42 2010 UTC (13 years, 11 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 | niro | 532 | /* 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 | niro | 816 | /* This function is used from NOFORK applets. It must not allocate anything */ |
15 | niro | 532 | |
16 | niro | 816 | #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 | niro | 532 | { |
20 | static const mode_t who_mask[] = { | ||
21 | S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */ | ||
22 | niro | 816 | S_ISUID | S_IRWXU, /* u */ |
23 | S_ISGID | S_IRWXG, /* g */ | ||
24 | S_IRWXO /* o */ | ||
25 | niro | 532 | }; |
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 | niro | 816 | S_ISUID | S_ISGID, /* s */ |
32 | S_ISVTX /* t */ | ||
33 | niro | 532 | }; |
34 | niro | 816 | static const char who_chars[] ALIGN1 = "augo"; |
35 | static const char perm_chars[] ALIGN1 = "rwxXst"; | ||
36 | niro | 532 | |
37 | const char *p; | ||
38 | mode_t wholist; | ||
39 | mode_t permlist; | ||
40 | mode_t new_mode; | ||
41 | char op; | ||
42 | |||
43 | niro | 984 | if ((unsigned char)(*s - '0') < 8) { |
44 | niro | 532 | unsigned long tmp; |
45 | char *e; | ||
46 | |||
47 | niro | 816 | tmp = strtoul(s, &e, 8); |
48 | niro | 532 | 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 | niro | 816 | /* Note: we allow empty clauses, and hence empty modes. |
58 | niro | 532 | * 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 | niro | 816 | WHO_LIST: |
69 | niro | 532 | 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 | niro | 816 | * wholist, or all file bits if wholist is empty. */ |
87 | niro | 532 | 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 | niro | 816 | PERM_LIST: |
116 | niro | 532 | p = perm_chars; |
117 | do { | ||
118 | if (*p == *s) { | ||
119 | if ((*p != 'X') | ||
120 | niro | 816 | || (new_mode & (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH)) |
121 | niro | 532 | ) { |
122 | permlist |= perm_mask[(int)(p-perm_chars)]; | ||
123 | } | ||
124 | if (!*++s) { | ||
125 | break; | ||
126 | } | ||
127 | goto PERM_LIST; | ||
128 | } | ||
129 | } while (*++p); | ||
130 | niro | 816 | GOT_ACTION: |
131 | niro | 532 | if (permlist) { /* The permlist was nonempty. */ |
132 | niro | 816 | mode_t tmp = wholist; |
133 | if (!wholist) { | ||
134 | mode_t u_mask = umask(0); | ||
135 | umask(u_mask); | ||
136 | tmp = ~u_mask; | ||
137 | niro | 532 | } |
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 | } |