aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-02-24 10:39:47 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-02-24 10:39:47 +0100
commit64bb95a361c9d82e2abed90e0402459c68fb14b2 (patch)
tree3b2618d7b09e6d7db4b9c3e4ec20447b3ab20479
parentbf1d347964eac6bf25c1595d29fcb761e58c99c3 (diff)
downloadbusybox-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.c54
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 */
110static void make_device(char *path, int delete) 107static 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);