changeset 1325:41fc44c76ade draft

makedevs - making devices/nodes in a range. Supports reading the tabled entry from file.
author Ashwini Sharma <ak.ashwini1981@gmail.com>
date Thu, 29 May 2014 08:20:30 -0500
parents 3191aa9490aa
children 78a3eaf5555f
files toys/pending/makedevs.c
diffstat 1 files changed, 124 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/pending/makedevs.c	Thu May 29 08:20:30 2014 -0500
@@ -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);
+}