[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox-cvs
Subject:    [git commit] mdev: use $DEVNAME in uevent sysfs file for device node name
From:       Denys Vlasenko <vda.linux () googlemail ! com>
Date:       2013-05-13 1:55:11
Message-ID: 20130513015616.58AA49A190 () busybox ! osuosl ! org
[Download RAW message or body]

commit: http://git.busybox.net/busybox/commit/?id=c3cf1e30a3022453311a7e9fe11d94c7a381640e
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

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>
---
 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 1d74136..e80b58f 100644
--- a/util-linux/mdev.c
+++ b/util-linux/mdev.c
@@ -295,8 +295,8 @@ struct globals {
 /* Prevent infinite loops in /sys symlinks */
 #define MAX_SYSFS_DEPTH 3
 
-/* We use additional 64+ bytes in make_device() */
-#define SCRATCH_SIZE 80
+/* We use additional bytes in make_device() */
+#define SCRATCH_SIZE 128
 
 #if ENABLE_FEATURE_MDEV_CONF
 
@@ -541,7 +541,7 @@ static char *build_alias(char *alias, const char *device_name)
 
 /* mknod in /dev based on a path like "/sys/block/hda/hda1"
  * NB1: path parameter needs to have SCRATCH_SIZE scratch bytes
- * after NUL, but we promise to not mangle (IOW: to restore if needed)
+ * after NUL, but we promise to not mangle (IOW: to restore NUL if needed)
  * path string.
  * NB2: "mdev -s" may call us many times, do not leak memory/fds!
  *
@@ -551,6 +551,7 @@ static char *build_alias(char *alias, const char *device_name)
 static void make_device(char *device_name, char *path, int operation)
 {
 	int major, minor, type, len;
+	char *path_end = path + strlen(path);
 
 	/* 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
@@ -559,17 +560,15 @@ static void make_device(char *device_name, char *path, int operation)
 	 */
 	major = -1;
 	if (operation == OP_add) {
-		char *dev_maj_min = path + strlen(path);
-
-		strcpy(dev_maj_min, "/dev");
-		len = open_read_close(path, dev_maj_min + 1, 64);
-		*dev_maj_min = '\0';
+		strcpy(path_end, "/dev");
+		len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1);
+		*path_end = '\0';
 		if (len < 1) {
 			if (!ENABLE_FEATURE_MDEV_EXEC)
 				return;
 			/* no "dev" file, but we can still run scripts
 			 * based on device name */
-		} else if (sscanf(++dev_maj_min, "%u:%u", &major, &minor) == 2) {
+		} else if (sscanf(path_end + 1, "%u:%u", &major, &minor) == 2) {
 			dbg1("dev %u,%u", major, minor);
 		} else {
 			major = -1;
@@ -577,9 +576,33 @@ static void make_device(char *device_name, char *path, int operation)
 	}
 	/* else: for delete, -1 still deletes the node, but < -1 suppresses that */
 
-	/* Determine device name, type, major and minor */
-	if (!device_name)
-		device_name = (char*) bb_basename(path);
+	/* Determine device name */
+	if (!device_name) {
+		/*
+		 * There was no $DEVNAME envvar (for example, mdev -s never has).
+		 * But it is very useful: it contains the *path*, not only basename,
+		 * Thankfully, uevent file has it.
+		 * Example of .../sound/card0/controlC0/uevent file on Linux-3.7.7:
+		 * MAJOR=116
+		 * MINOR=7
+		 * DEVNAME=snd/controlC0
+		 */
+		strcpy(path_end, "/uevent");
+		len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1);
+		if (len < 0)
+			len = 0;
+		*path_end = '\0';
+		path_end[1 + len] = '\0';
+		device_name = strstr(path_end + 1, "\nDEVNAME=");
+		if (device_name) {
+			device_name += sizeof("\nDEVNAME=")-1;
+			strchrnul(device_name, '\n')[0] = '\0';
+		} else {
+			/* Fall back to just basename */
+			device_name = (char*) bb_basename(path);
+		}
+	}
+	/* Determine device type */
 	/*
 	 * http://kernel.org/doc/pending/hotplug.txt says that only
 	 * "/sys/block/..." is for block devices. "/sys/bus" etc is not.
_______________________________________________
busybox-cvs mailing list
busybox-cvs@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox-cvs
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic