]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
udev: handle all events - not only class and block devices
authorKay Sievers <kay.sievers@suse.de>
Sun, 5 Jun 2005 13:55:29 +0000 (15:55 +0200)
committerKay Sievers <kay.sievers@suse.de>
Sun, 5 Jun 2005 13:55:29 +0000 (15:55 +0200)
Handle all events with rules. If udev is expected to handle hotplug.d/
the exernal helper must be called.

Signed-off-by: Kay Sievers <kay.sievers@suse.de>
14 files changed:
Makefile
extras/run_directory/udev_run_hotplugd.c
udev.8.in
udev.c
udev.h
udev.spec
udev_add.c
udev_config.c
udev_multiplex.c [deleted file]
udev_remove.c
udev_rules.c
udev_rules.h
udev_rules_parse.c
udevstart.c

index 1cf3e54fb725afde4f4a3d385c3758cc28a992d1..d36bd5866c6250d75aca6d85a50ee0a2ce4882f8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -143,7 +143,6 @@ UDEV_OBJS = \
        udev_remove.o           \
        udev_sysfs.o            \
        udev_db.o               \
-       udev_multiplex.o        \
        udev_rules.o            \
        udev_rules_parse.o      \
        udev_libc_wrapper.o
@@ -382,6 +381,7 @@ install: install-config install-man install-dev.d all
        - ln -f -s $(sbindir)/$(SENDER) $(DESTDIR)$(hotplugdir)/10-udev.hotplug
 ifndef DESTDIR
        - killall $(DAEMON)
+       - $(sbindir)/$(DAEMON) -d
        - rm -rf $(udevdb)
 endif
        @extras="$(EXTRAS)" ; for target in $$extras ; do \
index 463473d7c726a762cf9229e338983fc72c5322a3..54b6bf44e30458835c0d985b5a082d5f401b67ea 100644 (file)
@@ -58,9 +58,6 @@ 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");
 
index 79c4a83d160917828591716c772ff3b1217edb59..e4c1c11af2e396c96851e9d31e1132a6bdd4cc81 100644 (file)
--- a/udev.8.in
+++ b/udev.8.in
@@ -306,11 +306,9 @@ following the '[' is a '!', any characters not enclosed are matched.
 .P
 After device node creation, removal, or network device renaming,
 .B udev
-executes the programs located in the directory tree under
-.IR /etc/dev.d/ .
-The name of a program must have the suffix
-.I .dev
-to be recognized.
+executes the programs specified by the
+.B RUN
+key.
 .br
 In addition to the kernel provided hotplug environment variables,
 .B UDEV_LOG
@@ -319,15 +317,7 @@ is set and contains the numerical priority value, if udev is configured to use
 Executed programs may want to follow that setting.
 .B DEVNAME
 is exported to make the name of the created node, or the name the network
