changeset 1362:b9605ebd3af4 draft

Cleanup pass on makedevs. Need to test it before promoting.
author Rob Landley <rob@landley.net>
date Wed, 25 Jun 2014 06:26:17 -0500
parents b6226bf22826
children e65f9a9ba62d
files toys/pending/makedevs.c
diffstat 1 files changed, 62 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/toys/pending/makedevs.c	Tue Jun 24 21:47:07 2014 -0500
+++ b/toys/pending/makedevs.c	Wed Jun 25 06:26:17 2014 -0500
@@ -12,20 +12,26 @@
   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)
+    Where name is the file name, and type is one of the following:
 
-    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.
+    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 @@
 
 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 @@
       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);
 }