find:: get rid of nested function (it's a gcc-ism)
[oweals/busybox.git] / miscutils / makedevs.c
index 91da16924e0b43e39aae9e919807a72aadc82740..c945a1352cb895f2a688dcb9db21ea94e4e5f0bd 100644 (file)
@@ -7,6 +7,66 @@
  * known bugs: can't deal with alpha ranges
  */
 
+//usage:#if ENABLE_FEATURE_MAKEDEVS_LEAF
+//usage:#define makedevs_trivial_usage
+//usage:       "NAME TYPE MAJOR MINOR FIRST LAST [s]"
+//usage:#define makedevs_full_usage "\n\n"
+//usage:       "Create a range of block or character special files"
+//usage:     "\n"
+//usage:     "\nTYPE is:"
+//usage:     "\n       b       Block device"
+//usage:     "\n       c       Character device"
+//usage:     "\n       f       FIFO, MAJOR and MINOR are ignored"
+//usage:     "\n"
+//usage:     "\nFIRST..LAST specify numbers appended to NAME."
+//usage:     "\nIf 's' is the last argument, the base device is created as well."
+//usage:     "\n"
+//usage:     "\nExamples:"
+//usage:     "\n       makedevs /dev/ttyS c 4 66 2 63   ->  ttyS2-ttyS63"
+//usage:     "\n       makedevs /dev/hda b 3 0 0 8 s    ->  hda,hda1-hda8"
+//usage:
+//usage:#define makedevs_example_usage
+//usage:       "# makedevs /dev/ttyS c 4 66 2 63\n"
+//usage:       "[creates ttyS2-ttyS63]\n"
+//usage:       "# makedevs /dev/hda b 3 0 0 8 s\n"
+//usage:       "[creates hda,hda1-hda8]\n"
+//usage:#endif
+//usage:
+//usage:#if ENABLE_FEATURE_MAKEDEVS_TABLE
+//usage:#define makedevs_trivial_usage
+//usage:       "[-d device_table] rootdir"
+//usage:#define makedevs_full_usage "\n\n"
+//usage:       "Create a range of special files as specified in a device table.\n"
+//usage:       "Device table entries take the form of:\n"
+//usage:       "<name> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count>\n"
+//usage:       "Where name is the file name, type can be one of:\n"
+//usage:       "       f       Regular file\n"
+//usage:       "       d       Directory\n"
+//usage:       "       c       Character device\n"
+//usage:       "       b       Block device\n"
+//usage:       "       p       Fifo (named pipe)\n"
+//usage:       "uid is the user id for the target file, gid is the group id for the\n"
+//usage:       "target file. The rest of the entries (major, minor, etc) apply to\n"
+//usage:       "to device special files. A '-' may be used for blank entries."
+//usage:
+//usage:#define makedevs_example_usage
+//usage:       "For example:\n"
+//usage:       "<name>    <type> <mode><uid><gid><major><minor><start><inc><count>\n"
+//usage:       "/dev         d   755    0    0    -      -      -      -    -\n"
+//usage:       "/dev/console c   666    0    0    5      1      -      -    -\n"
+//usage:       "/dev/null    c   666    0    0    1      3      0      0    -\n"
+//usage:       "/dev/zero    c   666    0    0    1      5      0      0    -\n"
+//usage:       "/dev/hda     b   640    0    0    3      0      0      0    -\n"
+//usage:       "/dev/hda     b   640    0    0    3      1      1      1    15\n\n"
+//usage:       "Will Produce:\n"
+//usage:       "/dev\n"
+//usage:       "/dev/console\n"
+//usage:       "/dev/null\n"
+//usage:       "/dev/zero\n"
+//usage:       "/dev/hda\n"
+//usage:       "/dev/hda[0-15]\n"
+//usage:#endif
+
 #include "libbb.h"
 
 #if ENABLE_FEATURE_MAKEDEVS_LEAF
@@ -15,7 +75,7 @@ makedevs NAME TYPE MAJOR MINOR FIRST LAST [s]
 TYPEs:
 b       Block device
 c       Character device
-p       FIFO
+f       FIFO
 
 FIRST..LAST specify numbers appended to NAME.
 If 's' is the last argument, the base device is created as well.
@@ -36,10 +96,10 @@ int makedevs_main(int argc, char **argv)
        basedev = argv[1];
        buf = xasprintf("%s%u", argv[1], (unsigned)-1);
        type = argv[2];
-       Smajor = xatoi_u(argv[3]);
-       Sminor = xatoi_u(argv[4]);
-       S = xatoi_u(argv[5]);
-       E = xatoi_u(argv[6]);
+       Smajor = xatoi_positive(argv[3]);
+       Sminor = xatoi_positive(argv[4]);
+       S = xatoi_positive(argv[5]);
+       E = xatoi_positive(argv[6]);
        nodname = argv[7] ? basedev : buf;
 
        mode = 0660;
@@ -63,7 +123,7 @@ int makedevs_main(int argc, char **argv)
                /* if mode != S_IFCHR and != S_IFBLK,
                 * third param in mknod() ignored */
                if (mknod(nodname, mode, makedev(Smajor, Sminor)))
-                       bb_perror_msg("can't create %s", nodname);
+                       bb_perror_msg("can't create '%s'", nodname);
 
                /*if (nodname == basedev)*/ /* ex. /dev/hda - to /dev/hda1 ... */
                        nodname = buf;
@@ -76,34 +136,33 @@ int makedevs_main(int argc, char **argv)
 
 #elif ENABLE_FEATURE_MAKEDEVS_TABLE
 
-/* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */
+/* Licensed under GPLv2 or later, see file LICENSE in this source tree. */
 
 int makedevs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int makedevs_main(int argc UNUSED_PARAM, char **argv)
 {
        parser_t *parser;
-       char *rootdir = NULL;
        char *line = (char *)"-";
-       int linenum;
        int ret = EXIT_SUCCESS;
 
        opt_complementary = "=1"; /* exactly one param */
        getopt32(argv, "d:", &line);
-       rootdir = argv[optind];
-       parser = config_open(line);
+       argv += optind;
 
-       xchdir(rootdir);
+       xchdir(*argv); /* ensure root dir exists */
 
        umask(0);
 
-       printf("rootdir=%s\n", rootdir);
+       printf("rootdir=%s\ntable=", *argv);
        if (NOT_LONE_DASH(line)) {
-               printf("table='%s'\n", line);
+               printf("'%s'\n", line);
        } else {
-               printf("table=<stdin>\n");
+               puts("<stdin>");
        }
 
+       parser = config_open(line);
        while (config_read(parser, &line, 1, 1, "# \t", PARSE_NORMAL)) {
+               int linenum;
                char type;
                unsigned mode = 0755;
                unsigned major = 0;
@@ -114,7 +173,7 @@ int makedevs_main(int argc UNUSED_PARAM, char **argv)
                char name[41];
                char user[41];
                char group[41];
-               char *full_name;
+               char *full_name = name;
                uid_t uid;
                gid_t gid;
 
@@ -122,7 +181,7 @@ int makedevs_main(int argc UNUSED_PARAM, char **argv)
 
                if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u",
                                        name, &type, &mode, user, group,
-                                       &major, &minor, &start, &increment, &count))
+                                       &major, &minor, &start, &increment, &count))
                 || ((unsigned)(major | minor | start | count | increment) > 255)
                ) {
                        bb_error_msg("invalid line %d: '%s'", linenum, line);
@@ -132,7 +191,10 @@ int makedevs_main(int argc UNUSED_PARAM, char **argv)
 
                gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid();
                uid = (*user) ? get_ug_id(user, xuname2uid) : getuid();
-               full_name = concat_path_file(rootdir, name);
+               /* We are already in the right root dir,
+                * so make absolute paths relative */
+               if ('/' == *full_name)
+                       full_name++;
 
                if (type == 'd') {
                        bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
@@ -140,20 +202,20 @@ int makedevs_main(int argc UNUSED_PARAM, char **argv)
  chown_fail:
                                bb_perror_msg("line %d: can't chown %s", linenum, full_name);
                                ret = EXIT_FAILURE;
-                               goto loop;
+                               continue;
                        }
                        if (chmod(full_name, mode) < 0) {
  chmod_fail:
                                bb_perror_msg("line %d: can't chmod %s", linenum, full_name);
                                ret = EXIT_FAILURE;
-                               goto loop;
+                               continue;
                        }
                } else if (type == 'f') {
                        struct stat st;
                        if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) {
                                bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name);
                                ret = EXIT_FAILURE;
-                               goto loop;
+                               continue;
                        }
                        if (chown(full_name, uid, gid) < 0)
                                goto chown_fail;
@@ -173,7 +235,7 @@ int makedevs_main(int argc UNUSED_PARAM, char **argv)
                        } else {
                                bb_error_msg("line %d: unsupported file type %c", linenum, type);
                                ret = EXIT_FAILURE;
-                               goto loop;
+                               continue;
                        }
 
                        full_name_inc = xmalloc(strlen(full_name) + sizeof(int)*3 + 2);
@@ -195,8 +257,6 @@ int makedevs_main(int argc UNUSED_PARAM, char **argv)
                        }
                        free(full_name_inc);
                }
-loop:
-               free(full_name);
        }
        if (ENABLE_FEATURE_CLEAN_UP)
                config_close(parser);