You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.2 KiB
113 lines
3.2 KiB
/* 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()
|
|
{
|
|
int fd = 0, line_no, i;
|
|
char *line = NULL;
|
|
|
|
// Open file and chdir, verbosely
|
|
xprintf("rootdir = %s\n", *toys.optargs);
|
|
if ((toys.optflags & FLAG_d) && strcmp(TT.d, "-")) {
|
|
fd = xopenro(TT.d);
|
|
xprintf("table = %s\n", TT.d);
|
|
} else xprintf("table = <stdin>\n");
|
|
xchdir(*toys.optargs);
|
|
|
|
for (line_no = 0; (line = get_line(fd)); free(line)) {
|
|
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);
|
|
}
|
|
}
|
|
xclose(fd);
|
|
}
|