-device is renamed to, available to the executed program. The programs in every
-directory are sorted in lexical order, while the directories are searched in
-the following order:
-.sp
-.nf
-/etc/dev.d/$(DEVNAME)/*.dev
-/etc/dev.d/$(SUBSYSTEM)/*.dev
-/etc/dev.d/default/*.dev
-.fi
+device is renamed to, available to the executed programs.
 .SH "ENVIRONMENT"
 .P
 The following variables are read from the environment:
@@ -353,20 +343,10 @@ Overrides the log priority specified in the config file.
 .TP
 .B UDEV_RUN
 If set to "0", it disables the execution of programs added by rules.
-.TP
-.B UDEV_NO_DEVD
-The default behavior of
-.B udev
-is to execute programs in the
-.I /etc/dev.d/
-directory after device handling. If set,
-.B udev
-will skip this step.
 .SH "FILES"
 .nf
 /sbin/udev                           udev program
 /etc/udev/*                          udev config files
-/etc/dev.d/*                         programs invoked by udev
 .fi
 .SH "SEE ALSO"
 .BR udevinfo (8),
diff --git a/udev.c b/udev.c
index 3f76e98b2413e996ebcef1b02ad723e7d1a11b48..d623cbcc675f7988d44da2f320b71940d953b7e3 100644 (file)
--- 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();
diff --git a/udev.h b/udev.h
index 2c3377ad2e716fae1a923d3d6e254e70c18e3195..11fbe024606f24e9cafd4b2f56fe500208139f6d 100644 (file)
--- a/udev.h
+++ b/udev.h
 #define SEQNUM_SIZE                    32
 #define VALUE_SIZE                     128
 
-#define DEVD_DIR                       "/etc/dev.d"
-#define DEVD_SUFFIX                    ".dev"
-
-#define HOTPLUGD_DIR                   "/etc/hotplug.d"
-#define HOTPLUG_SUFFIX                 ".hotplug"
-
 #define DEFAULT_PARTITIONS_COUNT       15
 
 enum device_type {
@@ -62,6 +56,7 @@ struct udevice {
 
        enum device_type type;
        char name[PATH_SIZE];
+       int name_set;
        char devname[PATH_SIZE];
        struct list_head symlink_list;
        int symlink_final;
@@ -92,7 +87,6 @@ extern int udev_add_device(struct udevice *udev, struct sysfs_class_device *clas
 extern int udev_remove_device(struct udevice *udev);
 extern void udev_init_config(void);
 extern int udev_start(void);
-extern void udev_multiplex_directory(struct udevice *udev, const char *basedir, const char *suffix);
 extern int udev_make_node(struct udevice *udev, const char *file, dev_t devt, mode_t mode, uid_t uid, gid_t gid);
 
 extern char sysfs_path[PATH_SIZE];
@@ -102,6 +96,5 @@ 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_hotplug_d;
 
 #endif
index 28f19565da5a4b9362611c581f0f018004ba6d9c..0430a1259d8d0efd760a999aa23d7c31960fcf55 100644 (file)
--- a/udev.spec
+++ b/udev.spec
@@ -112,9 +112,6 @@ rm -rf $RPM_BUILD_ROOT
 %attr(-,root,root) /etc/hotplug.d/default/udev.hotplug
 %attr(755,root,root) /etc/init.d/udev
 %attr(0644,root,root) %{_mandir}/man8/udev*.8*
-%attr(755,root,root) %dir /etc/dev.d/
-%attr(755,root,root) %dir /etc/dev.d/net/
-%attr(0755,root,root) /etc/dev.d/net/hotplug.dev
 
 %if %{scsi_id}
        %attr(755,root,root) /sbin/scsi_id
index 9764cb9bcd6c07aabbe625ca07d8b6ebddde0d78..2081e503c7d33d8eb5f0cee4cbd0f09684665ef3 100644 (file)
@@ -268,22 +268,7 @@ int udev_add_device(struct udevice *udev, struct sysfs_class_device *class_dev)
        char *pos;
        int retval = 0;
 
-       if (udev->type == DEV_BLOCK || udev->type == DEV_CLASS) {
-               udev->devt = get_devt(class_dev);
-               if (!udev->devt) {
-                       dbg("no dev-file found, do nothing");
-                       return 0;
-               }
-       }
-
-       udev_rules_get_name(udev, class_dev);
-       if (udev->ignore_device) {
-               dbg("device event will be ignored");
-               return 0;
-       }
-
        dbg("adding name='%s'", udev->name);
-
        selinux_init();
 
        if (udev->type == DEV_BLOCK || udev->type == DEV_CLASS) {
@@ -325,6 +310,5 @@ int udev_add_device(struct udevice *udev, struct sysfs_class_device *class_dev)
 
 exit:
        selinux_exit();
-
        return retval;
 }
index 0701d37e845d0466b8e639788a0e0f50dcb964f8..773ee67f9e1a48abff33430ec7cc8ea95a65063f 100644 (file)
@@ -45,7 +45,6 @@ char udev_config_filename[PATH_SIZE];
 char udev_rules_filename[PATH_SIZE];
 int udev_log_priority;
 int udev_run;
-int udev_hotplug_d;
 
 static int get_key(char **line, char **key, char **value)
 {
@@ -187,7 +186,6 @@ void udev_init_config(void)
        strcpy(udev_rules_filename, UDEV_RULES_FILE);
        udev_log_priority = LOG_ERR;
        udev_run = 1;
-       udev_hotplug_d = 1;
        sysfs_get_mnt_path(sysfs_path, sizeof(sysfs_path));
 
        /* disable RUN key execution */
@@ -195,10 +193,6 @@ void udev_init_config(void)
        if (env && !string_is_true(env))
                udev_run = 0;
 
