chiark / gitweb /
consistent key naming to match only the event device or include all parent devices
authorKay Sievers <kay.sievers@suse.de>
Sat, 19 Aug 2006 14:06:25 +0000 (16:06 +0200)
committerKay Sievers <kay.sievers@suse.de>
Sat, 19 Aug 2006 14:06:25 +0000 (16:06 +0200)
This scheme is more consistent and makes it obvious if a match happens
against the event device only, or the full chain of parent devices.

The old key names are now:
  BUS -> SUBSYSTEMS
  ID -> KERNELS
  SYSFS -> ATTRS
  DRIVER -> DRIVERS

Match keys for the event device:
  KERNEL
  SUBSYSTEM
  ATTR
  DRIVER (in a future release, for now the same as DRIVERS)

Match keys for all devices along the parent device chain:
  KERNELS
  SUBSYSTEMS
  ATTRS
  DRIVERS

ID, BUS, SYSFS are no longer mentioned in the man page but still work.
DRIVER must be converted to DRIVERS to match the new scheme. For now,
an error is logged, if DRIVER is used. In a future release, the DRIVER
key behaviour will change.

15 files changed:
extras/scsi_id/scsi_id.c
extras/scsi_id/scsi_serial.c
extras/usb_id/usb_id.c
test/udev-test.pl
udev.7
udev.h
udev.xml
udev_db.c
udev_device.c
udev_node.c
udev_rules.c
udev_rules.h
udev_rules_parse.c
udev_sysfs.c
udevinfo.c

index 446df70..c64e203 100644 (file)
@@ -679,7 +679,7 @@ static int scsi_id(const char *devpath, char *maj_min_dev)
                        if (reformat_serial)
                                format_serial(serial);
                        if (display_bus_id)
-                               printf("%s: ", dev_scsi->kernel_name);
+                               printf("%s: ", dev_scsi->kernel);
                        printf("%s\n", serial);
                }
                dbg("%s\n", serial);
index 0ecfebe..a0a3ae9 100644 (file)
@@ -179,7 +179,7 @@ static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io)
 
        sb_len = io->sb_len_wr;
        if (sb_len < 1) {
-               info("%s: sense buffer empty", dev_scsi->kernel_name);
+               info("%s: sense buffer empty", dev_scsi->kernel);
                return -1;
        }
 
@@ -194,7 +194,7 @@ static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io)
                s = sense_buffer[7] + 8;
                if (sb_len < s) {
                        info("%s: sense buffer too small %d bytes, %d bytes too short",
-                           dev_scsi->kernel_name, sb_len, s - sb_len);
+                           dev_scsi->kernel, sb_len, s - sb_len);
                        return -1;
                }
                if ((code == 0x0) || (code == 0x1)) {
@@ -205,7 +205,7 @@ static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io)
                                 * Possible?
                                 */
                                info("%s: sense result too" " small %d bytes",
-                                   dev_scsi->kernel_name, s);
+                                   dev_scsi->kernel, s);
                                return -1;
                        }
                        asc = sense_buffer[12];
@@ -217,25 +217,25 @@ static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io)
                        ascq = sense_buffer[3];
                } else {
                        info("%s: invalid sense code 0x%x",
-                           dev_scsi->kernel_name, code);
+                           dev_scsi->kernel, code);
                        return -1;
                }
                info("%s: sense key 0x%x ASC 0x%x ASCQ 0x%x",
-                   dev_scsi->kernel_name, sense_key, asc, ascq);
+                   dev_scsi->kernel, sense_key, asc, ascq);
        } else {
                if (sb_len < 4) {
                        info("%s: sense buffer too small %d bytes, %d bytes too short",
-                           dev_scsi->kernel_name, sb_len, 4 - sb_len);
+                           dev_scsi->kernel, sb_len, 4 - sb_len);
                        return -1;
                }
 
                if (sense_buffer[0] < 15)
-                       info("%s: old sense key: 0x%x", dev_scsi->kernel_name, sense_buffer[0] & 0x0f);
+                       info("%s: old sense key: 0x%x", dev_scsi->kernel, sense_buffer[0] & 0x0f);
                else
                        info("%s: sense = %2x %2x",
-                           dev_scsi->kernel_name, sense_buffer[0], sense_buffer[2]);
+                           dev_scsi->kernel, sense_buffer[0], sense_buffer[2]);
                info("%s: non-extended sense class %d code 0x%0x",
-                   dev_scsi->kernel_name, sense_class, code);
+                   dev_scsi->kernel, sense_class, code);
 
        }
 
@@ -247,8 +247,8 @@ static int scsi_dump_sense(struct sysfs_device *dev_scsi, struct sg_io_hdr *io)
                out_buffer[j++] = ' ';
        }
        out_buffer[j] = '\0';
-       info("%s: sense dump:", dev_scsi->kernel_name);
-       info("%s: %s", dev_scsi->kernel_name, out_buffer);
+       info("%s: sense dump:", dev_scsi->kernel);
+       info("%s: %s", dev_scsi->kernel, out_buffer);
 
 #endif
        return -1;
@@ -266,7 +266,7 @@ static int scsi_dump(struct sysfs_device *dev_scsi, struct sg_io_hdr *io)
        }
 
        info("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x",
-           dev_scsi->kernel_name, io->driver_status, io->host_status, io->msg_status, io->status);
+           dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status);
        if (io->status == SCSI_CHECK_CONDITION)
                return scsi_dump_sense(dev_scsi, io);
        else
@@ -290,7 +290,7 @@ static int scsi_inquiry(struct sysfs_device *dev_scsi, int fd,
        }
 
 resend:
-       dbg("%s evpd %d, page 0x%x\n", dev_scsi->kernel_name, evpd, page);
+       dbg("%s evpd %d, page 0x%x\n", dev_scsi->kernel, evpd, page);
 
        memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
        io_hdr.interface_id = 'S';
@@ -304,7 +304,7 @@ resend:
        io_hdr.timeout = DEF_TIMEOUT;
 
        if (ioctl(fd, SG_IO, &io_hdr) < 0) {
-               info("%s: ioctl failed: %s", dev_scsi->kernel_name, strerror(errno));
+               info("%s: ioctl failed: %s", dev_scsi->kernel, strerror(errno));
                retval = -1;
                goto error;
        }
@@ -328,7 +328,7 @@ resend:
                retval = buflen;
        } else if (retval > 0) {
                if (--retry > 0) {
-                       dbg("%s: Retrying ...\n", dev_scsi->kernel_name);
+                       dbg("%s: Retrying ...\n", dev_scsi->kernel);
                        goto resend;
                }
                retval = -1;
@@ -337,7 +337,7 @@ resend:
 error:
        if (retval < 0)
                info("%s: Unable to get INQUIRY vpd %d page 0x%x.",
-                   dev_scsi->kernel_name, evpd, page);
+                   dev_scsi->kernel, evpd, page);
 
        return retval;
 }
