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#define FOR_makedevs
36#include "toys.h"
37
38GLOBALS(
39 char *d;
40)
41
42void makedevs_main(void)
43{
44 FILE *fp = stdin;
45 char *line = NULL;
46 size_t allocated_length = 0;
47 int line_no = 0, i;
48
49
50 xprintf("rootdir = %s\n", *toys.optargs);
51 if (FLAG(d) && strcmp(TT.d, "-")) {
52 fp = xfopen(TT.d, "r");
53 xprintf("table = %s\n", TT.d);
54 } else xprintf("table = <stdin>\n");
55 xchdir(*toys.optargs);
56
57 while (getline(&line, &allocated_length, fp) > 0) {
58 char type=0, user[64], group[64], *node, *ptr = line;
59 unsigned int mode = 0755, major = 0, minor = 0, cnt = 0, incr = 0,
60 st_val = 0;
61 uid_t uid;
62 gid_t gid;
63 struct stat st;
64
65 line_no++;
66 while (isspace(*ptr)) ptr++;
67 if (!*ptr || *ptr == '#') continue;
68 node = ptr;
69
70 while (*ptr && !isspace(*ptr)) ptr++;
71 if (*ptr) *(ptr++) = 0;
72 *user = *group = 0;
73 sscanf(ptr, "%c %o %63s %63s %u %u %u %u %u", &type, &mode,
74 user, group, &major, &minor, &st_val, &incr, &cnt);
75
76
77 i = stridx("pcbdf", type);
78 if (i == -1) {
79 error_msg("line %d: bad type %c", line_no, type);
80 continue;
81 } else mode |= (mode_t[]){S_IFIFO, S_IFCHR, S_IFBLK, 0, 0}[i];
82
83 uid = *user ? xgetuid(user) : getuid();
84 gid = *group ? xgetgid(group) : getgid();
85
86 while (*node == '/') node++;
87
88 for (i = 0; (!cnt && !i) || i < cnt; i++) {
89 if (cnt>1) {
90 snprintf(toybuf, sizeof(toybuf), "%.999s%u", node, st_val + i);
91 ptr = toybuf;
92 } else ptr = node;
93
94 if (type == 'd') {
95 if (mkpathat(AT_FDCWD, ptr, mode, MKPATHAT_MKLAST | MKPATHAT_MAKE)) {
96 perror_msg("can't create directory '%s'", ptr);
97 continue;
98 }
99 } else if (type == 'f') {
100 if (stat(ptr, &st) || !S_ISREG(st.st_mode)) {
101 perror_msg("line %d: file '%s' does not exist", line_no, ptr);
102 continue;
103 }
104 } else if (mknod(ptr, mode, dev_makedev(major, minor + i*incr))) {
105 perror_msg("line %d: can't create node '%s'", line_no, ptr);
106 continue;
107 }
108
109 if (chown(ptr, uid, gid) || chmod(ptr, mode))
110 perror_msg("line %d: can't chown/chmod '%s'", line_no, ptr);
111 }
112 }
113 free(line);
114 if (fp != stdin) fclose(fp);
115}
116