123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- /* 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 y
- help
- usage: makedevs [-d device_table] rootdir
- Create a range of special files as specified in a device table.
- -d File containing device table (default reads from stdin)
- Each line of the device table has the fields:
- <name> <type> <mode> <uid> <gid> <major> <minor> <start> <increment> <count>
- 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"
- GLOBALS(
- char *d;
- )
- void makedevs_main(void)
- {
- FILE *fp = stdin;
- char *line = NULL;
- size_t allocated_length = 0;
- int line_no = 0, i;
- // Open file and chdir, verbosely
- xprintf("rootdir = %s\n", *toys.optargs);
- if (FLAG(d) && strcmp(TT.d, "-")) {
- fp = xfopen(TT.d, "r");
- xprintf("table = %s\n", TT.d);
- } else xprintf("table = <stdin>\n");
- xchdir(*toys.optargs);
- while (getline(&line, &allocated_length, fp) > 0) {
- char type=0, user[64], group[64], *node, *ptr = line;
- unsigned int mode = 0755, major = 0, minor = 0, cnt = 0, incr = 0,
- st_val = 0;
- uid_t uid;
- gid_t gid;
- struct stat st;
- line_no++;
- while (isspace(*ptr)) ptr++;
- if (!*ptr || *ptr == '#') continue;
- node = ptr;
- 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];
- uid = *user ? xgetuid(user) : getuid();
- gid = *group ? xgetgid(group) : getgid();
- while (*node == '/') node++; // using relative path
- for (i = 0; (!cnt && !i) || i < cnt; i++) {
- if (cnt>1) {
- snprintf(toybuf, sizeof(toybuf), "%.999s%u", node, st_val + i);
- ptr = toybuf;
- } else ptr = node;
- if (type == 'd') {
- if (mkpathat(AT_FDCWD, ptr, mode, MKPATHAT_MKLAST | MKPATHAT_MAKE)) {
- perror_msg("can't create directory '%s'", ptr);
- continue;
- }
- } else if (type == 'f') {
- if (stat(ptr, &st) || !S_ISREG(st.st_mode)) {
- perror_msg("line %d: file '%s' does not exist", line_no, ptr);
- continue;
- }
- } else if (mknod(ptr, mode, dev_makedev(major, minor + i*incr))) {
- perror_msg("line %d: can't create node '%s'", line_no, ptr);
- continue;
- }
- if (chown(ptr, uid, gid) || chmod(ptr, mode))
- perror_msg("line %d: can't chown/chmod '%s'", line_no, ptr);
- }
- }
- free(line);
- if (fp != stdin) fclose(fp);
- }
|