@@ -355,11 +355,11 @@ static int do_scsi_page0_inquiry(struct sysfs_device *dev_scsi, int fd,
                return 1;
 
        if (buffer[1] != 0) {
-               info("%s: page 0 not available.", dev_scsi->kernel_name);
+               info("%s: page 0 not available.", dev_scsi->kernel);
                return 1;
        }
        if (buffer[3] > len) {
-               info("%s: page 0 buffer too long %d", dev_scsi->kernel_name,  buffer[3]);
+               info("%s: page 0 buffer too long %d", dev_scsi->kernel,  buffer[3]);
                return 1;
        }
 
@@ -377,11 +377,11 @@ static int do_scsi_page0_inquiry(struct sysfs_device *dev_scsi, int fd,
                 */
                vendor = sysfs_attr_get_value(dev_scsi->devpath, "vendor");
                if (!vendor) {
-                       info("%s: cannot get model attribute", dev_scsi->kernel_name);
+                       info("%s: cannot get model attribute", dev_scsi->kernel);
                        return 1;
                }
                if (!strncmp((char *)&buffer[VENDOR_LENGTH], vendor, VENDOR_LENGTH)) {
-                       info("%s: invalid page0 data", dev_scsi->kernel_name);
+                       info("%s: invalid page0 data", dev_scsi->kernel);
                        return 1;
                }
        }
@@ -399,7 +399,7 @@ static int prepend_vendor_model(struct sysfs_device *dev_scsi, char *serial)
 
        attr = sysfs_attr_get_value(dev_scsi->devpath, "vendor");
        if (!attr) {
-               info("%s: cannot get vendor attribute", dev_scsi->kernel_name);
+               info("%s: cannot get vendor attribute", dev_scsi->kernel);
                return 1;
        }
        strncpy(serial, attr, VENDOR_LENGTH);
@@ -407,7 +407,7 @@ static int prepend_vendor_model(struct sysfs_device *dev_scsi, char *serial)
 
        attr = sysfs_attr_get_value(dev_scsi->devpath, "model");
        if (!attr) {
-               info("%s: cannot get model attribute", dev_scsi->kernel_name);
+               info("%s: cannot get model attribute", dev_scsi->kernel);
                return 1;
        }
        strncat(serial, attr, MODEL_LENGTH);
@@ -420,7 +420,7 @@ static int prepend_vendor_model(struct sysfs_device *dev_scsi, char *serial)
         */
        if (ind != (VENDOR_LENGTH + MODEL_LENGTH)) {
                info("%s: expected length %d, got length %d",
-                    dev_scsi->kernel_name, (VENDOR_LENGTH + MODEL_LENGTH), ind);
+                    dev_scsi->kernel, (VENDOR_LENGTH + MODEL_LENGTH), ind);
                return 1;
        }
        return ind;
@@ -478,7 +478,7 @@ static int check_fill_0x83_id(struct sysfs_device *dev_scsi,
 
        if (max_len < len) {
                info("%s: length %d too short - need %d",
-                   dev_scsi->kernel_name, max_len, len);
+                   dev_scsi->kernel, max_len, len);
                return 1;
        }
 
@@ -534,7 +534,7 @@ static int check_fill_0x83_prespc3(struct sysfs_device *dev_scsi,
                serial[j++] = hex_str[(page_83[4+i] & 0xf0) >> 4];
                serial[j++] = hex_str[ page_83[4+i] & 0x0f];
        }
-       dbg("using pre-spc3-83 for %s.\n", dev_scsi->kernel_name);
+       dbg("using pre-spc3-83 for %s.\n", dev_scsi->kernel);
        return 0;
 }
 
