source: branches/3.2/mindi-busybox/miscutils/makedevs.c @ 3232

Last change on this file since 3232 was 3232, checked in by bruno, 5 years ago
  • Update mindi-busybox to 1.21.1
File size: 7.8 KB
RevLine 
[821]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
[3232]10//usage:#if ENABLE_FEATURE_MAKEDEVS_LEAF
11//usage:#define makedevs_trivial_usage
12//usage:       "NAME TYPE MAJOR MINOR FIRST LAST [s]"
13//usage:#define makedevs_full_usage "\n\n"
14//usage:       "Create a range of block or character special files"
15//usage:     "\n"
16//usage:     "\nTYPE is:"
17//usage:     "\n    b   Block device"
18//usage:     "\n    c   Character device"
19//usage:     "\n    f   FIFO, MAJOR and MINOR are ignored"
20//usage:     "\n"
21//usage:     "\nFIRST..LAST specify numbers appended to NAME."
22//usage:     "\nIf 's' is the last argument, the base device is created as well."
23//usage:     "\n"
24//usage:     "\nExamples:"
25//usage:     "\n    makedevs /dev/ttyS c 4 66 2 63   ->  ttyS2-ttyS63"
26//usage:     "\n    makedevs /dev/hda b 3 0 0 8 s    ->  hda,hda1-hda8"
27//usage:
28//usage:#define makedevs_example_usage
29//usage:       "# makedevs /dev/ttyS c 4 66 2 63\n"
30//usage:       "[creates ttyS2-ttyS63]\n"
31//usage:       "# makedevs /dev/hda b 3 0 0 8 s\n"
32//usage:       "[creates hda,hda1-hda8]\n"
33//usage:#endif
34//usage:
35//usage:#if ENABLE_FEATURE_MAKEDEVS_TABLE
36//usage:#define makedevs_trivial_usage
37//usage:       "[-d device_table] rootdir"
38//usage:#define makedevs_full_usage "\n\n"
39//usage:       "Create a range of special files as specified in a device table.\n"
40//usage:       "Device table entries take the form of:\n"
41//usage:       "<name> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count>\n"
42//usage:       "Where name is the file name, type can be one of:\n"
43//usage:       "    f   Regular file\n"
44//usage:       "    d   Directory\n"
45//usage:       "    c   Character device\n"
46//usage:       "    b   Block device\n"
47//usage:       "    p   Fifo (named pipe)\n"
48//usage:       "uid is the user id for the target file, gid is the group id for the\n"
49//usage:       "target file. The rest of the entries (major, minor, etc) apply to\n"
50//usage:       "to device special files. A '-' may be used for blank entries."
51//usage:
52//usage:#define makedevs_example_usage
53//usage:       "For example:\n"
54//usage:       "<name>    <type> <mode><uid><gid><major><minor><start><inc><count>\n"
55//usage:       "/dev         d   755    0    0    -      -      -      -    -\n"
56//usage:       "/dev/console c   666    0    0    5      1      -      -    -\n"
57//usage:       "/dev/null    c   666    0    0    1      3      0      0    -\n"
58//usage:       "/dev/zero    c   666    0    0    1      5      0      0    -\n"
59//usage:       "/dev/hda     b   640    0    0    3      0      0      0    -\n"
60//usage:       "/dev/hda     b   640    0    0    3      1      1      1    15\n\n"
61//usage:       "Will Produce:\n"
62//usage:       "/dev\n"
63//usage:       "/dev/console\n"
64//usage:       "/dev/null\n"
65//usage:       "/dev/zero\n"
66//usage:       "/dev/hda\n"
67//usage:       "/dev/hda[0-15]\n"
68//usage:#endif
69
[1765]70#include "libbb.h"
[821]71
[1765]72#if ENABLE_FEATURE_MAKEDEVS_LEAF
[2725]73/*
74makedevs NAME TYPE MAJOR MINOR FIRST LAST [s]
75TYPEs:
76b       Block device
77c       Character device
78f       FIFO
79
80FIRST..LAST specify numbers appended to NAME.
81If 's' is the last argument, the base device is created as well.
82Examples:
83        makedevs /dev/ttyS c 4 66 2 63   ->  ttyS2-ttyS63
84        makedevs /dev/hda b 3 0 0 8 s    ->  hda,hda1-hda8
85*/
86int makedevs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
[821]87int makedevs_main(int argc, char **argv)
88{
89    mode_t mode;
[2725]90    char *basedev, *type, *nodname, *buf;
[821]91    int Smajor, Sminor, S, E;
92
[2725]93    if (argc < 7 || argv[1][0] == '-')
[821]94        bb_show_usage();
95
96    basedev = argv[1];
[2725]97    buf = xasprintf("%s%u", argv[1], (unsigned)-1);
[821]98    type = argv[2];
[2725]99    Smajor = xatoi_positive(argv[3]);
100    Sminor = xatoi_positive(argv[4]);
101    S = xatoi_positive(argv[5]);
102    E = xatoi_positive(argv[6]);
103    nodname = argv[7] ? basedev : buf;
[821]104
105    mode = 0660;
106    switch (type[0]) {
107    case 'c':
108        mode |= S_IFCHR;
109        break;
110    case 'b':
111        mode |= S_IFBLK;
112        break;
113    case 'f':
114        mode |= S_IFIFO;
115        break;
116    default:
117        bb_show_usage();
118    }
119
120    while (S <= E) {
[2725]121        sprintf(buf, "%s%u", basedev, S);
[821]122
[2725]123        /* if mode != S_IFCHR and != S_IFBLK,
124         * third param in mknod() ignored */
[821]125        if (mknod(nodname, mode, makedev(Smajor, Sminor)))
[2725]126            bb_perror_msg("can't create '%s'", nodname);
[821]127
[2725]128        /*if (nodname == basedev)*/ /* ex. /dev/hda - to /dev/hda1 ... */
[821]129            nodname = buf;
130        S++;
131        Sminor++;
132    }
133
134    return 0;
135}
136
[1765]137#elif ENABLE_FEATURE_MAKEDEVS_TABLE
[821]138
[2725]139/* Licensed under GPLv2 or later, see file LICENSE in this source tree. */
[821]140
[2725]141int makedevs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
142int makedevs_main(int argc UNUSED_PARAM, char **argv)
[821]143{
[2725]144    parser_t *parser;
145    char *line = (char *)"-";
[821]146    int ret = EXIT_SUCCESS;
147
[2725]148    opt_complementary = "=1"; /* exactly one param */
[1765]149    getopt32(argv, "d:", &line);
[2725]150    argv += optind;
[821]151
[2725]152    xchdir(*argv); /* ensure root dir exists */
[821]153
154    umask(0);
155
[2725]156    printf("rootdir=%s\ntable=", *argv);
157    if (NOT_LONE_DASH(line)) {
158        printf("'%s'\n", line);
[821]159    } else {
[2725]160        puts("<stdin>");
[821]161    }
162
[2725]163    parser = config_open(line);
164    while (config_read(parser, &line, 1, 1, "# \t", PARSE_NORMAL)) {
165        int linenum;
[821]166        char type;
[2725]167        unsigned mode = 0755;
168        unsigned major = 0;
169        unsigned minor = 0;
170        unsigned count = 0;
171        unsigned increment = 0;
172        unsigned start = 0;
[821]173        char name[41];
174        char user[41];
175        char group[41];
[2725]176        char *full_name = name;
[821]177        uid_t uid;
178        gid_t gid;
179
[2725]180        linenum = parser->lineno;
[821]181
[2725]182        if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u",
183                    name, &type, &mode, user, group,
184                    &major, &minor, &start, &increment, &count))
185         || ((unsigned)(major | minor | start | count | increment) > 255)
186        ) {
187            bb_error_msg("invalid line %d: '%s'", linenum, line);
[821]188            ret = EXIT_FAILURE;
189            continue;
190        }
191
[1765]192        gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid();
193        uid = (*user) ? get_ug_id(user, xuname2uid) : getuid();
[2725]194        /* We are already in the right root dir,
195         * so make absolute paths relative */
196        if ('/' == *full_name)
197            full_name++;
[821]198
199        if (type == 'd') {
200            bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
201            if (chown(full_name, uid, gid) == -1) {
[2725]202 chown_fail:
203                bb_perror_msg("line %d: can't chown %s", linenum, full_name);
[821]204                ret = EXIT_FAILURE;
[2725]205                continue;
[821]206            }
[2725]207            if (chmod(full_name, mode) < 0) {
208 chmod_fail:
209                bb_perror_msg("line %d: can't chmod %s", linenum, full_name);
[821]210                ret = EXIT_FAILURE;
[2725]211                continue;
[821]212            }
213        } else if (type == 'f') {
214            struct stat st;
215            if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) {
216                bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name);
217                ret = EXIT_FAILURE;
[2725]218                continue;
[821]219            }
[2725]220            if (chown(full_name, uid, gid) < 0)
221                goto chown_fail;
222            if (chmod(full_name, mode) < 0)
223                goto chmod_fail;
[1765]224        } else {
[821]225            dev_t rdev;
[2725]226            unsigned i;
227            char *full_name_inc;
[821]228
229            if (type == 'p') {
230                mode |= S_IFIFO;
[2725]231            } else if (type == 'c') {
[821]232                mode |= S_IFCHR;
[2725]233            } else if (type == 'b') {
[821]234                mode |= S_IFBLK;
235            } else {
236                bb_error_msg("line %d: unsupported file type %c", linenum, type);
237                ret = EXIT_FAILURE;
[2725]238                continue;
[821]239            }
240
[2725]241            full_name_inc = xmalloc(strlen(full_name) + sizeof(int)*3 + 2);
242            if (count)
243                count--;
244            for (i = start; i <= start + count; i++) {
245                sprintf(full_name_inc, count ? "%s%u" : "%s", full_name, i);
246                rdev = makedev(major, minor + (i - start) * increment);
247                if (mknod(full_name_inc, mode, rdev) < 0) {
248                    bb_perror_msg("line %d: can't create node %s", linenum, full_name_inc);
[821]249                    ret = EXIT_FAILURE;
[2725]250                } else if (chown(full_name_inc, uid, gid) < 0) {
251                    bb_perror_msg("line %d: can't chown %s", linenum, full_name_inc);
[821]252                    ret = EXIT_FAILURE;
[2725]253                } else if (chmod(full_name_inc, mode) < 0) {
254                    bb_perror_msg("line %d: can't chmod %s", linenum, full_name_inc);
[821]255                    ret = EXIT_FAILURE;
256                }
257            }
[2725]258            free(full_name_inc);
[821]259        }
260    }
[2725]261    if (ENABLE_FEATURE_CLEAN_UP)
262        config_close(parser);
[821]263
264    return ret;
265}
266
267#else
268# error makedevs configuration error, either leaf or table must be selected
269#endif
Note: See TracBrowser for help on using the repository browser.