X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=udev_rules.c;h=ea850a84c339a90712ff89c792b8d987b3ba1322;hb=ad1be3e7ad01b263312eaf2a06db0c24c9c90441;hp=884cb7098c12559f6b31c727eabda1cf4a3809c3;hpb=c70560feef0eb61a150cd2f956f0beead4313ffe;p=elogind.git diff --git a/udev_rules.c b/udev_rules.c index 884cb7098..ea850a84c 100644 --- a/udev_rules.c +++ b/udev_rules.c @@ -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) {