diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2010-02-24 10:39:47 +0100 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-02-24 10:39:47 +0100 |
| commit | 64bb95a361c9d82e2abed90e0402459c68fb14b2 (patch) | |
| tree | 3b2618d7b09e6d7db4b9c3e4ec20447b3ab20479 | |
| parent | bf1d347964eac6bf25c1595d29fcb761e58c99c3 (diff) | |
| download | busybox-w32-64bb95a361c9d82e2abed90e0402459c68fb14b2.tar.gz busybox-w32-64bb95a361c9d82e2abed90e0402459c68fb14b2.tar.bz2 busybox-w32-64bb95a361c9d82e2abed90e0402459c68fb14b2.zip | |
mdev: fix subsystem passing (new kernels broke it again) - bugs 639, 721.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
| -rw-r--r-- | util-linux/mdev.c | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 69e1e6937..9c9d95f8a 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
| @@ -66,9 +66,6 @@ struct globals { | |||
| 66 | char *subsystem; | 66 | char *subsystem; |
| 67 | } FIX_ALIASING; | 67 | } FIX_ALIASING; |
| 68 | #define G (*(struct globals*)&bb_common_bufsiz1) | 68 | #define G (*(struct globals*)&bb_common_bufsiz1) |
| 69 | #define root_major (G.root_major) | ||
| 70 | #define root_minor (G.root_minor) | ||
| 71 | #define subsystem (G.subsystem ) | ||
| 72 | 69 | ||
| 73 | /* Prevent infinite loops in /sys symlinks */ | 70 | /* Prevent infinite loops in /sys symlinks */ |
| 74 | #define MAX_SYSFS_DEPTH 3 | 71 | #define MAX_SYSFS_DEPTH 3 |
| @@ -109,7 +106,7 @@ static char *build_alias(char *alias, const char *device_name) | |||
| 109 | */ | 106 | */ |
| 110 | static void make_device(char *path, int delete) | 107 | static void make_device(char *path, int delete) |
| 111 | { | 108 | { |
| 112 | char *device_name; | 109 | char *device_name, *subsystem_slash_devname; |
| 113 | int major, minor, type, len; | 110 | int major, minor, type, len; |
| 114 | mode_t mode; | 111 | mode_t mode; |
| 115 | parser_t *parser; | 112 | parser_t *parser; |
| @@ -140,17 +137,29 @@ static void make_device(char *path, int delete) | |||
| 140 | device_name = (char*) bb_basename(path); | 137 | device_name = (char*) bb_basename(path); |
| 141 | /* http://kernel.org/doc/pending/hotplug.txt says that only | 138 | /* http://kernel.org/doc/pending/hotplug.txt says that only |
| 142 | * "/sys/block/..." is for block devices. "/sys/bus" etc is not. | 139 | * "/sys/block/..." is for block devices. "/sys/bus" etc is not. |
| 143 | * But since 2.6.25 block devices are also in /sys/class/block, | 140 | * But since 2.6.25 block devices are also in /sys/class/block. |
| 144 | * we use strstr("/block/") to forestall future surprises. */ | 141 | * We use strstr("/block/") to forestall future surprises. */ |
| 145 | type = S_IFCHR; | 142 | type = S_IFCHR; |
| 146 | if (strstr(path, "/block/")) | 143 | if (strstr(path, "/block/") || strncmp(G.subsystem, "block", 5) == 0) |
| 147 | type = S_IFBLK; | 144 | type = S_IFBLK; |
| 148 | 145 | ||
| 149 | /* Make path point to "subsystem/device_name" */ | 146 | /* Make path point to "subsystem/device_name" */ |
| 150 | if (path[5] == 'b') /* legacy /sys/block? */ | 147 | subsystem_slash_devname = NULL; |
| 148 | /* Check for coldplug invocations first */ | ||
| 149 | if (strncmp(path, "/sys/block/", 11) == 0) /* legacy case */ | ||
| 151 | path += sizeof("/sys/") - 1; | 150 | path += sizeof("/sys/") - 1; |
| 152 | else | 151 | else if (strncmp(path, "/sys/class/", 11) == 0) |
| 153 | path += sizeof("/sys/class/") - 1; | 152 | path += sizeof("/sys/class/") - 1; |
| 153 | else { | ||
| 154 | /* Example of a hotplug invocation: | ||
| 155 | * SUBSYSTEM="block" | ||
| 156 | * DEVPATH="/sys" + "/devices/virtual/mtd/mtd3/mtdblock3" | ||
| 157 | * ("/sys" is added by mdev_main) | ||
| 158 | * - path does not contain subsystem | ||
| 159 | */ | ||
| 160 | subsystem_slash_devname = concat_path_file(G.subsystem, device_name); | ||
| 161 | path = subsystem_slash_devname; | ||
| 162 | } | ||
| 154 | 163 | ||
| 155 | /* If we have config file, look up user settings */ | 164 | /* If we have config file, look up user settings */ |
| 156 | if (ENABLE_FEATURE_MDEV_CONF) | 165 | if (ENABLE_FEATURE_MDEV_CONF) |
| @@ -332,7 +341,7 @@ static void make_device(char *path, int delete) | |||
| 332 | if (!delete && major >= 0) { | 341 | if (!delete && major >= 0) { |
| 333 | if (mknod(node_name, mode | type, makedev(major, minor)) && errno != EEXIST) | 342 | if (mknod(node_name, mode | type, makedev(major, minor)) && errno != EEXIST) |
| 334 | bb_perror_msg("can't create %s", node_name); | 343 | bb_perror_msg("can't create %s", node_name); |
| 335 | if (major == root_major && minor == root_minor) | 344 | if (major == G.root_major && minor == G.root_minor) |
| 336 | symlink(node_name, "root"); | 345 | symlink(node_name, "root"); |
| 337 | if (ENABLE_FEATURE_MDEV_CONF) { | 346 | if (ENABLE_FEATURE_MDEV_CONF) { |
| 338 | chmod(node_name, mode); | 347 | chmod(node_name, mode); |
| @@ -347,7 +356,7 @@ static void make_device(char *path, int delete) | |||
| 347 | if (ENABLE_FEATURE_MDEV_EXEC && command) { | 356 | if (ENABLE_FEATURE_MDEV_EXEC && command) { |
| 348 | /* setenv will leak memory, use putenv/unsetenv/free */ | 357 | /* setenv will leak memory, use putenv/unsetenv/free */ |
| 349 | char *s = xasprintf("%s=%s", "MDEV", node_name); | 358 | char *s = xasprintf("%s=%s", "MDEV", node_name); |
| 350 | char *s1 = xasprintf("%s=%s", "SUBSYSTEM", subsystem); | 359 | char *s1 = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem); |
| 351 | putenv(s); | 360 | putenv(s); |
| 352 | putenv(s1); | 361 | putenv(s1); |
| 353 | if (system(command) == -1) | 362 | if (system(command) == -1) |
| @@ -381,6 +390,7 @@ static void make_device(char *path, int delete) | |||
| 381 | 390 | ||
| 382 | if (ENABLE_FEATURE_MDEV_CONF) | 391 | if (ENABLE_FEATURE_MDEV_CONF) |
| 383 | config_close(parser); | 392 | config_close(parser); |
| 393 | free(subsystem_slash_devname); | ||
| 384 | } | 394 | } |
| 385 | 395 | ||
| 386 | /* File callback for /sys/ traversal */ | 396 | /* File callback for /sys/ traversal */ |
| @@ -398,7 +408,7 @@ static int FAST_FUNC fileAction(const char *fileName, | |||
| 398 | 408 | ||
| 399 | strcpy(scratch, fileName); | 409 | strcpy(scratch, fileName); |
| 400 | scratch[len] = '\0'; | 410 | scratch[len] = '\0'; |
| 401 | make_device(scratch, 0); | 411 | make_device(scratch, /*delete:*/ 0); |
| 402 | 412 | ||
| 403 | return TRUE; | 413 | return TRUE; |
| 404 | } | 414 | } |
| @@ -412,10 +422,10 @@ static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM, | |||
| 412 | /* Extract device subsystem -- the name of the directory | 422 | /* Extract device subsystem -- the name of the directory |
| 413 | * under /sys/class/ */ | 423 | * under /sys/class/ */ |
| 414 | if (1 == depth) { | 424 | if (1 == depth) { |
| 415 | free(subsystem); | 425 | free(G.subsystem); |
| 416 | subsystem = strrchr(fileName, '/'); | 426 | G.subsystem = strrchr(fileName, '/'); |
| 417 | if (subsystem) | 427 | if (G.subsystem) |
| 418 | subsystem = xstrdup(subsystem + 1); | 428 | G.subsystem = xstrdup(G.subsystem + 1); |
| 419 | } | 429 | } |
| 420 | 430 | ||
| 421 | return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE); | 431 | return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE); |
| @@ -500,8 +510,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
| 500 | struct stat st; | 510 | struct stat st; |
| 501 | 511 | ||
| 502 | xstat("/", &st); | 512 | xstat("/", &st); |
| 503 | root_major = major(st.st_dev); | 513 | G.root_major = major(st.st_dev); |
| 504 | root_minor = minor(st.st_dev); | 514 | G.root_minor = minor(st.st_dev); |
| 505 | 515 | ||
| 506 | /* ACTION_FOLLOWLINKS is needed since in newer kernels | 516 | /* ACTION_FOLLOWLINKS is needed since in newer kernels |
| 507 | * /sys/block/loop* (for example) are symlinks to dirs, | 517 | * /sys/block/loop* (for example) are symlinks to dirs, |
| @@ -538,8 +548,8 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
| 538 | */ | 548 | */ |
| 539 | action = getenv("ACTION"); | 549 | action = getenv("ACTION"); |
| 540 | env_path = getenv("DEVPATH"); | 550 | env_path = getenv("DEVPATH"); |
| 541 | subsystem = getenv("SUBSYSTEM"); | 551 | G.subsystem = getenv("SUBSYSTEM"); |
| 542 | if (!action || !env_path /*|| !subsystem*/) | 552 | if (!action || !env_path /*|| !G.subsystem*/) |
| 543 | bb_show_usage(); | 553 | bb_show_usage(); |
| 544 | fw = getenv("FIRMWARE"); | 554 | fw = getenv("FIRMWARE"); |
| 545 | op = index_in_strings(keywords, action); | 555 | op = index_in_strings(keywords, action); |
| @@ -574,10 +584,10 @@ int mdev_main(int argc UNUSED_PARAM, char **argv) | |||
| 574 | * to happen and to cause erroneous deletion | 584 | * to happen and to cause erroneous deletion |
| 575 | * of device nodes. */ | 585 | * of device nodes. */ |
| 576 | if (!fw) | 586 | if (!fw) |
| 577 | make_device(temp, 1); | 587 | make_device(temp, /*delete:*/ 1); |
| 578 | } | 588 | } |
| 579 | else if (op == OP_add) { | 589 | else if (op == OP_add) { |
| 580 | make_device(temp, 0); | 590 | make_device(temp, /*delete:*/ 0); |
| 581 | if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE) { | 591 | if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE) { |
| 582 | if (fw) | 592 | if (fw) |
| 583 | load_firmware(fw, temp); | 593 | load_firmware(fw, temp); |
