makedevs.c revision 936ab6d68b747ed7a315ef9c27bb9b90088686f3
19f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma/* makedevs.c - Make ranges of device files.
29f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma *
39f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma * Copyright 2014 Bilal Qureshi <bilal.jmi@gmail.com>
49f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma * Copyright 2014 Kyungwan Han <asura321@gmail.com>
59f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma *
69f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma * No Standard
79f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
89f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini SharmaUSE_MAKEDEVS(NEWTOY(makedevs, "<1>1d:", TOYFLAG_USR|TOYFLAG_BIN))
99f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
109f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharmaconfig MAKEDEVS
119f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma  bool "makedevs"
129f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma  default n
139f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma  help
149f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    usage: makedevs [-d device_table] rootdir
156ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley
169f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    Create a range of special files as specified in a device table.
176ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley
186ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    -d	file containing device table (default reads from stdin)
196ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley
206ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    Each line of of the device table has the fields:
219f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    <name> <type> <mode> <uid> <gid> <major> <minor> <start> <increment> <count>
226ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    Where name is the file name, and type is one of the following:
236ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley
246ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    b	Block device
256ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    c	Character device
266ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    d	Directory
276ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    f	Regular file
286ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    p	Named pipe (fifo)
296ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley
306ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    Other fields specify permissions, user and group id owning the file,
316ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    and additional fields for device special files. Use '-' for blank entries,
326ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    unspecified fields are treated as '-'.
339f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma*/
346ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley
359f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma#define FOR_makedevs
369f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma#include "toys.h"
379f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
389f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini SharmaGLOBALS(
399f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma  char *fname;
409f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma)
419f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
429f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharmavoid makedevs_main()
439f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma{
446ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley  int value, fd = 0, line_no, i;
459f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma  char *line = NULL;
469f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
476ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley  // Open file and chdir, verbosely
486ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley  xprintf("rootdir = %s\n", *toys.optargs);
496ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley  if (toys.optflags & FLAG_d && strcmp(TT.fname, "-")) {
506ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    fd = xopen(TT.fname, O_RDONLY);
516ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    xprintf("table = %s\n", TT.fname);
52936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley  } else xprintf("table = <stdin>\n");
536ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley  xchdir(*toys.optargs);
549f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
559f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma  for (line_no = 0; (line = get_line(fd)); free(line)) {
56936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley    char type=0, user[64], group[64], *node, *ptr = line;
579f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    unsigned int mode = 0755, major = 0, minor = 0, cnt = 0, incr = 0,
586ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley                 st_val = 0;
599f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    uid_t uid;
609f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    gid_t gid;
619f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    struct stat st;
629f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
639f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    line_no++;
646ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    while (isspace(*ptr)) ptr++;
659f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    if (!*ptr || *ptr == '#') continue;
66936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley    node = ptr;
676ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley
686ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    while (*ptr && !isspace(*ptr)) ptr++;
69936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley    if (*ptr) *(ptr++) = 0;
706ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    *user = *group = 0;
716ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    sscanf(ptr, "%c %o %63s %63s %u %u %u %u %u", &type, &mode,
726ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley           user, group, &major, &minor, &st_val, &incr, &cnt);
736ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley
746ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    // type order here needs to line up with actions[] order.
756ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    i = stridx("pcbdf", type);
766ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    if (i == -1) {
776ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley      error_msg("line %d: bad type %c", line_no, type);
789f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      continue;
796ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    } else mode |= (mode_t[]){S_IFIFO, S_IFCHR, S_IFBLK, 0, 0}[i];
809f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
819f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    if (*user) {
829f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      struct passwd *usr;
839f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
849f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      if (!(usr = getpwnam(user)) && isdigit(*user)) {
856ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley        sscanf(user, "%u", &value);
869f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma        usr = xgetpwuid(value);
879f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      }
889f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      if (!usr) error_exit("bad user '%s'", user);
899f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      uid = usr->pw_uid;
909f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    } else uid = getuid();
919f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
929f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    if (*group) {
939f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      struct group *grp;
949f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
959f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      if (!(grp = getgrnam(group)) && isdigit(*group)) {
966ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley        sscanf (group, "%u", &value);
979f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma        grp = getgrgid(value);
989f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      }
999f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      if (!grp) error_exit("bad group '%s'", group);
1009f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma      gid = grp->gr_gid;
1019f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    } else gid = getgid();
1029f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma
1036ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley    while (*node == '/') node++; // using relative path
104936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley
105936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley    for (i = 0; (!cnt && !i) || i < cnt; i++) {
106936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley      if (cnt) {
107936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley        snprintf(toybuf, sizeof(toybuf), "%s%u", node, st_val + i);
108936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley        ptr = toybuf;
109936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley      } else ptr = node;
110936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley
111936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley      if (type == 'd') {
112936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley        if (mkpathat(AT_FDCWD, ptr, mode, 3))  {
113936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley          perror_msg("can't create directory '%s'", ptr);
114936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley          continue;
115936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley        }
116936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley      } else if (type == 'f') {
117936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley        if (stat(ptr, &st) || !S_ISREG(st.st_mode)) {
118936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley          perror_msg("line %d: file '%s' does not exist", line_no, ptr);
1196ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley          continue;
1209f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma        }
121936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley      } else if (mknod(ptr, mode, makedev(major, minor + i*incr))) {
122936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley        perror_msg("line %d: can't create node '%s'", line_no, ptr);
123936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley        continue;
1246ad3207b65438870dfc9f76a3dcf4bb04096297eRob Landley      }
125936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley
126936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley      if (chown(ptr, uid, gid) || chmod(ptr, mode))
127936ab6d68b747ed7a315ef9c27bb9b90088686f3Rob Landley        perror_msg("line %d: can't chown/chmod '%s'", line_no, ptr);
1289f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma    }
1299f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma  }
1309f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma  xclose(fd);
1319f1a00a859d1b085fdf7a1a5f66e51f41c6217eeAshwini Sharma}
132