chiark / gitweb /
[PATCH] don't rely on field order in namedev_parse
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Wed, 17 Dec 2003 07:36:19 +0000 (23:36 -0800)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:13:08 +0000 (21:13 -0700)
  o change the parsing to get a key from the rule and sort it
    into our list of known keys instead of expecting a special order
  o the key to match a sysfs file must be prependend by 'SYSFS_' now
    to match with the new parsing.
    (The config must be changed, but it's a bit more descriptive too.)
  o put names of fields in define's, like the name of the methods
  o update all tests and the man page

namedev.h
namedev_parse.c
test/label_test
test/udev-test.pl
udev.8
udev.rules.demo

index 39cf3ae..69c4889 100644 (file)
--- 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 {
index b5d0d64..3578058 100644 (file)
@@ -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)
 {
index fb3fa23..09ccab3 100644 (file)
@@ -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
index 1a35e3d..08b99f0 100644 (file)
@@ -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 d36145f..08f1290 100644 (file)
--- 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"
index 6426ce2..9ea7895 100644 (file)
@@ -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"