source: MondoRescue/branches/2.2.5/mindi-busybox/miscutils/makedevs.c

Last change on this file was 1765, checked in by Bruno Cornec, 13 years ago

Update to busybox 1.7.2

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