summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rwxr-xr-xtest/udev-test.pl13
-rw-r--r--udev_rules.c5
-rw-r--r--udev_rules.h3
-rw-r--r--udev_rules_parse.c39
5 files changed, 60 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index a8f2851cab..b740838ace 100644
--- a/Makefile
+++ b/Makefile
@@ -377,8 +377,8 @@ install: install-config install-man all
$(INSTALL_PROGRAM) -D $(STARTER) $(DESTDIR)$(sbindir)/$(STARTER)
ifndef DESTDIR
- killall $(DAEMON)
- - $(sbindir)/$(DAEMON) --daemon
- rm -rf $(udevdb)
+ - $(sbindir)/$(DAEMON) --daemon
endif
@extras="$(EXTRAS)" ; for target in $$extras ; do \
echo $$target ; \
diff --git a/test/udev-test.pl b/test/udev-test.pl
index 1bb60bb76e..94cffeab07 100755
--- a/test/udev-test.pl
+++ b/test/udev-test.pl
@@ -1494,6 +1494,19 @@ EOF
KERNEL=="sda1", IMPORT{parent}="PARENT*", NAME="parentenv-\$env{PARENT_KEY}\$env{WRONG_PARENT_KEY}"
EOF
},
+ {
+ desc => "GOTO test",
+ subsys => "block",
+ devpath => "/block/sda/sda1",
+ exp_name => "right",
+ rules => <<EOF
+KERNEL=="sda1", GOTO="TEST"
+KERNEL=="sda1", NAME="wrong"
+KERNEL=="sda1", NAME="", LABEL="NO"
+KERNEL=="sda1", NAME="right", LABEL="TEST"
+KERNEL=="sda1", NAME="wrong2"
+EOF
+ },
);
# set env
diff --git a/udev_rules.c b/udev_rules.c
index 4bf05cd437..939febe8f6 100644
--- a/udev_rules.c
+++ b/udev_rules.c
@@ -1069,6 +1069,11 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev, struct s
dbg("last rule to be applied");
break;
}
+
+ if (rule->goto_label.operation != KEY_OP_UNSET) {
+ dbg("moving forward to label '%s'", key_val(rule, &rule->goto_label));
+ udev_rules_iter_label(rules, key_val(rule, &rule->goto_label));
+ }
}
}
diff --git a/udev_rules.h b/udev_rules.h
index 3f37d4b0b4..d22d31f7e1 100644
--- a/udev_rules.h
+++ b/udev_rules.h
@@ -62,6 +62,8 @@ enum import_type {
};
struct udev_rule {
+ struct key label;
+ struct key goto_label;
struct key kernel_name;
struct key subsystem;
struct key action;
@@ -108,6 +110,7 @@ extern void udev_rules_close(struct udev_rules *rules);
extern void udev_rules_iter_init(struct udev_rules *rules);
extern struct udev_rule *udev_rules_iter_next(struct udev_rules *rules);
+extern struct udev_rule *udev_rules_iter_label(struct udev_rules *rules, const char *label);
extern int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev, struct sysfs_class_device *class_dev);
extern int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev, struct sysfs_device *sysfs_device);
diff --git a/udev_rules_parse.c b/udev_rules_parse.c
index 7c3c2e7fc2..0259268c8f 100644
--- a/udev_rules_parse.c
+++ b/udev_rules_parse.c
@@ -52,8 +52,10 @@ struct udev_rule *udev_rules_iter_next(struct udev_rules *rules)
return NULL;
dbg("current=%zi", rules->current);
- if (rules->current >= rules->bufsize)
+ if (rules->current >= rules->bufsize) {
+ dbg("no more rules");
return NULL;
+ }
/* get next rule */
rule = (struct udev_rule *) (rules->buf + rules->current);
@@ -62,6 +64,28 @@ struct udev_rule *udev_rules_iter_next(struct udev_rules *rules)
return rule;
}
+struct udev_rule *udev_rules_iter_label(struct udev_rules *rules, const char *label)
+{
+ static struct udev_rule *rule;
+
+next:
+ dbg("current=%zi", rules->current);
+ if (rules->current >= rules->bufsize) {
+ dbg("no more rules");
+ return NULL;
+ }
+ rule = (struct udev_rule *) (rules->buf + rules->current);
+
+ if (strcmp(&rule->buf[rule->label.val_off], label) != 0) {
+ dbg("moving forward, looking for label '%s'", label);
+ rules->current += sizeof(struct udev_rule) + rule->bufsize;
+ goto next;
+ }
+
+ dbg("found label '%s'", label);
+ return rule;
+}
+
static int get_key(char **line, char **key, enum key_operation *operation, char **value)
{
char *linepos;
@@ -237,6 +261,18 @@ static int add_to_rules(struct udev_rules *rules, char *line)
if (retval)
break;
+ if (strcasecmp(key, "LABEL") == 0) {
+ add_rule_key(rule, &rule->label, operation, value);
+ valid = 1;
+ continue;
+ }
+
+ if (strcasecmp(key, "GOTO") == 0) {
+ add_rule_key(rule, &rule->goto_label, operation, value);
+ valid = 1;
+ continue;
+ }
+
if (strcasecmp(key, "KERNEL") == 0) {
add_rule_key(rule, &rule->kernel_name, operation, value);
valid = 1;
@@ -475,6 +511,7 @@ static int add_to_rules(struct udev_rules *rules, char *line)
err("realloc failed");
goto exit;
}
+ dbg("adding rule to offset %zi", rules->bufsize);
memcpy(rules->buf + rules->bufsize, rule, rule_size);
rules->bufsize += rule_size;
exit: