diff options
Diffstat (limited to 'toys/pending/makedevs.c')
-rw-r--r-- | toys/pending/makedevs.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/toys/pending/makedevs.c b/toys/pending/makedevs.c new file mode 100644 index 00000000..a8e42e89 --- /dev/null +++ b/toys/pending/makedevs.c @@ -0,0 +1,124 @@ +/* makedevs.c - Make ranges of device files. + * + * Copyright 2014 Bilal Qureshi <bilal.jmi@gmail.com> + * Copyright 2014 Kyungwan Han <asura321@gmail.com> + * + * No Standard + +USE_MAKEDEVS(NEWTOY(makedevs, "<1>1d:", TOYFLAG_USR|TOYFLAG_BIN)) + +config MAKEDEVS + bool "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: + <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. +*/ +#define FOR_makedevs +#include "toys.h" + +GLOBALS( + char *fname; +) + +void makedevs_main() +{ + int value, fd = 0, line_no; + 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>"); + + 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; + unsigned int mode = 0755, major = 0, minor = 0, cnt = 0, incr = 0, + st_val = 0, i; + uid_t uid; + gid_t gid; + dev_t dev; + struct stat st; + + line_no++; + while (*ptr == ' ' || *ptr == '\t') 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); + continue; + } + + if (*user) { + struct passwd *usr; + + if (!(usr = getpwnam(user)) && isdigit(*user)) { + sscanf (user, "%d", &value); + usr = xgetpwuid(value); + } + if (!usr) error_exit("bad user '%s'", user); + uid = usr->pw_uid; + } else uid = getuid(); + + if (*group) { + struct group *grp; + + if (!(grp = getgrnam(group)) && isdigit(*group)) { + sscanf (group, "%d", &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); + } + break; + default: + error_msg("line %d: file type %c is unsupported", line_no, type); + break; + } + } + xclose(fd); +} |