X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=util-linux%2Fmdev.c;h=78bb48ac0b809615b66f32c5c19fd2b40af4cb5a;hb=a2333c8938af4829a8eac8c09615e6652cd412f1;hp=f6440b19011e9725b76b632edf1468efdfcc910d;hpb=df96df9c7c78d0f19c8d1ac1aa3d8d80abbe16bb;p=oweals%2Fbusybox.git diff --git a/util-linux/mdev.c b/util-linux/mdev.c index f6440b190..78bb48ac0 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -59,8 +59,7 @@ static void make_device(char *path, int delete) int major, minor, type, len; int mode = 0660; #if ENABLE_FEATURE_MDEV_CONF - uid_t uid = 0; - gid_t gid = 0; + struct bb_uidgid_t ugid = { 0, 0 }; parser_t *parser; char *tokens[5]; #endif @@ -78,9 +77,10 @@ static void make_device(char *path, int delete) /* Try to read major/minor string. Note that the kernel puts \n after * the data, so we don't need to worry about null terminating the string - * because sscanf() will stop at the first nondigit, which \n is. We - * also depend on path having writeable space after it. + * because sscanf() will stop at the first nondigit, which \n is. + * We also depend on path having writeable space after it. */ + major = -1; if (!delete) { strcpy(dev_maj_min, "/dev"); len = open_read_close(path, dev_maj_min + 1, 64); @@ -90,6 +90,8 @@ static void make_device(char *path, int delete) return; /* no "dev" file, so just try to run script */ *dev_maj_min = '\0'; + } else if (sscanf(dev_maj_min, "%u:%u", &major, &minor) != 2) { + major = -1; } } @@ -99,25 +101,37 @@ static void make_device(char *path, int delete) * "/sys/block/..." is for block devices. "/sys/bus" etc is not. * But since 2.6.25 block devices are also in /sys/class/block. * We use strstr("/block/") to forestall future surprises. */ - type = S_IFCHR; + type = S_IFCHR; if (strstr(path, "/block/")) - type = S_IFBLK; + type = S_IFBLK; #if ENABLE_FEATURE_MDEV_CONF parser = config_open2("/etc/mdev.conf", fopen_for_read); /* If we have config file, look up user settings */ - if (!parser) - goto end_parse; - - while (config_read(parser, tokens, 4, 3, "# \t", PARSE_LAST_IS_GREEDY)) { + while (config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)) { regmatch_t off[1 + 9*ENABLE_FEATURE_MDEV_RENAME_REGEXP]; char *val; /* Fields: regex uid:gid mode [alias] [cmd] */ - /* 1st field: regex to match this device */ - { + /* 1st field: @... */ + if (tokens[0][0] == '@') { + /* @major,minor[-last] */ + /* (useful when name is ambiguous: + * "/sys/class/usb/lp0" and + * "/sys/class/printer/lp0") */ + int cmaj, cmin0, cmin1, sc; + if (major < 0) + continue; /* no dev, no match */ + sc = sscanf(tokens[0], "@%u,%u-%u", &cmaj, &cmin0, &cmin1); + if (sc < 1 || major != cmaj + || (sc == 2 && minor != cmin0) + || (sc == 3 && (minor < cmin0 || minor > cmin1)) + ) { + continue; /* no match */ + } + } else { /* ... or regex to match device name */ regex_t match; int result; @@ -147,27 +161,7 @@ static void make_device(char *path, int delete) * after parsing the rest of fields */ /* 2nd field: uid:gid - device ownership */ - { - struct passwd *pass; - struct group *grp; - char *str_uid = tokens[1]; - char *str_gid = strchrnul(str_uid, ':'); - - if (*str_gid) - *str_gid++ = '\0'; - /* Parse UID */ - pass = getpwnam(str_uid); - if (pass) - uid = pass->pw_uid; - else - uid = strtoul(str_uid, NULL, 10); - /* Parse GID */ - grp = getgrnam(str_gid); - if (grp) - gid = grp->gr_gid; - else - gid = strtoul(str_gid, NULL, 10); - } + parse_chown_usergroup_or_die(&ugid, tokens[1]); /* 3rd field: mode - device permissions */ mode = strtoul(tokens[2], NULL, 8); @@ -185,8 +179,9 @@ static void make_device(char *path, int delete) unsigned i, n; #endif char *a = val; - s = strchr(val, ' '); - val = (s && s[1]) ? s+1 : NULL; + s = strchrnul(val, ' '); + val = (s[0] && s[1]) ? s+1 : NULL; + s[0] = '\0'; #if ENABLE_FEATURE_MDEV_RENAME_REGEXP /* substitute %1..9 with off[1..9], if any */ n = 0; @@ -244,10 +239,9 @@ static void make_device(char *path, int delete) } /* end of "while line is read from /etc/mdev.conf" */ config_close(parser); - end_parse: #endif /* ENABLE_FEATURE_MDEV_CONF */ - if (!delete && sscanf(dev_maj_min, "%u:%u", &major, &minor) == 2) { + if (!delete && major >= 0) { if (ENABLE_FEATURE_MDEV_RENAME) unlink(device_name); @@ -259,7 +253,7 @@ static void make_device(char *path, int delete) symlink(device_name, "root"); #if ENABLE_FEATURE_MDEV_CONF - chown(device_name, uid, gid); + chown(device_name, ugid.uid, ugid.gid); #if ENABLE_FEATURE_MDEV_RENAME if (alias) { @@ -283,8 +277,7 @@ static void make_device(char *path, int delete) putenv(s); if (system(command) == -1) bb_perror_msg_and_die("can't run '%s'", command); - s[4] = '\0'; - unsetenv(s); + unsetenv("MDEV"); free(s); free(command); } @@ -427,10 +420,17 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) * /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) */ - recursive_action("/sys/block", - ACTION_RECURSE | ACTION_FOLLOWLINKS, - fileAction, dirAction, temp, 0); + * 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. + */ + recursive_action("/sys/block", + ACTION_RECURSE | ACTION_FOLLOWLINKS, + // not needed now? | ACTION_QUIET + fileAction, dirAction, temp, 0); + } recursive_action("/sys/class", ACTION_RECURSE | ACTION_FOLLOWLINKS, fileAction, dirAction, temp, 0);