summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>2005-03-13 11:40:32 +0100
committerGreg KH <gregkh@suse.de>2005-04-26 23:53:18 -0700
commit3e5958dee5f24283eb5c6a2d2d95e1a39428a3b8 (patch)
treebaa33eae18ff92944084d140b3ff6049ce826b39
parent79f651f4bd2fb395a705792eb8ce551a6021bcd6 (diff)
[PATCH] add ENV{} key to match agains environment variables
-rw-r--r--test/udev-test.pl32
-rw-r--r--udev.8.in10
-rw-r--r--udev_rules.c71
-rw-r--r--udev_rules.h6
-rw-r--r--udev_rules_parse.c24
5 files changed, 100 insertions, 43 deletions
diff --git a/test/udev-test.pl b/test/udev-test.pl
index ebceccecb2..2ece431735 100644
--- a/test/udev-test.pl
+++ b/test/udev-test.pl
@@ -259,15 +259,6 @@ BUS=="scsi", ID=="0:0:0:0", NAME="M%M-m%m-n%n-b%3b-s%3s{vendor}"
EOF
},
{
- desc => "old style SYSFS_ attribute",
- subsys => "block",
- devpath => "/block/sda",
- exp_name => "good" ,
- conf => <<EOF
-BUS=="scsi", SYSFS_vendor=="IBM-ESXS", NAME="good"
-EOF
- },
- {
desc => "sustitution of sysfs value (%s{file})",
subsys => "block",
devpath => "/block/sda",
@@ -1171,6 +1162,29 @@ KERNEL == "sda1" , NAME = "true"
BUS=="scsi", KERNEL=="sda1", NAME="wrong"
EOF
},
+ {
+ desc => "ENV{} test",
+ subsys => "block",
+ devpath => "/block/sda/sda1",
+ exp_name => "true",
+ conf => <<EOF
+BUS=="scsi", KERNEL=="sda1", ENV{UDEV_TEST}=="go", NAME="wrong"
+BUS=="scsi", KERNEL=="sda1", ENV{UDEV_TEST}=="yes", NAME="true"
+BUS=="scsi", KERNEL=="sda1", ENV{UDEV_TEST}=="bad", NAME="bad"
+EOF
+ },
+ {
+ desc => "ENV{} test",
+ subsys => "block",
+ devpath => "/block/sda/sda1",
+ exp_name => "true",
+ conf => <<EOF
+BUS=="scsi", KERNEL=="sda1", ENV{UDEV_TEST}=="go", NAME="wrong"
+BUS=="scsi", KERNEL=="sda1", ENV{UDEV_TEST}=="yes", ENV{ACTION}=="add", ENV{DEVPATH}=="/block/sda/sdax1", NAME="no"
+BUS=="scsi", KERNEL=="sda1", ENV{UDEV_TEST}=="yes", ENV{ACTION}=="add", ENV{DEVPATH}=="/block/sda/sda1", NAME="true"
+BUS=="scsi", KERNEL=="sda1", ENV{UDEV_TEST}=="bad", NAME="bad"
+EOF
+ },
);
# set env
diff --git a/udev.8.in b/udev.8.in
index dbba297972..84d8a313da 100644
--- a/udev.8.in
+++ b/udev.8.in
@@ -115,13 +115,17 @@ Match the kernel driver name.
Match the device number on the bus, like PCI bus id.
.TP
.BI SYSFS{ filename }
-Match sysfs device attribute like label, vendor, USB serial number, SCSI UUID
-or file system label. Up to 5 different sysfs files can be checked, with
-all of the values being required to match the rule.
+Match sysfs device attribute like vendor and product id's, USB serial number
+or the SCSI disk model number. Up to 5 different sysfs files can be checked,
+with all of the values being required to match the rule.
.br
Trailing whitespace characters in the sysfs attribute value are ignored, if
the key doesn't have any trailing whitespace characters by itself.
.TP
+.BI ENV{ variable }
+Match an environment variable. Up to 5 different environment variables can be
+checked, with all of the values being required to match the rule.
+.TP
.B PROGRAM
Call external program. This key is valid if the program returns successful.
The environment variables of
diff --git a/udev_rules.c b/udev_rules.c
index d1192614aa..551c06131b 100644
--- a/udev_rules.c
+++ b/udev_rules.c
@@ -498,30 +498,6 @@ static int compare_sysfs_attribute(struct sysfs_class_device *class_dev, struct
return 0;
}
-static int match_sysfs_pairs(struct udev_rule *rule, struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device)
-{
- int i;
-
- for (i = 0; i < rule->sysfs_pair_count; i++) {
- struct key_pair *pair;
-
- pair = &rule->sysfs_pair[i];
- if ((pair->name[0] == '\0') || (pair->value[0] == '\0'))
- break;
- if (compare_sysfs_attribute(class_dev, sysfs_device, pair) != 0) {
- dbg("sysfs pair #%u does not match", i);
- if (pair->operation != KEY_OP_NOMATCH)
- return -1;
- } else {
- dbg("sysfs pair #%u matches", i);
- if (pair->operation == KEY_OP_NOMATCH)
- return -1;
- }
- }
-
- return 0;
-}
-
static int match_id(struct udev_rule *rule, struct sysfs_device *sysfs_device)
{
char path[PATH_SIZE];
@@ -570,6 +546,33 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule,
dbg(KEY_SUBSYSTEM " key is true");
}
+ if (rule->env_pair_count) {
+ int i;
+
+ dbg("check for " KEY_ENV " pairs");
+ for (i = 0; i < rule->env_pair_count; i++) {
+ struct key_pair *pair;
+ const char *value;
+
+ pair = &rule->env_pair[i];
+ value = getenv(pair->name);
+ if (!value) {
+ dbg(KEY_ENV "{'%s'} is not found", pair->name);
+ goto exit;
+ }
+ if (strcmp_pattern(pair->value, value) != 0) {
+ dbg(KEY_ENV "{'%s'} is not matching", pair->name);
+ if (pair->operation != KEY_OP_NOMATCH)
+ goto exit;
+ } else {
+ dbg(KEY_ENV "{'%s'} matches", pair->name);
+ if (pair->operation == KEY_OP_NOMATCH)
+ goto exit;
+ }
+ }
+ dbg(KEY_ENV " key is true");
+ }
+
/* walk up the chain of physical devices and find a match */
while (1) {
/* check for matching driver */
@@ -632,11 +635,23 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule,
}
/* check for matching sysfs pairs */
- if (rule->sysfs_pair[0].name[0] != '\0') {
+ if (rule->sysfs_pair_count) {
+ int i;
+
dbg("check " KEY_SYSFS " pairs");
- if (match_sysfs_pairs(rule, class_dev, sysfs_device) != 0) {
- dbg(KEY_SYSFS " is not matching");
- goto try_parent;
+ for (i = 0; i < rule->sysfs_pair_count; i++) {
+ struct key_pair *pair;
+
+ pair = &rule->sysfs_pair[i];
+ if (compare_sysfs_attribute(class_dev, sysfs_device, pair) != 0) {
+ dbg(KEY_SYSFS "{'%s'} is not matching", pair->name);
+ if (pair->operation != KEY_OP_NOMATCH)
+ goto try_parent;
+ } else {
+ dbg(KEY_SYSFS "{'%s'} matches", pair->name);
+ if (pair->operation == KEY_OP_NOMATCH)
+ goto try_parent;
+ }
}
dbg(KEY_SYSFS " keys are true");
}
diff --git a/udev_rules.h b/udev_rules.h
index 94a5d9d5fd..423a6f641e 100644
--- a/udev_rules.h
+++ b/udev_rules.h
@@ -31,11 +31,12 @@
#define KEY_KERNEL "KERNEL"
#define KEY_SUBSYSTEM "SUBSYSTEM"
#define KEY_BUS "BUS"
-#define KEY_SYSFS "SYSFS"
#define KEY_ID "ID"
#define KEY_PROGRAM "PROGRAM"
#define KEY_RESULT "RESULT"
#define KEY_DRIVER "DRIVER"
+#define KEY_SYSFS "SYSFS"
+#define KEY_ENV "ENV"
#define KEY_NAME "NAME"
#define KEY_SYMLINK "SYMLINK"
#define KEY_OWNER "OWNER"
@@ -49,6 +50,7 @@
#define OPTION_PARTITIONS "all_partitions"
#define KEY_SYSFS_PAIRS_MAX 5
+#define KEY_ENV_PAIRS_MAX 5
#define RULEFILE_SUFFIX ".rules"
@@ -85,6 +87,8 @@ struct udev_rule {
enum key_operation result_operation;
struct key_pair sysfs_pair[KEY_SYSFS_PAIRS_MAX];
int sysfs_pair_count;
+ struct key_pair env_pair[KEY_ENV_PAIRS_MAX];
+ int env_pair_count;
char name[PATH_SIZE];
char symlink[PATH_SIZE];
diff --git a/udev_rules_parse.c b/udev_rules_parse.c
index c4c684d059..face496ab3 100644
--- a/udev_rules_parse.c
+++ b/udev_rules_parse.c
@@ -278,16 +278,36 @@ static int rules_parse(struct udevice *udev, const char *filename)
goto error;
}
pair = &rule.sysfs_pair[rule.sysfs_pair_count];
- rule.sysfs_pair_count++;
-
attr = get_key_attribute(key + sizeof(KEY_SYSFS)-1);
if (attr == NULL) {
dbg("error parsing " KEY_SYSFS " attribute");
+ goto error;
+ }
+ strlcpy(pair->name, attr, sizeof(pair->name));
+ strlcpy(pair->value, value, sizeof(pair->value));
+ pair->operation = operation;
+ rule.sysfs_pair_count++;
+ valid = 1;
+ continue;
+ }
+
+ if (strncasecmp(key, KEY_ENV, sizeof(KEY_ENV)-1) == 0) {
+ struct key_pair *pair;
+
+ if (rule.env_pair_count >= KEY_ENV_PAIRS_MAX) {
+ dbg("skip rule, to many " KEY_ENV " keys in a single rule");
+ goto error;
+ }
+ pair = &rule.env_pair[rule.env_pair_count];
+ attr = get_key_attribute(key + sizeof(KEY_ENV)-1);
+ if (attr == NULL) {
+ dbg("error parsing " KEY_ENV " attribute");
continue;
}
strlcpy(pair->name, attr, sizeof(pair->name));
strlcpy(pair->value, value, sizeof(pair->value));
pair->operation = operation;
+ rule.env_pair_count++;
valid = 1;
continue;
}