diff options
-rw-r--r-- | toys/pending/makedevs.c | 123 |
1 files changed, 63 insertions, 60 deletions
diff --git a/toys/pending/makedevs.c b/toys/pending/makedevs.c index a8e42e89..19ccac76 100644 --- a/toys/pending/makedevs.c +++ b/toys/pending/makedevs.c @@ -12,20 +12,26 @@ config MAKEDEVS default n help usage: makedevs [-d device_table] rootdir + Create a range of special files as specified in a device table. - Device table entries take the following form: + + -d file containing device table (default reads from stdin) + + Each line of of the device table has the fields: <name> <type> <mode> <uid> <gid> <major> <minor> <start> <increment> <count> - Where name is the file name, type can be one of the following: - b Block device - c Character device - d Directory - f Regular file - p Fifo (named pipe) - - uid is the user id and gid is the group id for the target file. - The rest of the entries (major, minor, etc.) apply to device - special files. A '-' may be used for blank entries. + Where name is the file name, and type is one of the following: + + b Block device + c Character device + d Directory + f Regular file + p Named pipe (fifo) + + Other fields specify permissions, user and group id owning the file, + and additional fields for device special files. Use '-' for blank entries, + unspecified fields are treated as '-'. */ + #define FOR_makedevs #include "toys.h" @@ -35,40 +41,47 @@ GLOBALS( void makedevs_main() { - int value, fd = 0, line_no; + int value, fd = 0, line_no, i; char *line = NULL; - if (toys.optflags & FLAG_d) { - xprintf("rootdir = %s\ntable = %s\n", *toys.optargs, - (!strcmp(TT.fname, "-")) ? "<stdin>": TT.fname); - fd = (!strcmp(TT.fname, "-")) ? 0 : xopen(TT.fname, O_RDONLY); - } else xprintf("rootdir = %s\ntable = %s\n", *toys.optargs, "<stdin>"); + // Open file and chdir, verbosely + xprintf("rootdir = %s\n", *toys.optargs); + if (toys.optflags & FLAG_d && strcmp(TT.fname, "-")) { + fd = xopen(TT.fname, O_RDONLY); + xprintf("table = %s\n", TT.fname); + } else xprintf("table = <stdin>"); + xchdir(*toys.optargs); - xchdir(*toys.optargs); // root dir for (line_no = 0; (line = get_line(fd)); free(line)) { - char type, str[64], user[64], group [64], *node = str, *ptr = line; + char type=0, str[64], user[64], group[64], *node = str, *ptr = line; unsigned int mode = 0755, major = 0, minor = 0, cnt = 0, incr = 0, - st_val = 0, i; + st_val = 0; uid_t uid; gid_t gid; - dev_t dev; struct stat st; line_no++; - while (*ptr == ' ' || *ptr == '\t') ptr++; + while (isspace(*ptr)) ptr++; if (!*ptr || *ptr == '#') continue; - sscanf(line, "%63s %c %o %63s %63s %u %u %u %u %u", node, &type, &mode, - user, group, &major, &minor, &st_val, &incr, &cnt); - if ((major | minor | st_val | cnt | incr) > 255) { - error_msg("invalid line %d: '%s'", line_no, line); + + while (*ptr && !isspace(*ptr)) ptr++; + if (*ptr) *ptr++ = 0; + *user = *group = 0; + sscanf(ptr, "%c %o %63s %63s %u %u %u %u %u", &type, &mode, + user, group, &major, &minor, &st_val, &incr, &cnt); + + // type order here needs to line up with actions[] order. + i = stridx("pcbdf", type); + if (i == -1) { + error_msg("line %d: bad type %c", line_no, type); continue; - } + } else mode |= (mode_t[]){S_IFIFO, S_IFCHR, S_IFBLK, 0, 0}[i]; if (*user) { struct passwd *usr; if (!(usr = getpwnam(user)) && isdigit(*user)) { - sscanf (user, "%d", &value); + sscanf(user, "%u", &value); usr = xgetpwuid(value); } if (!usr) error_exit("bad user '%s'", user); @@ -79,46 +92,36 @@ void makedevs_main() struct group *grp; if (!(grp = getgrnam(group)) && isdigit(*group)) { - sscanf (group, "%d", &value); + sscanf (group, "%u", &value); grp = getgrgid(value); } if (!grp) error_exit("bad group '%s'", group); gid = grp->gr_gid; } else gid = getgid(); - if (*node == '/') node++; // using relative path - switch (type) { - case 'd': - if (mkpathat(AT_FDCWD, node, mode, 3)) - perror_msg("can't create directory '%s'", node); - else if (chown(node, uid, gid) || chmod(node, mode)) - perror_msg("line %d: can't chown/chmod '%s'", line_no, node); - break; - case 'f': - if ((stat(node, &st) || !S_ISREG(st.st_mode))) - perror_msg("line %d: regular file '%s' does not exist", - line_no, node); - else if (chown(node, uid, gid) || chmod(node, mode)) - perror_msg("line %d: can't chown/chmod '%s'", line_no, node); - break; - case 'p': mode |= S_IFIFO; goto CREATENODE; - case 'c': mode |= S_IFCHR; goto CREATENODE; - case 'b': mode |= S_IFBLK; -CREATENODE: - if (cnt) --cnt; - for (i = st_val; i <= st_val + cnt; i++) { - sprintf(toybuf, cnt ? "%s%u" : "%s", node, i); - dev = makedev(major, minor + (i - st_val) * incr); - if (mknod(toybuf, mode, dev)) - perror_msg("line %d: can't create node '%s'", line_no, toybuf); - else if (chown(toybuf, uid, gid) || chmod(toybuf, mode)) - perror_msg("line %d: can't chown/chmod '%s'", line_no, toybuf); + while (*node == '/') node++; // using relative path + if (type == 'd') { + if (mkpathat(AT_FDCWD, node, mode, 3)) { + perror_msg("can't create directory '%s'", node); + continue; + } + } else if (type == 'f') { + if (stat(node, &st) || !S_ISREG(st.st_mode)) { + perror_msg("line %d: regular file '%s' does not exist", line_no, node); + continue; + } + } else { + if (cnt) --cnt; + for (i = 0; i <= cnt; i++) { + sprintf(toybuf, cnt ? "%s%u" : "%s", node, st_val + i); + if (mknod(toybuf, mode, makedev(major, minor + i*incr))) { + perror_msg("line %d: can't create node '%s'", line_no, toybuf); + continue; } - break; - default: - error_msg("line %d: file type %c is unsupported", line_no, type); - break; + } } + if (chown(toybuf, uid, gid) || chmod(toybuf, mode)) + perror_msg("line %d: can't chown/chmod '%s'", line_no, toybuf); } xclose(fd); } |