mdev: use $DEVNAME in uevent sysfs file for device node name
516530c932
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>
This commit is contained in:
parent
ff463a885d
commit
c3cf1e30a3
@ -295,8 +295,8 @@ struct globals {
|
|||||||
/* Prevent infinite loops in /sys symlinks */
|
/* Prevent infinite loops in /sys symlinks */
|
||||||
#define MAX_SYSFS_DEPTH 3
|
#define MAX_SYSFS_DEPTH 3
|
||||||
|
|
||||||
/* We use additional 64+ bytes in make_device() */
|
/* We use additional bytes in make_device() */
|
||||||
#define SCRATCH_SIZE 80
|
#define SCRATCH_SIZE 128
|
||||||
|
|
||||||
#if ENABLE_FEATURE_MDEV_CONF
|
#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"
|
/* mknod in /dev based on a path like "/sys/block/hda/hda1"
|
||||||
* NB1: path parameter needs to have SCRATCH_SIZE scratch bytes
|
* 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.
|
* path string.
|
||||||
* NB2: "mdev -s" may call us many times, do not leak memory/fds!
|
* 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)
|
static void make_device(char *device_name, char *path, int operation)
|
||||||
{
|
{
|
||||||
int major, minor, type, len;
|
int major, minor, type, len;
|
||||||
|
char *path_end = path + strlen(path);
|
||||||
|
|
||||||
/* Try to read major/minor string. Note that the kernel puts \n after
|
/* 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
|
* 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;
|
major = -1;
|
||||||
if (operation == OP_add) {
|
if (operation == OP_add) {
|
||||||
char *dev_maj_min = path + strlen(path);
|
strcpy(path_end, "/dev");
|
||||||
|
len = open_read_close(path, path_end + 1, SCRATCH_SIZE - 1);
|
||||||
strcpy(dev_maj_min, "/dev");
|
*path_end = '\0';
|
||||||
len = open_read_close(path, dev_maj_min + 1, 64);
|
|
||||||
*dev_maj_min = '\0';
|
|
||||||
if (len < 1) {
|
if (len < 1) {
|
||||||
if (!ENABLE_FEATURE_MDEV_EXEC)
|
if (!ENABLE_FEATURE_MDEV_EXEC)
|
||||||
return;
|
return;
|
||||||
/* no "dev" file, but we can still run scripts
|
/* no "dev" file, but we can still run scripts
|
||||||
* based on device name */
|
* 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);
|
dbg1("dev %u,%u", major, minor);
|
||||||
} else {
|
} else {
|
||||||
major = -1;
|
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 */
|
/* else: for delete, -1 still deletes the node, but < -1 suppresses that */
|
||||||
|
|
||||||
/* Determine device name, type, major and minor */
|
/* Determine device name */
|
||||||
if (!device_name)
|
if (!device_name) {
|
||||||
device_name = (char*) bb_basename(path);
|
/*
|
||||||
|
* 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
|
* http://kernel.org/doc/pending/hotplug.txt says that only
|
||||||
* "/sys/block/..." is for block devices. "/sys/bus" etc is not.
|
* "/sys/block/..." is for block devices. "/sys/bus" etc is not.
|
||||||
|
Loading…
Reference in New Issue
Block a user