chiark / gitweb /
volume_id: support for oracleasm
[elogind.git] / udev_rules.c
index 884cb7098c12559f6b31c727eabda1cf4a3809c3..ea850a84c339a90712ff89c792b8d987b3ba1322 100644 (file)
@@ -528,35 +528,40 @@ int udev_rules_run(struct udevice *udev)
 }
 
 #define WAIT_LOOP_PER_SECOND           50
-static int wait_for_sysfs(struct udevice *udev, const char *file, int timeout)
+static int wait_for_file(struct udevice *udev, const char *file, int timeout)
 {
-       char devicepath[PATH_SIZE];
        char filepath[PATH_SIZE];
+       char devicepath[PATH_SIZE] = "";
        struct stat stats;
        int loop = timeout * WAIT_LOOP_PER_SECOND;
 
-       strlcpy(devicepath, sysfs_path, sizeof(devicepath));
-       strlcat(devicepath, udev->dev->devpath, sizeof(devicepath));
-       strlcpy(filepath, devicepath, sizeof(filepath));
-       strlcat(filepath, "/", sizeof(filepath));
-       strlcat(filepath, file, sizeof(filepath));
+       /* a relative path is a device attribute */
+       if (file[0] != '/') {
+               strlcpy(devicepath, sysfs_path, sizeof(devicepath));
+               strlcat(devicepath, udev->dev->devpath, sizeof(devicepath));
 
-       dbg("will wait %i sec for '%s'\n", timeout, filepath);
+               strlcpy(filepath, devicepath, sizeof(filepath));
+               strlcat(filepath, "/", sizeof(filepath));
+               strlcat(filepath, file, sizeof(filepath));
+               file = filepath;
+       }
+
+       dbg("will wait %i sec for '%s'\n", timeout, file);
        while (--loop) {
                /* lookup file */
-               if (stat(filepath, &stats) == 0) {
-                       info("file '%s' appeared after %i loops\n", filepath, (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
+               if (stat(file, &stats) == 0) {
+                       info("file '%s' appeared after %i loops\n", file, (timeout * WAIT_LOOP_PER_SECOND) - loop-1);
                        return 0;
                }
                /* make sure, the device did not disappear in the meantime */
-               if (stat(devicepath, &stats) != 0) {
-                       info("device disappeared while waiting for '%s'\n", filepath);
+               if (devicepath[0] != '\0' && stat(devicepath, &stats) != 0) {
+                       info("device disappeared while waiting for '%s'\n", file);
                        return -2;
                }
-               info("wait for '%s' for %i mseconds\n", filepath, 1000 / WAIT_LOOP_PER_SECOND);
+               info("wait for '%s' for %i mseconds\n", file, 1000 / WAIT_LOOP_PER_SECOND);
                usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
        }
-       info("waiting for '%s' failed\n", filepath);
+       info("waiting for '%s' failed\n", file);
        return -1;
 }
 
@@ -658,6 +663,7 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
                SUBST_PARENT,
                SUBST_TEMP_NODE,
                SUBST_NAME,
+               SUBST_LINKS,
                SUBST_ROOT,
                SUBST_SYS,
                SUBST_ENV,
@@ -680,6 +686,7 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
                { .name = "parent",     .fmt = 'P',     .type = SUBST_PARENT },
                { .name = "tempnode",   .fmt = 'N',     .type = SUBST_TEMP_NODE },
                { .name = "name",       .fmt = 'D',     .type = SUBST_NAME },
+               { .name = "links",      .fmt = 'L',     .type = SUBST_LINKS },
                { .name = "root",       .fmt = 'r',     .type = SUBST_ROOT },
                { .name = "sys",        .fmt = 'S',     .type = SUBST_SYS },
                { .name = "env",        .fmt = 'E',     .type = SUBST_ENV },
@@ -899,8 +906,26 @@ found:
                        dbg("substitute temporary device node name '%s'\n", udev->tmp_node);
                        break;
                case SUBST_NAME:
-                       strlcat(string, udev->name, maxsize);
-                       dbg("substitute udev->name '%s'\n", udev->name);
+                       if (udev->name[0] == '\0') {
+                               strlcat(string, udev->dev->kernel, maxsize);
+                               dbg("substitute udev->kernel '%s'\n", udev->name);
+                       } else {
+                               strlcat(string, udev->name, maxsize);
+                               dbg("substitute udev->name '%s'\n", udev->name);
+                       }
+                       break;
+               case SUBST_LINKS:
+                       if (!list_empty(&udev->symlink_list)) {
+                               struct name_entry *name_loop;
+                               char symlinks[PATH_SIZE] = "";
+
+                               list_for_each_entry(name_loop, &udev->symlink_list, node) {
+                                       strlcat(symlinks, name_loop->name, sizeof(symlinks));
+                                       strlcat(symlinks, " ", sizeof(symlinks));
+                               }
+                               remove_trailing_chars(symlinks, ' ');
+                               strlcat(string, symlinks, maxsize);
+                       }
                        break;
                case SUBST_ROOT:
                        strlcat(string, udev_root, maxsize);
@@ -1076,7 +1101,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                attr_subst_subdir(filename, sizeof(filename));
 
                match = (stat(filename, &statbuf) == 0);
-               info("'%s' %s", filename, match ? "exists" : "does not exist\n");
+               info("'%s' %s", filename, match ? "exists\n" : "does not exist\n");
                if (match && rule->test_mode_mask > 0) {
                        match = ((statbuf.st_mode & rule->test_mode_mask) > 0);
                        info("'%s' has mode=%#o and %s %#o\n", filename, statbuf.st_mode,
@@ -1090,11 +1115,14 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                dbg("TEST key is true\n");
        }
 
-       if (rule->wait_for_sysfs.operation != KEY_OP_UNSET) {
+       if (rule->wait_for.operation != KEY_OP_UNSET) {
+               char filename[PATH_SIZE];
                int found;
 
-               found = (wait_for_sysfs(udev, key_val(rule, &rule->wait_for_sysfs), 10) == 0);
-               if (!found && (rule->wait_for_sysfs.operation != KEY_OP_NOMATCH))
+               strlcpy(filename, key_val(rule, &rule->wait_for), sizeof(filename));
+               udev_rules_apply_format(udev, filename, sizeof(filename));
+               found = (wait_for_file(udev, filename, 10) == 0);
+               if (!found && (rule->wait_for.operation != KEY_OP_NOMATCH))
                        goto nomatch;
        }
 
@@ -1377,6 +1405,10 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
                                udev->link_priority = rule->link_priority;
                                info("link_priority=%i\n", udev->link_priority);
                        }
+                       if (rule->event_timeout >= 0) {
+                               udev->event_timeout = rule->event_timeout;
+                               info("event_timeout=%i\n", udev->event_timeout);
+                       }
                        /* apply all_partitions option only at a main block device */
                        if (rule->partitions &&
                            strcmp(udev->dev->subsystem, "block") == 0 && udev->dev->kernel_number[0] == '\0') {
@@ -1388,7 +1420,10 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
                        if (!udev->mode_final && rule->mode.operation != KEY_OP_UNSET) {
                                if (rule->mode.operation == KEY_OP_ASSIGN_FINAL)
                                        udev->mode_final = 1;
-                               udev->mode = strtol(key_val(rule, &rule->mode), NULL, 8);
+                               char buf[20];
+                               strlcpy(buf, key_val(rule, &rule->mode), sizeof(buf));
+                               udev_rules_apply_format(udev, buf, sizeof(buf));
+                               udev->mode = strtol(buf, NULL, 8);
                                dbg("applied mode=%#o to '%s'\n", udev->mode, udev->dev->kernel);
                        }
                        if (!udev->owner_final && rule->owner.operation != KEY_OP_UNSET) {