chiark / gitweb /
udevd: serialize events if they refer to the same major:minor number
[elogind.git] / udev_rules.c
index 3ec8477461e43fe61be68d2e4f2d24dedd9dc0bf..1521db08def5ac5c92a66b2fce51744dedb50492 100644 (file)
@@ -26,6 +26,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <syslog.h>
+#include <dirent.h>
 #include <fnmatch.h>
 #include <sys/socket.h>
 #include <sys/un.h>
@@ -585,6 +586,44 @@ out:
        return found;
 }
 
+static int attr_subst_subdir(char *attr, size_t len)
+{
+       char *pos;
+       int found = 0;
+
+       pos = strstr(attr, "/*/");
+       if (pos != NULL) {
+               char str[PATH_SIZE];
+               DIR *dir;
+
+               pos[1] = '\0';
+               strlcpy(str, &pos[2], sizeof(str));
+               dir = opendir(attr);
+               if (dir != NULL) {
+                       struct dirent *dent;
+
+                       for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+                               struct stat stats;
+
+                               if (dent->d_name[0] == '.')
+                                       continue;
+                               strlcat(attr, dent->d_name, len);
+                               strlcat(attr, str, len);
+                               if (stat(attr, &stats) == 0) {
+                                       found = 1;
+                                       break;
+                               }
+                               pos[1] = '\0';
+                       }
+                       closedir(dir);
+               }
+               if (!found)
+                       strlcat(attr, str, len);
+       }
+
+       return found;
+}
+
 void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
 {
        char temp[PATH_SIZE];
@@ -1022,6 +1061,8 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                        strlcpy(filename, tmp, sizeof(filename));
                }
 
+               attr_subst_subdir(filename, sizeof(filename));
+
                match = (stat(filename, &statbuf) == 0);
                info("'%s' %s", filename, match ? "exists" : "does not exist");
                if (match && rule->test_mode_mask > 0) {
@@ -1264,6 +1305,8 @@ try_parent:
                                strlcat(attr, key_name, sizeof(attr));
                        }
 
+                       attr_subst_subdir(attr, sizeof(attr));
+
                        strlcpy(value, key_val(rule, &pair->key), sizeof(value));
                        udev_rules_apply_format(udev, value, sizeof(value));
                        info("writing '%s' to sysfs file '%s'", value, attr);
@@ -1446,7 +1489,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
        }
 
        if (!name_set) {
-               info("no node name set, will use kernel name '%s'", udev->name);
+               info("no node name set, will use kernel name '%s'", udev->dev->kernel);
                strlcpy(udev->name, udev->dev->kernel, sizeof(udev->name));
        }