+<p>
+As you can see, udevinfo simply produces a list of attributes you can use as-is as match keys in your udev rules. From the above example, I could produce (e.g.) either of the following two rules for this device:
+</p>
+
+<blockquote><pre>
+SUBSYSTEM=="block", <span class="green">SYSFS{size}=="234441648",</span> NAME="my_hard_disk"
+BUS=="scsi", <span class="blue">SYSFS{model}=="ST3120827AS",</span> NAME="my_hard_disk"</pre></blockquote>
+
+<p>
+You may have noted the use of colour in the above examples. This is to demonstrate that you generally can <em>not</em> mix-and-match attributes from different sections of the udevinfo output - your rule will not work. For example, the following rule is <em>invalid</em>:
+</p>
+
+<blockquote><pre>
+SUBSYSTEM=="block", <span class="green">SYSFS{size}=="234441648",</span> <span class="blue">SYSFS{model}=="ST3120827AS",</span> NAME="my_hard_disk"</pre></blockquote>
+
+<p>
+You are usually provided with a large number of attributes, and you must pick a number of them (from the same section) to construct your rule. In general, you want to choose attributes which identify your device in a persistent and human-recognisable way. In the examples above, I chose the size of my disk and its model number. I did not use meaningless numbers such as SYSFS{iodone_cnt}=="0x31737".
+</p>
+
+<p>
+Another point to note is that it is common for text attributes to appear in the udevinfo output to be padded with spaces (e.g. see ST3120827AS above). In your rules, you can either specify the extra spaces, or you can cut them off as I have done.
+</p>
+
+<p>
+The only complication with using udevinfo is that you are required to know the top-level device path (/sys/block/sda in the example above). This is not always obvious. However, as you are generally writing rules for device nodes which already exist, you can use udevinfo to look up the device path for you:
+</p>
+
+<blockquote><pre># udevinfo -a -p $(udevinfo -q path -n /dev/sda)</pre></blockquote>
+
+<a name="sysfsalt"></a>
+<h3>Alternative methods</h3>
+
+<p>
+Although udevinfo is almost certainly the most straightforward way of listing the exact attributes you can build rules from, some users are happier with other tools. Utilities such as <a href="http://www.kroah.com/linux/usb/">usbview</a> display a similar set of information, most of which can be used in rules.
+</p>
+
+<h2>Advanced topics</h2>
+
+<a name="ownership"></a>
+<h3>Controlling permissions and ownership</h3>
+
+<p>
+udev allows you to use additional assignments in rules to control ownership and permission attributes on each device.
+</p>
+
+<p>
+The <em>GROUP</em> assignment allows you to define which Unix group should own the device node. Here is an example rule which defines that the <em>video</em> group will own the framebuffer devices:
+</p>
+
+<blockquote><pre>KERNEL=="fb[0-9]*", NAME="fb/%n", SYMLINK+="%k", GROUP="video"</pre></blockquote>
+
+<p>
+The <em>OWNER</em> key, perhaps less useful, allows you to define which Unix user should have ownership permissions on the device node. Assuming the slightly odd situation where you would want <em>john</em> to own your floppy devices, you could use:
+</p>
+
+<blockquote><pre>KERNEL=="fd[0-9]*", OWNER="john"</pre></blockquote>
+
+<p>
+udev defaults to creating nodes with Unix permissions of 0660 (read/write to owner and group). If you need to, you can override these defaults on certain devices using rules including the <em>MODE</em> assignment. As an example, the following rule defines that the inotify node shall be readable and writable to everyone:
+</p>
+
+<blockquote><pre>KERNEL=="inotify", NAME="misc/%k", SYMLINK+="%k", MODE="0666"</pre></blockquote>
+
+<a name="external-naming"></a>
+<h3>Using external programs to name devices</h3>
+
+<p>
+Under some circumstances, you may require more flexibility than standard udev rules can provide. In this case, you can ask udev to run a program and use the standard output from that program to provide device naming.
+</p>
+
+<p>
+To use this functionality, you simply specify the absolute path of the program to run (and any parameters) in the <em>PROGRAM</em> assignment, and you then use some variant of the <em>%c</em> substitution in the NAME/SYMLINK assignments.
+</p>
+
+<p>
+The following examples refer to a fictional program found at <em>/bin/device_namer</em>. device_namer takes one command line argument which is the kernel name for the device. Based upon this kernel name, device_namer does its magic and produces some output to the usual <em>stdout</em> pipe, split into several parts. Each part is just a single word, and parts are separated by a single space.
+</p>
+
+<p>
+In our first example, we assume that device_namer outputs a number of parts, each one to form a symbolic link (alternative name) for the device in question.
+</p>
+
+<blockquote><pre>KERNEL=="hda", PROGRAM="/bin/device_namer %k", SYMLINK+="%c"</pre></blockquote>
+
+<p>
+The next example assumes that device_namer outputs two parts, the first being the device name, and the second being the name for an additional symbolic link. We now introduce the <em>%c{N}</em> substitution, which refers to part N of the output:
+</p>
+
+<blockquote><pre>KERNEL=="hda", PROGRAM="/bin/device_namer %k", NAME="%c{1}", SYMLINK+="%c{2}"</pre></blockquote>
+
+<p>
+The next example assumes that device_namer outputs one part for the device name, followed by any number of parts which will form additional symbolic links. We now introduce the <em>%c{N+}</em> substitution, which evaluates to part N, N+1, N+2, ... until the end of the output.
+</p>
+
+<blockquote><pre>KERNEL=="hda", PROGRAM="/bin/device_namer %k", NAME="%c{1}", SYMLINK+="%c{2+}"</pre></blockquote>
+
+<p>
+Output parts can be used in any assignment key, not only NAME and SYMLINK. The example below uses a fictional program to determine the Unix group which should own the device:
+</p>
+
+<blockquote><pre>KERNEL=="hda", PROGRAM="/bin/who_owns_device %k", GROUP="%c"</pre></blockquote>
+
+<a name="external-run"></a>
+<h3>Running external programs upon certain events</h3>
+
+<p>
+Yet another reason for writing udev rules is to run a particular program when a device is connected or disconnected. For example, you might want to execute a script to automatically download all of your photos from your digital camera when it is connected.
+</p>
+
+<p>
+Do not confuse this with the <em>PROGRAM</em> functionality described above. <em>PROGRAM</em> is used for running programs which produce device names (and they shouldn't do anything other than that). When those programs are being executed, the device node has not yet been created, so acting upon the device in any way is not possible.
+</p>
+
+<p>
+The functionality introduced here allows you to run a program after the device node is put in place. This program can act on the device, however it must not run for any extended period of time, because udev is effectively paused while these programs are running. One workaround for this limitation is to make sure your program immediately detaches itself.
+</p>
+
+<p>
+Here is an example rule which demonstrates the use of the <em>RUN</em> list assignment:
+</p>
+
+<blockquote><pre>KERNEL=="sdb", RUN+="/usr/bin/my_program"</pre></blockquote>
+
+<p>
+When <em>/usr/bin/my_program</em> is executed, various parts of the udev environment are available as environment variables, including key values such as <em>SUBSYSTEM</em>. You can also use the <em>ACTION</em> environment variable to detect whether the device is being connected or disconnected - ACTION will be either "add" or "remove" respectively.
+</p>
+
+<a name="env"></a>
+<h3>Environment interaction</h3>
+
+<p>
+udev provides an <em>ENV</em> key for environment variables which can be used for both matching and assignment.
+</p>
+
+<p>
+In the assignment case, you can set environment variables which you can then match against later. You can also set environment variables which can be used by any external programs invoked using the techniques mentioned above. A fictional example rule which sets an environment variable is shown below.
+</p>
+
+<blockquote><pre>KERNEL=="fd0", SYMLINK+="floppy", ENV{some_var}="value"</pre></blockquote>
+
+<p>
+In the matching case, you can ensure that rules only run depending on the value of an environment variable. Note that the environment that udev sees will not be the same user environment as you get on the console. A fictional rule involving an environment match is shown below.
+</p>
+
+<blockquote><pre>KERNEL=="fd0", ENV{an_env_var}=="yes", SYMLINK+="floppy"</pre></blockquote>
+
+<p>
+The above rule only creates the <em>/dev/floppy</em> link if $an_env_var is set to "yes" in udev's environment.
+</p>
+
+<a name="options"></a>
+<h3>Additional options</h3>
+
+<p>
+Another assignment which can prove useful is the <em>OPTIONS</em> list. A few options are available:
+</p>
+
+<ul>
+<li><b>all_partitions</b> - create all possible partitions for a block device, rather than only those that were initially detected</li>
+<li><b>ignore_device</b> - ignore the event completely</li>
+<li><b>last_rule</b> - ensure that no later rules have any effect</li>
+</ul>
+
+<p>
+For example, the rule below sets the group ownership on my hard disk node, and ensures that no later rule can have any effect:
+</p>
+
+<blockquote><pre>KERNEL=="sda", GROUP="disk", OPTIONS+="last_rule"</pre></blockquote>
+
+
+<h2>Examples</h2>
+
+<a name="example-printer"></a>
+<h3>USB Printer</h3>
+
+<p>
+I power on my printer, and it is assigned device node <em>/dev/lp0</em>. Not satisfied with such a bland name, I decide to use udevinfo to aid me in writing a rule which will provide an alternative name:
+</p>
+