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); |