* Make ranges of device files quickly.
* known bugs: can't deal with alpha ranges
*/
+//config:config MAKEDEVS
+//config: bool "makedevs (9.3 kb)"
+//config: default y
+//config: help
+//config: 'makedevs' is a utility used to create a batch of devices with
+//config: one command.
+//config:
+//config: There are two choices for command line behaviour, the interface
+//config: as used by LEAF/Linux Router Project, or a device table file.
+//config:
+//config: 'leaf' is traditionally what busybox follows, it allows multiple
+//config: devices of a particluar type to be created per command.
+//config: e.g. /dev/hda[0-9]
+//config: Device properties are passed as command line arguments.
+//config:
+//config: 'table' reads device properties from a file or stdin, allowing
+//config: a batch of unrelated devices to be made with one command.
+//config: User/group names are allowed as an alternative to uid/gid.
+//config:
+//config:choice
+//config: prompt "Choose makedevs behaviour"
+//config: depends on MAKEDEVS
+//config: default FEATURE_MAKEDEVS_TABLE
+//config:
+//config:config FEATURE_MAKEDEVS_LEAF
+//config: bool "leaf"
+//config:
+//config:config FEATURE_MAKEDEVS_TABLE
+//config: bool "table"
+//config:
+//config:endchoice
+
+//applet:IF_MAKEDEVS(APPLET(makedevs, BB_DIR_SBIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_MAKEDEVS) += makedevs.o
//usage:#if ENABLE_FEATURE_MAKEDEVS_LEAF
//usage:#define makedevs_trivial_usage
/* if mode != S_IFCHR and != S_IFBLK,
* third param in mknod() ignored */
- if (mknod(nodname, mode, makedev(Smajor, Sminor)))
+ if (mknod(nodname, mode, makedev(Smajor, Sminor)) != 0
+ && errno != EEXIST
+ ) {
bb_perror_msg("can't create '%s'", nodname);
+ }
/*if (nodname == basedev)*/ /* ex. /dev/hda - to /dev/hda1 ... */
nodname = buf;
unsigned count = 0;
unsigned increment = 0;
unsigned start = 0;
- char name[41];
char user[41];
char group[41];
- char *full_name = name;
+ char *full_name;
+ int name_len;
uid_t uid;
gid_t gid;
linenum = parser->lineno;
- if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u",
- name, &type, &mode, user, group,
+ if ((1 > sscanf(line, "%*s%n %c %o %40s %40s %u %u %u %u %u",
+ &name_len, &type, &mode, user, group,
&major, &minor, &start, &increment, &count))
|| ((unsigned)(major | minor | start | count | increment) > 255)
) {
gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid();
uid = (*user) ? get_ug_id(user, xuname2uid) : getuid();
+ line[name_len] = '\0';
+ full_name = line;
/* We are already in the right root dir,
* so make absolute paths relative */
- if ('/' == *full_name)
+ if ('/' == full_name[0])
full_name++;
if (type == 'd') {
if (chmod(full_name, mode) < 0)
goto chmod_fail;
} else {
- dev_t rdev;
unsigned i;
- char *full_name_inc;
if (type == 'p') {
mode |= S_IFIFO;
continue;
}
- full_name_inc = xmalloc(strlen(full_name) + sizeof(int)*3 + 2);
- if (count)
+ if (count != 0)
count--;
- for (i = start; i <= start + count; i++) {
- sprintf(full_name_inc, count ? "%s%u" : "%s", full_name, i);
- rdev = makedev(major, minor + (i - start) * increment);
- if (mknod(full_name_inc, mode, rdev) < 0) {
- bb_perror_msg("line %d: can't create node %s", linenum, full_name_inc);
+ for (i = 0; i <= count; i++) {
+ dev_t rdev;
+ char *nameN = full_name;
+ if (count != 0)
+ nameN = xasprintf("%s%u", full_name, start + i);
+ rdev = makedev(major, minor + i * increment);
+ if (mknod(nameN, mode, rdev) != 0
+ && errno != EEXIST
+ ) {
+ bb_perror_msg("line %d: can't create node %s", linenum, nameN);
ret = EXIT_FAILURE;
- } else if (chown(full_name_inc, uid, gid) < 0) {
- bb_perror_msg("line %d: can't chown %s", linenum, full_name_inc);
+ } else if (chown(nameN, uid, gid) < 0) {
+ bb_perror_msg("line %d: can't chown %s", linenum, nameN);
ret = EXIT_FAILURE;
- } else if (chmod(full_name_inc, mode) < 0) {
- bb_perror_msg("line %d: can't chmod %s", linenum, full_name_inc);
+ } else if (chmod(nameN, mode) < 0) {
+ bb_perror_msg("line %d: can't chmod %s", linenum, nameN);
ret = EXIT_FAILURE;
}
+ if (count != 0)
+ free(nameN);
}
- free(full_name_inc);
}
}
if (ENABLE_FEATURE_CLEAN_UP)