chiark / gitweb /
fix BUS, ID, $id usage
authorKay Sievers <kay.sievers@suse.de>
Mon, 16 Jan 2006 05:12:49 +0000 (06:12 +0100)
committerKay Sievers <kay.sievers@suse.de>
Mon, 16 Jan 2006 05:12:49 +0000 (06:12 +0100)
Signed-off-by: Kay Sievers <kay.sievers@suse.de>
TODO
docs/udev.xml
test/udev-test.pl
udev.8
udev.h
udev_rules.c

diff --git a/TODO b/TODO
index 19aae9edf0a82b5e511b651a1e2cd9c874383474..bdd2e1e1f6947c17b4174c22ed80370a5401208e 100644 (file)
--- a/TODO
+++ b/TODO
@@ -4,12 +4,6 @@ These things need to be done, or would be nice to have:
     to syslog, so any error logged from the kernel can be associated with
     any of the links at that time.
 
     to syslog, so any error logged from the kernel can be associated with
     any of the links at that time.
 
-  o Fix inconsistency with KERNEL and ID. ID will walk up the device chain
-    but it matches on "KERNEL names" too. And ID and SYSFS can only match
-    on the same device in the chain. That's pretty hard to explain and to
-    understand. Same for SUBSYSTEM and BUS.
-
-
 These things are deprecated and scheduled for removal in a future
 udev version:
 
 These things are deprecated and scheduled for removal in a future
 udev version:
 
index 7f6a30df521de55a379bf8c8b957b59f09ff03d5..ab8174e6a9649b31361182590e6b5de47679c68a 100644 (file)
             <varlistentry>
               <term><option>ACTION</option></term>
               <listitem>
             <varlistentry>
               <term><option>ACTION</option></term>
               <listitem>
-                <para>Match the kernel action name.</para>
+                <para>Match the name of the event action.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>KERNEL</option></term>
               <listitem>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>KERNEL</option></term>
               <listitem>
-                <para>Match the kernel device name</para>
+                <para>Match the name of the device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>DEVPATH</option></term>
               <listitem>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>DEVPATH</option></term>
               <listitem>
-                <para>Match the kernel devpath.</para>
+                <para>Match the devpath of the device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>SUBSYSTEM</option></term>
               <listitem>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>SUBSYSTEM</option></term>
               <listitem>
-                <para>Match the kernel subsystem name</para>
+                <para>Match the subsystem of the device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>BUS</option></term>
               <listitem>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>BUS</option></term>
               <listitem>
-                <para>Match the type of bus the device is connected to.</para>
+                <para>Search the devpath upwards for a matching device subsystem name.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>DRIVER</option></term>
               <listitem>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>DRIVER</option></term>
               <listitem>
-                <para>Match the kernel driver name.</para>
+                <para>Search the devpath upwards for a matching device driver name.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>ID</option></term>
               <listitem>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>ID</option></term>
               <listitem>
-                <para>Match the device number on the bus.</para>
+                <para>Search the devpath upwards for a matching device name.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>ENV{<replaceable>key</replaceable>}</option></term>
+              <term><option>SYSFS{<replaceable>filename</replaceable>}</option></term>
               <listitem>
               <listitem>
-                <para>Match against the value of an environment key. Depending on
-                the specified operation, this key is also used as an assignment.</para>
+                <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
+                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>
             </varlistentry>
 
             <varlistentry>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>SYSFS{<replaceable>filename</replaceable>}</option></term>
+              <term><option>ENV{<replaceable>key</replaceable>}</option></term>
               <listitem>
               <listitem>
-                <para>Match the sysfs attribute value. Up to five values can be specified.
-                Trailing whitespace is ignored, if the specified match value does not contain
-                trailing whitespace itself.</para>
+                <para>Match against the value of an environment variable. Up to five <option>ENV</option>
+                keys can be specified per rule. This key can also be used to export a variable to
+                the environment.</para>
               </listitem>
             </varlistentry>
 
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>ENV{<replaceable>key</replaceable>}</option></term>
               <listitem>
             <varlistentry>
               <term><option>ENV{<replaceable>key</replaceable>}</option></term>
               <listitem>
-                <para>Export the key to the environment. Depending on the specified
-                operation, this key is also used as a match.</para>
+                <para>Export a variable to the environment. This key can also be used to match
+                against an environment variable.</para>
               </listitem>
             </varlistentry>
 
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <term><option>IMPORT{<replaceable>type</replaceable>}</option></term>
               <listitem>
             <varlistentry>
               <term><option>IMPORT{<replaceable>type</replaceable>}</option></term>
               <listitem>
-                <para>Import the printed result or the content of a file in environment key
+                <para>Import the printed result or the value of a file in environment key
                 format into the event environment. <option>program</option> will execute an
                 external program and read its output. <option>file</option> will inport a
                 text file. If no option is given, udev will determine it from the  executable
                 format into the event environment. <option>program</option> will execute an
                 external program and read its output. <option>file</option> will inport a
                 text file. If no option is given, udev will determine it from the  executable
             <varlistentry>
               <term><option>WAIT_FOR_SYSFS</option></term>
               <listitem>
             <varlistentry>
               <term><option>WAIT_FOR_SYSFS</option></term>
               <listitem>
