aboutsummaryrefslogtreecommitdiff
path: root/toys/pending/makedevs.c
diff options
context:
space:
mode:
Diffstat (limited to 'toys/pending/makedevs.c')
-rw-r--r--toys/pending/makedevs.c123
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);
}