-       env = getenv("UDEV_NO_HOTPLUGD");
-       if (env && string_is_true(env))
-               udev_hotplug_d = 0;
-
        env = getenv("UDEV_CONFIG_FILE");
        if (env) {
                strlcpy(udev_config_filename, env, sizeof(udev_config_filename));
diff --git a/udev_multiplex.c b/udev_multiplex.c
deleted file mode 100644 (file)
index 22bbaf7..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * udev_multiplex.c directory multiplexer
- * 
- * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
- *
- *     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.
- */
-
-/*
- * This essentially emulates the following shell script logic in C:
- *     DIR="/etc/dev.d"
- *     export DEVNAME="whatever_dev_name_udev_just_gave"
- *     for I in "${DIR}/$DEVNAME/"*.dev "${DIR}/$1/"*.dev "${DIR}/default/"*.dev ; do
- *             if [ -f $I ]; then $I $1 ; fi
- *     done
- *     exit 1;
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "udev.h"
-#include "udev_libc_wrapper.h"
-#include "udev_utils.h"
-#include "logging.h"
-
-
-/* 
- * runs files in these directories in order:
- *     <node name given by udev>/
- *     subsystem/
- *     default/
- */
-void udev_multiplex_directory(struct udevice *udev, const char *basedir, const char *suffix)
-{
-       char dirname[PATH_SIZE];
-       struct name_entry *name_loop, *name_tmp;
-       LIST_HEAD(name_list);
-
-       /* chop the device name up into pieces based on '/' */
-       if (udev->name[0] != '\0') {
-               char devname[PATH_SIZE];
-               char *temp;
-
-               strlcpy(devname, udev->name, sizeof(devname));
-               temp = strchr(devname, '/');
-               while (temp != NULL) {
-                       temp[0] = '\0';
-
-                       /* don't call the subsystem directory here */
-                       if (strcmp(devname, udev->subsystem) != 0) {
-                               snprintf(dirname, sizeof(dirname), "%s/%s", basedir, devname);
-                               dirname[sizeof(dirname)-1] = '\0';
-                               add_matching_files(&name_list, dirname, suffix);
-                       }
-
-                       temp[0] = '/';
-                       ++temp;
-                       temp = strchr(temp, '/');
-               }
-       }
-
-       if (udev->name[0] != '\0') {
-               snprintf(dirname, sizeof(dirname), "%s/%s", basedir, udev->name);
-               dirname[sizeof(dirname)-1] = '\0';
-               add_matching_files(&name_list, dirname, suffix);
-       }
-
-       if (udev->subsystem[0] != '\0') {
-               snprintf(dirname, sizeof(dirname), "%s/%s", basedir, udev->subsystem);
-               dirname[sizeof(dirname)-1] = '\0';
-               add_matching_files(&name_list, dirname, suffix);
-       }
-
-       snprintf(dirname, sizeof(dirname), "%s/default", basedir);
-       dirname[sizeof(dirname)-1] = '\0';
-       add_matching_files(&name_list, dirname, suffix);
-
-       list_for_each_entry_safe(name_loop, name_tmp, &name_list, node) {
-               execute_command(name_loop->name, udev->subsystem);
-               list_del(&name_loop->node);
-       }
-
-}
index 2df555327bbeef9a7dd6270e98b7a1201b651424..cf28ff37a9bfb56044e9feb625af239ef2f74582 100644 (file)
@@ -140,26 +140,20 @@ static int delete_node(struct udevice *udev)
  */
 int udev_remove_device(struct udevice *udev)
 {
-       const char *temp;
-
        if (udev->type != DEV_BLOCK && udev->type != DEV_CLASS)
                return 0;
 
-       if (udev_db_get_device(udev, udev->devpath) == 0) {
-               if (udev->ignore_remove) {
-                       dbg("remove event for '%s' requested to be ignored by rule", udev->name);
-                       return 0;
-               }
-               dbg("remove name='%s'", udev->name);
-               udev_db_delete_device(udev);
-       } else {
-               /* fall back to kernel name */
-               temp = strrchr(udev->devpath, '/');
-               if (temp == NULL)
-                       return -ENODEV;
-               strlcpy(udev->name, &temp[1], sizeof(udev->name));
-               info("'%s' not found in database, falling back on default name", udev->name);
+       /* remove node only if we can find it in our database */
+       if (udev_db_get_device(udev, udev->devpath) != 0) {
+               dbg("'%s' not found in database, ignore event", udev->name);
+               return -1;
+       }
+       if (udev->ignore_remove) {
+               dbg("remove event for '%s' requested to be ignored by rule", udev->name);
+               return 0;
        }
+       dbg("remove name='%s'", udev->name);
+       udev_db_delete_device(udev);
 
        /* use full path to the environment */
        snprintf(udev->devname, sizeof(udev->devname), "%s/%s", udev_root, udev->name);
index 631cc4270ab019c7fa490258d76475f7b640c85a..cbd76e66ebe84f3f4f31a82fdffa3de0c1e69973 100644 (file)
@@ -731,7 +731,7 @@ int udev_rules_get_name(struct udevice *udev, struct sysfs_class_device *class_d
        list_for_each_entry(rule, &udev_rule_list, node) {
                dbg("process rule");
                if (match_rule(udev, rule, class_dev, sysfs_device) == 0) {
-                       if (udev->name[0] != '\0' && rule->name[0] != '\0') {
+                       if (udev->name_set && rule->name_operation != KEY_OP_UNSET) {
                                dbg("node name already set, rule ignored");
                                continue;
                        }
@@ -776,73 +776,84 @@ int udev_rules_get_name(struct udevice *udev, struct sysfs_class_device *class_d
                        }
 
                        /* collect symlinks */
-                       if (!udev->symlink_final && rule->symlink[0] != '\0') {
+                       if (!udev->symlink_final && rule->symlink_operation != KEY_OP_UNSET) {
                                char temp[PATH_SIZE];
                                char *pos, *next;
 
                                if (rule->symlink_operation == KEY_OP_ASSIGN_FINAL)
                                        udev->symlink_final = 1;
-                               else if (rule->symlink_operation == KEY_OP_ASSIGN) {
+                               if (rule->symlink_operation == KEY_OP_ASSIGN || rule->symlink_operation == KEY_OP_ASSIGN_FINAL) {
                                        struct name_entry *name_loop;
                                        struct name_entry *temp_loop;
 
+                                       info("reset symlink list");
                                        list_for_each_entry_safe(name_loop, temp_loop, &udev->symlink_list, node) {
                                                list_del(&name_loop->node);
                                                free(name_loop);
                                        }
                                }
-                               info("configured rule in '%s[%i]' applied, added symlink '%s'",
-                                    rule->config_file, rule->config_line, rule->symlink);
-                               strlcpy(temp, rule->symlink, sizeof(temp));
-                               apply_format(udev, temp, sizeof(temp), class_dev, sysfs_device);
-
-                               /* add multiple symlinks separated by spaces */
-                               pos = temp;
-                               next = strchr(temp, ' ');
-                               while (next) {
-                                       next[0] = '\0';
+                               if (rule->symlink[0] != '\0') {
+                                       info("configured rule in '%s[%i]' applied, added symlink '%s'",
+                                            rule->config_file, rule->config_line, rule->symlink);
+                                       strlcpy(temp, rule->symlink, sizeof(temp));
+                                       apply_format(udev, temp, sizeof(temp), class_dev, sysfs_device);
+
+                                       /* add multiple symlinks separated by spaces */
+                                       pos = temp;
+                                       next = strchr(temp, ' ');
+                                       while (next) {
+                                               next[0] = '\0';
+                                               info("add symlink '%s'", pos);
+                                               name_list_add(&udev->symlink_list, pos, 0);
+                                               pos = &next[1];
+                                               next = strchr(pos, ' ');
+                                       }
                                        info("add symlink '%s'", pos);
                                        name_list_add(&udev->symlink_list, pos, 0);
-                                       pos = &next[1];
-                                       next = strchr(pos, ' ');
                                }
-                               info("add symlink '%s'", pos);
-                               name_list_add(&udev->symlink_list, pos, 0);
                        }
 
                        /* set name, later rules with name set will be ignored */
-                       if (rule->name[0] != '\0') {
-                               info("configured rule in '%s[%i]' applied, '%s' becomes '%s'",
-                                    rule->config_file, rule->config_line, udev->kernel_name, rule->name);
-
-                               strlcpy(udev->name, rule->name, sizeof(udev->name));
-                               apply_format(udev, udev->name, sizeof(udev->name), class_dev, sysfs_device);
-                               strlcpy(udev->config_file, rule->config_file, sizeof(udev->config_file));
-                               udev->config_line = rule->config_line;
-
-                               if (udev->type != DEV_NET)
-                                       dbg("name, '%s' is going to have owner='%s', group='%s', mode=%#o partitions=%i",
-                                           udev->name, udev->owner, udev->group, udev->mode, udev->partitions);
+                       if (rule->name_operation != KEY_OP_UNSET) {
+                               udev->name_set = 1;
+                               if (rule->name[0] == '\0') {
+                                       info("configured rule in '%s[%i]' applied, node handling for '%s' supressed",
+                                            rule->config_file, rule->config_line, udev->kernel_name);
+                               } else {
+                                       strlcpy(udev->name, rule->name, sizeof(udev->name));
+                                       apply_format(udev, udev->name, sizeof(udev->name), class_dev, sysfs_device);
+                                       strlcpy(udev->config_file, rule->config_file, sizeof(udev->config_file));
+                                       udev->config_line = rule->config_line;
+
+                                       info("configured rule in '%s:%i' applied, '%s' becomes '%s'",
+                                            rule->config_file, rule->config_line, udev->kernel_name, rule->name);
+                                       if (udev->type != DEV_NET)
+                                               dbg("name, '%s' is going to have owner='%s', group='%s', mode=%#o partitions=%i",
+                                                   udev->name, udev->owner, udev->group, udev->mode, udev->partitions);
+                               }
                        }
 
-                       if (!udev->run_final && rule->run[0] != '\0') {
+                       if (!udev->run_final && rule->run_operation != KEY_OP_UNSET) {
                                char program[PATH_SIZE];
 
                                if (rule->run_operation == KEY_OP_ASSIGN_FINAL)
                                        udev->run_final = 1;
-                               else if (rule->run_operation == KEY_OP_ASSIGN) {
+                               if (rule->run_operation == KEY_OP_ASSIGN || rule->run_operation == KEY_OP_ASSIGN_FINAL) {
                                        struct name_entry *name_loop;
                                        struct name_entry *temp_loop;
 
+                                       info("reset run list");
                                        list_for_each_entry_safe(name_loop, temp_loop, &udev->run_list, node) {
                                                list_del(&name_loop->node);
                                                free(name_loop);
                                        }
                                }
-                               strlcpy(program, rule->run, sizeof(program));
-                               apply_format(udev, program, sizeof(program), class_dev, sysfs_device);
-                               dbg("add run '%s'", program);
-                               name_list_add(&udev->run_list, program, 0);
+                               if (rule->run[0] != '\0') {
+                                       strlcpy(program, rule->run, sizeof(program));
+                                       apply_format(udev, program, sizeof(program), class_dev, sysfs_device);
+                                       dbg("add run '%s'", program);
+                                       name_list_add(&udev->run_list, program, 0);
+                               }
                        }
 
                        if (rule->last_rule) {
@@ -866,113 +877,58 @@ int udev_rules_get_name(struct udevice *udev, struct sysfs_class_device *class_d
        return 0;
 }
 
-int udev_rules_get_run(struct udevice *udev)
+int udev_rules_get_run(struct udevice *udev, struct sysfs_device *sysfs_device)
 {
        struct udev_rule *rule;
-       char program[PATH_SIZE];
 
        /* look for a matching rule to apply */
        list_for_each_entry(rule, &udev_rule_list, node) {
                dbg("process rule");
 
-               if (rule->run[0] == '\0')
+               if (rule->run_operation == KEY_OP_UNSET)
                        continue;
 
-               if (rule->name[0] != '\0' || rule->symlink[0] != '\0' ||
+               if (rule->name_operation != KEY_OP_UNSET || rule->symlink_operation != KEY_OP_UNSET ||
                    rule->mode != 0000 || rule->owner[0] != '\0' || rule->group[0] != '\0') {
                        dbg("skip rule that names a device");
                        continue;
                }
 
-               if (rule->action_operation != KEY_OP_UNSET) {
-                       dbg("check for " KEY_ACTION " rule->action='%s' udev->action='%s'",
-                           rule->action, udev->action);
-                       if (strcmp_pattern(rule->action, udev->action) != 0) {
-                               dbg(KEY_ACTION " is not matching");
-                               if (rule->action_operation != KEY_OP_NOMATCH)
-                                       continue;
-                       } else {
-                               dbg(KEY_ACTION " matches");
-                               if (rule->action_operation == KEY_OP_NOMATCH)
-                                       continue;
-                       }
-                       dbg(KEY_ACTION " key is true");
-               }
-
-               if (rule->kernel_operation != KEY_OP_UNSET) {
-                       dbg("check for " KEY_KERNEL " rule->kernel='%s' udev->kernel_name='%s'",
-                           rule->kernel, udev->kernel_name);
-                       if (strcmp_pattern(rule->kernel, udev->kernel_name) != 0) {
-                               dbg(KEY_KERNEL " is not matching");
-                               if (rule->kernel_operation != KEY_OP_NOMATCH)
-                                       continue;
-               } else {
-                               dbg(KEY_KERNEL " matches");
-                               if (rule->kernel_operation == KEY_OP_NOMATCH)
-                                       continue;
-                       }
-                       dbg(KEY_KERNEL " key is true");
-               }
-
-               if (rule->subsystem_operation != KEY_OP_UNSET) {
-                       dbg("check for " KEY_SUBSYSTEM " rule->subsystem='%s' udev->subsystem='%s'",
-                           rule->subsystem, udev->subsystem);
-                       if (strcmp_pattern(rule->subsystem, udev->subsystem) != 0) {
-                               dbg(KEY_SUBSYSTEM " is not matching");
-                               if (rule->subsystem_operation != KEY_OP_NOMATCH)
-                                       continue;
-                       } else {
-                               dbg(KEY_SUBSYSTEM " matches");
-                               if (rule->subsystem_operation == KEY_OP_NOMATCH)
-                                       continue;
+               if (match_rule(udev, rule, NULL, sysfs_device) == 0) {
+                       if (rule->ignore_device) {
+                               info("configured rule in '%s[%i]' applied, '%s' is ignored",
+                                    rule->config_file, rule->config_line, udev->kernel_name);
+                               udev->ignore_device = 1;
+                               return 0;
                        }
-                       dbg(KEY_SUBSYSTEM " key is true");
-               }
 
-               if (rule->env_pair_count) {
-                       int i;
+                       if (!udev->run_final && rule->run_operation != KEY_OP_UNSET) {
+                               char program[PATH_SIZE];
 
-                       dbg("check for " KEY_ENV " pairs");
-                       for (i = 0; i < rule->env_pair_count; i++) {
-                               struct key_pair *pair;
-                               const char *value;
+                               if (rule->run_operation == KEY_OP_ASSIGN || rule->run_operation == KEY_OP_ASSIGN_FINAL) {
+                                       struct name_entry *name_loop;
+                                       struct name_entry *temp_loop;
 
-                               pair = &rule->env_pair[i];
-                               value = getenv(pair->name);
-                               if (!value) {
-                                       dbg(KEY_ENV "{'%s'} is not found", pair->name);
-                                       continue;
+                                       info("reset run list");
+                                       list_for_each_entry_safe(name_loop, temp_loop, &udev->run_list, node) {
+                                               list_del(&name_loop->node);
+                                               free(name_loop);
+                                       }
                                }
-                               if (strcmp_pattern(pair->value, value) != 0) {
-                                       dbg(KEY_ENV "{'%s'} is not matching", pair->name);
-                                       if (pair->operation != KEY_OP_NOMATCH)
-                                               continue;
-                               } else {
-                                       dbg(KEY_ENV "{'%s'} matches", pair->name);
-                                       if (pair->operation == KEY_OP_NOMATCH)
-                                               continue;
+                               if (rule->run[0] != '\0') {
+                                       strlcpy(program, rule->run, sizeof(program));
+                                       apply_format(udev, program, sizeof(program), NULL, NULL);
+                                       dbg("add run '%s'", program);
+                                       name_list_add(&udev->run_list, program, 0);
                                }
+                               if (rule->run_operation == KEY_OP_ASSIGN_FINAL)
+                                       break;
                        }
-                       dbg(KEY_ENV " key is true");
-               }
-
-               /* rule matches */
-
-               if (rule->ignore_device) {
-                       info("configured rule in '%s[%i]' applied, '%s' is ignored",
-                            rule->config_file, rule->config_line, udev->kernel_name);
-                       udev->ignore_device = 1;
-                       return 0;
-               }
-
-               strlcpy(program, rule->run, sizeof(program));
-               apply_format(udev, program, sizeof(program), NULL, NULL);
-               dbg("add run '%s'", program);
-               name_list_add(&udev->run_list, program, 0);
 
-               if (rule->last_rule) {
-                       dbg("last rule to be applied");
-                       break;
+                       if (rule->last_rule) {
+                               dbg("last rule to be applied");
+                               break;
+                       }
                }
        }
 
index f4a74bba4564e2b06b4bfe668293c00c57e4da67..75ffd5cb0f47b13ccb325910b7b979f896400384 100644 (file)
@@ -96,6 +96,7 @@ struct udev_rule {
        int env_pair_count;
 
        char name[PATH_SIZE];
+       enum key_operation name_operation;
        char symlink[PATH_SIZE];
        enum key_operation symlink_operation;
        char owner[USER_SIZE];
@@ -120,7 +121,7 @@ extern struct list_head udev_rule_list;
 
 extern int udev_rules_init(void);
 extern int udev_rules_get_name(struct udevice *udev, struct sysfs_class_device *class_dev);
-extern int udev_rules_get_run(struct udevice *udev);
+extern int udev_rules_get_run(struct udevice *udev, struct sysfs_device *sysfs_device);
 extern void udev_rules_close(void);
 
 #endif
index 3f07521ccb81210994cb93a0117d1cb234317cd5..57c797dd31bfb34f351fee53b892dc68f751c4a0 100644 (file)
@@ -349,21 +349,19 @@ static int rules_parse(const char *filename)
 
                        if (strncasecmp(key, KEY_NAME, sizeof(KEY_NAME)-1) == 0) {
                                attr = get_key_attribute(key + sizeof(KEY_NAME)-1);
-                               /* FIXME: remove old style options and make OPTIONS= mandatory */
                                if (attr != NULL) {
                                        if (strstr(attr, OPTION_PARTITIONS) != NULL) {
                                                dbg("creation of partition nodes requested");
                                                rule.partitions = DEFAULT_PARTITIONS_COUNT;
                                        }
+                                       /* FIXME: remove old style option and make OPTIONS= mandatory */
                                        if (strstr(attr, OPTION_IGNORE_REMOVE) != NULL) {
                                                dbg("remove event should be ignored");
                                                rule.ignore_remove = 1;
                                        }
                                }
-                               if (value[0] != '\0')
-                                       strlcpy(rule.name, value, sizeof(rule.name));
-                               else
-                                       rule.ignore_device = 1;
+                               rule.name_operation = operation;
+                               strlcpy(rule.name, value, sizeof(rule.name));
                                valid = 1;
                                continue;
                        }
index 34f3835d65f3e0026805489736240b1afb3c6769..d1a0a8379c772669902a47d299ca498123dfde54 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "libsysfs/sysfs/libsysfs.h"
 #include "udev_libc_wrapper.h"
+#include "udev_sysfs.h"
 #include "udev.h"
 #include "udev_version.h"
 #include "logging.h"
@@ -110,25 +111,37 @@ static int add_device(const char *path, const char *subsystem)
        const char *devpath;
 
        devpath = &path[strlen(sysfs_path)];
-
-       /* set environment for callouts and dev.d/ */
        setenv("DEVPATH", devpath, 1);
        setenv("SUBSYSTEM", subsystem, 1);
-
        dbg("exec: '%s' (%s)\n", devpath, path);
 
        class_dev = sysfs_open_class_device_path(path);
        if (class_dev == NULL) {
                dbg ("sysfs_open_class_device_path failed");
-               return -ENODEV;
+               return -1;
        }
 
        udev_init_device(&udev, devpath, subsystem, "add");
-       udev_add_device(&udev, class_dev);
+       udev.devt = get_devt(class_dev);
+       if (!udev.devt) {
+               dbg ("sysfs_open_class_device_path failed");
+               return -1;
+       }
+       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;
+       }
 
+       udev_add_device(&udev, class_dev);
        if (udev.devname[0] != '\0')
                setenv("DEVNAME", udev.devname, 1);
 
+run:
        if (udev_run && !list_empty(&udev.run_list)) {
                struct name_entry *name_loop;
 
@@ -137,6 +150,7 @@ static int add_device(const char *path, const char *subsystem)
                        execute_command(name_loop->name, udev.subsystem);
        }
 
+exit:
        sysfs_close_class_device(class_dev);
        udev_cleanup_device(&udev);