diff options
Diffstat (limited to 'miscutils/makedevs.c')
-rw-r--r-- | miscutils/makedevs.c | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/miscutils/makedevs.c b/miscutils/makedevs.c new file mode 100644 index 000000000..3bc1559c7 --- /dev/null +++ b/miscutils/makedevs.c | |||
@@ -0,0 +1,230 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com> | ||
4 | * | ||
5 | * makedevs | ||
6 | * Make ranges of device files quickly. | ||
7 | * known bugs: can't deal with alpha ranges | ||
8 | */ | ||
9 | |||
10 | #include "busybox.h" | ||
11 | |||
12 | #ifdef CONFIG_FEATURE_MAKEDEVS_LEAF | ||
13 | int makedevs_main(int argc, char **argv) | ||
14 | { | ||
15 | mode_t mode; | ||
16 | char *basedev, *type, *nodname, buf[255]; | ||
17 | int Smajor, Sminor, S, E; | ||
18 | |||
19 | if (argc < 7 || *argv[1]=='-') | ||
20 | bb_show_usage(); | ||
21 | |||
22 | basedev = argv[1]; | ||
23 | type = argv[2]; | ||
24 | Smajor = xatoi_u(argv[3]); | ||
25 | Sminor = xatoi_u(argv[4]); | ||
26 | S = xatoi_u(argv[5]); | ||
27 | E = xatoi_u(argv[6]); | ||
28 | nodname = argc == 8 ? basedev : buf; | ||
29 | |||
30 | mode = 0660; | ||
31 | |||
32 | switch (type[0]) { | ||
33 | case 'c': | ||
34 | mode |= S_IFCHR; | ||
35 | break; | ||
36 | case 'b': | ||
37 | mode |= S_IFBLK; | ||
38 | break; | ||
39 | case 'f': | ||
40 | mode |= S_IFIFO; | ||
41 | break; | ||
42 | default: | ||
43 | bb_show_usage(); | ||
44 | } | ||
45 | |||
46 | while (S <= E) { | ||
47 | int sz; | ||
48 | |||
49 | sz = snprintf(buf, sizeof(buf), "%s%d", basedev, S); | ||
50 | if(sz<0 || sz>=sizeof(buf)) /* libc different */ | ||
51 | bb_error_msg_and_die("%s too large", basedev); | ||
52 | |||
53 | /* if mode != S_IFCHR and != S_IFBLK third param in mknod() ignored */ | ||
54 | |||
55 | if (mknod(nodname, mode, makedev(Smajor, Sminor))) | ||
56 | bb_error_msg("failed to create: %s", nodname); | ||
57 | |||
58 | if (nodname == basedev) /* ex. /dev/hda - to /dev/hda1 ... */ | ||
59 | nodname = buf; | ||
60 | S++; | ||
61 | Sminor++; | ||
62 | } | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | #elif defined CONFIG_FEATURE_MAKEDEVS_TABLE | ||
68 | |||
69 | /* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */ | ||
70 | |||
71 | int makedevs_main(int argc, char **argv) | ||
72 | { | ||
73 | FILE *table = stdin; | ||
74 | char *rootdir = NULL; | ||
75 | char *line = NULL; | ||
76 | int linenum = 0; | ||
77 | int ret = EXIT_SUCCESS; | ||
78 | |||
79 | getopt32(argc, argv, "d:", &line); | ||
80 | if (line) | ||
81 | table = xfopen(line, "r"); | ||
82 | |||
83 | if (optind >= argc || (rootdir=argv[optind])==NULL) { | ||
84 | bb_error_msg_and_die("root directory not specified"); | ||
85 | } | ||
86 | |||
87 | xchdir(rootdir); | ||
88 | |||
89 | umask(0); | ||
90 | |||
91 | printf("rootdir=%s\n", rootdir); | ||
92 | if (line) { | ||
93 | printf("table='%s'\n", line); | ||
94 | } else { | ||
95 | printf("table=<stdin>\n"); | ||
96 | } | ||
97 | |||
98 | while ((line = xmalloc_getline(table))) { | ||
99 | char type; | ||
100 | unsigned int mode = 0755; | ||
101 | unsigned int major = 0; | ||
102 | unsigned int minor = 0; | ||
103 | unsigned int count = 0; | ||
104 | unsigned int increment = 0; | ||
105 | unsigned int start = 0; | ||
106 | char name[41]; | ||
107 | char user[41]; | ||
108 | char group[41]; | ||
109 | char *full_name; | ||
110 | uid_t uid; | ||
111 | gid_t gid; | ||
112 | |||
113 | linenum++; | ||
114 | |||
115 | if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name, | ||
116 | &type, &mode, user, group, &major, | ||
117 | &minor, &start, &increment, &count)) || | ||
118 | ((major | minor | start | count | increment) > 255)) | ||
119 | { | ||
120 | if (*line=='\0' || *line=='#' || isspace(*line)) | ||
121 | continue; | ||
122 | bb_error_msg("line %d invalid: '%s'", linenum, line); | ||
123 | ret = EXIT_FAILURE; | ||
124 | continue; | ||
125 | } | ||
126 | if (name[0] == '#') { | ||
127 | continue; | ||
128 | } | ||
129 | |||
130 | gid = (*group) ? get_ug_id(group, bb_xgetgrnam) : getgid(); | ||
131 | uid = (*user) ? get_ug_id(user, bb_xgetpwnam) : getuid(); | ||
132 | full_name = concat_path_file(rootdir, name); | ||
133 | |||
134 | if (type == 'd') { | ||
135 | bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR); | ||
136 | if (chown(full_name, uid, gid) == -1) { | ||
137 | bb_perror_msg("line %d: chown failed for %s", linenum, full_name); | ||
138 | ret = EXIT_FAILURE; | ||
139 | goto loop; | ||
140 | } | ||
141 | if ((mode != -1) && (chmod(full_name, mode) < 0)){ | ||
142 | bb_perror_msg("line %d: chmod failed for %s", linenum, full_name); | ||
143 | ret = EXIT_FAILURE; | ||
144 | goto loop; | ||
145 | } | ||
146 | } else if (type == 'f') { | ||
147 | struct stat st; | ||
148 | if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) { | ||
149 | bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name); | ||
150 | ret = EXIT_FAILURE; | ||
151 | goto loop; | ||
152 | } | ||
153 | if (chown(full_name, uid, gid) == -1) { | ||
154 | bb_perror_msg("line %d: chown failed for %s", linenum, full_name); | ||
155 | ret = EXIT_FAILURE; | ||
156 | goto loop; | ||
157 | } | ||
158 | if ((mode != -1) && (chmod(full_name, mode) < 0)){ | ||
159 | bb_perror_msg("line %d: chmod failed for %s", linenum, full_name); | ||
160 | ret = EXIT_FAILURE; | ||
161 | goto loop; | ||
162 | } | ||
163 | } else | ||
164 | { | ||
165 | dev_t rdev; | ||
166 | |||
167 | if (type == 'p') { | ||
168 | mode |= S_IFIFO; | ||
169 | } | ||
170 | else if (type == 'c') { | ||
171 | mode |= S_IFCHR; | ||
172 | } | ||
173 | else if (type == 'b') { | ||
174 | mode |= S_IFBLK; | ||
175 | } else { | ||
176 | bb_error_msg("line %d: unsupported file type %c", linenum, type); | ||
177 | ret = EXIT_FAILURE; | ||
178 | goto loop; | ||
179 | } | ||
180 | |||
181 | if (count > 0) { | ||
182 | int i; | ||
183 | char *full_name_inc; | ||
184 | |||
185 | full_name_inc = xmalloc(strlen(full_name) + 4); | ||
186 | for (i = start; i < count; i++) { | ||
187 | sprintf(full_name_inc, "%s%d", full_name, i); | ||
188 | rdev = (major << 8) + minor + (i * increment - start); | ||
189 | if (mknod(full_name_inc, mode, rdev) == -1) { | ||
190 | bb_perror_msg("line %d: cannot create node %s", linenum, full_name_inc); | ||
191 | ret = EXIT_FAILURE; | ||
192 | } | ||
193 | else if (chown(full_name_inc, uid, gid) == -1) { | ||
194 | bb_perror_msg("line %d: chown failed for %s", linenum, full_name_inc); | ||
195 | ret = EXIT_FAILURE; | ||
196 | } | ||
197 | if ((mode != -1) && (chmod(full_name_inc, mode) < 0)){ | ||
198 | bb_perror_msg("line %d: chmod failed for %s", linenum, full_name_inc); | ||
199 | ret = EXIT_FAILURE; | ||
200 | } | ||
201 | } | ||
202 | free(full_name_inc); | ||
203 | } else { | ||
204 | rdev = (major << 8) + minor; | ||
205 | if (mknod(full_name, mode, rdev) == -1) { | ||
206 | bb_perror_msg("line %d: cannot create node %s", linenum, full_name); | ||
207 | ret = EXIT_FAILURE; | ||
208 | } | ||
209 | else if (chown(full_name, uid, gid) == -1) { | ||
210 | bb_perror_msg("line %d: chown failed for %s", linenum, full_name); | ||
211 | ret = EXIT_FAILURE; | ||
212 | } | ||
213 | if ((mode != -1) && (chmod(full_name, mode) < 0)){ | ||
214 | bb_perror_msg("line %d: chmod failed for %s", linenum, full_name); | ||
215 | ret = EXIT_FAILURE; | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | loop: | ||
220 | free(line); | ||
221 | free(full_name); | ||
222 | } | ||
223 | fclose(table); | ||
224 | |||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | #else | ||
229 | # error makedevs configuration error, either leaf or table must be selected | ||
230 | #endif | ||