chiark / gitweb /
add udev_rules_run() to handle RUN list
[elogind.git] / udevtrigger.c
index 2b4ab80901c803a467af6437063628367f02d31a..4ef9612af070c0fe413c4070116af4ed1725dc89 100644 (file)
@@ -101,7 +101,7 @@ static int device_list_insert(const char *path)
        return 0;
 }
 
-static void trigger_uevent(const char *devpath)
+static void trigger_uevent(const char *devpath, const char *action)
 {
        char filename[PATH_SIZE];
        int fd;
@@ -118,17 +118,17 @@ static void trigger_uevent(const char *devpath)
 
        fd = open(filename, O_WRONLY);
        if (fd < 0) {
-               dbg("error on opening %s: %s\n", filename, strerror(errno));
+               dbg("error on opening %s: %s", filename, strerror(errno));
                return;
        }
 
-       if (write(fd, "add", 3) < 0)
-               info("error on triggering %s: %s\n", filename, strerror(errno));
+       if (write(fd, action, strlen(action)) < 0)
+               info("error writing '%s' to '%s': %s", action, filename, strerror(errno));
 
        close(fd);
 }
 
-static void exec_list(void)
+static void exec_list(const char *action)
 {
        struct name_entry *loop_device;
        struct name_entry *tmp_device;
@@ -137,14 +137,14 @@ static void exec_list(void)
                if (delay_device(loop_device->name))
                        continue;
 
-               trigger_uevent(loop_device->name);
+               trigger_uevent(loop_device->name, action);
                list_del(&loop_device->node);
                free(loop_device);
        }
 
        /* trigger remaining delayed devices */
        list_for_each_entry_safe(loop_device, tmp_device, &device_list, node) {
-               trigger_uevent(loop_device->name);
+               trigger_uevent(loop_device->name, action);
                list_del(&loop_device->node);
                free(loop_device);
        }
@@ -237,14 +237,15 @@ static int attr_filtered(const char *path)
        return 0;
 }
 
-static void scan_bus(void)
+static void scan_subsystem(const char *subsys)
 {
        char base[PATH_SIZE];
        DIR *dir;
        struct dirent *dent;
 
        strlcpy(base, sysfs_path, sizeof(base));
-       strlcat(base, "/bus", sizeof(base));
+       strlcat(base, "/", sizeof(base));
+       strlcat(base, subsys, sizeof(base));
 
        dir = opendir(base);
        if (dir != NULL) {
@@ -292,13 +293,6 @@ static void scan_block(void)
        char base[PATH_SIZE];
        DIR *dir;
        struct dirent *dent;
-       struct stat statbuf;
-
-       /* skip if "block" is already a "class" */
-       strlcpy(base, sysfs_path, sizeof(base));
-       strlcat(base, "/class/block", sizeof(base));
-       if (stat(base, &statbuf) == 0)
-               return;
 
        if (subsystem_filtered("block"))
                return;
@@ -413,22 +407,14 @@ static void scan_failed(void)
        if (dir != NULL) {
                for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
                        char device[PATH_SIZE];
-                       size_t start, end, i;
+                       size_t start;
 
                        if (dent->d_name[0] == '.')
                                continue;
 
-                       strlcpy(device, sysfs_path, sizeof(device));
-                       start = strlcat(device, "/", sizeof(device));
-                       end = strlcat(device, dent->d_name, sizeof(device));
-                       if (end > sizeof(device))
-                               end = sizeof(device);
-
-                       /* replace PATH_TO_NAME_CHAR with '/' */
-                       for (i = start; i < end; i++)
-                               if (device[i] == PATH_TO_NAME_CHAR)
-                                       device[i] = '/';
-
+                       start = strlcpy(device, sysfs_path, sizeof(device));
+                       strlcat(device, dent->d_name, sizeof(device));
+                       path_decode(&device[start]);
                        device_list_insert(device);
                }
                closedir(dir);
@@ -439,11 +425,13 @@ int main(int argc, char *argv[], char *envp[])
 {
        int failed = 0;
        int option;
+       const char *action = "add";
        static const struct option options[] = {
                { "verbose", 0, NULL, 'v' },
                { "dry-run", 0, NULL, 'n' },
                { "retry-failed", 0, NULL, 'F' },
                { "help", 0, NULL, 'h' },
+               { "action", 1, NULL, 'c' },
                { "subsystem-match", 1, NULL, 's' },
                { "subsystem-nomatch", 1, NULL, 'S' },
                { "attr-match", 1, NULL, 'a' },
@@ -457,7 +445,7 @@ int main(int argc, char *argv[], char *envp[])
        sysfs_init();
 
        while (1) {
-               option = getopt_long(argc, argv, "vnFhs:S:a:A:", options, NULL);
+               option = getopt_long(argc, argv, "vnFhc:s:S:a:A:", options, NULL);
                if (option == -1)
                        break;
 
@@ -471,6 +459,9 @@ int main(int argc, char *argv[], char *envp[])
                case 'F':
                        failed = 1;
                        break;
+               case 'c':
+                       action = optarg;
+                       break;
                case 's':
                        name_list_add(&filter_subsystem_match_list, optarg, 0);
                        break;
@@ -506,11 +497,26 @@ int main(int argc, char *argv[], char *envp[])
        if (failed)
                scan_failed();
        else {
-               scan_bus();
-               scan_class();
-               scan_block();
+               char base[PATH_SIZE];
+               struct stat statbuf;
+
+               /* if we have /sys/subsystem, forget all the old stuff */
+               strlcpy(base, sysfs_path, sizeof(base));
+               strlcat(base, "/subsystem", sizeof(base));
+               if (stat(base, &statbuf) == 0)
+                       scan_subsystem("subsystem");
+               else {
+                       scan_subsystem("bus");
+                       scan_class();
+
+                       /* scan "block" if it isn't a "class" */
+                       strlcpy(base, sysfs_path, sizeof(base));
+                       strlcat(base, "/class/block", sizeof(base));
+                       if (stat(base, &statbuf) != 0)
+                               scan_block();
+               }
        }
-       exec_list();
+       exec_list(action);
 
 exit:
        name_list_cleanup(&filter_subsystem_match_list);