summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--namedev.h10
-rw-r--r--namedev_parse.c285
-rw-r--r--test/label_test2
-rw-r--r--test/udev-test.pl22
-rw-r--r--udev.811
-rw-r--r--udev.rules.demo4
6 files changed, 143 insertions, 191 deletions
diff --git a/namedev.h b/namedev.h
index 39cf3ae641..69c488936d 100644
--- a/namedev.h
+++ b/namedev.h
@@ -49,6 +49,16 @@ enum config_type {
#define TYPE_TOPOLOGY "TOPOLOGY"
#define TYPE_REPLACE "REPLACE"
#define TYPE_CALLOUT "CALLOUT"
+
+#define FIELD_BUS "BUS"
+#define FIELD_ID "ID"
+#define FIELD_SYSFS "SYSFS_"
+#define FIELD_PLACE "PLACE"
+#define FIELD_PROGRAM "PROGRAM"
+#define FIELD_KERNEL "KERNEL"
+#define FIELD_NAME "NAME"
+#define FIELD_SYMLINK "SYMLINK"
+
#define CALLOUT_MAXARG 8
struct config_device {
diff --git a/namedev_parse.c b/namedev_parse.c
index b5d0d64b9d..3578058a76 100644
--- a/namedev_parse.c
+++ b/namedev_parse.c
@@ -45,7 +45,7 @@ int get_pair(char **orig_string, char **left, char **right)
return -ENODEV;
/* eat any whitespace */
- while (isspace(*string))
+ while (isspace(*string) || *string == ',')
++string;
/* split based on '=' */
@@ -71,19 +71,6 @@ int get_pair(char **orig_string, char **left, char **right)
return 0;
}
-static int get_value(const char *left, char **orig_string, char **ret_string)
-{
- int retval;
- char *left_string;
-
- retval = get_pair(orig_string, &left_string, ret_string);
- if (retval)
- return retval;
- if (strcasecmp(left_string, left) != 0)
- return -ENODEV;
- return 0;
-}
-
void dump_config_dev(struct config_device *dev)
{
switch (dev->type) {
@@ -169,13 +156,8 @@ int namedev_init_rules(void)
if (temp == NULL)
goto exit;
lineno++;
-
dbg_parse("read '%s'", temp);
- /* eat the whitespace at the beginning of the line */
- while (isspace(*temp))
- ++temp;
-
/* empty line? */
if (*temp == 0x00)
continue;
@@ -184,199 +166,160 @@ int namedev_init_rules(void)
if (*temp == COMMENT_CHARACTER)
continue;
+ /* eat the whitespace */
+ while (isspace(*temp))
+ ++temp;
+
memset(&dev, 0x00, sizeof(struct config_device));
- /* parse the line */
+ /* get the method */
temp2 = strsep(&temp, ",");
+
if (strcasecmp(temp2, TYPE_LABEL) == 0) {
- /* label type */
dev.type = LABEL;
-
- /* BUS="bus" */
- retval = get_value("BUS", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.bus, temp3);
-
- /* file="value" */
- temp2 = strsep(&temp, ",");
- retval = get_pair(&temp, &temp2, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.sysfs_file, temp2);
- strfieldcpy(dev.sysfs_value, temp3);
-
- /* NAME="new_name" */
- temp2 = strsep(&temp, ",");
- retval = get_value("NAME", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.name, temp3);
-
- /* SYMLINK="name" */
- temp2 = strsep(&temp, ",");
- retval = get_value("SYMLINK", &temp, &temp3);
- if (retval == 0)
- strfieldcpy(dev.symlink, temp3);
-
- dbg_parse("LABEL name='%s', bus='%s', "
- "sysfs_file='%s', sysfs_value='%s', symlink='%s'",
- dev.name, dev.bus, dev.sysfs_file,
- dev.sysfs_value, dev.symlink);
+ goto keys;
}
if (strcasecmp(temp2, TYPE_NUMBER) == 0) {
- /* number type */
dev.type = NUMBER;
-
- /* BUS="bus" */
- retval = get_value("BUS", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.bus, temp3);
-
- /* ID="id" */
- temp2 = strsep(&temp, ",");
- retval = get_value("ID", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.id, temp3);
-
- /* NAME="new_name" */
- temp2 = strsep(&temp, ",");
- retval = get_value("NAME", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.name, temp3);
-
- /* SYMLINK="name" */
- temp2 = strsep(&temp, ",");
- retval = get_value("SYMLINK", &temp, &temp3);
- if (retval == 0)
- strfieldcpy(dev.symlink, temp3);
-
- dbg_parse("NUMBER name='%s', bus='%s', id='%s', symlink='%s'",
- dev.name, dev.bus, dev.id, dev.symlink);
+ goto keys;
}
if (strcasecmp(temp2, TYPE_TOPOLOGY) == 0) {
- /* number type */
dev.type = TOPOLOGY;
-
- /* BUS="bus" */
- retval = get_value("BUS", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.bus, temp3);
-
- /* PLACE="place" */
- temp2 = strsep(&temp, ",");
- retval = get_value("PLACE", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.place, temp3);
-
- /* NAME="new_name" */
- temp2 = strsep(&temp, ",");
- retval = get_value("NAME", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.name, temp3);
-
- /* SYMLINK="name" */
- temp2 = strsep(&temp, ",");
- retval = get_value("SYMLINK", &temp, &temp3);
- if (retval == 0)
- strfieldcpy(dev.symlink, temp3);
-
- dbg_parse("TOPOLOGY name='%s', bus='%s', "
- "place='%s', symlink='%s'",
- dev.name, dev.bus, dev.place, dev.symlink);
+ goto keys;
}
if (strcasecmp(temp2, TYPE_REPLACE) == 0) {
- /* number type */
dev.type = REPLACE;
-
- /* KERNEL="kernel_name" */
- retval = get_value("KERNEL", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.kernel_name, temp3);
-
- /* NAME="new_name" */
- temp2 = strsep(&temp, ",");
- retval = get_value("NAME", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.name, temp3);
-
- /* SYMLINK="name" */
- temp2 = strsep(&temp, ",");
- retval = get_value("SYMLINK", &temp, &temp3);
- if (retval == 0)
- strfieldcpy(dev.symlink, temp3);
-
- dbg_parse("REPLACE name='%s', kernel_name='%s', symlink='%s'",
- dev.name, dev.kernel_name, dev.symlink);
+ goto keys;
}
if (strcasecmp(temp2, TYPE_CALLOUT) == 0) {
- /* number type */
dev.type = CALLOUT;
+ goto keys;
+ }
- /* BUS="bus" */
- retval = get_value("BUS", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.bus, temp3);
-
- /* PROGRAM="executable" */
- temp2 = strsep(&temp, ",");
- retval = get_value("PROGRAM", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.exec_program, temp3);
-
- /* ID="id" */
- temp2 = strsep(&temp, ",");
- retval = get_value("ID", &temp, &temp3);
- if (retval)
- break;
- strfieldcpy(dev.id, temp3);
-
- /* NAME="new_name" */
- temp2 = strsep(&temp, ",");
- retval = get_value("NAME", &temp, &temp3);
+ dbg_parse("unknown type of method '%s'", temp2);
+ goto error;
+keys:
+ /* get all known keys */
+ while (1) {
+ retval = get_pair(&temp, &temp2, &temp3);
if (retval)
break;
- strfieldcpy(dev.name, temp3);
- /* SYMLINK="name" */
- temp2 = strsep(&temp, ",");
- retval = get_value("SYMLINK", &temp, &temp3);
- if (retval == 0)
+ if (strcasecmp(temp2, FIELD_BUS) == 0) {
+ strfieldcpy(dev.bus, temp3);
+ continue;
+ }
+
+ if (strcasecmp(temp2, FIELD_ID) == 0) {
+ strfieldcpy(dev.id, temp3);
+ continue;
+ }
+
+ if (strcasecmp(temp2, FIELD_PLACE) == 0) {
+ strfieldcpy(dev.place, temp3);
+ continue;
+ }
+
+ if (strncasecmp(temp2, FIELD_SYSFS, sizeof(FIELD_SYSFS)-1) == 0) {
+ /* remove prepended 'SYSFS_' */
+ strfieldcpy(dev.sysfs_file, temp2 + sizeof(FIELD_SYSFS)-1);
+ strfieldcpy(dev.sysfs_value, temp3);
+ continue;
+ }
+
+ if (strcasecmp(temp2, FIELD_KERNEL) == 0) {
+ strfieldcpy(dev.kernel_name, temp3);
+ continue;
+ }
+
+ if (strcasecmp(temp2, FIELD_PROGRAM) == 0) {
+ strfieldcpy(dev.exec_program, temp3);
+ continue;
+ }
+
+ if (strcasecmp(temp2, FIELD_NAME) == 0) {
+ strfieldcpy(dev.name, temp3);
+ continue;
+ }
+
+ if (strcasecmp(temp2, FIELD_SYMLINK) == 0) {
strfieldcpy(dev.symlink, temp3);
+ continue;
+ }
+ dbg_parse("unknown type of field '%s'", temp2);
+ }
+
+ /* check presence of keys according to method type */
+ switch (dev.type) {
+ case LABEL:
+ dbg_parse("LABEL name='%s', bus='%s', "
+ "sysfs_file='%s', sysfs_value='%s', symlink='%s'",
+ dev.name, dev.bus, dev.sysfs_file,
+ dev.sysfs_value, dev.symlink);
+ if ((*dev.name == '\0') ||
+ (*dev.bus == '\0') ||
+ (*dev.sysfs_file == '\0') ||
+ (*dev.sysfs_value == '\0'))
+ goto error;
+ break;
+ case NUMBER:
+ dbg_parse("NUMBER name='%s', bus='%s', id='%s', symlink='%s'",
+ dev.name, dev.bus, dev.id, dev.symlink);
+ if ((*dev.name == '\0') ||
+ (*dev.bus == '\0') ||
+ (*dev.id == '\0'))
+ goto error;
+ break;
+ case TOPOLOGY:
+ dbg_parse("TOPOLOGY name='%s', bus='%s', "
+ "place='%s', symlink='%s'",
+ dev.name, dev.bus, dev.place, dev.symlink);
+ if ((*dev.name == '\0') ||
+ (*dev.bus == '\0') ||
+ (*dev.place == '\0'))
+ goto error;
+ break;
+ case REPLACE:
+ dbg_parse("REPLACE name='%s', kernel_name='%s', symlink='%s'",
+ dev.name, dev.kernel_name, dev.symlink);
+ if ((*dev.name == '\0') ||
+ (*dev.kernel_name == '\0'))
+ goto error;
+ break;
+ case CALLOUT:
dbg_parse("CALLOUT name='%s', bus='%s', program='%s', "
"id='%s', symlink='%s'",
dev.name, dev.bus, dev.exec_program,
dev.id, dev.symlink);
+ if ((*dev.name == '\0') ||
+ (*dev.bus == '\0') ||
+ (*dev.id == '\0') ||
+ (*dev.exec_program == '\0'))
+ goto error;
+ break;
+ default:
+ dbg_parse("xxx default method");
+ goto error;
}
retval = add_config_dev(&dev);
if (retval) {
dbg("add_config_dev returned with error %d", retval);
- goto exit;
+ continue;
}
}
- dbg_parse("%s:%d:%Zd: error parsing '%s'", udev_rules_filename,
- lineno, temp - line, temp);
+error:
+ dbg_parse("%s:%d:%Zd: field missing or parse error", udev_rules_filename,
+ lineno, temp - line);
exit:
fclose(fd);
return retval;
-}
-
+}
int namedev_init_permissions(void)
{
diff --git a/test/label_test b/test/label_test
index fb3fa2359f..09ccab366e 100644
--- a/test/label_test
+++ b/test/label_test
@@ -8,7 +8,7 @@ export SYSFS_PATH=$PWD/sys/
export UDEV_CONFIG_FILE=$PWD/$CONFIG
cat > $RULES << EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="boot_disk%n"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="boot_disk%n"
EOF
cat > $CONFIG << EOF
diff --git a/test/udev-test.pl b/test/udev-test.pl
index 1a35e3da82..08b99f041f 100644
--- a/test/udev-test.pl
+++ b/test/udev-test.pl
@@ -38,7 +38,7 @@ my @tests = (
devpath => "block/sda",
expected => "boot_disk" ,
conf => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="boot_disk%n"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="boot_disk%n"
REPLACE, KERNEL="ttyUSB0", NAME="visor"
EOF
},
@@ -48,7 +48,7 @@ EOF
devpath => "block/sda/sda1",
expected => "boot_disk1" ,
conf => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="boot_disk%n"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="boot_disk%n"
EOF
},
{
@@ -57,10 +57,10 @@ EOF
devpath => "block/sda/sda1",
expected => "boot_disk1" ,
conf => <<EOF
-LABEL, BUS="scsi", vendor="?IBM-ESXS", NAME="boot_disk%n-1"
-LABEL, BUS="scsi", vendor="IBM-ESXS?", NAME="boot_disk%n-2"
-LABEL, BUS="scsi", vendor="IBM-ES??", NAME="boot_disk%n"
-LABEL, BUS="scsi", vendor="IBM-ESXSS", NAME="boot_disk%n-3"
+LABEL, BUS="scsi", SYSFS_vendor="?IBM-ESXS", NAME="boot_disk%n-1"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS?", NAME="boot_disk%n-2"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ES??", NAME="boot_disk%n"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXSS", NAME="boot_disk%n-3"
EOF
},
{
@@ -167,7 +167,7 @@ EOF
devpath => "block/sda",
expected => "lun0/disc" ,
conf => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="lun0/%D"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="lun0/%D"
EOF
},
{
@@ -176,7 +176,7 @@ EOF
devpath => "block/sda/sda2",
expected => "lun0/part2" ,
conf => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="lun0/%D"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="lun0/%D"
EOF
},
{
@@ -205,7 +205,7 @@ EOF
devpath => "block/sda/sda2",
expected => "1/2/a/b/symlink" ,
conf => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="1/2/node", SYMLINK="1/2/a/b/symlink"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="1/2/node", SYMLINK="1/2/a/b/symlink"
EOF
},
{
@@ -214,7 +214,7 @@ EOF
devpath => "block/sda/sda2",
expected => "1/2/symlink" ,
conf => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/symlink"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/symlink"
EOF
},
{
@@ -223,7 +223,7 @@ EOF
devpath => "block/sda/sda2",
expected => "1/2/c/d/symlink" ,
conf => <<EOF
-LABEL, BUS="scsi", vendor="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/c/d/symlink"
+LABEL, BUS="scsi", SYSFS_vendor="IBM-ESXS", NAME="1/2/a/b/node", SYMLINK="1/2/c/d/symlink"
EOF
},
{
diff --git a/udev.8 b/udev.8
index d36145f43b..08f12908b5 100644
--- a/udev.8
+++ b/udev.8
@@ -18,7 +18,7 @@ On device creation,
.B udev
reads the sysfs directory of the given device to collect device attributes
like label, serial number or bus device number.
-These attributes are treated as a key
+These attributes are treated as a key
to determine a unique name for device file creation.
.B udev
maintains a database for devices present on the system.
@@ -87,7 +87,7 @@ The rules for udev to use when naming devices may specified at
.I /etc/udev/udev.rules
or specified by the
.I udev_rules
-value in the
+value in the
.I /etc/udev/udev.conf
file.
.P
@@ -114,8 +114,7 @@ calling external program, that returns a string to match
device label or serial number, like USB serial number, SCSI UUID or
file system label
.br
-.RB "keys: " BUS ", "
-.I sysfs_attribute
+.RB "keys: " BUS ", " SYSFS_
.TP
.B NUMBER
device number on the bus, like PCI bus id
@@ -130,7 +129,7 @@ device position on bus, like physical port of USB device
.B REPLACE
string replacement of the kernel device name
.br
-.RB "key: " KERNEL_NAME
+.RB "key: " KERNEL
.P
The methods are applied in the following order:
.BR CALLOUT ", " LABEL ", " NUMBER ", " TOPOLOGY ", " REPLACE "."
@@ -167,7 +166,7 @@ If this is not a partition, it will result in 'disc'.
CALLOUT, BUS="scsi", PROGRAM="/sbin/scsi_id", ID="OEM 0815", NAME="disk1"
# USB printer to be called lp_color
-LABEL, BUS="usb", serial="W09090207101241330", NAME="lp_color"
+LABEL, BUS="usb", SYSFS_serial="W09090207101241330", NAME="lp_color"
# sound card with PCI bus id 00:0b.0 to be called dsp
NUMBER, BUS="pci", ID="00:0b.0", NAME="dsp"
diff --git a/udev.rules.demo b/udev.rules.demo
index 6426ce2090..9ea7895791 100644
--- a/udev.rules.demo
+++ b/udev.rules.demo
@@ -1,8 +1,8 @@
# USB camera from Fuji to be named "camera"
-LABEL, BUS="usb", vendor="FUJIFILM", NAME="camera%n"
+LABEL, BUS="usb", SYSFS_vendor="FUJIFILM", NAME="camera%n"
# USB device plugged into the fourth port of the second hub to be called gps_device
-TOPOLOGY, BUS="usb", place="2.4", NAME="gps_device"
+TOPOLOGY, BUS="usb", PLACE="2.4", NAME="gps_device"
# ttyUSB1 should always be called visor
REPLACE, KERNEL="ttyUSB1", NAME="visor"