From 6a522681e1438bbd9c317654cc35d5d206d378ad Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sun, 5 Jun 2005 05:11:29 +0200 Subject: [PATCH] udev: move dev.d/ handling to external helper Modern rules are expected to call notification and postprocessing with the RUN key. For compatibility the current behavior can be emulated with an external helper. Signed-off-by: Kay Sievers --- etc/udev/udev.rules | 51 ++++++++------- etc/udev/udev.rules.examples | 63 ++++++++----------- extras/run_directory/Makefile | 55 +++++++++++++++++ extras/run_directory/run_directory.c | 79 ++++++++++++++++++++++++ extras/run_directory/udev_run_devd.c | 78 +++++++++++++++++++++++ extras/run_directory/udev_run_hotplugd.c | 79 ++++++++++++++++++++++++ test/simple-build-check.sh | 2 +- udev.c | 4 -- udev.h | 1 - udev_config.c | 37 ----------- udev_utils.c | 32 ++++++++++ udev_utils.h | 2 + udevstart.c | 4 -- 13 files changed, 378 insertions(+), 109 deletions(-) create mode 100644 extras/run_directory/Makefile create mode 100644 extras/run_directory/run_directory.c create mode 100644 extras/run_directory/udev_run_devd.c create mode 100644 extras/run_directory/udev_run_hotplugd.c diff --git a/etc/udev/udev.rules b/etc/udev/udev.rules index bc8c8bdd..bebf7480 100644 --- a/etc/udev/udev.rules +++ b/etc/udev/udev.rules @@ -5,43 +5,42 @@ # # if this is a ide cdrom, name it the default name, and create a symlink to cdrom -BUS="ide", KERNEL="*[!0-9]", PROGRAM="/bin/cat /proc/ide/%k/media", RESULT="cdrom", NAME="%k", SYMLINK="cdrom" - -# create a symlink named after the device map name -# note devmap_name comes with extras/multipath -KERNEL="dm-[0-9]*", PROGRAM="/sbin/devmap_name %M %m", NAME="%k", SYMLINK="%c" +BUS=="ide", KERNEL=="*[!0-9]", PROGRAM="/bin/cat /proc/ide/%k/media", RESULT="cdrom", NAME="%k", SYMLINK+="cdrom" # DRI devices always go into a subdirectory (as per the LSB spec) -KERNEL="card*", NAME="dri/card%n" +KERNEL=="card*", NAME="dri/card%n" # alsa devices -KERNEL="controlC[0-9]*", NAME="snd/%k" -KERNEL="hw[CD0-9]*", NAME="snd/%k" -KERNEL="pcm[CD0-9cp]*", NAME="snd/%k" -KERNEL="midiC[D0-9]*", NAME="snd/%k" -KERNEL="timer", NAME="snd/%k" -KERNEL="seq", NAME="snd/%k" +KERNEL=="controlC[0-9]*", NAME="snd/%k" +KERNEL=="hw[CD0-9]*", NAME="snd/%k" +KERNEL=="pcm[CD0-9cp]*", NAME="snd/%k" +KERNEL=="midiC[D0-9]*", NAME="snd/%k" +KERNEL=="timer", NAME="snd/%k" +KERNEL=="seq", NAME="snd/%k" # input devices -KERNEL="mice", NAME="input/%k" -KERNEL="mouse*", NAME="input/%k" -KERNEL="event*", NAME="input/%k" -KERNEL="js*", NAME="input/%k" -KERNEL="ts*", NAME="input/%k" +KERNEL=="mice", NAME="input/%k" +KERNEL=="mouse*", NAME="input/%k" +KERNEL=="event*", NAME="input/%k" +KERNEL=="js*", NAME="input/%k" +KERNEL=="ts*", NAME="input/%k" # USB devices -KERNEL="hiddev*", NAME="usb/%k" -KERNEL="auer*", NAME="usb/%k" -KERNEL="legousbtower*", NAME="usb/%k" -KERNEL="dabusb*", NAME="usb/%k" -BUS="usb", KERNEL="lp[0-9]*", NAME="usb/%k" +KERNEL=="hiddev*", NAME="usb/%k" +KERNEL=="auer*", NAME="usb/%k" +KERNEL=="legousbtower*", NAME="usb/%k" +KERNEL=="dabusb*", NAME="usb/%k" +BUS=="usb", KERNEL=="lp[0-9]*", NAME="usb/%k" # CAPI devices -KERNEL="capi", NAME="capi20", SYMLINK="isdn/capi20" -KERNEL="capi*", NAME="capi/%n" +KERNEL=="capi", NAME="capi20", SYMLINK+="isdn/capi20" +KERNEL=="capi*", NAME="capi/%n" # Network devices -KERNEL="tun", NAME="net/%k" +KERNEL=="tun", NAME="net/%k" # raw devices -KERNEL="raw[0-9]*", NAME="raw/%k" +KERNEL=="raw[0-9]*", NAME="raw/%k" + +# emulate dev.d/ +RUN="/sbin/udev_run_devd" diff --git a/etc/udev/udev.rules.examples b/etc/udev/udev.rules.examples index a464b6ba..1c452789 100644 --- a/etc/udev/udev.rules.examples +++ b/etc/udev/udev.rules.examples @@ -9,64 +9,55 @@ # # Looking for scsi bus id 42:0:0:1 -BUS="scsi", PROGRAM="/bin/echo -n test-%b", RESULT="test-42:0:0:1", NAME="%c" +BUS=="scsi", PROGRAM="/bin/echo -n test-%b", RESULT=="test-42:0:0:1", NAME="%c" # A usb camera. -BUS="usb", SYSFS{vendor}="FUJIFILM", SYSFS{model}="M100", NAME="camera%n" +BUS=="usb", SYSFS{vendor}=="FUJIFILM", SYSFS{model}=="M100", NAME="camera%n" # USB Epson printer to be called lp_epson -BUS="usb", SYSFS_serial="HXOLL0012202323480", NAME="lp_epson" +BUS=="usb", SYSFS_serial=="HXOLL0012202323480", NAME="lp_epson" # USB HP printer to be called lp_hp -BUS="usb", SYSFS{serial}="W09090207101241330", NAME="lp_hp" +BUS=="usb", SYSFS{serial}=="W09090207101241330", NAME="lp_hp" # sound card with PCI bus id 00:0b.0 to be the first sound card -BUS="pci", ID="00:0b.0", NAME="dsp" +BUS=="pci", ID=="00:0b.0", NAME="dsp" # sound card with PCI bus id 00:07.1 to be the second sound card -BUS="pci", ID="00:07.1", NAME="dsp1" - -# USB mouse plugged into the third port of the first hub to be called mouse0 -BUS="usb", PLACE="1.3", NAME="mouse0" - -# USB tablet plugged into the third port of the second hub to be called mouse1 -BUS="usb", PLACE="2.3", NAME="mouse1" -BUS="usb", PLACE="2.4", NAME="mouse2" +BUS=="pci", ID=="00:07.1", NAME="dsp1" # ttyUSB1 should always be called visor -KERNEL="ttyUSB1", NAME="visor" -KERNEL="ttyUSB0", NAME="pl2303" +KERNEL=="ttyUSB1", NAME="visor" +KERNEL=="ttyUSB0", NAME="pl2303" # a devfs like way to name some tty devices -KERNEL="ttyS*", NAME="tts/%n" -KERNEL="tty*", NAME="vc/%n" +KERNEL=="ttyS*", NAME="tts/%n" +KERNEL=="tty*", NAME="vc/%n" # if this is a ide cdrom, name it the default name, and create a symlink to cdrom -BUS="ide", KERNEL="*[!0-9]", PROGRAM="/bin/cat /proc/ide/%k/media", RESULT="cdrom", NAME="%k", SYMLINK="cdrom" - -# create a symlink named after the device map name -# note devmap_name comes with extras/multipath -KERNEL="dm-[0-9]*", PROGRAM="/sbin/devmap_name %M %m", NAME="%k", SYMLINK="%c" +BUS=="ide", KERNEL=="*[!0-9]", PROGRAM="/bin/cat /proc/ide/%k/media", RESULT=="cdrom", NAME="%k", SYMLINK+="cdrom" # DRI devices always go into a subdirectory (as per the LSB spec) -KERNEL="card*", NAME="dri/card%n" +KERNEL=="card*", NAME="dri/card%n" # create all 15 partitions of a USB flash card reader -# note the trailing spaces in the attribute, use udevinfo(8) to examine your device -BUS="scsi", SYSFS{model}="CF/MD ", NAME{all_partitions}="compactflash" +BUS=="scsi", SYSFS{model}=="CF/MD", NAME{all_partitions}="compactflash" # alsa devices -KERNEL="controlC[0-9]*", NAME="snd/%k" -KERNEL="hw[CD0-9]*", NAME="snd/%k" -KERNEL="pcm[CD0-9cp]*", NAME="snd/%k" -KERNEL="midi[CD0-9]*", NAME="snd/%k" -KERNEL="timer", NAME="snd/%k" -KERNEL="seq", NAME="snd/%k" +KERNEL=="controlC[0-9]*", NAME="snd/%k" +KERNEL=="hw[CD0-9]*", NAME="snd/%k" +KERNEL=="pcm[CD0-9cp]*", NAME="snd/%k" +KERNEL=="midi[CD0-9]*", NAME="snd/%k" +KERNEL=="timer", NAME="snd/%k" +KERNEL=="seq", NAME="snd/%k" # input devices -KERNEL="mice", NAME="input/%k" -KERNEL="mouse*", NAME="input/%k" -KERNEL="event*", NAME="input/%k" -KERNEL="js*", NAME="input/%k" -KERNEL="ts*", NAME="input/%k" +KERNEL=="mice", NAME="input/%k" +KERNEL=="mouse*", NAME="input/%k" +KERNEL=="event*", NAME="input/%k" +KERNEL=="js*", NAME="input/%k" +KERNEL=="ts*", NAME="input/%k" + +# emulate dev.d/ +RUN="/sbin/udev_run_devd" diff --git a/extras/run_directory/Makefile b/extras/run_directory/Makefile new file mode 100644 index 00000000..12dccf07 --- /dev/null +++ b/extras/run_directory/Makefile @@ -0,0 +1,55 @@ +# Makefile for udev_volume_id +# +# Copyright (C) 2004 Kay Sievers +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# + +DEVD = udev_run_devd +HOTPLUGD = udev_run_hotplugd + +all: $(DEVD) $(HOTPLUGD) + +prefix = +exec_prefix = ${prefix} +etcdir = ${prefix}/etc +sbindir = ${exec_prefix}/sbin +usrbindir = ${exec_prefix}/usr/bin +usrsbindir = ${exec_prefix}/usr/sbin +mandir = ${prefix}/usr/share/man +devddir = ${etcdir}/dev.d/default +configdir = ${etcdir}/udev/ +initdir = ${etcdir}/init.d/ +srcdir = . + +INSTALL = /usr/bin/install -c +INSTALL_PROGRAM = ${INSTALL} +INSTALL_DATA = ${INSTALL} -m 644 +INSTALL_SCRIPT = ${INSTALL_PROGRAM} + +override CFLAGS+=-D_FILE_OFFSET_BITS=64 + +OBJS = ../../udev.a ../../libsysfs/sysfs.a + +.c.o: + $(QUIET) $(CC) $(CFLAGS) -c -o $@ $< + +$(DEVD): $(HEADERS) $(DEVD).o run_directory.o + $(QUIET) $(LD) $(LDFLAGS) -o $(DEVD) $(DEVD).o run_directory.o $(OBJS) + +$(HOTPLUGD): $(HEADERS) $(HOTPLUGD).o run_directory.o + $(QUIET) $(LD) $(LDFLAGS) -o $(HOTPLUGD) $(HOTPLUGD).o run_directory.o $(OBJS) + +clean: + rm -f $(DEVD) $(HOTPLUGD) run_directory.o + +spotless: clean + +install: all + $(INSTALL_PROGRAM) $(DEVD) $(DESTDIR)$(sbindir)/$(DEVD) + $(INSTALL_PROGRAM) $(HOTPLUGD) $(DESTDIR)$(sbindir)/$(HOTPLUGD) + +uninstall: + - rm $(DESTDIR)$(sbindir)/$(DEVD) diff --git a/extras/run_directory/run_directory.c b/extras/run_directory/run_directory.c new file mode 100644 index 00000000..e6c6173e --- /dev/null +++ b/extras/run_directory/run_directory.c @@ -0,0 +1,79 @@ +/* + * udev_run_directory.c - directory multiplexer + * + * Copyright (C) 2005 Kay Sievers + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2 of the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../udev_utils.h" +#include "../../list.h" +#include "../../logging.h" + +int run_directory(const char *dir, const char *suffix, const char *subsystem); + +static int run_program(const char *filename, const char *subsystem) +{ + pid_t pid; + + dbg("running %s", filename); + pid = fork(); + switch (pid) { + case 0: + /* child */ + execl(filename, filename, subsystem, NULL); + dbg("exec of child failed"); + _exit(1); + case -1: + dbg("fork of child failed"); + break; + return -1; + default: + waitpid(pid, NULL, 0); + } + + return 0; +} + +int run_directory(const char *dir, const char *suffix, const char *subsystem) +{ + char dirname[NAME_SIZE]; + struct name_entry *name_loop, *name_tmp; + LIST_HEAD(name_list); + + if (subsystem) { + snprintf(dirname, sizeof(dirname), "%s/%s", dir, subsystem); + dirname[sizeof(dirname)-1] = '\0'; + dbg("looking at '%s'", dirname); + add_matching_files(&name_list, dirname, suffix); + } + + snprintf(dirname, sizeof(dirname), "%s/default", dir); + dirname[sizeof(dirname)-1] = '\0'; + dbg("looking at '%s'", dirname); + add_matching_files(&name_list, dirname, suffix); + + list_for_each_entry_safe(name_loop, name_tmp, &name_list, node) { + run_program(name_loop->name, subsystem); + list_del(&name_loop->node); + } + + logging_close(); + return 0; +} diff --git a/extras/run_directory/udev_run_devd.c b/extras/run_directory/udev_run_devd.c new file mode 100644 index 00000000..02bbc8c3 --- /dev/null +++ b/extras/run_directory/udev_run_devd.c @@ -0,0 +1,78 @@ +/* + * udev_run_devd.c - directory multiplexer + * + * Copyright (C) 2005 Kay Sievers + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2 of the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../udev_utils.h" +#include "../../list.h" +#include "../../logging.h" + +extern int run_directory(const char *dir, const char *suffix, const char *subsystem); + +#ifdef USE_LOG +void log_message (int priority, const char *format, ...) +{ + va_list args; + static int udev_log = -1; + + if (udev_log == -1) { + const char *value; + + value = getenv("UDEV_LOG"); + if (value) + udev_log = log_priority(value); + else + udev_log = LOG_ERR; + } + + if (priority > udev_log) + return; + + va_start(args, format); + vsyslog(priority, format, args); + va_end(args); +} +#endif + +int main(int argc, char *argv[], char *envp[]) +{ + const char *subsystem; + int fd; + + if (getenv("DEVNAME") == NULL) + exit(0); + + subsystem = argv[1]; + logging_init("udev_run_devd"); + + fd = open("/dev/null", O_RDWR); + if (fd >= 0) { + dup2(fd, STDOUT_FILENO); + dup2(fd, STDIN_FILENO); + dup2(fd, STDERR_FILENO); + close(fd); + } + dbg("running dev.d directory"); + + run_directory("/etc/dev.d", ".dev", subsystem); + exit(0); +} diff --git a/extras/run_directory/udev_run_hotplugd.c b/extras/run_directory/udev_run_hotplugd.c new file mode 100644 index 00000000..463473d7 --- /dev/null +++ b/extras/run_directory/udev_run_hotplugd.c @@ -0,0 +1,79 @@ +/* + * udev_run_hotplugd.c - directory multiplexer + * + * Copyright (C) 2005 Kay Sievers + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation version 2 of the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../udev_utils.h" +#include "../../list.h" +#include "../../logging.h" + +extern int run_directory(const char *dir, const char *suffix, const char *subsystem); + +#ifdef USE_LOG +void log_message (int priority, const char *format, ...) +{ + va_list args; + static int udev_log = -1; + + if (udev_log == -1) { + const char *value; + + value = getenv("UDEV_LOG"); + if (value) + udev_log = log_priority(value); + else + udev_log = LOG_ERR; + } + + if (priority > udev_log) + return; + + va_start(args, format); + vsyslog(priority, format, args); + va_end(args); +} +#endif + +int main(int argc, char *argv[], char *envp[]) +{ + const char *subsystem; + int fd; + + if (getenv("DEVNAME") == NULL) + exit(0); + + subsystem = argv[1]; + logging_init("udev_run_hotplugd"); + + fd = open("/dev/null", O_RDWR); + if (fd >= 0) { + dup2(fd, STDOUT_FILENO); + dup2(fd, STDIN_FILENO); + dup2(fd, STDERR_FILENO); + close(fd); + } + + dbg("running dev.d directory"); + + run_directory("/etc/hotplug.d", ".hotplug", subsystem); + exit(0); +} diff --git a/test/simple-build-check.sh b/test/simple-build-check.sh index d1e13e69..b653185b 100644 --- a/test/simple-build-check.sh +++ b/test/simple-build-check.sh @@ -1,6 +1,6 @@ #/bin/sh -EXTRAS="extras/chassis_id extras/scsi_id extras/volume_id" +EXTRAS="extras/chassis_id extras/scsi_id extras/volume_id extras/run_directory" [ -z "$KERNEL_DIR" ] && KERNEL_DIR=/lib/modules/`uname -r`/build echo KERNEL_DIR: "$KERNEL_DIR" diff --git a/udev.c b/udev.c index 2be4c357..999d25d4 100644 --- a/udev.c +++ b/udev.c @@ -219,10 +219,6 @@ int main(int argc, char *argv[], char *envp[]) execute_command(name_loop->name, udev.subsystem); } - /* run dev.d/ scripts if we created/deleted a node or changed a netif name */ - if (udev_dev_d && udev.devname[0] != '\0') - udev_multiplex_directory(&udev, DEVD_DIR, DEVD_SUFFIX); - } else if (udev.type == DEV_DEVICE) { if (strcmp(action, "add") == 0) { /* wait for sysfs */ diff --git a/udev.h b/udev.h index c6f26b3b..2c3377ad 100644 --- a/udev.h +++ b/udev.h @@ -102,7 +102,6 @@ extern char udev_config_filename[PATH_SIZE]; extern char udev_rules_filename[PATH_SIZE]; extern int udev_log_priority; extern int udev_run; -extern int udev_dev_d; extern int udev_hotplug_d; #endif diff --git a/udev_config.c b/udev_config.c index 6bc070d6..0701d37e 100644 --- a/udev_config.c +++ b/udev_config.c @@ -45,40 +45,8 @@ char udev_config_filename[PATH_SIZE]; char udev_rules_filename[PATH_SIZE]; int udev_log_priority; int udev_run; -int udev_dev_d; int udev_hotplug_d; -static int string_is_true(const char *str) -{ - if (strcasecmp(str, "true") == 0) - return 1; - if (strcasecmp(str, "yes") == 0) - return 1; - if (strcasecmp(str, "1") == 0) - return 1; - return 0; -} - -static int log_priority(const char *priority) -{ - char *endptr; - int prio; - - prio = strtol(priority, &endptr, 10); - if (endptr[0] == '\0') - return prio; - if (strncasecmp(priority, "err", 3) == 0) - return LOG_ERR; - if (strcasecmp(priority, "info") == 0) - return LOG_INFO; - if (strcasecmp(priority, "debug") == 0) - return LOG_DEBUG; - if (string_is_true(priority)) - return LOG_ERR; - - return 0; -} - static int get_key(char **line, char **key, char **value) { char *linepos; @@ -219,7 +187,6 @@ void udev_init_config(void) strcpy(udev_rules_filename, UDEV_RULES_FILE); udev_log_priority = LOG_ERR; udev_run = 1; - udev_dev_d = 1; udev_hotplug_d = 1; sysfs_get_mnt_path(sysfs_path, sizeof(sysfs_path)); @@ -228,10 +195,6 @@ void udev_init_config(void) if (env && !string_is_true(env)) udev_run = 0; - env = getenv("UDEV_NO_DEVD"); - if (env && string_is_true(env)) - udev_dev_d = 0; - env = getenv("UDEV_NO_HOTPLUGD"); if (env && string_is_true(env)) udev_hotplug_d = 0; diff --git a/udev_utils.c b/udev_utils.c index 74b55ed4..70b20e3a 100644 --- a/udev_utils.c +++ b/udev_utils.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -109,6 +110,37 @@ void udev_cleanup_device(struct udevice *udev) } } +int string_is_true(const char *str) +{ + if (strcasecmp(str, "true") == 0) + return 1; + if (strcasecmp(str, "yes") == 0) + return 1; + if (strcasecmp(str, "1") == 0) + return 1; + return 0; +} + +int log_priority(const char *priority) +{ + char *endptr; + int prio; + + prio = strtol(priority, &endptr, 10); + if (endptr[0] == '\0') + return prio; + if (strncasecmp(priority, "err", 3) == 0) + return LOG_ERR; + if (strcasecmp(priority, "info") == 0) + return LOG_INFO; + if (strcasecmp(priority, "debug") == 0) + return LOG_DEBUG; + if (string_is_true(priority)) + return LOG_ERR; + + return 0; +} + int kernel_release_satisfactory(unsigned int version, unsigned int patchlevel, unsigned int sublevel) { static unsigned int kversion = 0; diff --git a/udev_utils.h b/udev_utils.h index 9cdae6db..b3e604fb 100644 --- a/udev_utils.h +++ b/udev_utils.h @@ -34,6 +34,8 @@ extern void udev_cleanup_device(struct udevice *udev); extern int kernel_release_satisfactory(unsigned int version, unsigned int patchlevel, unsigned int sublevel); extern int create_path(const char *path); +extern int log_priority(const char *priority); +extern int string_is_true(const char *str); extern int parse_get_pair(char **orig_string, char **left, char **right); extern int unlink_secure(const char *filename); extern int file_map(const char *filename, char **buf, size_t *bufsize); diff --git a/udevstart.c b/udevstart.c index 60e63c5a..34f3835d 100644 --- a/udevstart.c +++ b/udevstart.c @@ -137,10 +137,6 @@ static int add_device(const char *path, const char *subsystem) execute_command(name_loop->name, udev.subsystem); } - /* run dev.d/ scripts if we created a node or changed a netif name */ - if (udev_dev_d && udev.devname[0] != '\0') - udev_multiplex_directory(&udev, DEVD_DIR, DEVD_SUFFIX); - sysfs_close_class_device(class_dev); udev_cleanup_device(&udev); -- 2.39.5