@@ -554,7 +554,7 @@ static int do_scsi_page83_inquiry(struct sysfs_device *dev_scsi, int fd,
                return 1;
 
        if (page_83[1] != PAGE_83) {
-               info("%s: Invalid page 0x83", dev_scsi->kernel_name);
+               info("%s: Invalid page 0x83", dev_scsi->kernel);
                return 1;
        }
        
@@ -605,7 +605,7 @@ static int do_scsi_page83_inquiry(struct sysfs_device *dev_scsi, int fd,
                        retval = check_fill_0x83_id(dev_scsi, &page_83[j],
                                                    &id_search_list[id_ind],
                                                    serial, len);
-                       dbg("%s id desc %d/%d/%d\n", dev_scsi->kernel_name,
+                       dbg("%s id desc %d/%d/%d\n", dev_scsi->kernel,
                                id_search_list[id_ind].id_type,
                                id_search_list[id_ind].naa_type,
                                id_search_list[id_ind].code_set);
@@ -643,7 +643,7 @@ static int do_scsi_page83_prespc3_inquiry(struct sysfs_device *dev_scsi, int fd,
                return 1;
 
        if (page_83[1] != PAGE_83) {
-               info("%s: Invalid page 0x83", dev_scsi->kernel_name);
+               info("%s: Invalid page 0x83", dev_scsi->kernel);
                return 1;
        }
        /*
@@ -687,7 +687,7 @@ static int do_scsi_page83_prespc3_inquiry(struct sysfs_device *dev_scsi, int fd,
                serial[j++] = hex_str[page_83[i] & 0x0f];
                i++;
        }
-       dbg("using pre-spc3-83 for %s.\n", dev_scsi->kernel_name);
+       dbg("using pre-spc3-83 for %s.\n", dev_scsi->kernel);
        return 0;
 }
 
@@ -707,14 +707,14 @@ static int do_scsi_page80_inquiry(struct sysfs_device *dev_scsi, int fd,
                return retval;
 
        if (buf[1] != PAGE_80) {
-               info("%s: Invalid page 0x80", dev_scsi->kernel_name);
+               info("%s: Invalid page 0x80", dev_scsi->kernel);
                return 1;
        }
 
        len = 1 + VENDOR_LENGTH + MODEL_LENGTH + buf[3];
        if (max_len < len) {
                info("%s: length %d too short - need %d",
-                   dev_scsi->kernel_name, max_len, len);
+                   dev_scsi->kernel, max_len, len);
                return 1;
        }
        /*
@@ -744,7 +744,7 @@ int scsi_get_serial (struct sysfs_device *dev_scsi, const char *devname,
        fd = open(devname, O_RDONLY | O_NONBLOCK);
        if (fd < 0) {
                info("%s: cannot open %s: %s",
-                   dev_scsi->kernel_name, devname, strerror(errno));
+                   dev_scsi->kernel, devname, strerror(errno));
                return 1;
        }
 
@@ -790,7 +790,7 @@ int scsi_get_serial (struct sysfs_device *dev_scsi, const char *devname,
                        goto completed;
                }
        } else if (page_code != 0x00) {
-               info("%s: unsupported page code 0x%d", dev_scsi->kernel_name, page_code);
+               info("%s: unsupported page code 0x%d", dev_scsi->kernel, page_code);
                return 1;
        }
 
@@ -808,7 +808,7 @@ int scsi_get_serial (struct sysfs_device *dev_scsi, const char *devname,
                goto completed;
        }
 
-       dbg("%s: Checking page0\n", dev_scsi->kernel_name);
+       dbg("%s: Checking page0\n", dev_scsi->kernel);
 
        for (ind = 4; ind <= page0[3] + 3; ind++)
                if (page0[ind] == PAGE_83)
@@ -834,6 +834,6 @@ int scsi_get_serial (struct sysfs_device *dev_scsi, const char *devname,
        retval = 1;
 completed:
        if (close(fd) < 0)
-               info("%s: close failed: %s", dev_scsi->kernel_name, strerror(errno));
+               info("%s: close failed: %s", dev_scsi->kernel, strerror(errno));
        return retval;
 }
index 85c6bed..ba8bfdf 100644 (file)
@@ -255,7 +255,7 @@ static int usb_id(const char *devpath)
 
        if_class = sysfs_attr_get_value(dev_interface->devpath, "bInterfaceClass");
        if (!if_class) {
-               info("%s: cannot get bInterfaceClass attribute", dev_interface->kernel_name);
+               info("%s: cannot get bInterfaceClass attribute", dev_interface->kernel);
                return 1;
        }
        if_class_num = strtoul(if_class, NULL, 16);
@@ -289,28 +289,28 @@ static int usb_id(const char *devpath)
                /* Generic SPC-2 device */
                scsi_vendor = sysfs_attr_get_value(dev_scsi->devpath, "vendor");
                if (!scsi_vendor) {
-                       info("%s: cannot get SCSI vendor attribute", dev_scsi->kernel_name);
+                       info("%s: cannot get SCSI vendor attribute", dev_scsi->kernel);
                        goto fallback;
                }
                set_str(vendor_str, scsi_vendor, sizeof(vendor_str)-1);
 
                scsi_model = sysfs_attr_get_value(dev_scsi->devpath, "model");
                if (!scsi_model) {
-                       info("%s: cannot get SCSI model attribute", dev_scsi->kernel_name);
+                       info("%s: cannot get SCSI model attribute", dev_scsi->kernel);
                        goto fallback;
                }
                set_str(model_str, scsi_model, sizeof(model_str)-1);
 
                scsi_type = sysfs_attr_get_value(dev_scsi->devpath, "type");
                if (!scsi_type) {
-                       info("%s: cannot get SCSI type attribute", dev_scsi->kernel_name);
+                       info("%s: cannot get SCSI type attribute", dev_scsi->kernel);
                        goto fallback;
                }
                set_scsi_type(type_str, scsi_type, sizeof(type_str)-1);
 
                scsi_rev = sysfs_attr_get_value(dev_scsi->devpath, "rev");
                if (!scsi_rev) {
-                       info("%s: cannot get SCSI revision attribute", dev_scsi->kernel_name);
+                       info("%s: cannot get SCSI revision attribute", dev_scsi->kernel);
                        goto fallback;
                }
                set_str(revision_str, scsi_rev, sizeof(revision_str)-1);
index 63715ac..c1c5302 100755 (executable)
@@ -1075,13 +1075,13 @@ BUS=="scsi", KERNEL=="sda", NAME="should_not_match2", SUBSYSTEM=="vc"
 EOF
        },
        {
-               desc            => "DRIVER match test",
+               desc            => "DRIVERS match test",
                subsys          => "block",
                devpath         => "/block/sda",
                exp_name        => "node",
                rules           => <<EOF
-BUS=="scsi", KERNEL=="sda", NAME="should_not_match", DRIVER=="sd-wrong"
-BUS=="scsi", KERNEL=="sda", NAME="node", DRIVER=="sd"
+BUS=="scsi", KERNEL=="sda", NAME="should_not_match", DRIVERS=="sd-wrong"
+BUS=="scsi", KERNEL=="sda", NAME="node", DRIVERS=="sd"
 EOF
        },
        {
diff --git a/udev.7 b/udev.7
index cef84de..e6828ee 100644 (file)
--- a/udev.7
+++ b/udev.7
@@ -76,27 +76,32 @@ The following key names can be used to match against device properties:
 \fBACTION\fR
 Match the name of the event action.
 .TP 3n
-\fBKERNEL\fR
-Match the name of the device.
-.TP 3n
 \fBDEVPATH\fR
-Match the devpath of the device.
+Match the devpath of the event device.
+.TP 3n
+\fBKERNEL\fR
+Match the name of the event device.
 .TP 3n
 \fBSUBSYSTEM\fR
-Match the subsystem of the device.
+Match the subsystem of the event device.
+.TP 3n
+\fBATTR{\fR\fB\fIfilename\fR\fR\fB}\fR
+Match sysfs attribute values of the event device. Up to five
+\fBATTR\fR
+keys can be specified per rule. Trailing whitespace in the attribute values is ignored, if the specified match value does not contain trailing whitespace itself.
 .TP 3n
-\fBBUS\fR
+\fBKERNELS\fR
+Search the devpath upwards for a matching device name.
+.TP 3n
+\fBSUBSYSTEMS\fR
 Search the devpath upwards for a matching device subsystem name.
 .TP 3n
-\fBDRIVER\fR
+\fBDRIVERS\fR
 Search the devpath upwards for a matching device driver name.
 .TP 3n
-\fBID\fR
-Search the devpath upwards for a matching device name.
-.TP 3n
-\fBSYSFS{\fR\fB\fIfilename\fR\fR\fB}\fR
+\fBATTRS{\fR\fB\fIfilename\fR\fR\fB}\fR
 Search the devpath upwards for a device with matching sysfs attribute values. Up to five
-\fBSYSFS\fR
+\fBATTRS\fR
 keys can be specified per rule. All attributes must match on the same device. Trailing whitespace in the attribute values is ignored, if the specified match value does not contain trailing whitespace itself.
 .TP 3n
 \fBENV{\fR\fB\fIkey\fR\fR\fB}\fR
@@ -187,13 +192,13 @@ The devpath of the device.
 .TP 3n
 \fB$id\fR, \fB%b\fR
 The name of the device matched while searching the devpath upwards for
-\fBBUS\fR,
-\fBID\fR
-\fBDRIVER\fR
+\fBSUBSYSTEMS\fR,
+\fBKERNELS\fR
+\fBDRIVERS\fR
 and
-\fBSYSFS\fR.
+\fBATTRS\fR.
 .TP 3n
-\fB$sysfs{\fR\fB\fIfile\fR\fR\fB}\fR, \fB%s{\fR\fB\fIfile\fR\fR\fB}\fR
+\fB$attr{\fR\fB\fIfile\fR\fR\fB}\fR, \fB%s{\fR\fB\fIfile\fR\fR\fB}\fR
 The value of a sysfs attribute found at the current or a parent device.
 .TP 3n
 \fB$env{\fR\fB\fIkey\fR\fR\fB}\fR, \fB%E{\fR\fB\fIkey\fR\fR\fB}\fR
diff --git a/udev.h b/udev.h
index a69ce08..d681ad5 100644 (file)
--- a/udev.h
+++ b/udev.h
@@ -54,8 +54,8 @@ struct sysfs_device {
        struct list_head node;                  /* for device cache */
        struct sysfs_device *parent;            /* already cached parent*/
        char devpath[PATH_SIZE];
-       char subsystem[NAME_SIZE];              /* $class/$bus/"drivers" */
-       char kernel_name[NAME_SIZE];            /* device instance name */
+       char subsystem[NAME_SIZE];              /* $class, $bus, drivers, module */
+       char kernel[NAME_SIZE];                 /* device instance name */
        char kernel_number[NAME_SIZE];
        char driver[NAME_SIZE];                 /* device driver name */
 };
index 01e9d52..8434156 100644 (file)
--- a/udev.xml
+++ b/udev.xml
             </varlistentry>
 
             <varlistentry>
-              <term><option>KERNEL</option></term>
+              <term><option>DEVPATH</option></term>
               <listitem>
-                <para>Match the name of the device.</para>
+                <para>Match the devpath of the event device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>DEVPATH</option></term>
+              <term><option>KERNEL</option></term>
               <listitem>
-                <para>Match the devpath of the device.</para>
+                <para>Match the name of the event device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>SUBSYSTEM</option></term>
               <listitem>
-                <para>Match the subsystem of the device.</para>
+                <para>Match the subsystem of the event device.</para>
+              </listitem>
+            </varlistentry>
+<!--
+            <varlistentry>
+              <term><option>DRIVER</option></term>
+              <listitem>
+                <para>Match the driver name of the event device. Only set for devices created by a bus driver.</para>
+              </listitem>
+            </varlistentry>
+-->
+            <varlistentry>
+              <term><option>ATTR{<replaceable>filename</replaceable>}</option></term>
+              <listitem>
+                <para>Match sysfs attribute values of the event device. Up to five
+                <option>ATTR</option> keys can be specified per rule. Trailing
+                whitespace in the attribute values is ignored, if the specified match
+                value does not contain trailing whitespace itself.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>BUS</option></term>
+              <term><option>KERNELS</option></term>
               <listitem>
-                <para>Search the devpath upwards for a matching device subsystem name.</para>
+                <para>Search the devpath upwards for a matching device name.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>DRIVER</option></term>
+              <term><option>SUBSYSTEMS</option></term>
               <listitem>
-                <para>Search the devpath upwards for a matching device driver name.</para>
+                <para>Search the devpath upwards for a matching device subsystem name.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>ID</option></term>
+              <term><option>DRIVERS</option></term>
               <listitem>
-                <para>Search the devpath upwards for a matching device name.</para>
+                <para>Search the devpath upwards for a matching device driver name.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>SYSFS{<replaceable>filename</replaceable>}</option></term>
+              <term><option>ATTRS{<replaceable>filename</replaceable>}</option></term>
               <listitem>
                 <para>Search the devpath upwards for a device with matching sysfs attribute values.
-                Up to five <option>SYSFS</option> keys can be specified per rule. All attributes
+                Up to five <option>ATTRS</option> keys can be specified per rule. All attributes
                 must match on the same device. Trailing whitespace in the attribute values is ignored,
                 if the specified match value does not contain trailing whitespace itself.</para>
               </listitem>
               <term><option>$id</option>, <option>%b</option></term>
               <listitem>
                 <para>The name of the device matched while searching the devpath upwards for
-                  <option>BUS</option>, <option>ID</option> <option>DRIVER</option> and <option>SYSFS</option>.
+                  <option>SUBSYSTEMS</option>, <option>KERNELS</option> <option>DRIVERS</option> and <option>ATTRS</option>.
                 </para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>$sysfs{<replaceable>file</replaceable>}</option>, <option>%s{<replaceable>file</replaceable>}</option></term>
+              <term><option>$attr{<replaceable>file</replaceable>}</option>, <option>%s{<replaceable>file</replaceable>}</option></term>
               <listitem>
                 <para>The value of a sysfs attribute found at the current or a parent device.</para>
               </listitem>
index b058351..c3034f5 100644 (file)
--- a/udev_db.c
+++ b/udev_db.c
@@ -81,7 +81,7 @@ int udev_db_add_device(struct udevice *udev)
         * create only a symlink with the name as the target
         * if we don't have any interesting data to remember
         */
-       if (strcmp(udev->name, udev->dev->kernel_name) == 0 &&
+       if (strcmp(udev->name, udev->dev->kernel) == 0 &&
            list_empty(&udev->symlink_list) && list_empty(&udev->env_list) &&
            !udev->partitions && !udev->ignore_remove) {
                dbg("nothing interesting to store, create symlink");
index 87f90c7..b680246 100644 (file)
@@ -87,7 +87,7 @@ static int rename_netif(struct udevice *udev)
        struct ifreq ifr;
        int retval;
 
-       info("changing net interface name from '%s' to '%s'", udev->dev->kernel_name, udev->name);
+       info("changing net interface name from '%s' to '%s'", udev->dev->kernel, udev->name);
        if (udev->test_run)
                return 0;
 
@@ -98,7 +98,7 @@ static int rename_netif(struct udevice *udev)
        }
 
        memset(&ifr, 0x00, sizeof(struct ifreq));
-       strlcpy(ifr.ifr_name, udev->dev->kernel_name, IFNAMSIZ);
+       strlcpy(ifr.ifr_name, udev->dev->kernel, IFNAMSIZ);
        strlcpy(ifr.ifr_newname, udev->name, IFNAMSIZ);
        retval = ioctl(sk, SIOCSIFNAME, &ifr);
        if (retval != 0) {
@@ -111,7 +111,7 @@ static int rename_netif(struct udevice *udev)
                }
 
                /* free our own name, another process may wait for us */
-               strlcpy(ifr.ifr_newname, udev->dev->kernel_name, IFNAMSIZ);
+               strlcpy(ifr.ifr_newname, udev->dev->kernel, IFNAMSIZ);
                strlcat(ifr.ifr_newname, "_rename", IFNAMSIZ);
                retval = ioctl(sk, SIOCSIFNAME, &ifr);
                if (retval != 0) {
@@ -211,7 +211,7 @@ int udev_device_event(struct udev_rules *rules, struct udevice *udev)
                }
 
                /* look if we want to change the name of the netif */
-               if (strcmp(udev->name, udev->dev->kernel_name) != 0) {
+               if (strcmp(udev->name, udev->dev->kernel) != 0) {
                        char *pos;
 
                        retval = rename_netif(udev);
@@ -220,14 +220,14 @@ int udev_device_event(struct udev_rules *rules, struct udevice *udev)
                        info("renamed netif to '%s'", udev->name);
 
                        /* export old name */
-                       setenv("INTERFACE_OLD", udev->dev->kernel_name, 1);
+                       setenv("INTERFACE_OLD", udev->dev->kernel, 1);
 
                        /* now fake the devpath, because the kernel name changed silently */
                        pos = strrchr(udev->dev->devpath, '/');
                        if (pos != NULL) {
                                pos[1] = '\0';
                                strlcat(udev->dev->devpath, udev->name, sizeof(udev->dev->devpath));
-                               strlcpy(udev->dev->kernel_name, udev->name, sizeof(udev->dev->kernel_name));
+                               strlcpy(udev->dev->kernel, udev->name, sizeof(udev->dev->kernel));
                                setenv("DEVPATH", udev->dev->devpath, 1);
                                setenv("INTERFACE", udev->name, 1);
                        }
@@ -250,8 +250,8 @@ int udev_device_event(struct udev_rules *rules, struct udevice *udev)
                        list_for_each_entry(name_loop, &udev->env_list, node)
                                putenv(name_loop->name);
                } else {
-                       dbg("'%s' not found in database, using kernel name '%s'", udev->dev->devpath, udev->dev->kernel_name);
-                       strlcpy(udev->name, udev->dev->kernel_name, sizeof(udev->name));
+                       dbg("'%s' not found in database, using kernel name '%s'", udev->dev->devpath, udev->dev->kernel);
+                       strlcpy(udev->name, udev->dev->kernel, sizeof(udev->name));
                }
 
                udev_rules_get_run(rules, udev);
index 12a738e..4ba1c26 100644 (file)
@@ -51,7 +51,7 @@ int udev_node_mknod(struct udevice *udev, const char *file, dev_t devt, mode_t m
        /* preserve node with already correct numbers, to prevent changing the inode number */
        if ((stats.st_mode & S_IFMT) == (mode & S_IFMT) && (stats.st_rdev == devt)) {
                info("preserve file '%s', because it has correct dev_t", file);
-               selinux_setfilecon(file, udev->dev->kernel_name, stats.st_mode);
+               selinux_setfilecon(file, udev->dev->kernel, stats.st_mode);
                goto perms;
        }
 
@@ -61,7 +61,7 @@ int udev_node_mknod(struct udevice *udev, const char *file, dev_t devt, mode_t m
                dbg("already present file '%s' unlinked", file);
 
 create:
-       selinux_setfscreatecon(file, udev->dev->kernel_name, mode);
+       selinux_setfscreatecon(file, udev->dev->kernel, mode);
        retval = mknod(file, mode, devt);
        selinux_resetfscreatecon();
        if (retval != 0) {
index 979b81d..4930629 100644 (file)
@@ -307,13 +307,13 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
        enum subst_type {
                SUBST_UNKNOWN,
                SUBST_DEVPATH,
+               SUBST_KERNEL,
                SUBST_KERNEL_NUMBER,
-               SUBST_KERNEL_NAME,
                SUBST_ID,
                SUBST_MAJOR,
                SUBST_MINOR,
                SUBST_RESULT,
-               SUBST_SYSFS,
+               SUBST_ATTR,
                SUBST_PARENT,
                SUBST_TEMP_NODE,
                SUBST_ROOT,
@@ -324,18 +324,19 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
                char fmt;
                enum subst_type type;
        } map[] = {
-               { .name = "devpath",            .fmt = 'p',     .type = SUBST_DEVPATH },
-               { .name = "number",             .fmt = 'n',     .type = SUBST_KERNEL_NUMBER },
-               { .name = "kernel",             .fmt = 'k',     .type = SUBST_KERNEL_NAME },
-               { .name = "id",                 .fmt = 'b',     .type = SUBST_ID },
-               { .name = "major",              .fmt = 'M',     .type = SUBST_MAJOR },
-               { .name = "minor",              .fmt = 'm',     .type = SUBST_MINOR },
-               { .name = "result",             .fmt = 'c',     .type = SUBST_RESULT },
-               { .name = "sysfs",              .fmt = 's',     .type = SUBST_SYSFS },
-               { .name = "parent",             .fmt = 'P',     .type = SUBST_PARENT },
-               { .name = "tempnode",           .fmt = 'N',     .type = SUBST_TEMP_NODE },
-               { .name = "root",               .fmt = 'r',     .type = SUBST_ROOT },
-               { .name = "env",                .fmt = 'E',     .type = SUBST_ENV },
+               { .name = "devpath",    .fmt = 'p',     .type = SUBST_DEVPATH },
+               { .name = "number",     .fmt = 'n',     .type = SUBST_KERNEL_NUMBER },
+               { .name = "kernel",     .fmt = 'k',     .type = SUBST_KERNEL },
+               { .name = "id",         .fmt = 'b',     .type = SUBST_ID },
+               { .name = "major",      .fmt = 'M',     .type = SUBST_MAJOR },
+               { .name = "minor",      .fmt = 'm',     .type = SUBST_MINOR },
+               { .name = "result",     .fmt = 'c',     .type = SUBST_RESULT },
+               { .name = "attr",       .fmt = 's',     .type = SUBST_ATTR },
+               { .name = "sysfs",      .fmt = 's',     .type = SUBST_ATTR },
+               { .name = "parent",     .fmt = 'P',     .type = SUBST_PARENT },
+               { .name = "tempnode",   .fmt = 'N',     .type = SUBST_TEMP_NODE },
+               { .name = "root",       .fmt = 'r',     .type = SUBST_ROOT },
+               { .name = "env",        .fmt = 'E',     .type = SUBST_ENV },
                { NULL, '\0', 0 }
        };
        enum subst_type type;
@@ -399,9 +400,9 @@ found:
                        strlcat(string, udev->dev->devpath, maxsize);
                        dbg("substitute devpath '%s'", udev->dev->devpath);
                        break;
-               case SUBST_KERNEL_NAME:
-                       strlcat(string, udev->dev->kernel_name, maxsize);
-                       dbg("substitute kernel name '%s'", udev->dev->kernel_name);
+               case SUBST_KERNEL:
+                       strlcat(string, udev->dev->kernel, maxsize);
+                       dbg("substitute kernel name '%s'", udev->dev->kernel);
                        break;
                case SUBST_KERNEL_NUMBER:
                        strlcat(string, udev->dev->kernel_number, maxsize);
@@ -409,8 +410,8 @@ found:
                        break;
                case SUBST_ID:
                        if (udev->dev_parent != NULL) {
-                               strlcat(string, udev->dev_parent->kernel_name, maxsize);
-                               dbg("substitute id '%s'", udev->dev_parent->kernel_name);
+                               strlcat(string, udev->dev_parent->kernel, maxsize);
+                               dbg("substitute id '%s'", udev->dev_parent->kernel);
                        }
                        break;
                case SUBST_MAJOR:
@@ -457,7 +458,7 @@ found:
                                dbg("substitute result string '%s'", udev->program_result);
                        }
                        break;
-               case SUBST_SYSFS:
+               case SUBST_ATTR:
                        if (attr == NULL) {
                                dbg("missing attribute");
                                break;
@@ -605,7 +606,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
        if (match_key("ACTION", rule, &rule->action, udev->action))
                goto nomatch;
 
-       if (match_key("KERNEL", rule, &rule->kernel_name, udev->dev->kernel_name))
+       if (match_key("KERNEL", rule, &rule->kernel, udev->dev->kernel))
                goto nomatch;
 
        if (match_key("SUBSYSTEM", rule, &rule->subsystem, udev->dev->subsystem))
@@ -614,7 +615,10 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
        if (match_key("DEVPATH", rule, &rule->devpath, udev->dev->devpath))
                goto nomatch;
 
-       /* compare NAME against a previously assigned value */
+       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;
 
@@ -646,26 +650,57 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                }
        }
 
+       /* check for matching sysfs attrubute pairs */
+       if (rule->attr.count) {
+               dbg("check %i ATTR keys", rule->attr.count);
+               for (i = 0; i < rule->attr.count; i++) {
+                       struct key_pair *pair = &rule->attr.keys[i];
+                       const char *key_name = key_pair_name(rule, pair);
+                       const char *key_value = key_val(rule, &pair->key);
+                       const char *value;
+                       char val[VALUE_SIZE];
+                       size_t len;
+
+                       value = sysfs_attr_get_value(udev->dev->devpath, key_name);
+                       if (value == NULL)
+                               goto nomatch;
+                       strlcpy(val, value, sizeof(val));
+
+                       /* strip trailing whitespace of value, if not asked to match for it */
+                       len = strlen(key_value);
+                       if (len > 0 && !isspace(key_value[len-1])) {
+                               len = strlen(val);
+                               while (len > 0 && isspace(val[len-1]))
+                                       val[--len] = '\0';
+                               dbg("removed %zi trailing whitespace chars from '%s'", strlen(val)-len, val);
+                       }
+
+                       if (match_key("ATTR", rule, &pair->key, val))
+                               goto nomatch;
+               }
+               dbg("all %i ATTR keys matched", rule->attr.count);
+       }
+
        /* walk up the chain of parent devices and find a match */
        udev->dev_parent = udev->dev;
        while (1) {
-               /* check for matching driver */
-               if (match_key("DRIVER", rule, &rule->driver, udev->dev_parent->driver))
+               /* check for matching kernel device name */
+               if (match_key("KERNELS", rule, &rule->kernels, udev->dev_parent->kernel))
                        goto try_parent;
 
-               /* check for matching subsystem/bus value */
-               if (match_key("BUS", rule, &rule->bus, udev->dev_parent->subsystem))
+               /* check for matching subsystem value */
+               if (match_key("SUBSYSTEMS", rule, &rule->subsystems, udev->dev_parent->subsystem))
                        goto try_parent;
 
-               /* check for matching bus id (device name) */
-               if (match_key("ID", rule, &rule->id, udev->dev_parent->kernel_name))
+               /* check for matching driver */
+               if (match_key("DRIVERS", rule, &rule->drivers, udev->dev_parent->driver))
                        goto try_parent;
 
-               /* check for matching sysfs pairs */
-               if (rule->sysfs.count) {
-                       dbg("check %i SYSFS keys", rule->sysfs.count);
-                       for (i = 0; i < rule->sysfs.count; i++) {
-                               struct key_pair *pair = &rule->sysfs.keys[i];
+               /* check for matching sysfs attrubute pairs */
+               if (rule->attrs.count) {
+                       dbg("check %i ATTRS keys", rule->attrs.count);
+                       for (i = 0; i < rule->attrs.count; i++) {
+                               struct key_pair *pair = &rule->attrs.keys[i];
                                const char *key_name = key_pair_name(rule, pair);
                                const char *key_value = key_val(rule, &pair->key);
                                const char *value;
@@ -688,10 +723,10 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                                        dbg("removed %zi trailing whitespace chars from '%s'", strlen(val)-len, val);
                                }
 
-                               if (match_key("SYSFS", rule, &pair->key, val))
+                               if (match_key("ATTRS", rule, &pair->key, val))
                                        goto try_parent;
                        }
-                       dbg("all %i SYSFS keys matched", rule->sysfs.count);
+                       dbg("all %i ATTRS keys matched", rule->attrs.count);
                }
 
                /* found matching device  */
@@ -703,7 +738,7 @@ try_parent:
                if (udev->dev_parent == NULL)
                        goto nomatch;
                dbg("looking at dev_parent->devpath='%s'", udev->dev_parent->devpath);
-               dbg("looking at dev_parent->bus_kernel_name='%s'", udev->dev_parent->kernel_name);
+               dbg("looking at dev_parent->kernel='%s'", udev->dev_parent->kernel);
        }
 
        /* execute external program */
@@ -794,7 +829,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
        int name_set = 0;
 
        dbg("udev->dev->devpath='%s'", udev->dev->devpath);
-       dbg("udev->dev->kernel_name='%s'", udev->dev->kernel_name);
+       dbg("udev->dev->kernel='%s'", udev->dev->kernel);
 
        /* look for a matching rule to apply */
        udev_rules_iter_init(rules);
@@ -815,7 +850,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
                if (match_rule(udev, rule) == 0) {
                        /* apply options */
                        if (rule->ignore_device) {
-                               info("rule applied, '%s' is ignored", udev->dev->kernel_name);
+                               info("rule applied, '%s' is ignored", udev->dev->kernel);
                                udev->ignore_device = 1;
                                return 0;
                        }
@@ -835,21 +870,21 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
                                if (rule->mode_operation == KEY_OP_ASSIGN_FINAL)
                                        udev->mode_final = 1;
                                udev->mode = rule->mode;
-                               dbg("applied mode=%#o to '%s'", rule->mode, udev->dev->kernel_name);
+                               dbg("applied mode=%#o to '%s'", rule->mode, udev->dev->kernel);
                        }
                        if (!udev->owner_final && rule->owner.operation != KEY_OP_UNSET) {
                                if (rule->owner.operation == KEY_OP_ASSIGN_FINAL)
                                        udev->owner_final = 1;
                                strlcpy(udev->owner, key_val(rule, &rule->owner), sizeof(udev->owner));
                                udev_rules_apply_format(udev, udev->owner, sizeof(udev->owner));
-                               dbg("applied owner='%s' to '%s'", udev->owner, udev->dev->kernel_name);
+                               dbg("applied owner='%s' to '%s'", udev->owner, udev->dev->kernel);
                        }
                        if (!udev->group_final && rule->group.operation != KEY_OP_UNSET) {
                                if (rule->group.operation == KEY_OP_ASSIGN_FINAL)
                                        udev->group_final = 1;
                                strlcpy(udev->group, key_val(rule, &rule->group), sizeof(udev->group));
                                udev_rules_apply_format(udev, udev->group, sizeof(udev->group));
-                               dbg("applied group='%s' to '%s'", udev->group, udev->dev->kernel_name);
+                               dbg("applied group='%s' to '%s'", udev->group, udev->dev->kernel);
                        }
 
                        /* collect symlinks */
@@ -904,7 +939,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
                                if (count)
                                        info("%i untrusted character(s) replaced", count);
 
-                               info("rule applied, '%s' becomes '%s'", udev->dev->kernel_name, udev->name);
+                               info("rule applied, '%s' becomes '%s'", udev->dev->kernel, udev->name);
                                if (strcmp(udev->dev->subsystem, "net") != 0)
                                        dbg("name, '%s' is going to have owner='%s', group='%s', mode=%#o partitions=%i",
                                            udev->name, udev->owner, udev->group, udev->mode, udev->partitions);
@@ -934,7 +969,7 @@ int udev_rules_get_name(struct udev_rules *rules, struct udevice *udev)
        }
 
        if (!name_set) {
-               strlcpy(udev->name, udev->dev->kernel_name, sizeof(udev->name));
+               strlcpy(udev->name, udev->dev->kernel, sizeof(udev->name));
                info("no node name set, will use kernel name '%s'", udev->name);
        }
 
@@ -951,7 +986,7 @@ int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev)
 {
        struct udev_rule *rule;
 
-       dbg("udev->kernel_name='%s'", udev->dev->kernel_name);
+       dbg("udev->kernel='%s'", udev->dev->kernel);
 
        /* look for a matching rule to apply */
        udev_rules_iter_init(rules);
@@ -969,7 +1004,7 @@ int udev_rules_get_run(struct udev_rules *rules, struct udevice *udev)
 
                if (match_rule(udev, rule) == 0) {
                        if (rule->ignore_device) {
-                               info("rule applied, '%s' is ignored", udev->dev->kernel_name);
+                               info("rule applied, '%s' is ignored", udev->dev->kernel);
                                udev->ignore_device = 1;
                                return 0;
                        }
index 2c956fc..dac0dfc 100644 (file)
@@ -60,30 +60,34 @@ enum import_type {
 };
 
 struct udev_rule {
-       struct key label;
-       struct key goto_label;
-       struct key kernel_name;
-       struct key subsystem;
        struct key action;
        struct key devpath;
-       struct key bus;
-       struct key id;
+       struct key kernel;
+       struct key subsystem;
        struct key driver;
+       struct key_pairs attr;
+
+       struct key kernels;
+       struct key subsystems;
+       struct key drivers;
+       struct key_pairs attrs;
+
+       struct key_pairs env;
        struct key program;
        struct key result;
        struct key import;
        enum import_type import_type;
+       struct key run;
        struct key wait_for_sysfs;
-       struct key_pairs sysfs;
-       struct key_pairs env;
+       struct key label;
+       struct key goto_label;
 
        struct key name;
        struct key symlink;
-       struct key run;
        struct key owner;
        struct key group;
-       enum key_operation mode_operation;
        mode_t mode;
+       enum key_operation mode_operation;
 
        unsigned int partitions;
        unsigned int last_rule:1,
index 8d69e74..5e93e60 100644 (file)
@@ -263,14 +263,24 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
                if (retval)
                        break;
 
-               if (strcasecmp(key, "LABEL") == 0) {
-                       add_rule_key(rule, &rule->label, operation, value);
+               if (strcasecmp(key, "ACTION") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid ACTION operation");
+                               goto invalid;
+                       }
+                       add_rule_key(rule, &rule->action, operation, value);
                        valid = 1;
                        continue;
                }
 
-               if (strcasecmp(key, "GOTO") == 0) {
-                       add_rule_key(rule, &rule->goto_label, operation, value);
+               if (strcasecmp(key, "DEVPATH") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid DEVPATH operation");
+                               goto invalid;
+                       }
+                       add_rule_key(rule, &rule->devpath, operation, value);
                        valid = 1;
                        continue;
                }
@@ -281,7 +291,7 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
                                err("invalid KERNEL operation");
                                goto invalid;
                        }
-                       add_rule_key(rule, &rule->kernel_name, operation, value);
+                       add_rule_key(rule, &rule->kernel, operation, value);
                        valid = 1;
                        continue;
                }
@@ -297,68 +307,84 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
                        continue;
                }
 
-               if (strcasecmp(key, "ACTION") == 0) {
+               if (strcasecmp(key, "DRIVER") == 0) {
                        if (operation != KEY_OP_MATCH &&
                            operation != KEY_OP_NOMATCH) {
-                               err("invalid ACTION operation");
+                               err("invalid DRIVER operation");
                                goto invalid;
                        }
-                       add_rule_key(rule, &rule->action, operation, value);
+                       err("DRIVER== will change in a future relase, "
+                           "please use DRIVERS== in %s:%u", filename, lineno);
+                       /* FIXME: this should be rule->driver to match only the event device */
+                       add_rule_key(rule, &rule->drivers, operation, value);
                        valid = 1;
                        continue;
                }
 
-               if (strcasecmp(key, "DEVPATH") == 0) {
+               if (strncasecmp(key, "ATTR", sizeof("ATTR")-1) == 0) {
                        if (operation != KEY_OP_MATCH &&
                            operation != KEY_OP_NOMATCH) {
-                               err("invalid DEVPATH operation");
+                               err("invalid ATTR operation");
                                goto invalid;
                        }
-                       add_rule_key(rule, &rule->devpath, operation, value);
+                       attr = get_key_attribute(key + sizeof("ATTR")-1);
+                       if (attr == NULL) {
+                               err("error parsing ATTR attribute in '%s'", line);
+                               continue;
+                       }
+                       add_rule_key_pair(rule, &rule->attr, operation, attr, value);
                        valid = 1;
                        continue;
                }
 
-               if (strcasecmp(key, "BUS") == 0) {
+               if (strcasecmp(key, "KERNELS") == 0 ||
+                   strcasecmp(key, "ID") == 0) {
                        if (operation != KEY_OP_MATCH &&
                            operation != KEY_OP_NOMATCH) {
-                               err("invalid BUS operation");
+                               err("invalid KERNELS operation");
                                goto invalid;
                        }
-                       add_rule_key(rule, &rule->bus, operation, value);
+                       add_rule_key(rule, &rule->kernels, operation, value);
                        valid = 1;
                        continue;
                }
 
-               if (strcasecmp(key, "ID") == 0) {
+               if (strcasecmp(key, "SUBSYTEMS") == 0 ||
+                   strcasecmp(key, "BUS") == 0) {
                        if (operation != KEY_OP_MATCH &&
                            operation != KEY_OP_NOMATCH) {
-                               err("invalid ID operation");
+                               err("invalid SUBSYSTEMS operation");
                                goto invalid;
                        }
-                       add_rule_key(rule, &rule->id, operation, value);
+                       add_rule_key(rule, &rule->subsystems, operation, value);
                        valid = 1;
                        continue;
                }
 
-               if (strncasecmp(key, "SYSFS", sizeof("SYSFS")-1) == 0) {
+               if (strcasecmp(key, "DRIVERS") == 0) {
                        if (operation != KEY_OP_MATCH &&
                            operation != KEY_OP_NOMATCH) {
-                               err("invalid SYSFS operation");
+                               err("invalid DRIVERS operation");
                                goto invalid;
                        }
-                       attr = get_key_attribute(key + sizeof("SYSFS")-1);
-                       if (attr == NULL) {
-                               err("error parsing SYSFS attribute in '%s'", line);
-                               continue;
-                       }
-                       add_rule_key_pair(rule, &rule->sysfs, operation, attr, value);
+                       add_rule_key(rule, &rule->drivers, operation, value);
                        valid = 1;
                        continue;
                }
 
-               if (strcasecmp(key, "WAIT_FOR_SYSFS") == 0) {
-                       add_rule_key(rule, &rule->wait_for_sysfs, operation, value);
+               if (strncasecmp(key, "ATTRS", sizeof("ATTRS")-1) == 0 ||
+                   strncasecmp(key, "SYSFS", sizeof("SYSFS")-1) == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid ATTRSS operation");
+                               goto invalid;
+                       }
+                       attr = get_key_attribute(key + sizeof("ATTRS")-1);
+                       if (attr == NULL) {
+                               err("error parsing ATTRS attribute in '%s'", line);
+                               continue;
+                       }
+                       add_rule_key_pair(rule, &rule->attrs, operation, attr, value);
                        valid = 1;
                        continue;
                }
@@ -374,6 +400,23 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
                        continue;
                }
 
+               if (strcasecmp(key, "PROGRAM") == 0) {
+                       add_rule_key(rule, &rule->program, operation, value);
+                       valid = 1;
+                       continue;
+               }
+
+               if (strcasecmp(key, "RESULT") == 0) {
+                       if (operation != KEY_OP_MATCH &&
+                           operation != KEY_OP_NOMATCH) {
+                               err("invalid RESULT operation");
+                               goto invalid;
+                       }
+                       add_rule_key(rule, &rule->result, operation, value);
+                       valid = 1;
+                       continue;
+               }
+
                if (strncasecmp(key, "IMPORT", sizeof("IMPORT")-1) == 0) {
                        attr = get_key_attribute(key + sizeof("IMPORT")-1);
                        if (attr && strstr(attr, "program")) {
@@ -419,30 +462,26 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
                        continue;
                }
 
-               if (strcasecmp(key, "DRIVER") == 0) {
-                       if (operation != KEY_OP_MATCH &&
-                           operation != KEY_OP_NOMATCH) {
-                               err("invalid DRIVER operation");
-                               goto invalid;
-                       }
-                       add_rule_key(rule, &rule->driver, operation, value);
+               if (strcasecmp(key, "RUN") == 0) {
+                       add_rule_key(rule, &rule->run, operation, value);
                        valid = 1;
                        continue;
                }
 
-               if (strcasecmp(key, "RESULT") == 0) {
-                       if (operation != KEY_OP_MATCH &&
-                           operation != KEY_OP_NOMATCH) {
-                               err("invalid RESULT operation");
-                               goto invalid;
-                       }
-                       add_rule_key(rule, &rule->result, operation, value);
+               if (strcasecmp(key, "WAIT_FOR_SYSFS") == 0) {
+                       add_rule_key(rule, &rule->wait_for_sysfs, operation, value);
                        valid = 1;
                        continue;
                }
 
-               if (strcasecmp(key, "PROGRAM") == 0) {
-                       add_rule_key(rule, &rule->program, operation, value);
+               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;
                }
@@ -516,12 +555,6 @@ static int add_to_rules(struct udev_rules *rules, char *line, const char *filena
                        continue;
                }
 
-               if (strcasecmp(key, "RUN") == 0) {
-                       add_rule_key(rule, &rule->run, operation, value);
-                       valid = 1;
-                       continue;
-               }
-
                if (strcasecmp(key, "OPTIONS") == 0) {
                        if (strstr(value, "last_rule") != NULL) {
                                dbg("last rule to be applied");
index 85ea4d1..c4afe0c 100644 (file)
@@ -95,11 +95,11 @@ void sysfs_device_set_values(struct sysfs_device *dev, const char *devpath,
        if (pos == NULL)
                return;
 
-       strlcpy(dev->kernel_name, &pos[1], sizeof(dev->kernel_name));
-       dbg("kernel_name='%s'", dev->kernel_name);
+       strlcpy(dev->kernel, &pos[1], sizeof(dev->kernel));
+       dbg("kernel='%s'", dev->kernel);
 
        /* some devices have '!' in their name, change that to '/' */
-       pos = dev->kernel_name;
+       pos = dev->kernel;
        while (pos[0] != '\0') {
                if (pos[0] == '!')
                        pos[0] = '/';
@@ -107,7 +107,7 @@ void sysfs_device_set_values(struct sysfs_device *dev, const char *devpath,
        }
 
        /* get kernel number */
-       pos = &dev->kernel_name[strlen(dev->kernel_name)];
+       pos = &dev->kernel[strlen(dev->kernel)];
        while (isdigit(pos[-1]))
                pos--;
        strlcpy(dev->kernel_number, pos, sizeof(dev->kernel_number));
index 1a10f9a..d6f5640 100644 (file)
@@ -45,7 +45,7 @@ void log_message (int priority, const char *format, ...)
 }
 #endif
 
-static void print_all_attributes(const char *devpath)
+static void print_all_attributes(const char *devpath, const char *key)
 {
        char path[PATH_SIZE];
        DIR *dir;
@@ -80,7 +80,7 @@ static void print_all_attributes(const char *devpath)
                        }
 
                        replace_untrusted_chars(value);
-                       printf("    SYSFS{%s}==\"%s\"\n", dent->d_name, value);
+                       printf("    %s{%s}==\"%s\"\n", key, dent->d_name, value);
                }
        }
        printf("\n");
@@ -103,10 +103,10 @@ static int print_device_chain(const char *devpath)
                return -1;
 
        printf("  looking at device '%s':\n", dev->devpath);
-       printf("    KERNEL==\"%s\"\n", dev->kernel_name);
+       printf("    KERNEL==\"%s\"\n", dev->kernel);
        printf("    SUBSYSTEM==\"%s\"\n", dev->subsystem);
        printf("    DRIVER==\"%s\"\n", dev->driver);
-       print_all_attributes(dev->devpath);
+       print_all_attributes(dev->devpath, "ATTR");
 
        /* walk up the chain of devices */
        while (1) {
@@ -114,11 +114,11 @@ static int print_device_chain(const char *devpath)
                if (dev == NULL)
                        break;
                printf("  looking at parent device '%s':\n", dev->devpath);
-               printf("    ID==\"%s\"\n", dev->kernel_name);
-               printf("    BUS==\"%s\"\n", dev->subsystem);
-               printf("    DRIVER==\"%s\"\n", dev->driver);
+               printf("    KERNELS==\"%s\"\n", dev->kernel);
+               printf("    SUBSYTEMS==\"%s\"\n", dev->subsystem);
+               printf("    DRIVERS==\"%s\"\n", dev->driver);
 
-               print_all_attributes(dev->devpath);
+               print_all_attributes(dev->devpath, "ATTRS");
        }
 
        return 0;