X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev_rules.c;h=5ae4aa2b7817c0f6a1f48e0480eb879a1e6676c7;hp=400ebad9e33b6841302065576e528feed81707b4;hb=c8e826147a0e39cf09079ea4e546f732f58b4eba;hpb=e2ecb34ffd4fd8b0d31a65ec0c59dc4f8023ad6d diff --git a/udev_rules.c b/udev_rules.c index 400ebad9e..5ae4aa2b7 100644 --- a/udev_rules.c +++ b/udev_rules.c @@ -349,11 +349,6 @@ static int import_keys_into_env(struct udevice *udev, const char *buf, size_t bu cur += count+1; lineno++; - if (count >= sizeof(line)) { - err("line too long, conf line skipped %s, line %d", udev_config_filename, lineno); - continue; - } - /* eat the whitespace */ while ((count > 0) && isspace(bufline[0])) { bufline++; @@ -366,6 +361,11 @@ static int import_keys_into_env(struct udevice *udev, const char *buf, size_t bu if (bufline[0] == COMMENT_CHARACTER) continue; + if (count >= sizeof(line)) { + err("line too long, conf line skipped %s, line %d", udev_config_filename, lineno); + continue; + } + memcpy(line, bufline, count); line[count] = '\0'; @@ -475,10 +475,12 @@ static int pass_env_to_socket(const char *sockname, const char *devpath, const c bufpos = snprintf(buf, sizeof(buf)-1, "%s@%s", action, devpath); bufpos++; - for (i = 0; environ[i] != NULL && bufpos < sizeof(buf); i++) { + for (i = 0; environ[i] != NULL && bufpos < (sizeof(buf)-1); i++) { bufpos += strlcpy(&buf[bufpos], environ[i], sizeof(buf) - bufpos-1); bufpos++; } + if (bufpos > sizeof(buf)) + bufpos = sizeof(buf); count = sendto(sock, &buf, bufpos, 0, (struct sockaddr *)&saddr, addrlen); if (count < 0) @@ -597,12 +599,14 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize) SUBST_KERNEL, SUBST_KERNEL_NUMBER, SUBST_ID, + SUBST_DRIVER, SUBST_MAJOR, SUBST_MINOR, SUBST_RESULT, SUBST_ATTR, SUBST_PARENT, SUBST_TEMP_NODE, + SUBST_NAME, SUBST_ROOT, SUBST_SYS, SUBST_ENV, @@ -616,6 +620,7 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize) { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER }, { .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL }, { .name = "id", .fmt = 'b', .type = SUBST_ID }, + { .name = "driver", .fmt = 'd', .type = SUBST_DRIVER }, { .name = "major", .fmt = 'M', .type = SUBST_MAJOR }, { .name = "minor", .fmt = 'm', .type = SUBST_MINOR }, { .name = "result", .fmt = 'c', .type = SUBST_RESULT }, @@ -623,6 +628,7 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize) { .name = "sysfs", .fmt = 's', .type = SUBST_ATTR }, { .name = "parent", .fmt = 'P', .type = SUBST_PARENT }, { .name = "tempnode", .fmt = 'N', .type = SUBST_TEMP_NODE }, + { .name = "name", .fmt = 'D', .type = SUBST_NAME }, { .name = "root", .fmt = 'r', .type = SUBST_ROOT }, { .name = "sys", .fmt = 'S', .type = SUBST_SYS }, { .name = "env", .fmt = 'E', .type = SUBST_ENV }, @@ -707,6 +713,12 @@ found: dbg("substitute id '%s'", udev->dev_parent->kernel); } break; + case SUBST_DRIVER: + if (udev->dev_parent != NULL) { + strlcat(string, udev->dev_parent->driver, maxsize); + dbg("substitute driver '%s'", udev->dev_parent->driver); + } + break; case SUBST_MAJOR: sprintf(temp2, "%d", major(udev->devt)); strlcat(string, temp2, maxsize); @@ -835,6 +847,10 @@ found: strlcat(string, udev->tmp_node, maxsize); dbg("substitute temporary device node name '%s'", udev->tmp_node); break; + case SUBST_NAME: + strlcat(string, udev->name, maxsize); + dbg("substitute udev->name '%s'", udev->name); + break; case SUBST_ROOT: strlcat(string, udev_root, maxsize); dbg("substitute udev_root '%s'", udev_root); @@ -944,6 +960,22 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) if (match_key("NAME", rule, &rule->name, udev->name)) goto nomatch; + /* match against current list of symlinks */ + if (rule->symlink_match.operation == KEY_OP_MATCH || + rule->symlink_match.operation == KEY_OP_NOMATCH) { + struct name_entry *name_loop; + int match = 0; + + list_for_each_entry(name_loop, &udev->symlink_list, node) { + if (match_key("SYMLINK", rule, &rule->symlink_match, name_loop->name) == 0) { + match = 1; + break; + } + } + if (!match) + goto nomatch; + } + for (i = 0; i < rule->env.count; i++) { struct key_pair *pair = &rule->env.keys[i]; @@ -962,7 +994,8 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) } } - if (rule->test.operation != KEY_OP_UNSET) { + if (rule->test.operation == KEY_OP_MATCH || + rule->test.operation == KEY_OP_NOMATCH) { char filename[PATH_SIZE]; char devpath[PATH_SIZE]; char *attr; @@ -979,6 +1012,14 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) strlcat(filename, "/", sizeof(filename)); strlcat(filename, attr, sizeof(filename)); } + } else if (filename[0] != '/') { + char tmp[PATH_SIZE]; + + strlcpy(tmp, sysfs_path, sizeof(tmp)); + strlcat(tmp, udev->dev->devpath, sizeof(tmp)); + strlcat(tmp, "/", sizeof(tmp)); + strlcat(tmp, filename, sizeof(tmp)); + strlcpy(filename, tmp, sizeof(filename)); } match = (stat(filename, &statbuf) == 0); @@ -999,7 +1040,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) if (rule->wait_for_sysfs.operation != KEY_OP_UNSET) { int found; - found = (wait_for_sysfs(udev, key_val(rule, &rule->wait_for_sysfs), 3) == 0); + found = (wait_for_sysfs(udev, key_val(rule, &rule->wait_for_sysfs), 10) == 0); if (!found && (rule->wait_for_sysfs.operation != KEY_OP_NOMATCH)) goto nomatch; } @@ -1311,14 +1352,18 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) } /* collect symlinks */ - if (!udev->symlink_final && rule->symlink.operation != KEY_OP_UNSET) { + if (!udev->symlink_final && + (rule->symlink.operation == KEY_OP_ASSIGN || + rule->symlink.operation == KEY_OP_ASSIGN_FINAL || + rule->symlink.operation == KEY_OP_ADD)) { char temp[PATH_SIZE]; char *pos, *next; int count; if (rule->symlink.operation == KEY_OP_ASSIGN_FINAL) udev->symlink_final = 1; - if (rule->symlink.operation == KEY_OP_ASSIGN || rule->symlink.operation == KEY_OP_ASSIGN_FINAL) { + if (rule->symlink.operation == KEY_OP_ASSIGN || + rule->symlink.operation == KEY_OP_ASSIGN_FINAL) { info("reset symlink list"); name_list_cleanup(&udev->symlink_list); } @@ -1401,8 +1446,8 @@ 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->dev->kernel); strlcpy(udev->name, udev->dev->kernel, sizeof(udev->name)); - info("no node name set, will use kernel name '%s'", udev->name); } if (udev->tmp_node[0] != '\0') { @@ -1428,9 +1473,14 @@ int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev) break; dbg("process rule"); - if (rule->name.operation != KEY_OP_UNSET || rule->symlink.operation != KEY_OP_UNSET || - rule->mode_operation != KEY_OP_UNSET || rule->owner.operation != KEY_OP_UNSET || - rule->group.operation != KEY_OP_UNSET) { + if (rule->name.operation == KEY_OP_ASSIGN || + rule->name.operation == KEY_OP_ASSIGN_FINAL || + rule->name.operation == KEY_OP_ADD || + rule->symlink.operation == KEY_OP_ASSIGN || + rule->symlink.operation == KEY_OP_ASSIGN_FINAL || + rule->symlink.operation == KEY_OP_ADD || + rule->mode_operation != KEY_OP_UNSET || + rule->owner.operation != KEY_OP_UNSET || rule->group.operation != KEY_OP_UNSET) { dbg("skip rule that names a device"); continue; } @@ -1441,6 +1491,10 @@ int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev) udev->ignore_device = 1; return 0; } + if (rule->ignore_remove) { + udev->ignore_remove = 1; + dbg("remove event should be ignored"); + } if (!udev->run_final && rule->run.operation != KEY_OP_UNSET) { struct name_entry *entry;