5 # Provides automated testing of the udev binary.
6 # The whole test is self contained in this file, except the matching sysfs tree.
7 # Simply extend the @tests array, to add a new test variant.
9 # Every test is driven by its own temporary config file.
10 # This program prepares the environment, creates the config and calls udev.
12 # udev parses the rules, looks at the provided sysfs and
13 # first creates and then removes the device node.
14 # After creation and removal the result is checked against the
15 # expected value and the result is printed.
17 # Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
18 # Copyright (C) 2004 Leann Ogasawara <ogasawara@osdl.org>
23 my $udev_bin = "./test-udev";
26 my $udev_bin_valgrind = "valgrind --tool=memcheck --leak-check=yes --quiet $udev_bin";
27 my $udev_bin_gdb = "gdb --args $udev_bin";
28 my $udev_dev = "test/dev";
29 my $udev_run = "test/run";
30 my $udev_rules_dir = "$udev_run/udev/rules.d";
31 my $udev_rules = "$udev_rules_dir/udev-test.rules";
32 my $EXIT_TEST_SKIP = 77;
37 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
39 exp_rem_error => "yes",
45 desc => "label test of scsi disc",
46 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
47 exp_name => "boot_disk" ,
49 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
50 KERNEL=="ttyACM0", SYMLINK+="modem"
54 desc => "label test of scsi disc",
55 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
56 exp_name => "boot_disk" ,
58 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
59 KERNEL=="ttyACM0", SYMLINK+="modem"
63 desc => "label test of scsi disc",
64 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
65 exp_name => "boot_disk" ,
67 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
68 KERNEL=="ttyACM0", SYMLINK+="modem"
72 desc => "label test of scsi partition",
73 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
74 exp_name => "boot_disk1" ,
76 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
80 desc => "label test of pattern match",
81 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
82 exp_name => "boot_disk1" ,
84 SUBSYSTEMS=="scsi", ATTRS{vendor}=="?ATA", SYMLINK+="boot_disk%n-1"
85 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA?", SYMLINK+="boot_disk%n-2"
86 SUBSYSTEMS=="scsi", ATTRS{vendor}=="A??", SYMLINK+="boot_disk%n"
87 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATAS", SYMLINK+="boot_disk%n-3"
91 desc => "label test of multiple sysfs files",
92 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
93 exp_name => "boot_disk1" ,
95 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS X ", SYMLINK+="boot_diskX%n"
96 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="boot_disk%n"
100 desc => "label test of max sysfs files (skip invalid rule)",
101 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
102 exp_name => "boot_disk1" ,
104 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", ATTRS{queue_depth}=="32", SYMLINK+="boot_diskXX%n"
105 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", SYMLINK+="boot_disk%n"
109 desc => "catch device by *",
110 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
111 exp_name => "modem/0" ,
113 KERNEL=="ttyACM*", SYMLINK+="modem/%n"
117 desc => "catch device by * - take 2",
118 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
119 exp_name => "modem/0" ,
121 KERNEL=="*ACM1", SYMLINK+="bad"
122 KERNEL=="*ACM0", SYMLINK+="modem/%n"
126 desc => "catch device by ?",
127 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
128 exp_name => "modem/0" ,
130 KERNEL=="ttyACM??*", SYMLINK+="modem/%n-1"
131 KERNEL=="ttyACM??", SYMLINK+="modem/%n-2"
132 KERNEL=="ttyACM?", SYMLINK+="modem/%n"
136 desc => "catch device by character class",
137 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
138 exp_name => "modem/0" ,
140 KERNEL=="ttyACM[A-Z]*", SYMLINK+="modem/%n-1"
141 KERNEL=="ttyACM?[0-9]", SYMLINK+="modem/%n-2"
142 KERNEL=="ttyACM[0-9]*", SYMLINK+="modem/%n"
146 desc => "replace kernel name",
147 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
148 exp_name => "modem" ,
150 KERNEL=="ttyACM0", SYMLINK+="modem"
154 desc => "Handle comment lines in config file (and replace kernel name)",
155 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
156 exp_name => "modem" ,
159 KERNEL=="ttyACM0", SYMLINK+="modem"
164 desc => "Handle comment lines in config file with whitespace (and replace kernel name)",
165 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
166 exp_name => "modem" ,
168 # this is a comment with whitespace before the comment
169 KERNEL=="ttyACM0", SYMLINK+="modem"
174 desc => "Handle whitespace only lines (and replace kernel name)",
175 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
176 exp_name => "whitespace" ,
181 # this is a comment with whitespace before the comment
182 KERNEL=="ttyACM0", SYMLINK+="whitespace"
189 desc => "Handle empty lines in config file (and replace kernel name)",
190 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
191 exp_name => "modem" ,
194 KERNEL=="ttyACM0", SYMLINK+="modem"
199 desc => "Handle backslashed multi lines in config file (and replace kernel name)",
200 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
201 exp_name => "modem" ,
203 KERNEL=="ttyACM0", \\
209 desc => "preserve backslashes, if they are not for a newline",
210 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
213 KERNEL=="ttyACM0", PROGRAM=="/bin/echo -e \\101", RESULT=="A", SYMLINK+="aaa"
217 desc => "Handle stupid backslashed multi lines in config file (and replace kernel name)",
218 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
219 exp_name => "modem" ,
229 KERNEL=="ttyACM0", \\
235 desc => "subdirectory handling",
236 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
237 exp_name => "sub/direct/ory/modem" ,
239 KERNEL=="ttyACM0", SYMLINK+="sub/direct/ory/modem"
243 desc => "parent device name match of scsi partition",
244 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
245 exp_name => "first_disk5" ,
247 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="first_disk%n"
251 desc => "test substitution chars",
252 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
253 exp_name => "Major:8:minor:5:kernelnumber:5:id:0:0:0:0" ,
255 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:%M:minor:%m:kernelnumber:%n:id:%b"
259 desc => "import of shell-value returned from program",
260 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
261 exp_name => "node12345678",
263 SUBSYSTEMS=="scsi", IMPORT{program}="/bin/echo -e \' TEST_KEY=12345678\\n TEST_key2=98765\'", SYMLINK+="node\$env{TEST_KEY}"
264 KERNEL=="ttyACM0", SYMLINK+="modem"
268 desc => "sustitution of sysfs value (%s{file})",
269 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
270 exp_name => "disk-ATA-sda" ,
272 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="disk-%s{vendor}-%k"
273 KERNEL=="ttyACM0", SYMLINK+="modem"
277 desc => "program result substitution",
278 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
279 exp_name => "special-device-5" ,
280 not_exp_name => "not" ,
282 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n special-device", RESULT=="-special-*", SYMLINK+="not"
283 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n special-device", RESULT=="special-*", SYMLINK+="%c-%n"
287 desc => "program result substitution (newline removal)",
288 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
289 exp_name => "newline_removed" ,
291 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo test", RESULT=="test", SYMLINK+="newline_removed"
295 desc => "program result substitution",
296 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
297 exp_name => "test-0:0:0:0" ,
299 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n test-%b", RESULT=="test-0:0*", SYMLINK+="%c"
303 desc => "program with lots of arguments",
304 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
307 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="%c{7}"
311 desc => "program with subshell",
312 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
315 SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'echo foo3 foo4 foo5 foo6 foo7 foo8 foo9 | sed s/foo9/bar9/'", KERNEL=="sda5", SYMLINK+="%c{7}"
319 desc => "program arguments combined with apostrophes",
320 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
323 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n 'foo3 foo4' 'foo5 foo6 foo7 foo8'", KERNEL=="sda5", SYMLINK+="%c{5}"
327 desc => "characters before the %c{N} substitution",
328 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
329 exp_name => "my-foo9" ,
331 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{7}"
335 desc => "substitute the second to last argument",
336 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
337 exp_name => "my-foo8" ,
339 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{6}"
343 desc => "test substitution by variable name",
344 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
345 exp_name => "Major:8-minor:5-kernelnumber:5-id:0:0:0:0",
347 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:\$major-minor:\$minor-kernelnumber:\$number-id:\$id"
351 desc => "test substitution by variable name 2",
352 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
353 exp_name => "Major:8-minor:5-kernelnumber:5-id:0:0:0:0",
355 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="Major:\$major-minor:%m-kernelnumber:\$number-id:\$id"
359 desc => "test substitution by variable name 3",
360 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
361 exp_name => "850:0:0:05" ,
363 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="%M%m%b%n"
367 desc => "test substitution by variable name 4",
368 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
371 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="\$major\$minor\$number"
375 desc => "test substitution by variable name 5",
376 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
377 exp_name => "8550:0:0:0" ,
379 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="\$major%m%n\$id"
383 desc => "non matching SUBSYSTEMS for device with no parent",
384 devpath => "/devices/virtual/tty/console",
387 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo", RESULT=="foo", SYMLINK+="foo"
388 KERNEL=="console", SYMLINK+="TTY"
392 desc => "non matching SUBSYSTEMS",
393 devpath => "/devices/virtual/tty/console",
396 SUBSYSTEMS=="foo", ATTRS{dev}=="5:1", SYMLINK+="foo"
397 KERNEL=="console", SYMLINK+="TTY"
401 desc => "ATTRS match",
402 devpath => "/devices/virtual/tty/console",
405 KERNEL=="console", SYMLINK+="TTY"
406 ATTRS{dev}=="5:1", SYMLINK+="foo"
410 desc => "ATTR (empty file)",
411 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
412 exp_name => "empty" ,
414 KERNEL=="sda", ATTR{test_empty_file}=="?*", SYMLINK+="something"
415 KERNEL=="sda", ATTR{test_empty_file}!="", SYMLINK+="not-empty"
416 KERNEL=="sda", ATTR{test_empty_file}=="", SYMLINK+="empty"
417 KERNEL=="sda", ATTR{test_empty_file}!="?*", SYMLINK+="not-something"
421 desc => "ATTR (non-existent file)",
422 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
423 exp_name => "non-existent" ,
425 KERNEL=="sda", ATTR{nofile}=="?*", SYMLINK+="something"
426 KERNEL=="sda", ATTR{nofile}!="", SYMLINK+="not-empty"
427 KERNEL=="sda", ATTR{nofile}=="", SYMLINK+="empty"
428 KERNEL=="sda", ATTR{nofile}!="?*", SYMLINK+="not-something"
429 KERNEL=="sda", TEST!="nofile", SYMLINK+="non-existent"
430 KERNEL=="sda", SYMLINK+="wrong"
434 desc => "program and bus type match",
435 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
436 exp_name => "scsi-0:0:0:0" ,
438 SUBSYSTEMS=="usb", PROGRAM=="/bin/echo -n usb-%b", SYMLINK+="%c"
439 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n scsi-%b", SYMLINK+="%c"
440 SUBSYSTEMS=="foo", PROGRAM=="/bin/echo -n foo-%b", SYMLINK+="%c"
444 desc => "sysfs parent hierarchy",
445 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
446 exp_name => "modem" ,
448 ATTRS{idProduct}=="007b", SYMLINK+="modem"
452 desc => "name test with ! in the name",
453 devpath => "/devices/virtual/block/fake!blockdev0",
454 exp_name => "is/a/fake/blockdev0" ,
456 SUBSYSTEMS=="scsi", SYMLINK+="is/not/a/%k"
457 SUBSYSTEM=="block", SYMLINK+="is/a/%k"
458 KERNEL=="ttyACM0", SYMLINK+="modem"
462 desc => "name test with ! in the name, but no matching rule",
463 devpath => "/devices/virtual/block/fake!blockdev0",
464 exp_name => "fake/blockdev0" ,
465 exp_rem_error => "yes",
467 KERNEL=="ttyACM0", SYMLINK+="modem"
471 desc => "KERNELS rule",
472 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
473 exp_name => "scsi-0:0:0:0",
475 SUBSYSTEMS=="usb", KERNELS=="0:0:0:0", SYMLINK+="not-scsi"
476 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:1", SYMLINK+="no-match"
477 SUBSYSTEMS=="scsi", KERNELS==":0", SYMLINK+="short-id"
478 SUBSYSTEMS=="scsi", KERNELS=="/0:0:0:0", SYMLINK+="no-match"
479 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="scsi-0:0:0:0"
483 desc => "KERNELS wildcard all",
484 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
485 exp_name => "scsi-0:0:0:0",
487 SUBSYSTEMS=="scsi", KERNELS=="*:1", SYMLINK+="no-match"
488 SUBSYSTEMS=="scsi", KERNELS=="*:0:1", SYMLINK+="no-match"
489 SUBSYSTEMS=="scsi", KERNELS=="*:0:0:1", SYMLINK+="no-match"
490 SUBSYSTEMS=="scsi", KERNEL=="0:0:0:0", SYMLINK+="before"
491 SUBSYSTEMS=="scsi", KERNELS=="*", SYMLINK+="scsi-0:0:0:0"
495 desc => "KERNELS wildcard partial",
496 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
497 exp_name => "scsi-0:0:0:0",
499 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
500 SUBSYSTEMS=="scsi", KERNELS=="*:0", SYMLINK+="scsi-0:0:0:0"
504 desc => "KERNELS wildcard partial 2",
505 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
506 exp_name => "scsi-0:0:0:0",
508 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
509 SUBSYSTEMS=="scsi", KERNELS=="*:0:0:0", SYMLINK+="scsi-0:0:0:0"
513 desc => "substitute attr with link target value (first match)",
514 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
515 exp_name => "driver-is-sd",
517 SUBSYSTEMS=="scsi", SYMLINK+="driver-is-\$attr{driver}"
521 desc => "substitute attr with link target value (currently selected device)",
522 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
523 exp_name => "driver-is-ahci",
525 SUBSYSTEMS=="pci", SYMLINK+="driver-is-\$attr{driver}"
529 desc => "ignore ATTRS attribute whitespace",
530 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
531 exp_name => "ignored",
533 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE", SYMLINK+="ignored"
537 desc => "do not ignore ATTRS attribute whitespace",
538 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
539 exp_name => "matched-with-space",
541 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE ", SYMLINK+="wrong-to-ignore"
542 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE ", SYMLINK+="matched-with-space"
546 desc => "permissions USER=bad GROUP=name",
547 devpath => "/devices/virtual/tty/tty33",
549 exp_perms => "0:0:0600",
551 KERNEL=="tty33", OWNER="bad", GROUP="name"
555 desc => "permissions OWNER=1",
556 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
558 exp_perms => "1::0600",
560 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="1"
564 desc => "permissions GROUP=1",
565 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
567 exp_perms => ":1:0660",
569 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", GROUP="1"
573 desc => "textual user id",
574 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
576 exp_perms => "nobody::0600",
578 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="nobody"
582 desc => "textual group id",
583 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
585 exp_perms => ":daemon:0660",
587 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", GROUP="daemon"
591 desc => "textual user/group id",
592 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
594 exp_perms => "root:mail:0660",
596 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="root", GROUP="mail"
600 desc => "permissions MODE=0777",
601 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
603 exp_perms => "::0777",
605 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", MODE="0777"
609 desc => "permissions OWNER=1 GROUP=1 MODE=0777",
610 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
612 exp_perms => "1:1:0777",
614 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="1", GROUP="1", MODE="0777"
618 desc => "permissions OWNER to 1",
619 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
620 exp_name => "ttyACM0",
623 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", OWNER="1"
627 desc => "permissions GROUP to 1",
628 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
629 exp_name => "ttyACM0",
630 exp_perms => ":1:0660",
632 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", GROUP="1"
636 desc => "permissions MODE to 0060",
637 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
638 exp_name => "ttyACM0",
639 exp_perms => "::0060",
641 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", MODE="0060"
645 desc => "permissions OWNER, GROUP, MODE",
646 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
647 exp_name => "ttyACM0",
648 exp_perms => "1:1:0777",
650 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", OWNER="1", GROUP="1", MODE="0777"
654 desc => "permissions only rule",
655 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
656 exp_name => "ttyACM0",
657 exp_perms => "1:1:0777",
659 KERNEL=="ttyACM[0-9]*", OWNER="1", GROUP="1", MODE="0777"
660 KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
661 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n"
665 desc => "multiple permissions only rule",
666 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
667 exp_name => "ttyACM0",
668 exp_perms => "1:1:0777",
670 SUBSYSTEM=="tty", OWNER="1"
671 SUBSYSTEM=="tty", GROUP="1"
672 SUBSYSTEM=="tty", MODE="0777"
673 KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
674 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n"
678 desc => "permissions only rule with override at SYMLINK+ rule",
679 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
680 exp_name => "ttyACM0",
681 exp_perms => "1:2:0777",
683 SUBSYSTEM=="tty", OWNER="1"
684 SUBSYSTEM=="tty", GROUP="1"
685 SUBSYSTEM=="tty", MODE="0777"
686 KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
687 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", GROUP="2"
691 desc => "major/minor number test",
692 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
694 exp_majorminor => "8:0",
696 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node"
700 desc => "big major number test",
701 devpath => "/devices/virtual/misc/misc-fake1",
703 exp_majorminor => "4095:1",
705 KERNEL=="misc-fake1", SYMLINK+="node"
709 desc => "big major and big minor number test",
710 devpath => "/devices/virtual/misc/misc-fake89999",
712 exp_majorminor => "4095:89999",
714 KERNEL=="misc-fake89999", SYMLINK+="node"
718 desc => "multiple symlinks with format char",
719 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
720 exp_name => "symlink2-ttyACM0",
722 KERNEL=="ttyACM[0-9]*", SYMLINK="symlink1-%n symlink2-%k symlink3-%b"
726 desc => "multiple symlinks with a lot of s p a c e s",
727 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
731 KERNEL=="ttyACM[0-9]*", SYMLINK=" one two "
735 desc => "symlink creation (same directory)",
736 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
737 exp_name => "modem0",
739 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK="modem%n"
743 desc => "multiple symlinks",
744 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
745 exp_name => "second-0" ,
747 KERNEL=="ttyACM0", SYMLINK="first-%n second-%n third-%n"
751 desc => "symlink name '.'",
752 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
754 exp_add_error => "yes",
755 exp_rem_error => "yes",
757 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="."
761 desc => "symlink node to itself",
762 devpath => "/devices/virtual/tty/tty0",
764 exp_add_error => "yes",
765 exp_rem_error => "yes",
768 KERNEL=="tty0", SYMLINK+="tty0"
772 desc => "symlink %n substitution",
773 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
774 exp_name => "symlink0",
776 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="symlink%n"
780 desc => "symlink %k substitution",
781 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
782 exp_name => "symlink-ttyACM0",
784 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="symlink-%k"
788 desc => "symlink %M:%m substitution",
789 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
790 exp_name => "major-166:0",
792 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="major-%M:%m"
796 desc => "symlink %b substitution",
797 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
798 exp_name => "symlink-0:0:0:0",
800 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="symlink-%b"
804 desc => "symlink %c substitution",
805 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
808 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo test", SYMLINK+="%c"
812 desc => "symlink %c{N} substitution",
813 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
816 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo symlink test this", SYMLINK+="%c{2}"
820 desc => "symlink %c{N+} substitution",
821 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
824 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo symlink test this", SYMLINK+="%c{2+}"
828 desc => "symlink only rule with %c{N+}",
829 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
832 SUBSYSTEMS=="scsi", KERNEL=="sda", PROGRAM=="/bin/echo link test this" SYMLINK+="%c{2+}"
836 desc => "symlink %s{filename} substitution",
837 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
840 KERNEL=="ttyACM[0-9]*", SYMLINK+="%s{dev}"
844 desc => "program result substitution (numbered part of)",
845 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
848 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n node link1 link2", RESULT=="node *", SYMLINK+="%c{2} %c{3}"
852 desc => "program result substitution (numbered part of+)",
853 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
856 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n node link1 link2 link3 link4", RESULT=="node *", SYMLINK+="%c{2+}"
860 desc => "SUBSYSTEM match test",
861 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
864 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match", SUBSYSTEM=="vc"
865 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", SUBSYSTEM=="block"
866 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match2", SUBSYSTEM=="vc"
870 desc => "DRIVERS match test",
871 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
874 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match", DRIVERS=="sd-wrong"
875 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", DRIVERS=="sd"
879 desc => "devnode substitution test",
880 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
883 SUBSYSTEMS=="scsi", KERNEL=="sda", PROGRAM=="/usr/bin/test -b %N" SYMLINK+="node"
887 desc => "parent node name substitution test",
888 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
889 exp_name => "sda-part-1",
891 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="%P-part-1"
895 desc => "udev_root substitution",
896 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
897 exp_name => "start-/dev-end",
899 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="start-%r-end"
903 desc => "last_rule option",
904 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
907 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="last", OPTIONS="last_rule"
908 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="very-last"
912 desc => "negation KERNEL!=",
913 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
916 SUBSYSTEMS=="scsi", KERNEL!="sda1", SYMLINK+="matches-but-is-negated"
917 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
918 SUBSYSTEMS=="scsi", KERNEL!="xsda1", SYMLINK+="match"
922 desc => "negation SUBSYSTEM!=",
923 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
924 exp_name => "not-anything",
926 SUBSYSTEMS=="scsi", SUBSYSTEM=="block", KERNEL!="sda1", SYMLINK+="matches-but-is-negated"
927 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
928 SUBSYSTEMS=="scsi", SUBSYSTEM!="anything", SYMLINK+="not-anything"
932 desc => "negation PROGRAM!= exit code",
933 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
934 exp_name => "nonzero-program",
936 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
937 KERNEL=="sda1", PROGRAM!="/bin/false", SYMLINK+="nonzero-program"
941 desc => "ENV{} test",
942 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
945 ENV{ENV_KEY_TEST}="test"
946 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="go", SYMLINK+="wrong"
947 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="test", SYMLINK+="true"
948 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="bad", SYMLINK+="bad"
952 desc => "ENV{} test",
953 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
956 ENV{ENV_KEY_TEST}="test"
957 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="go", SYMLINK+="wrong"
958 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="yes", ENV{ACTION}=="add", ENV{DEVPATH}=="*/block/sda/sdax1", SYMLINK+="no"
959 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="test", ENV{ACTION}=="add", ENV{DEVPATH}=="*/block/sda/sda1", SYMLINK+="true"
960 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="bad", SYMLINK+="bad"
964 desc => "ENV{} test (assign)",
965 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
968 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="true"
969 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="yes", SYMLINK+="no"
970 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
971 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="true", SYMLINK+="true"
975 desc => "ENV{} test (assign 2 times)",
976 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
979 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="true"
980 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="absolutely-\$env{ASSIGN}"
981 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
982 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="yes", SYMLINK+="no"
983 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="absolutely-true", SYMLINK+="true"
987 desc => "ENV{} test (assign2)",
988 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
991 SUBSYSTEM=="block", KERNEL=="*[0-9]", ENV{PARTITION}="true", ENV{MAINDEVICE}="false"
992 SUBSYSTEM=="block", KERNEL=="*[!0-9]", ENV{PARTITION}="false", ENV{MAINDEVICE}="true"
993 ENV{MAINDEVICE}=="true", SYMLINK+="disk"
994 SUBSYSTEM=="block", SYMLINK+="before"
995 ENV{PARTITION}=="true", SYMLINK+="part"
999 desc => "untrusted string sanitize",
1000 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1003 SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e name; (/usr/bin/badprogram)", RESULT=="name_ _/usr/bin/badprogram_", SYMLINK+="sane"
1007 desc => "untrusted string sanitize (don't replace utf8)",
1008 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1011 SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e \\xc3\\xbcber" RESULT=="\xc3\xbcber", SYMLINK+="uber"
1015 desc => "untrusted string sanitize (replace invalid utf8)",
1016 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1017 exp_name => "replaced",
1019 SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e \\xef\\xe8garbage", RESULT=="__garbage", SYMLINK+="replaced"
1023 desc => "read sysfs value from parent device",
1024 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1025 exp_name => "serial-354172020305000",
1027 KERNEL=="ttyACM*", ATTRS{serial}=="?*", SYMLINK+="serial-%s{serial}"
1031 desc => "match against empty key string",
1032 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1035 KERNEL=="sda", ATTRS{nothing}!="", SYMLINK+="not-1-ok"
1036 KERNEL=="sda", ATTRS{nothing}=="", SYMLINK+="not-2-ok"
1037 KERNEL=="sda", ATTRS{vendor}!="", SYMLINK+="ok"
1038 KERNEL=="sda", ATTRS{vendor}=="", SYMLINK+="not-3-ok"
1042 desc => "check ACTION value",
1043 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1046 ACTION=="unknown", KERNEL=="sda", SYMLINK+="unknown-not-ok"
1047 ACTION=="add", KERNEL=="sda", SYMLINK+="ok"
1051 desc => "final assignment",
1052 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1054 exp_perms => "root:tty:0640",
1056 KERNEL=="sda", GROUP:="tty"
1057 KERNEL=="sda", GROUP="not-ok", MODE="0640", SYMLINK+="ok"
1061 desc => "final assignment 2",
1062 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1064 exp_perms => "root:tty:0640",
1066 KERNEL=="sda", GROUP:="tty"
1067 SUBSYSTEM=="block", MODE:="640"
1068 KERNEL=="sda", GROUP="not-ok", MODE="0666", SYMLINK+="ok"
1072 desc => "env substitution",
1073 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1074 exp_name => "node-add-me",
1076 KERNEL=="sda", MODE="0666", SYMLINK+="node-\$env{ACTION}-me"
1080 desc => "reset list to current value",
1081 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1082 exp_name => "three",
1083 not_exp_name => "two",
1085 KERNEL=="ttyACM[0-9]*", SYMLINK+="one"
1086 KERNEL=="ttyACM[0-9]*", SYMLINK+="two"
1087 KERNEL=="ttyACM[0-9]*", SYMLINK="three"
1091 desc => "test empty SYMLINK+ (empty override)",
1092 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1093 exp_name => "right",
1094 not_exp_name => "wrong",
1096 KERNEL=="ttyACM[0-9]*", SYMLINK+="wrong"
1097 KERNEL=="ttyACM[0-9]*", SYMLINK=""
1098 KERNEL=="ttyACM[0-9]*", SYMLINK+="right"
1102 desc => "test multi matches",
1103 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1104 exp_name => "right",
1106 KERNEL=="ttyACM*", SYMLINK+="before"
1107 KERNEL=="ttyACM*|nothing", SYMLINK+="right"
1111 desc => "test multi matches 2",
1112 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1113 exp_name => "right",
1115 KERNEL=="dontknow*|*nothing", SYMLINK+="nomatch"
1116 KERNEL=="ttyACM*", SYMLINK+="before"
1117 KERNEL=="dontknow*|ttyACM*|nothing*", SYMLINK+="right"
1121 desc => "test multi matches 3",
1122 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1123 exp_name => "right",
1125 KERNEL=="dontknow|nothing", SYMLINK+="nomatch"
1126 KERNEL=="dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong1"
1127 KERNEL=="X|attyACM0|dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong2"
1128 KERNEL=="dontknow|ttyACM0|nothing", SYMLINK+="right"
1132 desc => "test multi matches 4",
1133 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1134 exp_name => "right",
1136 KERNEL=="dontknow|nothing", SYMLINK+="nomatch"
1137 KERNEL=="dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong1"
1138 KERNEL=="X|attyACM0|dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong2"
1139 KERNEL=="all|dontknow|ttyACM0", SYMLINK+="right"
1140 KERNEL=="ttyACM0a|nothing", SYMLINK+="wrong3"
1144 desc => "IMPORT parent test sequence 1/2 (keep)",
1145 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1146 exp_name => "parent",
1149 KERNEL=="sda", IMPORT{program}="/bin/echo -e \'PARENT_KEY=parent_right\\nWRONG_PARENT_KEY=parent_wrong'"
1150 KERNEL=="sda", SYMLINK+="parent"
1154 desc => "IMPORT parent test sequence 2/2 (keep)",
1155 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1156 exp_name => "parentenv-parent_right",
1159 KERNEL=="sda1", IMPORT{parent}="PARENT*", SYMLINK+="parentenv-\$env{PARENT_KEY}\$env{WRONG_PARENT_KEY}"
1163 desc => "GOTO test",
1164 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1165 exp_name => "right",
1167 KERNEL=="sda1", GOTO="TEST"
1168 KERNEL=="sda1", SYMLINK+="wrong"
1169 KERNEL=="sda1", GOTO="BAD"
1170 KERNEL=="sda1", SYMLINK+="", LABEL="NO"
1171 KERNEL=="sda1", SYMLINK+="right", LABEL="TEST", GOTO="end"
1172 KERNEL=="sda1", SYMLINK+="wrong2", LABEL="BAD"
1177 desc => "GOTO label does not exist",
1178 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1179 exp_name => "right",
1181 KERNEL=="sda1", GOTO="does-not-exist"
1182 KERNEL=="sda1", SYMLINK+="right",
1187 desc => "SYMLINK+ compare test",
1188 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1189 exp_name => "right",
1190 not_exp_name => "wrong",
1192 KERNEL=="sda1", SYMLINK+="link"
1193 KERNEL=="sda1", SYMLINK=="link*", SYMLINK+="right"
1194 KERNEL=="sda1", SYMLINK=="nolink*", SYMLINK+="wrong"
1198 desc => "invalid key operation",
1199 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1202 KERNEL="sda1", SYMLINK+="no"
1203 KERNEL=="sda1", SYMLINK+="yes"
1207 desc => "operator chars in attribute",
1208 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1211 KERNEL=="sda", ATTR{test:colon+plus}=="?*", SYMLINK+="yes"
1215 desc => "overlong comment line",
1216 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1219 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
1220 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
1221 KERNEL=="sda1", SYMLINK+=="no"
1222 KERNEL=="sda1", SYMLINK+="yes"
1226 desc => "magic subsys/kernel lookup",
1227 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1228 exp_name => "00:16:41:e2:8d:ff",
1230 KERNEL=="sda", SYMLINK+="\$attr{[net/eth0]address}"
1234 desc => "TEST absolute path",
1235 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1236 exp_name => "there",
1238 TEST=="/etc/machine-id", SYMLINK+="there"
1239 TEST!="/etc/machine-id", SYMLINK+="notthere"
1243 desc => "TEST subsys/kernel lookup",
1244 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1247 KERNEL=="sda", TEST=="[net/eth0]", SYMLINK+="yes"
1251 desc => "TEST relative path",
1252 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1253 exp_name => "relative",
1255 KERNEL=="sda", TEST=="size", SYMLINK+="relative"
1259 desc => "TEST wildcard substitution (find queue/nr_requests)",
1260 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1261 exp_name => "found-subdir",
1263 KERNEL=="sda", TEST=="*/nr_requests", SYMLINK+="found-subdir"
1267 desc => "TEST MODE=0000",
1268 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1270 exp_perms => "0:0:0000",
1271 exp_rem_error => "yes",
1273 KERNEL=="sda", MODE="0000"
1277 desc => "TEST PROGRAM feeds OWNER, GROUP, MODE",
1278 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1280 exp_perms => "1:1:0400",
1281 exp_rem_error => "yes",
1283 KERNEL=="sda", MODE="666"
1284 KERNEL=="sda", PROGRAM=="/bin/echo 1 1 0400", OWNER="%c{1}", GROUP="%c{2}", MODE="%c{3}"
1288 desc => "TEST PROGRAM feeds MODE with overflow",
1289 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1291 exp_perms => "0:0:0440",
1292 exp_rem_error => "yes",
1294 KERNEL=="sda", MODE="440"
1295 KERNEL=="sda", PROGRAM=="/bin/echo 0 0 0400letsdoabuffferoverflow0123456789012345789012345678901234567890", OWNER="%c{1}", GROUP="%c{2}", MODE="%c{3}"
1299 desc => "magic [subsys/sysname] attribute substitution",
1300 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1301 exp_name => "sda-8741C4G-end",
1302 exp_perms => "0:0:0600",
1304 KERNEL=="sda", PROGRAM="/bin/true create-envp"
1305 KERNEL=="sda", ENV{TESTENV}="change-envp"
1306 KERNEL=="sda", SYMLINK+="%k-%s{[dmi/id]product_name}-end"
1310 desc => "builtin path_id",
1311 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1312 exp_name => "disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0",
1314 KERNEL=="sda", IMPORT{builtin}="path_id"
1315 KERNEL=="sda", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/\$env{ID_PATH}"
1321 my ($action, $devpath, $rules) = @_;
1323 # create temporary rules
1324 system("mkdir", "-p", "$udev_rules_dir");
1325 open CONF, ">$udev_rules" || die "unable to create rules file: $udev_rules";
1329 if ($valgrind > 0) {
1330 system("$udev_bin_valgrind $action $devpath");
1331 } elsif ($gdb > 0) {
1332 system("$udev_bin_gdb $action $devpath");
1334 system("$udev_bin", "$action", "$devpath");
1340 sub permissions_test {
1341 my($rules, $uid, $gid, $mode) = @_;
1347 $rules->{exp_perms} =~ m/^(.*):(.*):(.*)$/;
1349 if (defined(getpwnam($1))) {
1350 $userid = int(getpwnam($1));
1354 if ($uid != $userid) { $wrong = 1; }
1357 if (defined(getgrnam($2))) {
1358 $groupid = int(getgrnam($2));
1362 if ($gid != $groupid) { $wrong = 1; }
1365 if (($mode & 07777) != oct($3)) { $wrong = 1; };
1368 print "permissions: ok\n";
1370 printf " expected permissions are: %s:%s:%#o\n", $1, $2, oct($3);
1371 printf " created permissions are : %i:%i:%#o\n", $uid, $gid, $mode & 07777;
1372 print "permissions: error\n";
1378 sub major_minor_test {
1379 my($rules, $rdev) = @_;
1381 my $major = ($rdev >> 8) & 0xfff;
1382 my $minor = ($rdev & 0xff) | (($rdev >> 12) & 0xfff00);
1385 $rules->{exp_majorminor} =~ m/^(.*):(.*)$/;
1387 if ($major != $1) { $wrong = 1; };
1390 if ($minor != $2) { $wrong = 1; };
1393 print "major:minor: ok\n";
1395 printf " expected major:minor is: %i:%i\n", $1, $2;
1396 printf " created major:minor is : %i:%i\n", $major, $minor;
1397 print "major:minor: error\n";
1404 system("rm", "-rf", "$udev_dev");
1405 mkdir($udev_dev) || die "unable to create udev_dev: $udev_dev\n";
1406 # setting group and mode of udev_dev ensures the tests work
1407 # even if the parent directory has setgid bit enabled.
1408 chown (0, 0, $udev_dev) || die "unable to chown $udev_dev\n";
1409 chmod (0755, $udev_dev) || die "unable to chmod $udev_dev\n";
1411 system("rm", "-rf", "$udev_run");
1415 my ($rules, $number) = @_;
1417 print "TEST $number: $rules->{desc}\n";
1418 print "device \'$rules->{devpath}\' expecting node/link \'$rules->{exp_name}\'\n";
1420 udev("add", $rules->{devpath}, \$rules->{rules});
1421 if (defined($rules->{not_exp_name})) {
1422 if ((-e "$udev_dev/$rules->{not_exp_name}") ||
1423 (-l "$udev_dev/$rules->{not_exp_name}")) {
1424 print "nonexistent: error \'$rules->{not_exp_name}\' not expected to be there\n";
1430 if ((-e "$udev_dev/$rules->{exp_name}") ||
1431 (-l "$udev_dev/$rules->{exp_name}")) {
1433 my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
1434 $atime, $mtime, $ctime, $blksize, $blocks) = stat("$udev_dev/$rules->{exp_name}");
1436 if (defined($rules->{exp_perms})) {
1437 permissions_test($rules, $uid, $gid, $mode);
1439 if (defined($rules->{exp_majorminor})) {
1440 major_minor_test($rules, $rdev);
1445 if ($rules->{exp_add_error}) {
1446 print " as expected\n";
1449 system("tree", "$udev_dev");
1456 if (defined($rules->{option}) && $rules->{option} eq "keep") {
1461 udev("remove", $rules->{devpath}, \$rules->{rules});
1462 if ((-e "$udev_dev/$rules->{exp_name}") ||
1463 (-l "$udev_dev/$rules->{exp_name}")) {
1464 print "remove: error";
1465 if ($rules->{exp_rem_error}) {
1466 print " as expected\n";
1469 system("tree", "$udev_dev");
1475 print "remove: ok\n";
1480 if (defined($rules->{option}) && $rules->{option} eq "clean") {
1486 # only run if we have root permissions
1487 # due to mknod restrictions
1489 print "Must have root permissions to run properly.\n";
1493 # skip the test when running in a container
1494 system("systemd-detect-virt", "-c", "-q");
1496 print "Running in a container, skipping the test.\n";
1497 exit($EXIT_TEST_SKIP);
1505 foreach my $arg (@ARGV) {
1506 if ($arg =~ m/--valgrind/) {
1508 printf("using valgrind\n");
1509 } elsif ($arg =~ m/--gdb/) {
1511 printf("using gdb\n");
1518 foreach my $arg (@list) {
1519 if (defined($tests[$arg-1]->{desc})) {
1520 print "udev-test will run test number $arg:\n\n";
1521 run_test($tests[$arg-1], $arg);
1523 print "test does not exist.\n";
1528 print "\nudev-test will run ".($#tests + 1)." tests:\n\n";
1530 foreach my $rules (@tests) {
1531 run_test($rules, $test_num);
1536 print "$error errors occurred\n\n";
1539 system("rm", "-rf", "$udev_dev");
1540 system("rm", "-rf", "$udev_run");