source: branches/2.2.9/mindi-busybox/miscutils/makedevs.c @ 2725

Last change on this file since 2725 was 2725, checked in by bruno, 8 years ago
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File size: 5.1 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
13/*
14makedevs NAME TYPE MAJOR MINOR FIRST LAST [s]
15TYPEs:
16b       Block device
17c       Character device
18f       FIFO
19
20FIRST..LAST specify numbers appended to NAME.
21If 's' is the last argument, the base device is created as well.
22Examples:
23        makedevs /dev/ttyS c 4 66 2 63   ->  ttyS2-ttyS63
24        makedevs /dev/hda b 3 0 0 8 s    ->  hda,hda1-hda8
25*/
26int makedevs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
27int makedevs_main(int argc, char **argv)
28{
29    mode_t mode;
30    char *basedev, *type, *nodname, *buf;
31    int Smajor, Sminor, S, E;
32
33    if (argc < 7 || argv[1][0] == '-')
34        bb_show_usage();
35
36    basedev = argv[1];
37    buf = xasprintf("%s%u", argv[1], (unsigned)-1);
38    type = argv[2];
39    Smajor = xatoi_positive(argv[3]);
40    Sminor = xatoi_positive(argv[4]);
41    S = xatoi_positive(argv[5]);
42    E = xatoi_positive(argv[6]);
43    nodname = argv[7] ? basedev : buf;
44
45    mode = 0660;
46    switch (type[0]) {
47    case 'c':
48        mode |= S_IFCHR;
49        break;
50    case 'b':
51        mode |= S_IFBLK;
52        break;
53    case 'f':
54        mode |= S_IFIFO;
55        break;
56    default:
57        bb_show_usage();
58    }
59
60    while (S <= E) {
61        sprintf(buf, "%s%u", basedev, S);
62
63        /* if mode != S_IFCHR and != S_IFBLK,
64         * third param in mknod() ignored */
65        if (mknod(nodname, mode, makedev(Smajor, Sminor)))
66            bb_perror_msg("can't create '%s'", nodname);
67
68        /*if (nodname == basedev)*/ /* ex. /dev/hda - to /dev/hda1 ... */
69            nodname = buf;
70        S++;
71        Sminor++;
72    }
73
74    return 0;
75}
76
77#elif ENABLE_FEATURE_MAKEDEVS_TABLE
78
79/* Licensed under GPLv2 or later, see file LICENSE in this source tree. */
80
81int makedevs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
82int makedevs_main(int argc UNUSED_PARAM, char **argv)
83{
84    parser_t *parser;
85    char *line = (char *)"-";
86    int ret = EXIT_SUCCESS;
87
88    opt_complementary = "=1"; /* exactly one param */
89    getopt32(argv, "d:", &line);
90    argv += optind;
91
92    xchdir(*argv); /* ensure root dir exists */
93
94    umask(0);
95
96    printf("rootdir=%s\ntable=", *argv);
97    if (NOT_LONE_DASH(line)) {
98        printf("'%s'\n", line);
99    } else {
100        puts("<stdin>");
101    }
102
103    parser = config_open(line);
104    while (config_read(parser, &line, 1, 1, "# \t", PARSE_NORMAL)) {
105        int linenum;
106        char type;
107        unsigned mode = 0755;
108        unsigned major = 0;
109        unsigned minor = 0;
110        unsigned count = 0;
111        unsigned increment = 0;
112        unsigned start = 0;
113        char name[41];
114        char user[41];
115        char group[41];
116        char *full_name = name;
117        uid_t uid;
118        gid_t gid;
119
120        linenum = parser->lineno;
121
122        if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u",
123                    name, &type, &mode, user, group,
124                    &major, &minor, &start, &increment, &count))
125         || ((unsigned)(major | minor | start | count | increment) > 255)
126        ) {
127            bb_error_msg("invalid line %d: '%s'", linenum, line);
128            ret = EXIT_FAILURE;
129            continue;
130        }
131
132        gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid();
133        uid = (*user) ? get_ug_id(user, xuname2uid) : getuid();
134        /* We are already in the right root dir,
135         * so make absolute paths relative */
136        if ('/' == *full_name)
137            full_name++;
138
139        if (type == 'd') {
140            bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
141            if (chown(full_name, uid, gid) == -1) {
142 chown_fail:
143                bb_perror_msg("line %d: can't chown %s", linenum, full_name);
144                ret = EXIT_FAILURE;
145                continue;
146            }
147            if (chmod(full_name, mode) < 0) {
148 chmod_fail:
149                bb_perror_msg("line %d: can't chmod %s", linenum, full_name);
150                ret = EXIT_FAILURE;
151                continue;
152            }
153        } else if (type == 'f') {
154            struct stat st;
155            if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) {
156                bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name);
157                ret = EXIT_FAILURE;
158                continue;
159            }
160            if (chown(full_name, uid, gid) < 0)
161                goto chown_fail;
162            if (chmod(full_name, mode) < 0)
163                goto chmod_fail;
164        } else {
165            dev_t rdev;
166            unsigned i;
167            char *full_name_inc;
168
169            if (type == 'p') {
170                mode |= S_IFIFO;
171            } else if (type == 'c') {
172                mode |= S_IFCHR;
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                continue;
179            }
180
181            full_name_inc = xmalloc(strlen(full_name) + sizeof(int)*3 + 2);
182            if (count)
183                count--;
184            for (i = start; i <= start + count; i++) {
185                sprintf(full_name_inc, count ? "%s%u" : "%s", full_name, i);
186                rdev = makedev(major, minor + (i - start) * increment);
187                if (mknod(full_name_inc, mode, rdev) < 0) {
188                    bb_perror_msg("line %d: can't create node %s", linenum, full_name_inc);
189                    ret = EXIT_FAILURE;
190                } else if (chown(full_name_inc, uid, gid) < 0) {
191                    bb_perror_msg("line %d: can't chown %s", linenum, full_name_inc);
192                    ret = EXIT_FAILURE;
193                } else if (chmod(full_name_inc, mode) < 0) {
194                    bb_perror_msg("line %d: can't chmod %s", linenum, full_name_inc);
195                    ret = EXIT_FAILURE;
196                }
197            }
198            free(full_name_inc);
199        }
200    }
201    if (ENABLE_FEATURE_CLEAN_UP)
202        config_close(parser);
203
204    return ret;
205}
206
207#else
208# error makedevs configuration error, either leaf or table must be selected
209#endif
Note: See TracBrowser for help on using the repository browser.