-                <para>Wait for the specified sysfs file of the device to be created. May be used
-                to fight agains timing issues wth the kernel.</para>
+                <para>Wait for the specified sysfs file of the device to be created. Can be used
+                to fight against kernel sysfs timing issues.</para>
               </listitem>
             </varlistentry>
 
               </listitem>
             </varlistentry>
 
           printf-like string substitutions:</para>
           <variablelist>
             <varlistentry>
           printf-like string substitutions:</para>
           <variablelist>
             <varlistentry>
-              <term><option>%k</option>, <option>$kernel</option></term>
+              <term><option>$kernel</option>, <option>%k</option></term>
               <listitem>
                 <para>The kernel name for this device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <listitem>
                 <para>The kernel name for this device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>%n</option>, <option>$number</option></term>
+              <term><option>$number</option>, <option>%n</option></term>
               <listitem>
                 <para>The kernel number for this device. For example, 'sda3' has
                 kernel number of '3'</para>
               <listitem>
                 <para>The kernel number for this device. For example, 'sda3' has
                 kernel number of '3'</para>
             </varlistentry>
 
             <varlistentry>
             </varlistentry>
 
             <varlistentry>
-              <term><option>%p</option>, <option>$devpath</option></term>
+              <term><option>$devpath</option>, <option>%p</option></term>
               <listitem>
                 <para>The devpath of the device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <listitem>
                 <para>The devpath of the device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>%s{<replaceable>file</replaceable>}</option>, <option>$sysfs{<replaceable>file</replaceable>}</option></term>
+              <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>.
+                </para>
+              </listitem>
+            </varlistentry>
+
+            <varlistentry>
+              <term><option>$sysfs{<replaceable>file</replaceable>}</option>, <option>%s{<replaceable>file</replaceable>}</option></term>
               <listitem>
               <listitem>
-                <para>The content of a sysfs attribute.</para>
+                <para>The value of a sysfs attribute found at the current or a parent device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>%E{<replaceable>key</replaceable>}</option>, <option>$env{<replaceable>key</replaceable>}</option></term>
+              <term><option>$env{<replaceable>key</replaceable>}</option>, <option>%E{<replaceable>key</replaceable>}</option></term>
               <listitem>
                 <para>The value of an environment variable.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <listitem>
                 <para>The value of an environment variable.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>%m</option>, <option>$major</option></term>
+              <term><option>$major</option>, <option>%M</option></term>
               <listitem>
                 <para>The kernel major number for the device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <listitem>
                 <para>The kernel major number for the device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>%M</option> <option>$minor</option></term>
+              <term><option>$minor</option> <option>%m</option></term>
               <listitem>
                 <para>The kernel minor number for the device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <listitem>
                 <para>The kernel minor number for the device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>%c</option>, <option>$result</option></term>
+              <term><option>$result</option>, <option>%c</option></term>
               <listitem>
                 <para>The string returned by the external program requested with PROGRAM.
                 A single part of the string, separated by a space character may be selected
               <listitem>
                 <para>The string returned by the external program requested with PROGRAM.
                 A single part of the string, separated by a space character may be selected
             </varlistentry>
 
             <varlistentry>
             </varlistentry>
 
             <varlistentry>
-              <term><option>%P</option>, <option>$parent</option></term>
+              <term><option>$parent</option>, <option>%P</option></term>
               <listitem>
                 <para>The node name of the parent device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <listitem>
                 <para>The node name of the parent device.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>%r</option>, <option>$root</option></term>
+              <term><option>$root</option>, <option>%r</option></term>
               <listitem>
                 <para>The udev_root value.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
               <listitem>
                 <para>The udev_root value.</para>
               </listitem>
             </varlistentry>
 
             <varlistentry>
-              <term><option>%N</option>, <option>$tempnode</option></term>
+              <term><option>$tempnode</option>, <option>%N</option></term>
               <listitem>
                 <para>The name of a created temporary device node to provide access to
                 the device from a external program before the real node is created.</para>
               <listitem>
                 <para>The name of a created temporary device node to provide access to
                 the device from a external program before the real node is created.</para>
