X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=util-linux%2Fmdev.c;h=a59115dd45729654aa08ac2fb31072396c5a02ac;hb=52a515d18724bbb34e3ccbbb0218efcc4eccc0a8;hp=662e8ab38b0762256439f531296c94195b27de03;hpb=d840c5d139cfa50fbe4f6f67c178b0edf0c690c8;p=oweals%2Fbusybox.git diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 662e8ab38..a59115dd4 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -97,6 +97,7 @@ //usage: "If /dev/mdev.log file exists, debug log will be appended to it." #include "libbb.h" +#include "common_bufsiz.h" #include "xregex.h" /* "mdev -s" scans /sys/class/xxx, looking for directories which have dev @@ -285,8 +286,9 @@ struct globals { struct rule cur_rule; char timestr[sizeof("HH:MM:SS.123456")]; } FIX_ALIASING; -#define G (*(struct globals*)&bb_common_bufsiz1) +#define G (*(struct globals*)bb_common_bufsiz1) #define INIT_G() do { \ + setup_common_bufsiz(); \ IF_NOT_FEATURE_MDEV_CONF(G.cur_rule.maj = -1;) \ IF_NOT_FEATURE_MDEV_CONF(G.cur_rule.mode = 0660;) \ } while (0) @@ -400,13 +402,13 @@ static void parse_next_rule(void) } /* 2nd field: uid:gid - device ownership */ - if (get_uidgid(&G.cur_rule.ugid, tokens[1], /*allow_numeric:*/ 1) == 0) { + if (get_uidgid(&G.cur_rule.ugid, tokens[1]) == 0) { bb_error_msg("unknown user/group '%s' on line %d", tokens[1], G.parser->lineno); goto next_rule; } /* 3rd field: mode - device permissions */ - bb_parse_mode(tokens[2], &G.cur_rule.mode); + G.cur_rule.mode = bb_parse_mode(tokens[2], G.cur_rule.mode); /* 4th field (opt): ">|=alias" or "!" to not create the node */ val = tokens[3]; @@ -541,8 +543,7 @@ static char *build_alias(char *alias, const char *device_name) /* mknod in /dev based on a path like "/sys/block/hda/hda1" * NB1: path parameter needs to have SCRATCH_SIZE scratch bytes - * after NUL, but we promise to not mangle (IOW: to restore NUL if needed) - * path string. + * after NUL, but we promise to not mangle it (IOW: to restore NUL if needed). * NB2: "mdev -s" may call us many times, do not leak memory/fds! * * device_name = $DEVNAME (may be NULL) @@ -808,41 +809,39 @@ static void make_device(char *device_name, char *path, int operation) } /* for (;;) */ } -/* File callback for /sys/ traversal */ +/* File callback for /sys/ traversal. + * We act only on "/sys/.../dev" (pseudo)file + */ static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf UNUSED_PARAM, void *userData, int depth UNUSED_PARAM) { size_t len = strlen(fileName) - 4; /* can't underflow */ - char *scratch = userData; - - /* len check is for paranoid reasons */ - if (strcmp(fileName + len, "/dev") != 0 || len >= PATH_MAX) - return FALSE; - - strcpy(scratch, fileName); - scratch[len] = '\0'; - make_device(/*DEVNAME:*/ NULL, scratch, OP_add); - - return TRUE; -} - -/* Directory callback for /sys/ traversal */ -static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM, - struct stat *statbuf UNUSED_PARAM, - void *userData UNUSED_PARAM, - int depth) -{ - /* Extract device subsystem -- the name of the directory - * under /sys/class/ */ - if (1 == depth) { + char *path = userData; /* char array[PATH_MAX + SCRATCH_SIZE] */ + char subsys[PATH_MAX]; + int res; + + /* Is it a ".../dev" file? (len check is for paranoid reasons) */ + if (strcmp(fileName + len, "/dev") != 0 || len >= PATH_MAX - 32) + return FALSE; /* not .../dev */ + + strcpy(path, fileName); + path[len] = '\0'; + + /* Read ".../subsystem" symlink in the same directory where ".../dev" is */ + strcpy(subsys, path); + strcpy(subsys + len, "/subsystem"); + res = readlink(subsys, subsys, sizeof(subsys)-1); + if (res > 0) { + subsys[res] = '\0'; free(G.subsystem); if (G.subsys_env) { bb_unsetenv_and_free(G.subsys_env); G.subsys_env = NULL; } - G.subsystem = strrchr(fileName, '/'); + /* Set G.subsystem and $SUBSYSTEM from symlink's last component */ + G.subsystem = strrchr(subsys, '/'); if (G.subsystem) { G.subsystem = xstrdup(G.subsystem + 1); G.subsys_env = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem); @@ -850,6 +849,17 @@ static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM, } } + make_device(/*DEVNAME:*/ NULL, path, OP_add); + + return TRUE; +} + +/* Directory callback for /sys/ traversal */ +static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM, + struct stat *statbuf UNUSED_PARAM, + void *userData UNUSED_PARAM, + int depth) +{ return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE); } @@ -870,8 +880,9 @@ static void load_firmware(const char *firmware, const char *sysfs_path) int firmware_fd, loading_fd; /* check for /lib/firmware/$FIRMWARE */ - xchdir("/lib/firmware"); - firmware_fd = open(firmware, O_RDONLY); /* can fail */ + firmware_fd = -1; + if (chdir("/lib/firmware") == 0) + firmware_fd = open(firmware, O_RDONLY); /* can fail */ /* check for /sys/$DEVPATH/loading ... give 30 seconds to appear */ xchdir(sysfs_path); @@ -1063,25 +1074,10 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) putenv((char*)"ACTION=add"); - /* ACTION_FOLLOWLINKS is needed since in newer kernels - * /sys/block/loop* (for example) are symlinks to dirs, - * not real directories. - * (kernel's CONFIG_SYSFS_DEPRECATED makes them real dirs, - * but we can't enforce that on users) - */ - if (access("/sys/class/block", F_OK) != 0) { - /* Scan obsolete /sys/block only if /sys/class/block - * doesn't exist. Otherwise we'll have dupes. - * Also, do not complain if it doesn't exist. - * Some people configure kernel to have no blockdevs. - */ - recursive_action("/sys/block", - ACTION_RECURSE | ACTION_FOLLOWLINKS | ACTION_QUIET, - fileAction, dirAction, temp, 0); - } - recursive_action("/sys/class", - ACTION_RECURSE | ACTION_FOLLOWLINKS, - fileAction, dirAction, temp, 0); + /* Create all devices from /sys/dev hierarchy */ + recursive_action("/sys/dev", + ACTION_RECURSE | ACTION_FOLLOWLINKS, + fileAction, dirAction, temp, 0); } else { char *fw; char *seq;