diff options
author | Nikolaus Voss <n.voss@weinmann.de> | 2013-05-13 03:55:11 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2013-05-13 03:55:11 +0200 |
commit | c3cf1e30a3022453311a7e9fe11d94c7a381640e (patch) | |
tree | 0c451c05fd19f50a0b24368201a65e69500d6e8a | |
parent | ff463a885d7dbcea5493074cae498d58a5459539 (diff) | |
download | busybox-w32-c3cf1e30a3022453311a7e9fe11d94c7a381640e.tar.gz busybox-w32-c3cf1e30a3022453311a7e9fe11d94c7a381640e.tar.bz2 busybox-w32-c3cf1e30a3022453311a7e9fe11d94c7a381640e.zip |
mdev: use $DEVNAME in uevent sysfs file for device node name
516530c932bd17d87c9eb4347a490be051e495f4 uses $DEVNAME variable
for device node name. This is fine, but only works for hotplugging,
"mdev -s" will behave differently when DEVNAME and basename(path)
differ.
This patch extracts the DEVNAME from the uevent sysfs file in
make_device(), thus works for hot- and coldplugging; so using
the environment DEVNAME on hotplug events is no longer necessary.
Signed-off-by: Nikolaus Voss <n.voss@weinmann.de>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | util-linux/mdev.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 1d741367e..e80b58f2e 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c | |||
@@ -295,8 +295,8 @@ struct globals { | |||
295 | /* Prevent infinite loops in /sys symlinks */ | 295 | /* Prevent infinite loops in /sys symlinks */ |
296 | #define MAX_SYSFS_DEPTH 3 | 296 | #define MAX_SYSFS_DEPTH 3 |
297 | 297 | ||
298 | /* We use additional 64+ bytes in make_device() */ | 298 | /* We use additional bytes in make_device() */ |
299 | #define SCRATCH_SIZE 80 | 299 | #define SCRATCH_SIZE 128 |
300 | 300 | ||
301 | #if ENABLE_FEATURE_MDEV_CONF | 301 | #if ENABLE_FEATURE_MDEV_CONF |
302 | 302 | ||
@@ -541,7 +541,7 @@ static char *build_alias(char *alias, const char *device_name) | |||
541 | 541 | ||
542 | /* mknod in /dev based on a path like "/sys/block/hda/hda1" | 542 | /* mknod in /dev based on a path like "/sys/block/hda/hda1" |
543 | * NB1: path parameter needs to have SCRATCH_SIZE scratch bytes | 543 | * NB1: path parameter needs to have SCRATCH_SIZE scratch bytes |
544 | * after NUL, but we promise to not mangle (IOW: to restore if needed) | 544 | * after NUL, but we promise to not mangle (IOW: to restore NUL if needed) |
545 | * path string. | 545 | * path string. |
546 | * NB2: "mdev -s" may call us many times, do not leak memory/fds! | 546 | * NB2: "mdev -s" may call us many times, do not leak memory/fds! |
547 | * | 547 | * |
@@ -551,6 +551,7 @@ static char *build_alias(char *alias, const char *device_name) | |||
551 | static void make_device(char *device_name, char *path, int operation) | 551 | static void make_device(char *device_name, char *path, int operation) |
552 | { | 552 | { |
553 | int major, minor, type, len; | 553 | int major, minor, type, len; |
554 | char *path_end = path + strlen(path); | ||
554 | 555 | ||
555 | /* Try to read major/minor string. Note that the kernel puts \n after | 556 | /* Try to read major/minor string. Note that the kernel puts \n after |
556 | * the data, so we don't need to worry about null terminating the string | 557 | * the data, so we don't need to worry about null terminating the string |
@@ -559,17 +560,15 @@ static void make_device(char *device_name, char *path, int operation) | |||
559 | */ | 560 | */ |
560 | major = -1; | 561 | major = -1; |
561 | if (operation == OP_add) { | 562 | if (operation == OP_add) { |
562 | char *dev_maj_min = path + strlen(path); | 563 | strcpy(path_end, "/dev"); |
563 | 564 | len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1); | |
564 | strcpy(dev_maj_min, "/dev"); | 565 | *path_end = '\0'; |
565 | len = open_read_close(path, dev_maj_min + 1, 64); | ||
566 | *dev_maj_min = '\0'; | ||
567 | if (len < 1) { | 566 | if (len < 1) { |
568 | if (!ENABLE_FEATURE_MDEV_EXEC) | 567 | if (!ENABLE_FEATURE_MDEV_EXEC) |
569 | return; | 568 | return; |
570 | /* no "dev" file, but we can still run scripts | 569 | /* no "dev" file, but we can still run scripts |
571 | * based on device name */ | 570 | * based on device name */ |
572 | } else if (sscanf(++dev_maj_min, "%u:%u", &major, &minor) == 2) { | 571 | } else if (sscanf(path_end + 1, "%u:%u", &major, &minor) == 2) { |
573 | dbg1("dev %u,%u", major, minor); | 572 | dbg1("dev %u,%u", major, minor); |
574 | } else { | 573 | } else { |
575 | major = -1; | 574 | major = -1; |
@@ -577,9 +576,33 @@ static void make_device(char *device_name, char *path, int operation) | |||
577 | } | 576 | } |
578 | /* else: for delete, -1 still deletes the node, but < -1 suppresses that */ | 577 | /* else: for delete, -1 still deletes the node, but < -1 suppresses that */ |
579 | 578 | ||
580 | /* Determine device name, type, major and minor */ | 579 | /* Determine device name */ |
581 | if (!device_name) | 580 | if (!device_name) { |
582 | device_name = (char*) bb_basename(path); | 581 | /* |
582 | * There was no $DEVNAME envvar (for example, mdev -s never has). | ||
583 | * But it is very useful: it contains the *path*, not only basename, | ||
584 | * Thankfully, uevent file has it. | ||
585 | * Example of .../sound/card0/controlC0/uevent file on Linux-3.7.7: | ||
586 | * MAJOR=116 | ||
587 | * MINOR=7 | ||
588 | * DEVNAME=snd/controlC0 | ||
589 | */ | ||
590 | strcpy(path_end, "/uevent"); | ||
591 | len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1); | ||
592 | if (len < 0) | ||
593 | len = 0; | ||
594 | *path_end = '\0'; | ||
595 | path_end[1 + len] = '\0'; | ||
596 | device_name = strstr(path_end + 1, "\nDEVNAME="); | ||
597 | if (device_name) { | ||
598 | device_name += sizeof("\nDEVNAME=")-1; | ||
599 | strchrnul(device_name, '\n')[0] = '\0'; | ||
600 | } else { | ||
601 | /* Fall back to just basename */ | ||
602 | device_name = (char*) bb_basename(path); | ||
603 | } | ||
604 | } | ||
605 | /* Determine device type */ | ||
583 | /* | 606 | /* |
584 | * http://kernel.org/doc/pending/hotplug.txt says that only | 607 | * http://kernel.org/doc/pending/hotplug.txt says that only |
585 | * "/sys/block/..." is for block devices. "/sys/bus" etc is not. | 608 | * "/sys/block/..." is for block devices. "/sys/bus" etc is not. |