mode.c - sbase - suckless unix tools | |
git clone git://git.suckless.org/sbase | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
mode.c (2800B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include <stdlib.h> | |
3 #include <string.h> | |
4 #include <sys/stat.h> | |
5 #include <unistd.h> | |
6 | |
7 #include "../util.h" | |
8 | |
9 mode_t | |
10 getumask(void) | |
11 { | |
12 mode_t mask = umask(0); | |
13 umask(mask); | |
14 return mask; | |
15 } | |
16 | |
17 mode_t | |
18 parsemode(const char *str, mode_t mode, mode_t mask) | |
19 { | |
20 char *end; | |
21 const char *p = str; | |
22 int octal, op; | |
23 mode_t who, perm, clear; | |
24 | |
25 octal = strtol(str, &end, 8); | |
26 if (*end == '\0') { | |
27 if (octal < 0 || octal > 07777) | |
28 eprintf("%s: invalid mode\n", str); | |
29 return octal; | |
30 } | |
31 next: | |
32 /* first, determine which bits we will be modifying */ | |
33 for (who = 0; *p; p++) { | |
34 switch (*p) { | |
35 /* masks */ | |
36 case 'u': | |
37 who |= S_IRWXU|S_ISUID; | |
38 continue; | |
39 case 'g': | |
40 who |= S_IRWXG|S_ISGID; | |
41 continue; | |
42 case 'o': | |
43 who |= S_IRWXO|S_ISVTX; | |
44 continue; | |
45 case 'a': | |
46 who |= S_IRWXU|S_ISUID|S_IRWXG|S_ISGID|S_IRWXO|S… | |
47 continue; | |
48 } | |
49 break; | |
50 } | |
51 if (who) { | |
52 clear = who; | |
53 } else { | |
54 clear = S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO; | |
55 who = ~mask; | |
56 } | |
57 while (*p) { | |
58 switch (*p) { | |
59 /* opers */ | |
60 case '=': | |
61 case '+': | |
62 case '-': | |
63 op = (int)*p; | |
64 break; | |
65 default: | |
66 eprintf("%s: invalid mode\n", str); | |
67 } | |
68 | |
69 perm = 0; | |
70 switch (*++p) { | |
71 /* copy */ | |
72 case 'u': | |
73 if (mode & S_IRUSR) | |
74 perm |= S_IRUSR|S_IRGRP|S_IROTH; | |
75 if (mode & S_IWUSR) | |
76 perm |= S_IWUSR|S_IWGRP|S_IWOTH; | |
77 if (mode & S_IXUSR) | |
78 perm |= S_IXUSR|S_IXGRP|S_IXOTH; | |
79 if (mode & S_ISUID) | |
80 perm |= S_ISUID|S_ISGID; | |
81 p++; | |
82 break; | |
83 case 'g': | |
84 if (mode & S_IRGRP) | |
85 perm |= S_IRUSR|S_IRGRP|S_IROTH; | |
86 if (mode & S_IWGRP) | |
87 perm |= S_IWUSR|S_IWGRP|S_IWOTH; | |
88 if (mode & S_IXGRP) | |
89 perm |= S_IXUSR|S_IXGRP|S_IXOTH; | |
90 if (mode & S_ISGID) | |
91 perm |= S_ISUID|S_ISGID; | |
92 p++; | |
93 break; | |
94 case 'o': | |
95 if (mode & S_IROTH) | |
96 perm |= S_IRUSR|S_IRGRP|S_IROTH; | |
97 if (mode & S_IWOTH) | |
98 perm |= S_IWUSR|S_IWGRP|S_IWOTH; | |
99 if (mode & S_IXOTH) | |
100 perm |= S_IXUSR|S_IXGRP|S_IXOTH; | |
101 p++; | |
102 break; | |
103 default: | |
104 for (; *p; p++) { | |
105 switch (*p) { | |
106 /* modes */ | |
107 case 'r': | |
108 perm |= S_IRUSR|S_IRGRP|S_IROTH; | |
109 break; | |
110 case 'w': | |
111 perm |= S_IWUSR|S_IWGRP|S_IWOTH; | |
112 break; | |
113 case 'x': | |
114 perm |= S_IXUSR|S_IXGRP|S_IXOTH; | |
115 break; | |
116 case 'X': | |
117 if (S_ISDIR(mode) || mode & (S_I… | |
118 perm |= S_IXUSR|S_IXGRP|… | |
119 break; | |
120 case 's': | |
121 perm |= S_ISUID|S_ISGID; | |
122 break; | |
123 case 't': | |
124 perm |= S_ISVTX; | |
125 break; | |
126 default: | |
127 goto apply; | |
128 } | |
129 } | |
130 } | |
131 | |
132 apply: | |
133 /* apply */ | |
134 switch (op) { | |
135 case '=': | |
136 mode &= ~clear; | |
137 /* fallthrough */ | |
138 case '+': | |
139 mode |= perm & who; | |
140 break; | |
141 case '-': | |
142 mode &= ~(perm & who); | |
143 break; | |
144 } | |
145 /* if we hit a comma, move on to the next clause */ | |
146 if (*p == ',') { | |
147 p++; | |
148 goto next; | |
149 } | |
150 } | |
151 return mode & ~S_IFMT; | |
152 } |