1 /* makedevs.c - Make ranges of device files. 2 * 3 * Copyright 2014 Bilal Qureshi <bilal.jmi (at) gmail.com> 4 * Copyright 2014 Kyungwan Han <asura321 (at) gmail.com> 5 * 6 * No Standard 7 8 USE_MAKEDEVS(NEWTOY(makedevs, "<1>1d:", TOYFLAG_USR|TOYFLAG_BIN)) 9 10 config MAKEDEVS 11 bool "makedevs" 12 default y 13 help 14 usage: makedevs [-d device_table] rootdir 15 16 Create a range of special files as specified in a device table. 17 18 -d file containing device table (default reads from stdin) 19 20 Each line of of the device table has the fields: 21 <name> <type> <mode> <uid> <gid> <major> <minor> <start> <increment> <count> 22 Where name is the file name, and type is one of the following: 23 24 b Block device 25 c Character device 26 d Directory 27 f Regular file 28 p Named pipe (fifo) 29 30 Other fields specify permissions, user and group id owning the file, 31 and additional fields for device special files. Use '-' for blank entries, 32 unspecified fields are treated as '-'. 33 */ 34 35 #define FOR_makedevs 36 #include "toys.h" 37 38 GLOBALS( 39 char *fname; 40 ) 41 42 void makedevs_main() 43 { 44 int fd = 0, line_no, i; 45 char *line = NULL; 46 47 // Open file and chdir, verbosely 48 xprintf("rootdir = %s\n", *toys.optargs); 49 if (toys.optflags & FLAG_d && strcmp(TT.fname, "-")) { 50 fd = xopen(TT.fname, O_RDONLY); 51 xprintf("table = %s\n", TT.fname); 52 } else xprintf("table = <stdin>\n"); 53 xchdir(*toys.optargs); 54 55 for (line_no = 0; (line = get_line(fd)); free(line)) { 56 char type=0, user[64], group[64], *node, *ptr = line; 57 unsigned int mode = 0755, major = 0, minor = 0, cnt = 0, incr = 0, 58 st_val = 0; 59 uid_t uid; 60 gid_t gid; 61 struct stat st; 62 63 line_no++; 64 while (isspace(*ptr)) ptr++; 65 if (!*ptr || *ptr == '#') continue; 66 node = ptr; 67 68 while (*ptr && !isspace(*ptr)) ptr++; 69 if (*ptr) *(ptr++) = 0; 70 *user = *group = 0; 71 sscanf(ptr, "%c %o %63s %63s %u %u %u %u %u", &type, &mode, 72 user, group, &major, &minor, &st_val, &incr, &cnt); 73 74 // type order here needs to line up with actions[] order. 75 i = stridx("pcbdf", type); 76 if (i == -1) { 77 error_msg("line %d: bad type %c", line_no, type); 78 continue; 79 } else mode |= (mode_t[]){S_IFIFO, S_IFCHR, S_IFBLK, 0, 0}[i]; 80 81 uid = *user ? xgetpwnamid(user)->pw_uid : getuid(); 82 gid = *group ? xgetgrnamid(group)->gr_gid : getgid(); 83 84 while (*node == '/') node++; // using relative path 85 86 for (i = 0; (!cnt && !i) || i < cnt; i++) { 87 if (cnt>1) { 88 snprintf(toybuf, sizeof(toybuf), "%.999s%u", node, st_val + i); 89 ptr = toybuf; 90 } else ptr = node; 91 92 if (type == 'd') { 93 if (mkpathat(AT_FDCWD, ptr, mode, 3)) { 94 perror_msg("can't create directory '%s'", ptr); 95 continue; 96 } 97 } else if (type == 'f') { 98 if (stat(ptr, &st) || !S_ISREG(st.st_mode)) { 99 perror_msg("line %d: file '%s' does not exist", line_no, ptr); 100 continue; 101 } 102 } else if (mknod(ptr, mode, makedev(major, minor + i*incr))) { 103 perror_msg("line %d: can't create node '%s'", line_no, ptr); 104 continue; 105 } 106 107 if (chown(ptr, uid, gid) || chmod(ptr, mode)) 108 perror_msg("line %d: can't chown/chmod '%s'", line_no, ptr); 109 } 110 } 111 xclose(fd); 112 } 113