From c07669bd663d780e4957691e488798aa0178e76b Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sun, 5 Jun 2005 15:55:29 +0200 Subject: udev: handle all events - not only class and block devices Handle all events with rules. If udev is expected to handle hotplug.d/ the exernal helper must be called. Signed-off-by: Kay Sievers --- udev.c | 155 +++++++++++++++++++++++++++-------------------------------------- 1 file changed, 64 insertions(+), 91 deletions(-) (limited to 'udev.c') diff --git a/udev.c b/udev.c index 3f76e98b..d623cbcc 100644 --- a/udev.c +++ b/udev.c @@ -54,39 +54,6 @@ void log_message(int priority, const char *format, ...) } #endif -/* Decide if we should manage the whole uevent, including multiplexing - * of the hotplug directories. - * For now look if the kernel calls udevsend instead of /sbin/hotplug, - * or the uevent-helper in /proc/sys/kernel/hotplug is empty. - */ -static int manage_hotplug_event(void) { - char helper[256]; - int fd; - int len; - - /* don't handle hotplug.d if we are called directly */ - if (!getenv("UDEVD_EVENT")) - return 0; - - fd = open("/proc/sys/kernel/hotplug", O_RDONLY); - if (fd < 0) - return 0; - - len = read(fd, helper, sizeof(helper)-1); - close(fd); - - if (len < 0) - return 0; - helper[len] = '\0'; - - if (helper[0] == '\0' || helper[0] == '\n') - return 1; - if (strstr(helper, "udevsend")) - return 1; - - return 0; -} - static void asmlinkage sig_handler(int signum) { switch (signum) { @@ -100,15 +67,12 @@ static void asmlinkage sig_handler(int signum) int main(int argc, char *argv[], char *envp[]) { - struct sysfs_class_device *class_dev; - struct sysfs_device *devices_dev; struct udevice udev; char path[PATH_SIZE]; const char *error; const char *action; const char *devpath; const char *subsystem; - int managed_event; struct sigaction act; int retval = -EINVAL; @@ -133,11 +97,6 @@ int main(int argc, char *argv[], char *envp[]) /* trigger timeout to prevent hanging processes */ alarm(ALARM_TIMEOUT); - /* let the executed programs know if we handle the whole hotplug event */ - managed_event = manage_hotplug_event(); - if (managed_event) - setenv("MANAGED_EVENT", "1", 1); - action = getenv("ACTION"); devpath = getenv("DEVPATH"); subsystem = getenv("SUBSYSTEM"); @@ -145,14 +104,12 @@ int main(int argc, char *argv[], char *envp[]) if (!subsystem && argc == 2) subsystem = argv[1]; - udev_init_device(&udev, devpath, subsystem, action); - if (!action || !subsystem || !devpath) { err("action, subsystem or devpath missing"); - goto hotplug; + goto exit; } - /* export logging flag, as called programs may want to do the same as udev */ + /* export log_level , as called programs may want to do the same as udev */ if (udev_log_priority) { char priority[32]; @@ -160,93 +117,109 @@ int main(int argc, char *argv[], char *envp[]) setenv("UDEV_LOG", priority, 1); } - if (udev.type == DEV_BLOCK || udev.type == DEV_CLASS || udev.type == DEV_NET) { - udev_rules_init(); + udev_init_device(&udev, devpath, subsystem, action); + udev_rules_init(); + if (udev.type == DEV_BLOCK || udev.type == DEV_CLASS || udev.type == DEV_NET) { + /* handle device node */ if (strcmp(action, "add") == 0) { - /* wait for sysfs and possibly add node */ - dbg("udev add"); - - /* skip subsystems without "dev", but handle net devices */ - if (udev.type != DEV_NET && subsystem_expect_no_dev(udev.subsystem)) { - dbg("don't care about '%s' devices", udev.subsystem); - goto hotplug; - } + struct sysfs_class_device *class_dev; + /* wait for sysfs of /sys/class /sys/block */ + dbg("node add"); snprintf(path, sizeof(path), "%s%s", sysfs_path, udev.devpath); path[sizeof(path)-1] = '\0'; class_dev = wait_class_device_open(path); if (class_dev == NULL) { dbg("open class device failed"); - goto hotplug; + goto run; } dbg("opened class_dev->name='%s'", class_dev->name); - wait_for_class_device(class_dev, &error); - /* name, create node, store in db */ - retval = udev_add_device(&udev, class_dev); - + /* get major/minor */ + if (udev.type == DEV_BLOCK || udev.type == DEV_CLASS) { + udev.devt = get_devt(class_dev); + if (udev.devt) { + /* name device */ + udev_rules_get_name(&udev, class_dev); + if (udev.ignore_device) { + info("device event will be ignored"); + goto exit; + } + if (udev.name[0] == '\0') { + info("device node creation supressed"); + goto run; + } + + /* create node, store in db */ + retval = udev_add_device(&udev, class_dev); + } else { + dbg("no dev-file found"); + udev_rules_get_run(&udev, NULL); + if (udev.ignore_device) { + info("device event will be ignored"); + goto exit; + } + } + } sysfs_close_class_device(class_dev); } else if (strcmp(action, "remove") == 0) { - /* possibly remove a node */ - dbg("udev remove"); - - /* skip subsystems without "dev" */ - if (subsystem_expect_no_dev(udev.subsystem)) { - dbg("don't care about '%s' devices", udev.subsystem); - goto hotplug; - } - - udev_rules_get_run(&udev); + dbg("node remove"); + udev_rules_get_run(&udev, NULL); if (udev.ignore_device) { dbg("device event will be ignored"); - goto hotplug; + goto exit; } - /* get node from db, remove db-entry, delete created node */ + /* get name from db, remove db-entry, delete node */ retval = udev_remove_device(&udev); } + /* export name of device node or netif */ if (udev.devname[0] != '\0') setenv("DEVNAME", udev.devname, 1); - - if (udev_run && !list_empty(&udev.run_list)) { - struct name_entry *name_loop; - - dbg("executing run list"); - list_for_each_entry(name_loop, &udev.run_list, node) - execute_command(name_loop->name, udev.subsystem); - } - } else if (udev.type == DEV_DEVICE) { if (strcmp(action, "add") == 0) { - /* wait for sysfs */ - dbg("devices add"); + struct sysfs_device *devices_dev; + /* wait for sysfs of /sys/devices/ */ + dbg("devices add"); snprintf(path, sizeof(path), "%s%s", sysfs_path, devpath); path[sizeof(path)-1] = '\0'; devices_dev = wait_devices_device_open(path); if (!devices_dev) { dbg("devices device unavailable (probably remove has beaten us)"); - goto hotplug; + goto run; } dbg("devices device opened '%s'", path); - wait_for_devices_device(devices_dev, &error); - + udev_rules_get_run(&udev, devices_dev); sysfs_close_device(devices_dev); + if (udev.ignore_device) { + info("device event will be ignored"); + goto exit; + } } else if (strcmp(action, "remove") == 0) { dbg("devices remove"); + udev_rules_get_run(&udev, NULL); + if (udev.ignore_device) { + info("device event will be ignored"); + goto exit; + } } - } else { - dbg("unhandled"); } -hotplug: - if (udev_hotplug_d && managed_event) - udev_multiplex_directory(&udev, HOTPLUGD_DIR, HOTPLUG_SUFFIX); +run: + if (udev_run && !list_empty(&udev.run_list)) { + struct name_entry *name_loop; + + dbg("executing run list"); + list_for_each_entry(name_loop, &udev.run_list, node) + execute_command(name_loop->name, udev.subsystem); + } +exit: udev_cleanup_device(&udev); logging_close(); -- cgit 1.2.3-korg