10f66f451Sopenharmony_ci/* makedevs.c - Make ranges of device files. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2014 Bilal Qureshi <bilal.jmi@gmail.com> 40f66f451Sopenharmony_ci * Copyright 2014 Kyungwan Han <asura321@gmail.com> 50f66f451Sopenharmony_ci * 60f66f451Sopenharmony_ci * No Standard 70f66f451Sopenharmony_ci 80f66f451Sopenharmony_ciUSE_MAKEDEVS(NEWTOY(makedevs, "<1>1d:", TOYFLAG_USR|TOYFLAG_BIN)) 90f66f451Sopenharmony_ci 100f66f451Sopenharmony_ciconfig MAKEDEVS 110f66f451Sopenharmony_ci bool "makedevs" 120f66f451Sopenharmony_ci default y 130f66f451Sopenharmony_ci help 140f66f451Sopenharmony_ci usage: makedevs [-d device_table] rootdir 150f66f451Sopenharmony_ci 160f66f451Sopenharmony_ci Create a range of special files as specified in a device table. 170f66f451Sopenharmony_ci 180f66f451Sopenharmony_ci -d File containing device table (default reads from stdin) 190f66f451Sopenharmony_ci 200f66f451Sopenharmony_ci Each line of the device table has the fields: 210f66f451Sopenharmony_ci <name> <type> <mode> <uid> <gid> <major> <minor> <start> <increment> <count> 220f66f451Sopenharmony_ci Where name is the file name, and type is one of the following: 230f66f451Sopenharmony_ci 240f66f451Sopenharmony_ci b Block device 250f66f451Sopenharmony_ci c Character device 260f66f451Sopenharmony_ci d Directory 270f66f451Sopenharmony_ci f Regular file 280f66f451Sopenharmony_ci p Named pipe (fifo) 290f66f451Sopenharmony_ci 300f66f451Sopenharmony_ci Other fields specify permissions, user and group id owning the file, 310f66f451Sopenharmony_ci and additional fields for device special files. Use '-' for blank entries, 320f66f451Sopenharmony_ci unspecified fields are treated as '-'. 330f66f451Sopenharmony_ci*/ 340f66f451Sopenharmony_ci 350f66f451Sopenharmony_ci#define FOR_makedevs 360f66f451Sopenharmony_ci#include "toys.h" 370f66f451Sopenharmony_ci 380f66f451Sopenharmony_ciGLOBALS( 390f66f451Sopenharmony_ci char *d; 400f66f451Sopenharmony_ci) 410f66f451Sopenharmony_ci 420f66f451Sopenharmony_civoid makedevs_main(void) 430f66f451Sopenharmony_ci{ 440f66f451Sopenharmony_ci FILE *fp = stdin; 450f66f451Sopenharmony_ci char *line = NULL; 460f66f451Sopenharmony_ci size_t allocated_length = 0; 470f66f451Sopenharmony_ci int line_no = 0, i; 480f66f451Sopenharmony_ci 490f66f451Sopenharmony_ci // Open file and chdir, verbosely 500f66f451Sopenharmony_ci xprintf("rootdir = %s\n", *toys.optargs); 510f66f451Sopenharmony_ci if (FLAG(d) && strcmp(TT.d, "-")) { 520f66f451Sopenharmony_ci fp = xfopen(TT.d, "r"); 530f66f451Sopenharmony_ci xprintf("table = %s\n", TT.d); 540f66f451Sopenharmony_ci } else xprintf("table = <stdin>\n"); 550f66f451Sopenharmony_ci xchdir(*toys.optargs); 560f66f451Sopenharmony_ci 570f66f451Sopenharmony_ci while (getline(&line, &allocated_length, fp) > 0) { 580f66f451Sopenharmony_ci char type=0, user[64], group[64], *node, *ptr = line; 590f66f451Sopenharmony_ci unsigned int mode = 0755, major = 0, minor = 0, cnt = 0, incr = 0, 600f66f451Sopenharmony_ci st_val = 0; 610f66f451Sopenharmony_ci uid_t uid; 620f66f451Sopenharmony_ci gid_t gid; 630f66f451Sopenharmony_ci struct stat st; 640f66f451Sopenharmony_ci 650f66f451Sopenharmony_ci line_no++; 660f66f451Sopenharmony_ci while (isspace(*ptr)) ptr++; 670f66f451Sopenharmony_ci if (!*ptr || *ptr == '#') continue; 680f66f451Sopenharmony_ci node = ptr; 690f66f451Sopenharmony_ci 700f66f451Sopenharmony_ci while (*ptr && !isspace(*ptr)) ptr++; 710f66f451Sopenharmony_ci if (*ptr) *(ptr++) = 0; 720f66f451Sopenharmony_ci *user = *group = 0; 730f66f451Sopenharmony_ci sscanf(ptr, "%c %o %63s %63s %u %u %u %u %u", &type, &mode, 740f66f451Sopenharmony_ci user, group, &major, &minor, &st_val, &incr, &cnt); 750f66f451Sopenharmony_ci 760f66f451Sopenharmony_ci // type order here needs to line up with actions[] order. 770f66f451Sopenharmony_ci i = stridx("pcbdf", type); 780f66f451Sopenharmony_ci if (i == -1) { 790f66f451Sopenharmony_ci error_msg("line %d: bad type %c", line_no, type); 800f66f451Sopenharmony_ci continue; 810f66f451Sopenharmony_ci } else mode |= (mode_t[]){S_IFIFO, S_IFCHR, S_IFBLK, 0, 0}[i]; 820f66f451Sopenharmony_ci 830f66f451Sopenharmony_ci uid = *user ? xgetuid(user) : getuid(); 840f66f451Sopenharmony_ci gid = *group ? xgetgid(group) : getgid(); 850f66f451Sopenharmony_ci 860f66f451Sopenharmony_ci while (*node == '/') node++; // using relative path 870f66f451Sopenharmony_ci 880f66f451Sopenharmony_ci for (i = 0; (!cnt && !i) || i < cnt; i++) { 890f66f451Sopenharmony_ci if (cnt>1) { 900f66f451Sopenharmony_ci snprintf(toybuf, sizeof(toybuf), "%.999s%u", node, st_val + i); 910f66f451Sopenharmony_ci ptr = toybuf; 920f66f451Sopenharmony_ci } else ptr = node; 930f66f451Sopenharmony_ci 940f66f451Sopenharmony_ci if (type == 'd') { 950f66f451Sopenharmony_ci if (mkpathat(AT_FDCWD, ptr, mode, MKPATHAT_MKLAST | MKPATHAT_MAKE)) { 960f66f451Sopenharmony_ci perror_msg("can't create directory '%s'", ptr); 970f66f451Sopenharmony_ci continue; 980f66f451Sopenharmony_ci } 990f66f451Sopenharmony_ci } else if (type == 'f') { 1000f66f451Sopenharmony_ci if (stat(ptr, &st) || !S_ISREG(st.st_mode)) { 1010f66f451Sopenharmony_ci perror_msg("line %d: file '%s' does not exist", line_no, ptr); 1020f66f451Sopenharmony_ci continue; 1030f66f451Sopenharmony_ci } 1040f66f451Sopenharmony_ci } else if (mknod(ptr, mode, dev_makedev(major, minor + i*incr))) { 1050f66f451Sopenharmony_ci perror_msg("line %d: can't create node '%s'", line_no, ptr); 1060f66f451Sopenharmony_ci continue; 1070f66f451Sopenharmony_ci } 1080f66f451Sopenharmony_ci 1090f66f451Sopenharmony_ci if (chown(ptr, uid, gid) || chmod(ptr, mode)) 1100f66f451Sopenharmony_ci perror_msg("line %d: can't chown/chmod '%s'", line_no, ptr); 1110f66f451Sopenharmony_ci } 1120f66f451Sopenharmony_ci } 1130f66f451Sopenharmony_ci free(line); 1140f66f451Sopenharmony_ci if (fp != stdin) fclose(fp); 1150f66f451Sopenharmony_ci} 116