X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev_rules.c;h=5ae4aa2b7817c0f6a1f48e0480eb879a1e6676c7;hp=daf3d7fff7992841ab766b10a0339712828dabf2;hb=6bdec550afa1e3485233dac1e0c6727e5548e7f7;hpb=1ff1aa424baa05a0fd06deeb6609a11b289ecd65 diff --git a/udev_rules.c b/udev_rules.c index daf3d7fff..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); @@ -940,6 +956,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule) if (match_key("DRIVER", rule, &rule->driver, udev->dev->driver)) goto nomatch; + /* match NAME against a value assigned by an earlier rule */ if (match_key("NAME", rule, &rule->name, udev->name)) goto nomatch; @@ -977,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; @@ -994,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); @@ -1014,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; } @@ -1265,9 +1291,6 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev) dbg("udev->dev->devpath='%s'", udev->dev->devpath); dbg("udev->dev->kernel='%s'", udev->dev->kernel); - /* use kernel name as default node name */ - strlcpy(udev->name, udev->dev->kernel, sizeof(udev->name)); - /* look for a matching rule to apply */ udev_rules_iter_init(rules); while (1) { @@ -1422,8 +1445,10 @@ 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); + 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)); + } if (udev->tmp_node[0] != '\0') { dbg("removing temporary device node"); @@ -1448,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; } @@ -1461,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;