index 7ce920092fc05b0a99d888ca592ef84f62a01a5e..555d36e7f20837edad75874c9944a4beec46b054 100755 (executable)
@@ -231,7 +231,7 @@ KERNEL=="ttyUSB0", NAME="sub/direct/ory/visor"
 EOF
        },
        {
 EOF
        },
        {
-               desc            => "place on bus of scsi partition",
+               desc            => "parent device name match of scsi partition",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
                exp_name        => "first_disk3" ,
                subsys          => "block",
                devpath         => "/block/sda/sda3",
                exp_name        => "first_disk3" ,
@@ -243,18 +243,18 @@ EOF
                desc            => "test substitution chars",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
                desc            => "test substitution chars",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
-               exp_name        => "Major:8:minor:3:kernelnumber:3" ,
+               exp_name        => "Major:8:minor:3:kernelnumber:3:id:0:0:0:0" ,
                rules           => <<EOF
                rules           => <<EOF
-BUS=="scsi", ID=="0:0:0:0", NAME="Major:%M:minor:%m:kernelnumber:%n"
+BUS=="scsi", ID=="0:0:0:0", NAME="Major:%M:minor:%m:kernelnumber:%n:id:%b"
 EOF
        },
        {
                desc            => "test substitution chars (with length limit)",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
 EOF
        },
        {
                desc            => "test substitution chars (with length limit)",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
-               exp_name        => "M8-m3-n3-bsd-sIBM" ,
+               exp_name        => "M8-m3-n3-b0:0-sIBM" ,
                rules           => <<EOF
                rules           => <<EOF
-BUS=="scsi", ID=="0:0:0:0", NAME="M%M-m%m-n%n-b%2k-s%3s{vendor}"
+BUS=="scsi", ID=="0:0:0:0", NAME="M%M-m%m-n%n-b%3b-s%3s{vendor}"
 EOF
        },
        {
 EOF
        },
        {
@@ -322,9 +322,9 @@ EOF
                desc            => "program result substitution",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
                desc            => "program result substitution",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
-               exp_name        => "test-3" ,
+               exp_name        => "test-0:0:0:0" ,
                rules           => <<EOF
                rules           => <<EOF
-BUS=="scsi", PROGRAM=="/bin/echo -n test-%n", RESULT=="test-3*", NAME="%c"
+BUS=="scsi", PROGRAM=="/bin/echo -n test-%b", RESULT=="test-0:0*", NAME="%c"
 EOF
        },
        {
 EOF
        },
        {
@@ -385,27 +385,27 @@ EOF
                desc            => "test substitution by variable name",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
                desc            => "test substitution by variable name",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
-               exp_name        => "Major:8-minor:3-kernelnumber:3,
+               exp_name        => "Major:8-minor:3-kernelnumber:3-id:0:0:0:0",
                rules           => <<EOF
                rules           => <<EOF
-BUS=="scsi", ID=="0:0:0:0", NAME="Major:\$major-minor:\$minor-kernelnumber:\$number"
+BUS=="scsi", ID=="0:0:0:0", NAME="Major:\$major-minor:\$minor-kernelnumber:\$number-id:\$id"
 EOF
        },
        {
                desc            => "test substitution by variable name 2",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
 EOF
        },
        {
                desc            => "test substitution by variable name 2",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
-               exp_name        => "Major:8-minor:3-kernelnumber:3-name:sda3" ,
+               exp_name        => "Major:8-minor:3-kernelnumber:3-id:0:0:0:0",
                rules           => <<EOF
                rules           => <<EOF
-BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="Major:\$major-minor:%m-kernelnumber:\$number-name:\$kernel"
+BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="Major:\$major-minor:%m-kernelnumber:\$number-id:\$id"
 EOF
        },
        {
                desc            => "test substitution by variable name 3",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
 EOF
        },
        {
                desc            => "test substitution by variable name 3",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
-               exp_name        => "83sda33" ,
+               exp_name        => "830:0:0:03" ,
                rules           => <<EOF
                rules           => <<EOF
-BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="%M%m%k%n"
+BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="%M%m%b%n"
 EOF
        },
        {
 EOF
        },
        {
@@ -421,33 +421,23 @@ EOF
                desc            => "test substitution by variable name 5",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
                desc            => "test substitution by variable name 5",
                subsys          => "block",
                devpath         => "/block/sda/sda3",
-               exp_name        => "833sda3" ,
+               exp_name        => "8330:0:0:0" ,
                rules           => <<EOF
                rules           => <<EOF
-BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="\$major%m%n\$kernel"
+BUS=="scsi", ID=="0:0:0:0", DEVPATH="*/sda/*", NAME="\$major%m%n\$id"
 EOF
        },
        {
 EOF
        },
        {
-               desc            => "invalid program for device with no bus",
+               desc            => "non matching BUS for device with no parent",
                subsys          => "tty",
                devpath         => "/class/tty/console",
                subsys          => "tty",
                devpath         => "/class/tty/console",
-               exp_name        => "TTY" ,
+               exp_name        => "TTY",
                rules           => <<EOF
 BUS=="scsi", PROGRAM=="/bin/echo -n foo", RESULT=="foo", NAME="foo"
 KERNEL=="console", NAME="TTY"
 EOF
        },
        {
                rules           => <<EOF
 BUS=="scsi", PROGRAM=="/bin/echo -n foo", RESULT=="foo", NAME="foo"
 KERNEL=="console", NAME="TTY"
 EOF
        },
        {
-               desc            => "valid program for device with no bus",
-               subsys          => "tty",
-               devpath         => "/class/tty/console",
-               exp_name        => "foo" ,
-               rules           => <<EOF
-PROGRAM=="/bin/echo -n foo", RESULT=="foo", NAME="foo"
-KERNEL=="console", NAME="TTY"
-EOF
-       },
-       {
-               desc            => "invalid label for device with no bus",
+               desc            => "non matching BUS",
                subsys          => "tty",
                devpath         => "/class/tty/console",
                exp_name        => "TTY" ,
                subsys          => "tty",
                devpath         => "/class/tty/console",
                exp_name        => "TTY" ,
@@ -457,7 +447,7 @@ KERNEL=="console", NAME="TTY"
 EOF
        },
        {
 EOF
        },
        {
-               desc            => "valid label for device with no bus",
+               desc            => "SYSFS match",
                subsys          => "tty",
                devpath         => "/class/tty/console",
                exp_name        => "foo" ,
                subsys          => "tty",
                devpath         => "/class/tty/console",
                exp_name        => "foo" ,
@@ -470,11 +460,11 @@ EOF
                desc            => "program and bus type match",
                subsys          => "block",
                devpath         => "/block/sda",
                desc            => "program and bus type match",
                subsys          => "block",
                devpath         => "/block/sda",
-               exp_name        => "scsi-sda" ,
+               exp_name        => "scsi-0:0:0:0" ,
                rules           => <<EOF
                rules           => <<EOF
-BUS=="usb", PROGRAM=="/bin/echo -n usb-%k", NAME="%c"
-BUS=="scsi", PROGRAM=="/bin/echo -n scsi-%k", NAME="%c"
-BUS=="foo", PROGRAM=="/bin/echo -n foo-%k", NAME="%c"
+BUS=="usb", PROGRAM=="/bin/echo -n usb-%b", NAME="%c"
+BUS=="scsi", PROGRAM=="/bin/echo -n scsi-%b", NAME="%c"
+BUS=="foo", PROGRAM=="/bin/echo -n foo-%b", NAME="%c"
 EOF
        },
        {
 EOF
        },
        {
@@ -797,7 +787,7 @@ EOF
                exp_name        => "symlink2-ttyUSB0",
                exp_target      => "ttyUSB0",
                rules           => <<EOF
                exp_name        => "symlink2-ttyUSB0",
                exp_target      => "ttyUSB0",
                rules           => <<EOF
-KERNEL=="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="symlink1-%n symlink2-%k"
+KERNEL=="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK="symlink1-%n symlink2-%k symlink3-%b"
 EOF
        },
        {
 EOF
        },
        {
@@ -918,13 +908,13 @@ KERNEL=="ttyUSB[0-9]*", NAME="ttyUSB%n", SYMLINK+="major-%M:%m"
 EOF
        },
        {
 EOF
        },
        {
-               desc            => "symlink %k substitution",
+               desc            => "symlink %b substitution",
                subsys          => "block",
                devpath         => "/block/sda",
                subsys          => "block",
                devpath         => "/block/sda",
-               exp_name        => "symlink-sda",
+               exp_name        => "symlink-0:0:0:0",
                exp_target      => "node",
                rules           => <<EOF
                exp_target      => "node",
                rules           => <<EOF
-BUS=="scsi", KERNEL=="sda", NAME="node", SYMLINK+="symlink-%k"
+BUS=="scsi", KERNEL=="sda", NAME="node", SYMLINK+="symlink-%b"
 EOF
        },
        {
 EOF
        },
        {
@@ -1564,13 +1554,6 @@ sub udev {
 
        $ENV{DEVPATH} = $devpath;
 
 
        $ENV{DEVPATH} = $devpath;
 
-       open my $fd, "$sysfs$devpath/dev";
-       my $dev = <$fd>;
-       close $fd;
-       $dev =~ m/^(.+):(.+)$/;
-       $ENV{MAJOR} = $1;
-       $ENV{MINOR} = $2;
-
        # create temporary rules
        open CONF, ">$udev_rules" || die "unable to create rules file: $udev_rules";
        print CONF $$rules;
        # create temporary rules
        open CONF, ">$udev_rules" || die "unable to create rules file: $udev_rules";
        print CONF $$rules;
diff --git a/udev.8 b/udev.8
index 6d2f5e679eda9588b3f32c36ec0aed6801cbf103..8eb63c20150763d2b84290fc59efed7efd8533dc 100644 (file)
--- a/udev.8
+++ b/udev.8
@@ -70,31 +70,35 @@ Assign a value to a key finally; disallow any later changes, which may be used t
 The following key names can be used to match against device properties:
 .TP
 \fBACTION\fR
 The following key names can be used to match against device properties:
 .TP
 \fBACTION\fR
-Match the kernel action name.
+Match the name of the event action.
 .TP
 \fBKERNEL\fR
 .TP
 \fBKERNEL\fR
-Match the kernel device name
+Match the name of the device.
 .TP
 \fBDEVPATH\fR
 .TP
 \fBDEVPATH\fR
-Match the kernel devpath.
+Match the devpath of the device.
 .TP
 \fBSUBSYSTEM\fR
 .TP
 \fBSUBSYSTEM\fR
-Match the kernel subsystem name
+Match the subsystem of the device.
 .TP
 \fBBUS\fR
 .TP
 \fBBUS\fR
-Match the type of bus the device is connected to.
+Search the devpath upwards for a matching device subsystem name.
 .TP
 \fBDRIVER\fR
 .TP
 \fBDRIVER\fR
-Match the kernel driver name.
+Search the devpath upwards for a matching device driver name.
 .TP
 \fBID\fR
 .TP
 \fBID\fR
-Match the device number on the bus.
-.TP
-\fBENV{\fR\fB\fIkey\fR\fR\fB}\fR
-Match against the value of an environment key. Depending on the specified operation, this key is also used as an assignment.
+Search the devpath upwards for a matching device name.
 .TP
 \fBSYSFS{\fR\fB\fIfilename\fR\fR\fB}\fR
 .TP
 \fBSYSFS{\fR\fB\fIfilename\fR\fR\fB}\fR
-Match the sysfs attribute value. Up to five values can be specified. Trailing whitespace is ignored, if the specified match value does not contain trailing whitespace itself.
+Search the devpath upwards for a device with matching sysfs attribute values. Up to five 
+\fBSYSFS\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
+\fBENV{\fR\fB\fIkey\fR\fR\fB}\fR
+Match against the value of an environment variable. Up to five 
+\fBENV\fR 
+keys can be specified per rule. This key can also be used to export a variable to the environment.
 .TP
 \fBPROGRAM\fR
 Execute external program. The key is true, if the program returns without exit code zero. The whole event environment is available to the executed program. The program's output printed to stdout is available for the RESULT key.
 .TP
 \fBPROGRAM\fR
 Execute external program. The key is true, if the program returns without exit code zero. The whole event environment is available to the executed program. The program's output printed to stdout is available for the RESULT key.
@@ -125,7 +129,7 @@ The name of a symlink targeting the node. Every matching rule can add this value
 The permissions for the device node. Every specified value overwrites the compiled\-in default value.
 .TP
 \fBENV{\fR\fB\fIkey\fR\fR\fB}\fR
 The permissions for the device node. Every specified value overwrites the compiled\-in default value.
 .TP
 \fBENV{\fR\fB\fIkey\fR\fR\fB}\fR
-Export the key to the environment. Depending on the specified operation, this key is also used as a match.
+Export a variable to the environment. This key can also be used to match against an environment variable.
 .TP
 \fBRUN\fR
 Add a program to the list of programs to be executed for a specific device.
 .TP
 \fBRUN\fR
 Add a program to the list of programs to be executed for a specific device.
@@ -137,14 +141,14 @@ Named label where a GOTO can jump to.
 Jumps to the next LABEL with a matching gname
 .TP
 \fBIMPORT{\fR\fB\fItype\fR\fR\fB}\fR
 Jumps to the next LABEL with a matching gname
 .TP
 \fBIMPORT{\fR\fB\fItype\fR\fR\fB}\fR
-Import the printed result or the content of a file in environment key format into the event environment. 
+Import the printed result or the value of a file in environment key format into the event environment. 
 \fBprogram\fR 
 will execute an external program and read its output. 
 \fBfile\fR 
 will inport a text file. If no option is given, udev will determine it from the executable bit of of the file permissions.
 .TP
 \fBWAIT_FOR_SYSFS\fR
 \fBprogram\fR 
 will execute an external program and read its output. 
 \fBfile\fR 
 will inport a text file. If no option is given, udev will determine it from the executable bit of of the file permissions.
 .TP
 \fBWAIT_FOR_SYSFS\fR
-Wait for the specified sysfs file of the device to be created. May be used to fight agains timing issues wth the kernel.
+Wait for the specified sysfs file of the device to be created. Can be used to fight against kernel sysfs timing issues.
 .TP
 \fBOPTIONS\fR
 \fBlast_rule\fR 
 .TP
 \fBOPTIONS\fR
 \fBlast_rule\fR 
@@ -165,42 +169,46 @@ and
 \fBGROUP\fR 
 fields support simple printf\-like string substitutions:
 .TP
 \fBGROUP\fR 
 fields support simple printf\-like string substitutions:
 .TP
-\fB%k\fR, \fB$kernel\fR
+\fB$kernel\fR, \fB%k\fR
 The kernel name for this device.
 .TP
 The kernel name for this device.
 .TP
-\fB%b\fR, \fB$id\fR
-The kernel bus id for this device.
-.TP
-\fB%n\fR, \fB$number\fR
+\fB$number\fR, \fB%n\fR
 The kernel number for this device. For example, 'sda3' has kernel number of '3'
 .TP
 The kernel number for this device. For example, 'sda3' has kernel number of '3'
 .TP
-\fB%p\fR, \fB$devpath\fR
+\fB$devpath\fR, \fB%p\fR
 The devpath of the device.
 .TP
 The devpath of the device.
 .TP
-\fB%s{\fR\fB\fIfile\fR\fR\fB}\fR, \fB$sysfs{\fR\fB\fIfile\fR\fR\fB}\fR
-The content of a sysfs attribute.
+\fB$id\fR, \fB%b\fR
+The name of the device matched while searching the devpath upwards for 
+\fBBUS\fR, 
+\fBID\fR \fBDRIVER\fR 
+and 
+\fBSYSFS\fR.
+.TP
+\fB$sysfs{\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
 .TP
-\fB%E{\fR\fB\fIkey\fR\fR\fB}\fR, \fB$env{\fR\fB\fIkey\fR\fR\fB}\fR
+\fB$env{\fR\fB\fIkey\fR\fR\fB}\fR, \fB%E{\fR\fB\fIkey\fR\fR\fB}\fR
 The value of an environment variable.
 .TP
 The value of an environment variable.
 .TP
-\fB%m\fR, \fB$major\fR
+\fB$major\fR, \fB%M\fR
 The kernel major number for the device.
 .TP
 The kernel major number for the device.
 .TP
-\fB%M\fR \fB$minor\fR
+\fB$minor\fR \fB%m\fR
 The kernel minor number for the device.
 .TP
 The kernel minor number for the device.
 .TP
-\fB%c\fR, \fB$result\fR
+\fB$result\fR, \fB%c\fR
 The string returned by the external program requested with PROGRAM. A single part of the string, separated by a space character may be selected by specifying the part number as an attribute: 
 \fB%c{N}\fR. If the number is followed by the '+' char this part plus all remaining parts of the result string are substituted: 
 \fB%c{N+}\fR
 .TP
 The string returned by the external program requested with PROGRAM. A single part of the string, separated by a space character may be selected by specifying the part number as an attribute: 
 \fB%c{N}\fR. If the number is followed by the '+' char this part plus all remaining parts of the result string are substituted: 
 \fB%c{N+}\fR
 .TP
-\fB%P\fR, \fB$parent\fR
+\fB$parent\fR, \fB%P\fR
 The node name of the parent device.
 .TP
 The node name of the parent device.
 .TP
-\fB%r\fR, \fB$root\fR
+\fB$root\fR, \fB%r\fR
 The udev_root value.
 .TP
 The udev_root value.
 .TP
-\fB%N\fR, \fB$tempnode\fR
+\fB$tempnode\fR, \fB%N\fR
 The name of a created temporary device node to provide access to the device from a external program before the real node is created.
 .TP
 \fB%%\fR
 The name of a created temporary device node to provide access to the device from a external program before the real node is created.
 .TP
 \fB%%\fR
diff --git a/udev.h b/udev.h
index 6dc0c9e3547b2f48bf4cbf0d23be84d28f7c4796..5d54b5443248c894f142169de404bad78d8f4086 100644 (file)
--- a/udev.h
+++ b/udev.h
 #include "udev_libc_wrapper.h"
 #include "udev_version.h"
 
 #include "udev_libc_wrapper.h"
 #include "udev_version.h"
 
-#define COMMENT_CHARACTER              '#'
-#define PATH_TO_NAME_CHAR              '@'
-#define LINE_SIZE                      512
-#define NAME_SIZE                      128
-#define PATH_SIZE                      256
-#define USER_SIZE                      32
-#define SEQNUM_SIZE                    32
-#define VALUE_SIZE                     128
-
-#define DEFAULT_PARTITIONS_COUNT       15
-#define UDEV_ALARM_TIMEOUT             180
+#define COMMENT_CHARACTER                      '#'
+#define PATH_TO_NAME_CHAR                      '@'
+#define LINE_SIZE                              512
+#define NAME_SIZE                              128
+#define PATH_SIZE                              256
+#define USER_SIZE                              32
+#define SEQNUM_SIZE                            32
+#define VALUE_SIZE                             128
+
+#define DEFAULT_PARTITIONS_COUNT               15
+#define UDEV_ALARM_TIMEOUT                     180
 
 #define UDEV_MAX(a,b) ((a) > (b) ? (a) : (b))
 
 /* pipes */
 
 #define UDEV_MAX(a,b) ((a) > (b) ? (a) : (b))
 
 /* pipes */
-#define READ_END                       0
-#define WRITE_END                      1
+#define READ_END                               0
+#define WRITE_END                              1
 
 
-#define DB_DIR                         ".udev/db"
+#define DB_DIR                                 ".udev/db"
 
 struct udev_rules;
 
 struct sysfs_device {
 
 struct udev_rules;
 
 struct sysfs_device {
-       struct list_head node;          /* for device cache */
+       struct list_head node;                  /* for device cache */
        char devpath[PATH_SIZE];
        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" */
+       char kernel_name[NAME_SIZE];            /* device instance name */
        char kernel_number[NAME_SIZE];
        char kernel_number[NAME_SIZE];
-       char driver[NAME_SIZE];         /* device driver name */
+       char driver[NAME_SIZE];                 /* device driver name */
 };
 
 struct udevice {
        /* device event */
 };
 
 struct udevice {
        /* device event */
-       struct sysfs_device *dev;       /* points to dev_local by default */
+       struct sysfs_device *dev;               /* points to dev_local by default */
        struct sysfs_device dev_local;
        struct sysfs_device dev_local;
+       struct sysfs_device *dev_parent;        /* current parent device used for matching */
        char action[NAME_SIZE];
 
        /* node */
        char action[NAME_SIZE];
 
        /* node */
index fc1f3c9c3d02d27097ffaaaf4f6993cb71e76354..e9d8d7560e74f53b7edd3e23f9dd7541eb93d4b5 100644 (file)
@@ -376,6 +376,7 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize)
                SUBST_DEVPATH,
                SUBST_KERNEL_NUMBER,
                SUBST_KERNEL_NAME,
                SUBST_DEVPATH,
                SUBST_KERNEL_NUMBER,
                SUBST_KERNEL_NAME,
+               SUBST_ID,
                SUBST_MAJOR,
                SUBST_MINOR,
                SUBST_RESULT,
                SUBST_MAJOR,
                SUBST_MINOR,
                SUBST_RESULT,
@@ -395,6 +396,7 @@ static void apply_format(struct udevice *udev, char *string, size_t maxsize)
                { .name = "devpath",            .fmt = 'p',     .type = SUBST_DEVPATH },
                { .name = "number",             .fmt = 'n',     .type = SUBST_KERNEL_NUMBER },
                { .name = "kernel",             .fmt = 'k',     .type = SUBST_KERNEL_NAME },
                { .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 = "major",              .fmt = 'M',     .type = SUBST_MAJOR },
                { .name = "minor",              .fmt = 'm',     .type = SUBST_MINOR },
                { .name = "result",             .fmt = 'c',     .type = SUBST_RESULT },
@@ -477,6 +479,12 @@ found:
                        strlcat(string, udev->dev->kernel_number, maxsize);
                        dbg("substitute kernel number '%s'", udev->dev->kernel_number);
                        break;
                        strlcat(string, udev->dev->kernel_number, maxsize);
                        dbg("substitute kernel number '%s'", udev->dev->kernel_number);
                        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);
+                       }
+                       break;
                case SUBST_MAJOR:
                        sprintf(temp2, "%d", major(udev->devt));
                        strlcat(string, temp2, maxsize);
                case SUBST_MAJOR:
                        sprintf(temp2, "%d", major(udev->devt));
                        strlcat(string, temp2, maxsize);
@@ -681,20 +689,19 @@ static int match_key(const char *key_name, struct udev_rule *rule, struct key *k
 /* match a single rule against a given device and possibly its parent devices */
 static int match_rule(struct udevice *udev, struct udev_rule *rule)
 {
 /* match a single rule against a given device and possibly its parent devices */
 static int match_rule(struct udevice *udev, struct udev_rule *rule)
 {
-       struct sysfs_device *dev_parent;
        int i;
 
        if (match_key("ACTION", rule, &rule->action, udev->action))
        int i;
 
        if (match_key("ACTION", rule, &rule->action, udev->action))
-               goto exit;
+               goto nomatch;
 
        if (match_key("KERNEL", rule, &rule->kernel_name, udev->dev->kernel_name))
 
        if (match_key("KERNEL", rule, &rule->kernel_name, udev->dev->kernel_name))
-               goto exit;
+               goto nomatch;
 
        if (match_key("SUBSYSTEM", rule, &rule->subsystem, udev->dev->subsystem))
 
        if (match_key("SUBSYSTEM", rule, &rule->subsystem, udev->dev->subsystem))
-               goto exit;
+               goto nomatch;
 
        if (match_key("DEVPATH", rule, &rule->devpath, udev->dev->devpath))
 
        if (match_key("DEVPATH", rule, &rule->devpath, udev->dev->devpath))
-               goto exit;
+               goto nomatch;
 
        if (rule->modalias.operation != KEY_OP_UNSET) {
                const char *value;
 
        if (rule->modalias.operation != KEY_OP_UNSET) {
                const char *value;
@@ -702,10 +709,10 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                value = sysfs_attr_get_value(udev->dev->devpath, "modalias");
                if (value == NULL) {
                        dbg("MODALIAS value not found");
                value = sysfs_attr_get_value(udev->dev->devpath, "modalias");
                if (value == NULL) {
                        dbg("MODALIAS value not found");
-                       goto exit;
+                       goto nomatch;
                }
                if (match_key("MODALIAS", rule, &rule->modalias, value))
                }
                if (match_key("MODALIAS", rule, &rule->modalias, value))
-                       goto exit;
+                       goto nomatch;
        }
 
        for (i = 0; i < rule->env.count; i++) {
        }
 
        for (i = 0; i < rule->env.count; i++) {
@@ -721,7 +728,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                                value = "";
                        }
                        if (match_key("ENV", rule, &pair->key, value))
                                value = "";
                        }
                        if (match_key("ENV", rule, &pair->key, value))
-                               goto exit;
+                               goto nomatch;
                }
        }
 
                }
        }
 
@@ -741,24 +748,24 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                return -1;
        }
 
                return -1;
        }
 
