1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105#include "libbb.h"
106
107#if ENABLE_FEATURE_MAKEDEVS_LEAF
108
109
110
111
112
113
114
115
116
117
118
119
120
121int makedevs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
122int makedevs_main(int argc, char **argv)
123{
124 mode_t mode;
125 char *basedev, *type, *nodname, *buf;
126 int Smajor, Sminor, S, E;
127
128 if (argc < 7 || argv[1][0] == '-')
129 bb_show_usage();
130
131 basedev = argv[1];
132 buf = xasprintf("%s%u", argv[1], (unsigned)-1);
133 type = argv[2];
134 Smajor = xatoi_positive(argv[3]);
135 Sminor = xatoi_positive(argv[4]);
136 S = xatoi_positive(argv[5]);
137 E = xatoi_positive(argv[6]);
138 nodname = argv[7] ? basedev : buf;
139
140 mode = 0660;
141 switch (type[0]) {
142 case 'c':
143 mode |= S_IFCHR;
144 break;
145 case 'b':
146 mode |= S_IFBLK;
147 break;
148 case 'f':
149 mode |= S_IFIFO;
150 break;
151 default:
152 bb_show_usage();
153 }
154
155 while (S <= E) {
156 sprintf(buf, "%s%u", basedev, S);
157
158
159
160 if (mknod(nodname, mode, makedev(Smajor, Sminor)) != 0
161 && errno != EEXIST
162 ) {
163 bb_perror_msg("can't create '%s'", nodname);
164 }
165
166
167 nodname = buf;
168 S++;
169 Sminor++;
170 }
171
172 return 0;
173}
174
175#elif ENABLE_FEATURE_MAKEDEVS_TABLE
176
177
178
179int makedevs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
180int makedevs_main(int argc UNUSED_PARAM, char **argv)
181{
182 parser_t *parser;
183 char *line = (char *)"-";
184 int ret = EXIT_SUCCESS;
185
186 getopt32(argv, "^" "d:" "\0" "=1", &line);
187 argv += optind;
188
189 xchdir(*argv);
190
191 umask(0);
192
193 printf("rootdir=%s\ntable=", *argv);
194 if (NOT_LONE_DASH(line)) {
195 printf("'%s'\n", line);
196 } else {
197 puts("<stdin>");
198 }
199
200 parser = config_open(line);
201 while (config_read(parser, &line, 1, 1, "# \t", PARSE_NORMAL)) {
202 int linenum;
203 char type;
204 unsigned mode = 0755;
205 unsigned major = 0;
206 unsigned minor = 0;
207 unsigned count = 0;
208 unsigned increment = 0;
209 unsigned start = 0;
210 char user[41];
211 char group[41];
212 char *full_name;
213 int name_len;
214 uid_t uid;
215 gid_t gid;
216
217 linenum = parser->lineno;
218
219 if ((1 > sscanf(line, "%*s%n %c %o %40s %40s %u %u %u %u %u",
220 &name_len, &type, &mode, user, group,
221 &major, &minor, &start, &increment, &count))
222 || ((unsigned)(major | minor | start | count | increment) > 255)
223 ) {
224 bb_error_msg("invalid line %d: '%s'", linenum, line);
225 ret = EXIT_FAILURE;
226 continue;
227 }
228
229 gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid();
230 uid = (*user) ? get_ug_id(user, xuname2uid) : getuid();
231 line[name_len] = '\0';
232 full_name = line;
233
234
235 if ('/' == full_name[0])
236 full_name++;
237
238 if (type == 'd') {
239 bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
240 if (chown(full_name, uid, gid) == -1) {
241 chown_fail:
242 bb_perror_msg("line %d: can't chown %s", linenum, full_name);
243 ret = EXIT_FAILURE;
244 continue;
245 }
246 if (chmod(full_name, mode) < 0) {
247 chmod_fail:
248 bb_perror_msg("line %d: can't chmod %s", linenum, full_name);
249 ret = EXIT_FAILURE;
250 continue;
251 }
252 } else if (type == 'f') {
253 struct stat st;
254 if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) {
255 bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name);
256 ret = EXIT_FAILURE;
257 continue;
258 }
259 if (chown(full_name, uid, gid) < 0)
260 goto chown_fail;
261 if (chmod(full_name, mode) < 0)
262 goto chmod_fail;
263 } else {
264 unsigned i;
265
266 if (type == 'p') {
267 mode |= S_IFIFO;
268 } else if (type == 'c') {
269 mode |= S_IFCHR;
270 } else if (type == 'b') {
271 mode |= S_IFBLK;
272 } else {
273 bb_error_msg("line %d: unsupported file type %c", linenum, type);
274 ret = EXIT_FAILURE;
275 continue;
276 }
277
278 if (count != 0)
279 count--;
280 for (i = 0; i <= count; i++) {
281 dev_t rdev;
282 char *nameN = full_name;
283 if (count != 0)
284 nameN = xasprintf("%s%u", full_name, start + i);
285 rdev = makedev(major, minor + i * increment);
286 if (mknod(nameN, mode, rdev) != 0
287 && errno != EEXIST
288 ) {
289 bb_perror_msg("line %d: can't create node %s", linenum, nameN);
290 ret = EXIT_FAILURE;
291 } else if (chown(nameN, uid, gid) < 0) {
292 bb_perror_msg("line %d: can't chown %s", linenum, nameN);
293 ret = EXIT_FAILURE;
294 } else if (chmod(nameN, mode) < 0) {
295 bb_perror_msg("line %d: can't chmod %s", linenum, nameN);
296 ret = EXIT_FAILURE;
297 }
298 if (count != 0)
299 free(nameN);
300 }
301 }
302 }
303 if (ENABLE_FEATURE_CLEAN_UP)
304 config_close(parser);
305
306 return ret;
307}
308
309#else
310# error makedevs configuration error, either leaf or table must be selected
311#endif
312