summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xtest/udev-test.pl12
-rw-r--r--udev_rules.c32
-rw-r--r--udev_rules.h1
-rw-r--r--udev_rules_parse.c6
4 files changed, 32 insertions, 19 deletions
diff --git a/test/udev-test.pl b/test/udev-test.pl
index 53499d8871..a2043080e9 100755
--- a/test/udev-test.pl
+++ b/test/udev-test.pl
@@ -1519,18 +1519,6 @@ KERNEL=="sda1", NAME=="node*", SYMLINK+="link2"
EOF
},
{
- desc => "NAME compare test 2",
- subsys => "block",
- devpath => "/block/sda/sda1",
- exp_name => "link2",
- exp_target => "sda1",
- not_exp_name => "link",
- rules => <<EOF
-KERNEL=="sda1", NAME=="?*", SYMLINK+="link"
-KERNEL=="sda1", NAME!="?*", SYMLINK+="link2"
-EOF
- },
- {
desc => "invalid key operation",
subsys => "block",
devpath => "/block/sda/sda1",
diff --git a/udev_rules.c b/udev_rules.c
index 400ebad9e3..daf3d7fff7 100644
--- a/udev_rules.c
+++ b/udev_rules.c
@@ -940,10 +940,25 @@ 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;
+ /* 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];
@@ -1250,6 +1265,9 @@ 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) {
@@ -1311,14 +1329,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);
}
@@ -1400,10 +1422,8 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
}
}
- if (!name_set) {
- strlcpy(udev->name, udev->dev->kernel, sizeof(udev->name));
+ if (!name_set)
info("no node name set, will use kernel name '%s'", udev->name);
- }
if (udev->tmp_node[0] != '\0') {
dbg("removing temporary device node");
diff --git a/udev_rules.h b/udev_rules.h
index 556f55087d..0ad4ec3271 100644
--- a/udev_rules.h
+++ b/udev_rules.h
@@ -90,6 +90,7 @@ struct udev_rule {
struct key name;
struct key symlink;
+ struct key symlink_match;
struct key owner;
struct key group;
mode_t mode;
diff --git a/udev_rules_parse.c b/udev_rules_parse.c
index 124410a340..81c24b9cc1 100644
--- a/udev_rules_parse.c
+++ b/udev_rules_parse.c
@@ -525,7 +525,11 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
}
if (strcasecmp(key, "SYMLINK") == 0) {
- add_rule_key(rule, &rule->symlink, operation, value);
+ if (operation == KEY_OP_MATCH ||
+ operation == KEY_OP_NOMATCH)
+ add_rule_key(rule, &rule->symlink_match, operation, value);
+ else
+ add_rule_key(rule, &rule->symlink, operation, value);
valid = 1;
continue;
}