busybox/miscutils/makedevs.c
Rob Landley d921b2ecc0 Remove bb_ prefixes from xfuncs.c (and a few other places), consolidate
things like xasprintf() into xfuncs.c, remove xprint_file_by_name() (it only
had one user), clean up lots of #includes...  General cleanup pass.  What I've
been doing for the last couple days.

And it conflicts!  I've removed httpd.c from this checkin due to somebody else
touching that file.  It builds for me.  I have to catch a bus.  (Now you know
why I'm looking forward to Mercurial.)
2006-08-03 15:41:12 +00:00

232 lines
5.5 KiB
C

/* vi: set sw=4 ts=4: */
/*
* public domain -- Dave 'Kill a Cop' Cinege <dcinege@psychosis.com>
*
* makedevs
* Make ranges of device files quickly.
* known bugs: can't deal with alpha ranges
*/
#include "busybox.h"
#ifdef CONFIG_FEATURE_MAKEDEVS_LEAF
int makedevs_main(int argc, char **argv)
{
mode_t mode;
char *basedev, *type, *nodname, buf[255];
int Smajor, Sminor, S, E;
if (argc < 7 || *argv[1]=='-')
bb_show_usage();
basedev = argv[1];
type = argv[2];
Smajor = atoi(argv[3]);
Sminor = atoi(argv[4]);
S = atoi(argv[5]);
E = atoi(argv[6]);
nodname = argc == 8 ? basedev : buf;
mode = 0660;
switch (type[0]) {
case 'c':
mode |= S_IFCHR;
break;
case 'b':
mode |= S_IFBLK;
break;
case 'f':
mode |= S_IFIFO;
break;
default:
bb_show_usage();
}
while (S <= E) {
int sz;
sz = snprintf(buf, sizeof(buf), "%s%d", basedev, S);
if(sz<0 || sz>=sizeof(buf)) /* libc different */
bb_error_msg_and_die("%s too large", basedev);
/* if mode != S_IFCHR and != S_IFBLK third param in mknod() ignored */
if (mknod(nodname, mode, makedev(Smajor, Sminor)))
bb_error_msg("Failed to create: %s", nodname);
if (nodname == basedev) /* ex. /dev/hda - to /dev/hda1 ... */
nodname = buf;
S++;
Sminor++;
}
return 0;
}
#elif defined CONFIG_FEATURE_MAKEDEVS_TABLE
/* Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */
int makedevs_main(int argc, char **argv)
{
FILE *table = stdin;
char *rootdir = NULL;
char *line = NULL;
int linenum = 0;
int ret = EXIT_SUCCESS;
unsigned long flags;
flags = bb_getopt_ulflags(argc, argv, "d:", &line);
if (line)
table = xfopen(line, "r");
if (optind >= argc || (rootdir=argv[optind])==NULL) {
bb_error_msg_and_die("root directory not specified");
}
xchdir(rootdir);
umask(0);
printf("rootdir=%s\n", rootdir);
if (line) {
printf("table='%s'\n", line);
} else {
printf("table=<stdin>\n");
}
while ((line = bb_get_chomped_line_from_file(table))) {
char type;
unsigned int mode = 0755;
unsigned int major = 0;
unsigned int minor = 0;
unsigned int count = 0;
unsigned int increment = 0;
unsigned int start = 0;
char name[41];
char user[41];
char group[41];
char *full_name;
uid_t uid;
gid_t gid;
linenum++;
if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name,
&type, &mode, user, group, &major,
&minor, &start, &increment, &count)) ||
((major | minor | start | count | increment) > 255))
{
if (*line=='\0' || *line=='#' || isspace(*line))
continue;
bb_error_msg("line %d invalid: '%s'\n", linenum, line);
ret = EXIT_FAILURE;
continue;
}
if (name[0] == '#') {
continue;
}
gid = (*group) ? get_ug_id(group, bb_xgetgrnam) : getgid();
uid = (*user) ? get_ug_id(user, bb_xgetpwnam) : getuid();
full_name = concat_path_file(rootdir, name);
if (type == 'd') {
bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR);
if (chown(full_name, uid, gid) == -1) {
bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
ret = EXIT_FAILURE;
goto loop;
}
if ((mode != -1) && (chmod(full_name, mode) < 0)){
bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
ret = EXIT_FAILURE;
goto loop;
}
} else if (type == 'f') {
struct stat st;
if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) {
bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name);
ret = EXIT_FAILURE;
goto loop;
}
if (chown(full_name, uid, gid) == -1) {
bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
ret = EXIT_FAILURE;
goto loop;
}
if ((mode != -1) && (chmod(full_name, mode) < 0)){
bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
ret = EXIT_FAILURE;
goto loop;
}
} else
{
dev_t rdev;
if (type == 'p') {
mode |= S_IFIFO;
}
else if (type == 'c') {
mode |= S_IFCHR;
}
else if (type == 'b') {
mode |= S_IFBLK;
} else {
bb_error_msg("line %d: unsupported file type %c", linenum, type);
ret = EXIT_FAILURE;
goto loop;
}
if (count > 0) {
int i;
char *full_name_inc;
full_name_inc = xmalloc(strlen(full_name) + 4);
for (i = start; i < count; i++) {
sprintf(full_name_inc, "%s%d", full_name, i);
rdev = (major << 8) + minor + (i * increment - start);
if (mknod(full_name_inc, mode, rdev) == -1) {
bb_perror_msg("line %d: could not create node %s", linenum, full_name_inc);
ret = EXIT_FAILURE;
}
else if (chown(full_name_inc, uid, gid) == -1) {
bb_perror_msg("line %d: chown failed for %s", linenum, full_name_inc);
ret = EXIT_FAILURE;
}
if ((mode != -1) && (chmod(full_name_inc, mode) < 0)){
bb_perror_msg("line %d: chmod failed for %s", linenum, full_name_inc);
ret = EXIT_FAILURE;
}
}
free(full_name_inc);
} else {
rdev = (major << 8) + minor;
if (mknod(full_name, mode, rdev) == -1) {
bb_perror_msg("line %d: could not create node %s", linenum, full_name);
ret = EXIT_FAILURE;
}
else if (chown(full_name, uid, gid) == -1) {
bb_perror_msg("line %d: chown failed for %s", linenum, full_name);
ret = EXIT_FAILURE;
}
if ((mode != -1) && (chmod(full_name, mode) < 0)){
bb_perror_msg("line %d: chmod failed for %s", linenum, full_name);
ret = EXIT_FAILURE;
}
}
}
loop:
free(line);
free(full_name);
}
fclose(table);
return ret;
}
#else
# error makedevs configuration error, either leaf or table must be selected
#endif