-       /* walk up the chain of physical devices and find a match */
-       dev_parent = udev->dev;
+       /* walk up the chain of parent devices and find a match */
+       udev->dev_parent = udev->dev;
        while (1) {
                /* check for matching driver */
                if (rule->driver.operation != KEY_OP_UNSET) {
        while (1) {
                /* check for matching driver */
                if (rule->driver.operation != KEY_OP_UNSET) {
-                       if (match_key("DRIVER", rule, &rule->driver, dev_parent->driver))
+                       if (match_key("DRIVER", rule, &rule->driver, udev->dev_parent->driver))
                                goto try_parent;
                }
 
                                goto try_parent;
                }
 
-               /* check for matching bus value */
+               /* check for matching subsystem/bus value */
                if (rule->bus.operation != KEY_OP_UNSET) {
                if (rule->bus.operation != KEY_OP_UNSET) {
-                       if (match_key("BUS", rule, &rule->bus, dev_parent->subsystem))
+                       if (match_key("BUS", rule, &rule->bus, udev->dev_parent->subsystem))
                                goto try_parent;
                }
 
                                goto try_parent;
                }
 
-               /* check for matching bus id */
+               /* check for matching bus id (device name) */
                if (rule->id.operation != KEY_OP_UNSET) {
                if (rule->id.operation != KEY_OP_UNSET) {
-                       if (match_key("ID", rule, &rule->id, dev_parent->kernel_name))
+                       if (match_key("ID", rule, &rule->id, udev->dev_parent->kernel_name))
                                goto try_parent;
                }
 
                                goto try_parent;
                }
 
@@ -773,7 +780,7 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                                char val[VALUE_SIZE];
                                size_t len;
 
                                char val[VALUE_SIZE];
                                size_t len;
 
-                               value = sysfs_attr_get_value(dev_parent->devpath, key_name);
+                               value = sysfs_attr_get_value(udev->dev_parent->devpath, key_name);
                                if (value == NULL)
                                        goto try_parent;
                                strlcpy(val, value, sizeof(val));
                                if (value == NULL)
                                        goto try_parent;
                                strlcpy(val, value, sizeof(val));
@@ -796,12 +803,13 @@ static int match_rule(struct udevice *udev, struct udev_rule *rule)
                /* found matching device  */
                break;
 try_parent:
                /* found matching device  */
                break;
 try_parent:
+               /* move to parent device */
                dbg("try parent sysfs device");
                dbg("try parent sysfs device");
-               dev_parent = sysfs_device_get_parent(dev_parent);
-               if (dev_parent == NULL)
-                       goto exit;
-               dbg("looking at dev_parent->devpath='%s'", dev_parent->devpath);
-               dbg("looking at dev_parent->bus_kernel_name='%s'", dev_parent->kernel_name);
+               udev->dev_parent = sysfs_device_get_parent(udev->dev_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);
        }
 
        /* execute external program */
        }
 
        /* execute external program */
