view toys/pending/makedevs.c @ 1349:bf2e5591bdf0 draft

Cleanup strings.
author Rob Landley <rob@landley.net>
date Wed, 11 Jun 2014 08:02:55 -0500
parents 41fc44c76ade
children b9605ebd3af4
line wrap: on
line source

/* 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);
}