@@ -815,7 +823,7 @@ try_parent:
                        dbg("PROGRAM is false");
                        udev->program_result[0] = '\0';
                        if (rule->program.operation != KEY_OP_NOMATCH)
                        dbg("PROGRAM is false");
                        udev->program_result[0] = '\0';
                        if (rule->program.operation != KEY_OP_NOMATCH)
-                               goto exit;
+                               goto nomatch;
                } else {
                        int count;
 
                } else {
                        int count;
 
@@ -828,14 +836,14 @@ try_parent:
                        strlcpy(udev->program_result, result, sizeof(udev->program_result));
                        dbg("PROGRAM returned successful");
                        if (rule->program.operation == KEY_OP_NOMATCH)
                        strlcpy(udev->program_result, result, sizeof(udev->program_result));
                        dbg("PROGRAM returned successful");
                        if (rule->program.operation == KEY_OP_NOMATCH)
-                               goto exit;
+                               goto nomatch;
                }
                dbg("PROGRAM key is true");
        }
 
        /* check for matching result of external program */
        if (match_key("RESULT", rule, &rule->result, udev->program_result))
                }
                dbg("PROGRAM key is true");
        }
 
        /* check for matching result of external program */
        if (match_key("RESULT", rule, &rule->result, udev->program_result))
-               goto exit;
+               goto nomatch;
 
        /* import variables returned from program or or file into environment */
        if (rule->import.operation != KEY_OP_UNSET) {
 
        /* import variables returned from program or or file into environment */
        if (rule->import.operation != KEY_OP_UNSET) {
@@ -857,7 +865,7 @@ try_parent:
                if (rc != 0) {
                        dbg("IMPORT failed");
                        if (rule->import.operation != KEY_OP_NOMATCH)
                if (rc != 0) {
                        dbg("IMPORT failed");
                        if (rule->import.operation != KEY_OP_NOMATCH)
-                               goto exit;
+                               goto nomatch;
                } else
                        dbg("IMPORT '%s' imported", key_val(rule, &rule->import));
                dbg("IMPORT key is true");
                } else
                        dbg("IMPORT '%s' imported", key_val(rule, &rule->import));
                dbg("IMPORT key is true");
@@ -879,7 +887,7 @@ try_parent:
 
        return 0;
 
 
        return 0;
 
-exit:
+nomatch:
        return -1;
 }
 
        return -1;
 }