]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/udev-test.pl
udev-test: remove a check for whether the test is run in a container
[thirdparty/systemd.git] / test / udev-test.pl
1 #!/usr/bin/env perl
2
3 # udev test
4 #
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.
8 #
9 # Every test is driven by its own temporary config file.
10 # This program prepares the environment, creates the config and calls udev.
11 #
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.
16 #
17 # Copyright © 2004 Leann Ogasawara <ogasawara@osdl.org>
18
19 use warnings;
20 use strict;
21
22 my $udev_bin = "./test-udev";
23 my $valgrind = 0;
24 my $gdb = 0;
25 my $strace = 0;
26 my $udev_bin_valgrind = "valgrind --tool=memcheck --leak-check=yes --track-origins=yes --quiet $udev_bin";
27 my $udev_bin_gdb = "gdb --args $udev_bin";
28 my $udev_bin_strace = "strace -efile $udev_bin";
29 my $udev_run = "test/run";
30 my $udev_tmpfs = "test/tmpfs";
31 my $udev_sys = "${udev_tmpfs}/sys";
32 my $udev_dev = "${udev_tmpfs}/dev";
33 my $udev_rules_dir = "$udev_run/udev/rules.d";
34 my $udev_rules = "$udev_rules_dir/udev-test.rules";
35 my $EXIT_TEST_SKIP = 77;
36
37 my $rules_10k_tags = "";
38 for (my $i = 1; $i <= 10000; ++$i) {
39 $rules_10k_tags .= 'KERNEL=="sda", TAG+="test' . $i . "\"\n";
40 }
41
42 my @tests = (
43 {
44 desc => "no rules",
45 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
46 exp_name => "sda" ,
47 exp_rem_error => "yes",
48 rules => <<EOF
49 #
50 EOF
51 },
52 {
53 desc => "label test of scsi disc",
54 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
55 exp_name => "boot_disk" ,
56 rules => <<EOF
57 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
58 KERNEL=="ttyACM0", SYMLINK+="modem"
59 EOF
60 },
61 {
62 desc => "label test of scsi disc",
63 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
64 exp_name => "boot_disk" ,
65 rules => <<EOF
66 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
67 KERNEL=="ttyACM0", SYMLINK+="modem"
68 EOF
69 },
70 {
71 desc => "label test of scsi disc",
72 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
73 exp_name => "boot_disk" ,
74 rules => <<EOF
75 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
76 KERNEL=="ttyACM0", SYMLINK+="modem"
77 EOF
78 },
79 {
80 desc => "label test of scsi partition",
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" ,
83 rules => <<EOF
84 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
85 EOF
86 },
87 {
88 desc => "label test of pattern match",
89 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
90 exp_name => "boot_disk1" ,
91 rules => <<EOF
92 SUBSYSTEMS=="scsi", ATTRS{vendor}=="?ATA", SYMLINK+="boot_disk%n-1"
93 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA?", SYMLINK+="boot_disk%n-2"
94 SUBSYSTEMS=="scsi", ATTRS{vendor}=="A??", SYMLINK+="boot_disk%n"
95 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATAS", SYMLINK+="boot_disk%n-3"
96 EOF
97 },
98 {
99 desc => "label test of multiple sysfs files",
100 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
101 exp_name => "boot_disk1" ,
102 rules => <<EOF
103 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS X ", SYMLINK+="boot_diskX%n"
104 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="boot_disk%n"
105 EOF
106 },
107 {
108 desc => "label test of max sysfs files (skip invalid rule)",
109 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
110 exp_name => "boot_disk1" ,
111 rules => <<EOF
112 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"
113 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", SYMLINK+="boot_disk%n"
114 EOF
115 },
116 {
117 desc => "catch device by *",
118 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
119 exp_name => "modem/0" ,
120 rules => <<EOF
121 KERNEL=="ttyACM*", SYMLINK+="modem/%n"
122 EOF
123 },
124 {
125 desc => "catch device by * - take 2",
126 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
127 exp_name => "modem/0" ,
128 rules => <<EOF
129 KERNEL=="*ACM1", SYMLINK+="bad"
130 KERNEL=="*ACM0", SYMLINK+="modem/%n"
131 EOF
132 },
133 {
134 desc => "catch device by ?",
135 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
136 exp_name => "modem/0" ,
137 rules => <<EOF
138 KERNEL=="ttyACM??*", SYMLINK+="modem/%n-1"
139 KERNEL=="ttyACM??", SYMLINK+="modem/%n-2"
140 KERNEL=="ttyACM?", SYMLINK+="modem/%n"
141 EOF
142 },
143 {
144 desc => "catch device by character class",
145 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
146 exp_name => "modem/0" ,
147 rules => <<EOF
148 KERNEL=="ttyACM[A-Z]*", SYMLINK+="modem/%n-1"
149 KERNEL=="ttyACM?[0-9]", SYMLINK+="modem/%n-2"
150 KERNEL=="ttyACM[0-9]*", SYMLINK+="modem/%n"
151 EOF
152 },
153 {
154 desc => "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" ,
157 rules => <<EOF
158 KERNEL=="ttyACM0", SYMLINK+="modem"
159 EOF
160 },
161 {
162 desc => "Handle comment lines in config file (and replace kernel name)",
163 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
164 exp_name => "modem" ,
165 rules => <<EOF
166 # this is a comment
167 KERNEL=="ttyACM0", SYMLINK+="modem"
168
169 EOF
170 },
171 {
172 desc => "Handle comment lines in config file with whitespace (and replace kernel name)",
173 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
174 exp_name => "modem" ,
175 rules => <<EOF
176 # this is a comment with whitespace before the comment
177 KERNEL=="ttyACM0", SYMLINK+="modem"
178
179 EOF
180 },
181 {
182 desc => "Handle whitespace only lines (and replace kernel name)",
183 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
184 exp_name => "whitespace" ,
185 rules => <<EOF
186
187
188
189 # this is a comment with whitespace before the comment
190 KERNEL=="ttyACM0", SYMLINK+="whitespace"
191
192
193
194 EOF
195 },
196 {
197 desc => "Handle empty lines in config file (and replace kernel name)",
198 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
199 exp_name => "modem" ,
200 rules => <<EOF
201
202 KERNEL=="ttyACM0", SYMLINK+="modem"
203
204 EOF
205 },
206 {
207 desc => "Handle backslashed multi lines in config file (and replace kernel name)",
208 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
209 exp_name => "modem" ,
210 rules => <<EOF
211 KERNEL=="ttyACM0", \\
212 SYMLINK+="modem"
213
214 EOF
215 },
216 {
217 desc => "preserve backslashes, if they are not for a newline",
218 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
219 exp_name => "aaa",
220 rules => <<EOF
221 KERNEL=="ttyACM0", PROGRAM=="/bin/echo -e \\101", RESULT=="A", SYMLINK+="aaa"
222 EOF
223 },
224 {
225 desc => "Handle stupid backslashed multi lines in config file (and replace kernel name)",
226 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
227 exp_name => "modem" ,
228 rules => <<EOF
229
230 #
231 \\
232
233 \\
234
235 #\\
236
237 KERNEL=="ttyACM0", \\
238 SYMLINK+="modem"
239
240 EOF
241 },
242 {
243 desc => "subdirectory handling",
244 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
245 exp_name => "sub/direct/ory/modem" ,
246 rules => <<EOF
247 KERNEL=="ttyACM0", SYMLINK+="sub/direct/ory/modem"
248 EOF
249 },
250 {
251 desc => "parent device name match of scsi partition",
252 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
253 exp_name => "first_disk5" ,
254 rules => <<EOF
255 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="first_disk%n"
256 EOF
257 },
258 {
259 desc => "test substitution chars",
260 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
261 exp_name => "Major:8:minor:5:kernelnumber:5:id:0:0:0:0" ,
262 rules => <<EOF
263 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:%M:minor:%m:kernelnumber:%n:id:%b"
264 EOF
265 },
266 {
267 desc => "import of shell-value returned from program",
268 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
269 exp_name => "node12345678",
270 rules => <<EOF
271 SUBSYSTEMS=="scsi", IMPORT{program}="/bin/echo -e \' TEST_KEY=12345678\\n TEST_key2=98765\'", SYMLINK+="node\$env{TEST_KEY}"
272 KERNEL=="ttyACM0", SYMLINK+="modem"
273 EOF
274 },
275 {
276 desc => "sustitution of sysfs value (%s{file})",
277 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
278 exp_name => "disk-ATA-sda" ,
279 rules => <<EOF
280 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="disk-%s{vendor}-%k"
281 KERNEL=="ttyACM0", SYMLINK+="modem"
282 EOF
283 },
284 {
285 desc => "program result substitution",
286 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
287 exp_name => "special-device-5" ,
288 not_exp_name => "not" ,
289 rules => <<EOF
290 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n special-device", RESULT=="-special-*", SYMLINK+="not"
291 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n special-device", RESULT=="special-*", SYMLINK+="%c-%n"
292 EOF
293 },
294 {
295 desc => "program result substitution (newline removal)",
296 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
297 exp_name => "newline_removed" ,
298 rules => <<EOF
299 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo test", RESULT=="test", SYMLINK+="newline_removed"
300 EOF
301 },
302 {
303 desc => "program result substitution",
304 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
305 exp_name => "test-0:0:0:0" ,
306 rules => <<EOF
307 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n test-%b", RESULT=="test-0:0*", SYMLINK+="%c"
308 EOF
309 },
310 {
311 desc => "program with lots of arguments",
312 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
313 exp_name => "foo9" ,
314 rules => <<EOF
315 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="%c{7}"
316 EOF
317 },
318 {
319 desc => "program with subshell",
320 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
321 exp_name => "bar9" ,
322 rules => <<EOF
323 SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'echo foo3 foo4 foo5 foo6 foo7 foo8 foo9 | sed s/foo9/bar9/'", KERNEL=="sda5", SYMLINK+="%c{7}"
324 EOF
325 },
326 {
327 desc => "program arguments combined with apostrophes",
328 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
329 exp_name => "foo7" ,
330 rules => <<EOF
331 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n 'foo3 foo4' 'foo5 foo6 foo7 foo8'", KERNEL=="sda5", SYMLINK+="%c{5}"
332 EOF
333 },
334 {
335 desc => "program arguments combined with escaped double quotes, part 1",
336 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
337 exp_name => "foo2" ,
338 rules => <<EOF
339 SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'printf %%s \\\"foo1 foo2\\\" | grep \\\"foo1 foo2\\\"'", KERNEL=="sda5", SYMLINK+="%c{2}"
340 EOF
341 },
342 {
343 desc => "program arguments combined with escaped double quotes, part 2",
344 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
345 exp_name => "foo2" ,
346 rules => <<EOF
347 SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c \\\"printf %%s 'foo1 foo2' | grep 'foo1 foo2'\\\"", KERNEL=="sda5", SYMLINK+="%c{2}"
348 EOF
349 },
350 {
351 desc => "program arguments combined with escaped double quotes, part 3",
352 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
353 exp_name => "foo2" ,
354 rules => <<EOF
355 SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'printf \\\"%%s %%s\\\" \\\"foo1 foo2\\\" \\\"foo3\\\"| grep \\\"foo1 foo2\\\"'", KERNEL=="sda5", SYMLINK+="%c{2}"
356 EOF
357 },
358 {
359 desc => "characters before the %c{N} substitution",
360 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
361 exp_name => "my-foo9" ,
362 rules => <<EOF
363 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{7}"
364 EOF
365 },
366 {
367 desc => "substitute the second to last argument",
368 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
369 exp_name => "my-foo8" ,
370 rules => <<EOF
371 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{6}"
372 EOF
373 },
374 {
375 desc => "test substitution by variable name",
376 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
377 exp_name => "Major:8-minor:5-kernelnumber:5-id:0:0:0:0",
378 rules => <<EOF
379 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:\$major-minor:\$minor-kernelnumber:\$number-id:\$id"
380 EOF
381 },
382 {
383 desc => "test substitution by variable name 2",
384 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
385 exp_name => "Major:8-minor:5-kernelnumber:5-id:0:0:0:0",
386 rules => <<EOF
387 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="Major:\$major-minor:%m-kernelnumber:\$number-id:\$id"
388 EOF
389 },
390 {
391 desc => "test substitution by variable name 3",
392 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
393 exp_name => "850:0:0:05" ,
394 rules => <<EOF
395 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="%M%m%b%n"
396 EOF
397 },
398 {
399 desc => "test substitution by variable name 4",
400 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
401 exp_name => "855" ,
402 rules => <<EOF
403 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="\$major\$minor\$number"
404 EOF
405 },
406 {
407 desc => "test substitution by variable name 5",
408 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
409 exp_name => "8550:0:0:0" ,
410 rules => <<EOF
411 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="\$major%m%n\$id"
412 EOF
413 },
414 {
415 desc => "non matching SUBSYSTEMS for device with no parent",
416 devpath => "/devices/virtual/tty/console",
417 exp_name => "TTY",
418 rules => <<EOF
419 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo", RESULT=="foo", SYMLINK+="foo"
420 KERNEL=="console", SYMLINK+="TTY"
421 EOF
422 },
423 {
424 desc => "non matching SUBSYSTEMS",
425 devpath => "/devices/virtual/tty/console",
426 exp_name => "TTY" ,
427 rules => <<EOF
428 SUBSYSTEMS=="foo", ATTRS{dev}=="5:1", SYMLINK+="foo"
429 KERNEL=="console", SYMLINK+="TTY"
430 EOF
431 },
432 {
433 desc => "ATTRS match",
434 devpath => "/devices/virtual/tty/console",
435 exp_name => "foo" ,
436 rules => <<EOF
437 KERNEL=="console", SYMLINK+="TTY"
438 ATTRS{dev}=="5:1", SYMLINK+="foo"
439 EOF
440 },
441 {
442 desc => "ATTR (empty file)",
443 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
444 exp_name => "empty" ,
445 rules => <<EOF
446 KERNEL=="sda", ATTR{test_empty_file}=="?*", SYMLINK+="something"
447 KERNEL=="sda", ATTR{test_empty_file}!="", SYMLINK+="not-empty"
448 KERNEL=="sda", ATTR{test_empty_file}=="", SYMLINK+="empty"
449 KERNEL=="sda", ATTR{test_empty_file}!="?*", SYMLINK+="not-something"
450 EOF
451 },
452 {
453 desc => "ATTR (non-existent file)",
454 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
455 exp_name => "non-existent" ,
456 rules => <<EOF
457 KERNEL=="sda", ATTR{nofile}=="?*", SYMLINK+="something"
458 KERNEL=="sda", ATTR{nofile}!="", SYMLINK+="not-empty"
459 KERNEL=="sda", ATTR{nofile}=="", SYMLINK+="empty"
460 KERNEL=="sda", ATTR{nofile}!="?*", SYMLINK+="not-something"
461 KERNEL=="sda", TEST!="nofile", SYMLINK+="non-existent"
462 KERNEL=="sda", SYMLINK+="wrong"
463 EOF
464 },
465 {
466 desc => "program and bus type match",
467 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
468 exp_name => "scsi-0:0:0:0" ,
469 rules => <<EOF
470 SUBSYSTEMS=="usb", PROGRAM=="/bin/echo -n usb-%b", SYMLINK+="%c"
471 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n scsi-%b", SYMLINK+="%c"
472 SUBSYSTEMS=="foo", PROGRAM=="/bin/echo -n foo-%b", SYMLINK+="%c"
473 EOF
474 },
475 {
476 desc => "sysfs parent hierarchy",
477 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
478 exp_name => "modem" ,
479 rules => <<EOF
480 ATTRS{idProduct}=="007b", SYMLINK+="modem"
481 EOF
482 },
483 {
484 desc => "name test with ! in the name",
485 devpath => "/devices/virtual/block/fake!blockdev0",
486 exp_name => "is/a/fake/blockdev0" ,
487 rules => <<EOF
488 SUBSYSTEMS=="scsi", SYMLINK+="is/not/a/%k"
489 SUBSYSTEM=="block", SYMLINK+="is/a/%k"
490 KERNEL=="ttyACM0", SYMLINK+="modem"
491 EOF
492 },
493 {
494 desc => "name test with ! in the name, but no matching rule",
495 devpath => "/devices/virtual/block/fake!blockdev0",
496 exp_name => "fake/blockdev0" ,
497 exp_rem_error => "yes",
498 rules => <<EOF
499 KERNEL=="ttyACM0", SYMLINK+="modem"
500 EOF
501 },
502 {
503 desc => "KERNELS rule",
504 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
505 exp_name => "scsi-0:0:0:0",
506 rules => <<EOF
507 SUBSYSTEMS=="usb", KERNELS=="0:0:0:0", SYMLINK+="not-scsi"
508 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:1", SYMLINK+="no-match"
509 SUBSYSTEMS=="scsi", KERNELS==":0", SYMLINK+="short-id"
510 SUBSYSTEMS=="scsi", KERNELS=="/0:0:0:0", SYMLINK+="no-match"
511 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="scsi-0:0:0:0"
512 EOF
513 },
514 {
515 desc => "KERNELS wildcard all",
516 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
517 exp_name => "scsi-0:0:0:0",
518 rules => <<EOF
519 SUBSYSTEMS=="scsi", KERNELS=="*:1", SYMLINK+="no-match"
520 SUBSYSTEMS=="scsi", KERNELS=="*:0:1", SYMLINK+="no-match"
521 SUBSYSTEMS=="scsi", KERNELS=="*:0:0:1", SYMLINK+="no-match"
522 SUBSYSTEMS=="scsi", KERNEL=="0:0:0:0", SYMLINK+="before"
523 SUBSYSTEMS=="scsi", KERNELS=="*", SYMLINK+="scsi-0:0:0:0"
524 EOF
525 },
526 {
527 desc => "KERNELS wildcard partial",
528 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
529 exp_name => "scsi-0:0:0:0",
530 rules => <<EOF
531 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
532 SUBSYSTEMS=="scsi", KERNELS=="*:0", SYMLINK+="scsi-0:0:0:0"
533 EOF
534 },
535 {
536 desc => "KERNELS wildcard partial 2",
537 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
538 exp_name => "scsi-0:0:0:0",
539 rules => <<EOF
540 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
541 SUBSYSTEMS=="scsi", KERNELS=="*:0:0:0", SYMLINK+="scsi-0:0:0:0"
542 EOF
543 },
544 {
545 desc => "substitute attr with link target value (first match)",
546 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
547 exp_name => "driver-is-sd",
548 rules => <<EOF
549 SUBSYSTEMS=="scsi", SYMLINK+="driver-is-\$attr{driver}"
550 EOF
551 },
552 {
553 desc => "substitute attr with link target value (currently selected device)",
554 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
555 exp_name => "driver-is-ahci",
556 rules => <<EOF
557 SUBSYSTEMS=="pci", SYMLINK+="driver-is-\$attr{driver}"
558 EOF
559 },
560 {
561 desc => "ignore ATTRS attribute whitespace",
562 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
563 exp_name => "ignored",
564 rules => <<EOF
565 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE", SYMLINK+="ignored"
566 EOF
567 },
568 {
569 desc => "do not ignore ATTRS attribute whitespace",
570 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
571 exp_name => "matched-with-space",
572 rules => <<EOF
573 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE ", SYMLINK+="wrong-to-ignore"
574 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE ", SYMLINK+="matched-with-space"
575 EOF
576 },
577 {
578 desc => "permissions USER=bad GROUP=name",
579 devpath => "/devices/virtual/tty/tty33",
580 exp_name => "tty33",
581 exp_perms => "0:0:0600",
582 rules => <<EOF
583 KERNEL=="tty33", OWNER="bad", GROUP="name"
584 EOF
585 },
586 {
587 desc => "permissions OWNER=1",
588 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
589 exp_name => "node",
590 exp_perms => "1::0600",
591 rules => <<EOF
592 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="1"
593 EOF
594 },
595 {
596 desc => "permissions GROUP=1",
597 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
598 exp_name => "node",
599 exp_perms => ":1:0660",
600 rules => <<EOF
601 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", GROUP="1"
602 EOF
603 },
604 {
605 desc => "textual user id",
606 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
607 exp_name => "node",
608 exp_perms => "daemon::0600",
609 rules => <<EOF
610 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="daemon"
611 EOF
612 },
613 {
614 desc => "textual group id",
615 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
616 exp_name => "node",
617 exp_perms => ":daemon:0660",
618 rules => <<EOF
619 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", GROUP="daemon"
620 EOF
621 },
622 {
623 desc => "textual user/group id",
624 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
625 exp_name => "node",
626 exp_perms => "root:mail:0660",
627 rules => <<EOF
628 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="root", GROUP="mail"
629 EOF
630 },
631 {
632 desc => "permissions MODE=0777",
633 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
634 exp_name => "node",
635 exp_perms => "::0777",
636 rules => <<EOF
637 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", MODE="0777"
638 EOF
639 },
640 {
641 desc => "permissions OWNER=1 GROUP=1 MODE=0777",
642 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
643 exp_name => "node",
644 exp_perms => "1:1:0777",
645 rules => <<EOF
646 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="1", GROUP="1", MODE="0777"
647 EOF
648 },
649 {
650 desc => "permissions OWNER to 1",
651 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
652 exp_name => "ttyACM0",
653 exp_perms => "1::",
654 rules => <<EOF
655 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", OWNER="1"
656 EOF
657 },
658 {
659 desc => "permissions GROUP to 1",
660 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
661 exp_name => "ttyACM0",
662 exp_perms => ":1:0660",
663 rules => <<EOF
664 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", GROUP="1"
665 EOF
666 },
667 {
668 desc => "permissions MODE to 0060",
669 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
670 exp_name => "ttyACM0",
671 exp_perms => "::0060",
672 rules => <<EOF
673 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", MODE="0060"
674 EOF
675 },
676 {
677 desc => "permissions OWNER, GROUP, MODE",
678 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
679 exp_name => "ttyACM0",
680 exp_perms => "1:1:0777",
681 rules => <<EOF
682 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", OWNER="1", GROUP="1", MODE="0777"
683 EOF
684 },
685 {
686 desc => "permissions only rule",
687 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
688 exp_name => "ttyACM0",
689 exp_perms => "1:1:0777",
690 rules => <<EOF
691 KERNEL=="ttyACM[0-9]*", OWNER="1", GROUP="1", MODE="0777"
692 KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
693 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n"
694 EOF
695 },
696 {
697 desc => "multiple permissions only rule",
698 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
699 exp_name => "ttyACM0",
700 exp_perms => "1:1:0777",
701 rules => <<EOF
702 SUBSYSTEM=="tty", OWNER="1"
703 SUBSYSTEM=="tty", GROUP="1"
704 SUBSYSTEM=="tty", MODE="0777"
705 KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
706 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n"
707 EOF
708 },
709 {
710 desc => "permissions only rule with override at SYMLINK+ rule",
711 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
712 exp_name => "ttyACM0",
713 exp_perms => "1:2:0777",
714 rules => <<EOF
715 SUBSYSTEM=="tty", OWNER="1"
716 SUBSYSTEM=="tty", GROUP="1"
717 SUBSYSTEM=="tty", MODE="0777"
718 KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
719 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", GROUP="2"
720 EOF
721 },
722 {
723 desc => "major/minor number test",
724 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
725 exp_name => "node",
726 exp_majorminor => "8:0",
727 rules => <<EOF
728 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node"
729 EOF
730 },
731 {
732 desc => "big major number test",
733 devpath => "/devices/virtual/misc/misc-fake1",
734 exp_name => "node",
735 exp_majorminor => "4095:1",
736 rules => <<EOF
737 KERNEL=="misc-fake1", SYMLINK+="node"
738 EOF
739 },
740 {
741 desc => "big major and big minor number test",
742 devpath => "/devices/virtual/misc/misc-fake89999",
743 exp_name => "node",
744 exp_majorminor => "4095:89999",
745 rules => <<EOF
746 KERNEL=="misc-fake89999", SYMLINK+="node"
747 EOF
748 },
749 {
750 desc => "multiple symlinks with format char",
751 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
752 exp_name => "symlink2-ttyACM0",
753 rules => <<EOF
754 KERNEL=="ttyACM[0-9]*", SYMLINK="symlink1-%n symlink2-%k symlink3-%b"
755 EOF
756 },
757 {
758 desc => "multiple symlinks with a lot of s p a c e s",
759 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
760 exp_name => "one",
761 not_exp_name => " ",
762 rules => <<EOF
763 KERNEL=="ttyACM[0-9]*", SYMLINK=" one two "
764 EOF
765 },
766 {
767 desc => "symlink with spaces in substituted variable",
768 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
769 exp_name => "name-one_two_three-end",
770 not_exp_name => " ",
771 rules => <<EOF
772 ENV{WITH_WS}="one two three"
773 SYMLINK="name-\$env{WITH_WS}-end"
774 EOF
775 },
776 {
777 desc => "symlink with leading space in substituted variable",
778 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
779 exp_name => "name-one_two_three-end",
780 not_exp_name => " ",
781 rules => <<EOF
782 ENV{WITH_WS}=" one two three"
783 SYMLINK="name-\$env{WITH_WS}-end"
784 EOF
785 },
786 {
787 desc => "symlink with trailing space in substituted variable",
788 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
789 exp_name => "name-one_two_three-end",
790 not_exp_name => " ",
791 rules => <<EOF
792 ENV{WITH_WS}="one two three "
793 SYMLINK="name-\$env{WITH_WS}-end"
794 EOF
795 },
796 {
797 desc => "symlink with lots of space in substituted variable",
798 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
799 exp_name => "name-one_two_three-end",
800 not_exp_name => " ",
801 rules => <<EOF
802 ENV{WITH_WS}=" one two three "
803 SYMLINK="name-\$env{WITH_WS}-end"
804 EOF
805 },
806 {
807 desc => "symlink with multiple spaces in substituted variable",
808 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
809 exp_name => "name-one_two_three-end",
810 not_exp_name => " ",
811 rules => <<EOF
812 ENV{WITH_WS}=" one two three "
813 SYMLINK="name-\$env{WITH_WS}-end"
814 EOF
815 },
816 {
817 desc => "symlink with space and var with space, part 1",
818 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
819 exp_name => "first",
820 not_exp_name => " ",
821 rules => <<EOF
822 ENV{WITH_WS}=" one two three "
823 SYMLINK=" first name-\$env{WITH_WS}-end another_symlink a b c "
824 EOF
825 },
826 {
827 desc => "symlink with space and var with space, part 2",
828 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
829 exp_name => "name-one_two_three-end",
830 not_exp_name => " ",
831 rules => <<EOF
832 ENV{WITH_WS}=" one two three "
833 SYMLINK=" first name-\$env{WITH_WS}-end another_symlink a b c "
834 EOF
835 },
836 {
837 desc => "symlink with space and var with space, part 3",
838 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
839 exp_name => "another_symlink",
840 not_exp_name => " ",
841 rules => <<EOF
842 ENV{WITH_WS}=" one two three "
843 SYMLINK=" first name-\$env{WITH_WS}-end another_symlink a b c "
844 EOF
845 },
846 {
847 desc => "symlink creation (same directory)",
848 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
849 exp_name => "modem0",
850 rules => <<EOF
851 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK="modem%n"
852 EOF
853 },
854 {
855 desc => "multiple symlinks",
856 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
857 exp_name => "second-0" ,
858 rules => <<EOF
859 KERNEL=="ttyACM0", SYMLINK="first-%n second-%n third-%n"
860 EOF
861 },
862 {
863 desc => "symlink name '.'",
864 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
865 exp_name => ".",
866 exp_add_error => "yes",
867 exp_rem_error => "yes",
868 rules => <<EOF
869 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="."
870 EOF
871 },
872 {
873 desc => "symlink node to itself",
874 devpath => "/devices/virtual/tty/tty0",
875 exp_name => "link",
876 exp_add_error => "yes",
877 exp_rem_error => "yes",
878 option => "clean",
879 rules => <<EOF
880 KERNEL=="tty0", SYMLINK+="tty0"
881 EOF
882 },
883 {
884 desc => "symlink %n substitution",
885 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
886 exp_name => "symlink0",
887 rules => <<EOF
888 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="symlink%n"
889 EOF
890 },
891 {
892 desc => "symlink %k substitution",
893 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
894 exp_name => "symlink-ttyACM0",
895 rules => <<EOF
896 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="symlink-%k"
897 EOF
898 },
899 {
900 desc => "symlink %M:%m substitution",
901 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
902 exp_name => "major-166:0",
903 rules => <<EOF
904 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="major-%M:%m"
905 EOF
906 },
907 {
908 desc => "symlink %b substitution",
909 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
910 exp_name => "symlink-0:0:0:0",
911 rules => <<EOF
912 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="symlink-%b"
913 EOF
914 },
915 {
916 desc => "symlink %c substitution",
917 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
918 exp_name => "test",
919 rules => <<EOF
920 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo test", SYMLINK+="%c"
921 EOF
922 },
923 {
924 desc => "symlink %c{N} substitution",
925 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
926 exp_name => "test",
927 rules => <<EOF
928 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo symlink test this", SYMLINK+="%c{2}"
929 EOF
930 },
931 {
932 desc => "symlink %c{N+} substitution",
933 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
934 exp_name => "this",
935 rules => <<EOF
936 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo symlink test this", SYMLINK+="%c{2+}"
937 EOF
938 },
939 {
940 desc => "symlink only rule with %c{N+}",
941 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
942 exp_name => "test",
943 rules => <<EOF
944 SUBSYSTEMS=="scsi", KERNEL=="sda", PROGRAM=="/bin/echo link test this" SYMLINK+="%c{2+}"
945 EOF
946 },
947 {
948 desc => "symlink %s{filename} substitution",
949 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
950 exp_name => "166:0",
951 rules => <<EOF
952 KERNEL=="ttyACM[0-9]*", SYMLINK+="%s{dev}"
953 EOF
954 },
955 {
956 desc => "program result substitution (numbered part of)",
957 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
958 exp_name => "link1",
959 rules => <<EOF
960 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n node link1 link2", RESULT=="node *", SYMLINK+="%c{2} %c{3}"
961 EOF
962 },
963 {
964 desc => "program result substitution (numbered part of+)",
965 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
966 exp_name => "link4",
967 rules => <<EOF
968 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n node link1 link2 link3 link4", RESULT=="node *", SYMLINK+="%c{2+}"
969 EOF
970 },
971 {
972 desc => "SUBSYSTEM match test",
973 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
974 exp_name => "node",
975 rules => <<EOF
976 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match", SUBSYSTEM=="vc"
977 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", SUBSYSTEM=="block"
978 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match2", SUBSYSTEM=="vc"
979 EOF
980 },
981 {
982 desc => "DRIVERS match test",
983 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
984 exp_name => "node",
985 rules => <<EOF
986 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match", DRIVERS=="sd-wrong"
987 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", DRIVERS=="sd"
988 EOF
989 },
990 {
991 desc => "devnode substitution test",
992 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
993 exp_name => "node",
994 rules => <<EOF
995 SUBSYSTEMS=="scsi", KERNEL=="sda", PROGRAM=="/usr/bin/test -b %N" SYMLINK+="node"
996 EOF
997 },
998 {
999 desc => "parent node name substitution test",
1000 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1001 exp_name => "sda-part-1",
1002 rules => <<EOF
1003 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="%P-part-1"
1004 EOF
1005 },
1006 {
1007 desc => "udev_root substitution",
1008 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1009 exp_name => "start-/dev-end",
1010 rules => <<EOF
1011 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="start-%r-end"
1012 EOF
1013 },
1014 {
1015 desc => "last_rule option",
1016 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1017 exp_name => "last",
1018 rules => <<EOF
1019 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="last", OPTIONS="last_rule"
1020 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="very-last"
1021 EOF
1022 },
1023 {
1024 desc => "negation KERNEL!=",
1025 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1026 exp_name => "match",
1027 rules => <<EOF
1028 SUBSYSTEMS=="scsi", KERNEL!="sda1", SYMLINK+="matches-but-is-negated"
1029 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
1030 SUBSYSTEMS=="scsi", KERNEL!="xsda1", SYMLINK+="match"
1031 EOF
1032 },
1033 {
1034 desc => "negation SUBSYSTEM!=",
1035 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1036 exp_name => "not-anything",
1037 rules => <<EOF
1038 SUBSYSTEMS=="scsi", SUBSYSTEM=="block", KERNEL!="sda1", SYMLINK+="matches-but-is-negated"
1039 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
1040 SUBSYSTEMS=="scsi", SUBSYSTEM!="anything", SYMLINK+="not-anything"
1041 EOF
1042 },
1043 {
1044 desc => "negation PROGRAM!= exit code",
1045 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1046 exp_name => "nonzero-program",
1047 rules => <<EOF
1048 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
1049 KERNEL=="sda1", PROGRAM!="/bin/false", SYMLINK+="nonzero-program"
1050 EOF
1051 },
1052 {
1053 desc => "ENV{} test",
1054 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1055 exp_name => "true",
1056 rules => <<EOF
1057 ENV{ENV_KEY_TEST}="test"
1058 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="go", SYMLINK+="wrong"
1059 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="test", SYMLINK+="true"
1060 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="bad", SYMLINK+="bad"
1061 EOF
1062 },
1063 {
1064 desc => "ENV{} test",
1065 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1066 exp_name => "true",
1067 rules => <<EOF
1068 ENV{ENV_KEY_TEST}="test"
1069 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="go", SYMLINK+="wrong"
1070 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="yes", ENV{ACTION}=="add", ENV{DEVPATH}=="*/block/sda/sdax1", SYMLINK+="no"
1071 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="test", ENV{ACTION}=="add", ENV{DEVPATH}=="*/block/sda/sda1", SYMLINK+="true"
1072 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="bad", SYMLINK+="bad"
1073 EOF
1074 },
1075 {
1076 desc => "ENV{} test (assign)",
1077 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1078 exp_name => "true",
1079 rules => <<EOF
1080 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="true"
1081 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="yes", SYMLINK+="no"
1082 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
1083 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="true", SYMLINK+="true"
1084 EOF
1085 },
1086 {
1087 desc => "ENV{} test (assign 2 times)",
1088 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1089 exp_name => "true",
1090 rules => <<EOF
1091 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="true"
1092 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="absolutely-\$env{ASSIGN}"
1093 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
1094 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="yes", SYMLINK+="no"
1095 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="absolutely-true", SYMLINK+="true"
1096 EOF
1097 },
1098 {
1099 desc => "ENV{} test (assign2)",
1100 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1101 exp_name => "part",
1102 rules => <<EOF
1103 SUBSYSTEM=="block", KERNEL=="*[0-9]", ENV{PARTITION}="true", ENV{MAINDEVICE}="false"
1104 SUBSYSTEM=="block", KERNEL=="*[!0-9]", ENV{PARTITION}="false", ENV{MAINDEVICE}="true"
1105 ENV{MAINDEVICE}=="true", SYMLINK+="disk"
1106 SUBSYSTEM=="block", SYMLINK+="before"
1107 ENV{PARTITION}=="true", SYMLINK+="part"
1108 EOF
1109 },
1110 {
1111 desc => "untrusted string sanitize",
1112 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1113 exp_name => "sane",
1114 rules => <<EOF
1115 SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e name; (/usr/bin/badprogram)", RESULT=="name_ _/usr/bin/badprogram_", SYMLINK+="sane"
1116 EOF
1117 },
1118 {
1119 desc => "untrusted string sanitize (don't replace utf8)",
1120 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1121 exp_name => "uber",
1122 rules => <<EOF
1123 SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e \\xc3\\xbcber" RESULT=="\xc3\xbcber", SYMLINK+="uber"
1124 EOF
1125 },
1126 {
1127 desc => "untrusted string sanitize (replace invalid utf8)",
1128 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1129 exp_name => "replaced",
1130 rules => <<EOF
1131 SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e \\xef\\xe8garbage", RESULT=="__garbage", SYMLINK+="replaced"
1132 EOF
1133 },
1134 {
1135 desc => "read sysfs value from parent device",
1136 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1137 exp_name => "serial-354172020305000",
1138 rules => <<EOF
1139 KERNEL=="ttyACM*", ATTRS{serial}=="?*", SYMLINK+="serial-%s{serial}"
1140 EOF
1141 },
1142 {
1143 desc => "match against empty key string",
1144 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1145 exp_name => "ok",
1146 rules => <<EOF
1147 KERNEL=="sda", ATTRS{nothing}!="", SYMLINK+="not-1-ok"
1148 KERNEL=="sda", ATTRS{nothing}=="", SYMLINK+="not-2-ok"
1149 KERNEL=="sda", ATTRS{vendor}!="", SYMLINK+="ok"
1150 KERNEL=="sda", ATTRS{vendor}=="", SYMLINK+="not-3-ok"
1151 EOF
1152 },
1153 {
1154 desc => "check ACTION value",
1155 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1156 exp_name => "ok",
1157 rules => <<EOF
1158 ACTION=="unknown", KERNEL=="sda", SYMLINK+="unknown-not-ok"
1159 ACTION=="add", KERNEL=="sda", SYMLINK+="ok"
1160 EOF
1161 },
1162 {
1163 desc => "final assignment",
1164 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1165 exp_name => "ok",
1166 exp_perms => "root:tty:0640",
1167 rules => <<EOF
1168 KERNEL=="sda", GROUP:="tty"
1169 KERNEL=="sda", GROUP="not-ok", MODE="0640", SYMLINK+="ok"
1170 EOF
1171 },
1172 {
1173 desc => "final assignment 2",
1174 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1175 exp_name => "ok",
1176 exp_perms => "root:tty:0640",
1177 rules => <<EOF
1178 KERNEL=="sda", GROUP:="tty"
1179 SUBSYSTEM=="block", MODE:="640"
1180 KERNEL=="sda", GROUP="not-ok", MODE="0666", SYMLINK+="ok"
1181 EOF
1182 },
1183 {
1184 desc => "env substitution",
1185 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1186 exp_name => "node-add-me",
1187 rules => <<EOF
1188 KERNEL=="sda", MODE="0666", SYMLINK+="node-\$env{ACTION}-me"
1189 EOF
1190 },
1191 {
1192 desc => "reset list to current value",
1193 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1194 exp_name => "three",
1195 not_exp_name => "two",
1196 rules => <<EOF
1197 KERNEL=="ttyACM[0-9]*", SYMLINK+="one"
1198 KERNEL=="ttyACM[0-9]*", SYMLINK+="two"
1199 KERNEL=="ttyACM[0-9]*", SYMLINK="three"
1200 EOF
1201 },
1202 {
1203 desc => "test empty SYMLINK+ (empty override)",
1204 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1205 exp_name => "right",
1206 not_exp_name => "wrong",
1207 rules => <<EOF
1208 KERNEL=="ttyACM[0-9]*", SYMLINK+="wrong"
1209 KERNEL=="ttyACM[0-9]*", SYMLINK=""
1210 KERNEL=="ttyACM[0-9]*", SYMLINK+="right"
1211 EOF
1212 },
1213 {
1214 desc => "test multi matches",
1215 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1216 exp_name => "right",
1217 rules => <<EOF
1218 KERNEL=="ttyACM*", SYMLINK+="before"
1219 KERNEL=="ttyACM*|nothing", SYMLINK+="right"
1220 EOF
1221 },
1222 {
1223 desc => "test multi matches 2",
1224 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1225 exp_name => "right",
1226 rules => <<EOF
1227 KERNEL=="dontknow*|*nothing", SYMLINK+="nomatch"
1228 KERNEL=="ttyACM*", SYMLINK+="before"
1229 KERNEL=="dontknow*|ttyACM*|nothing*", SYMLINK+="right"
1230 EOF
1231 },
1232 {
1233 desc => "test multi matches 3",
1234 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1235 exp_name => "right",
1236 rules => <<EOF
1237 KERNEL=="dontknow|nothing", SYMLINK+="nomatch"
1238 KERNEL=="dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong1"
1239 KERNEL=="X|attyACM0|dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong2"
1240 KERNEL=="dontknow|ttyACM0|nothing", SYMLINK+="right"
1241 EOF
1242 },
1243 {
1244 desc => "test multi matches 4",
1245 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1246 exp_name => "right",
1247 rules => <<EOF
1248 KERNEL=="dontknow|nothing", SYMLINK+="nomatch"
1249 KERNEL=="dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong1"
1250 KERNEL=="X|attyACM0|dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong2"
1251 KERNEL=="all|dontknow|ttyACM0", SYMLINK+="right"
1252 KERNEL=="ttyACM0a|nothing", SYMLINK+="wrong3"
1253 EOF
1254 },
1255 {
1256 desc => "IMPORT parent test sequence 1/2 (keep)",
1257 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1258 exp_name => "parent",
1259 option => "keep",
1260 rules => <<EOF
1261 KERNEL=="sda", IMPORT{program}="/bin/echo -e \'PARENT_KEY=parent_right\\nWRONG_PARENT_KEY=parent_wrong'"
1262 KERNEL=="sda", SYMLINK+="parent"
1263 EOF
1264 },
1265 {
1266 desc => "IMPORT parent test sequence 2/2 (keep)",
1267 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1268 exp_name => "parentenv-parent_right",
1269 option => "clean",
1270 rules => <<EOF
1271 KERNEL=="sda1", IMPORT{parent}="PARENT*", SYMLINK+="parentenv-\$env{PARENT_KEY}\$env{WRONG_PARENT_KEY}"
1272 EOF
1273 },
1274 {
1275 desc => "GOTO test",
1276 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1277 exp_name => "right",
1278 rules => <<EOF
1279 KERNEL=="sda1", GOTO="TEST"
1280 KERNEL=="sda1", SYMLINK+="wrong"
1281 KERNEL=="sda1", GOTO="BAD"
1282 KERNEL=="sda1", SYMLINK+="", LABEL="NO"
1283 KERNEL=="sda1", SYMLINK+="right", LABEL="TEST", GOTO="end"
1284 KERNEL=="sda1", SYMLINK+="wrong2", LABEL="BAD"
1285 LABEL="end"
1286 EOF
1287 },
1288 {
1289 desc => "GOTO label does not exist",
1290 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1291 exp_name => "right",
1292 rules => <<EOF
1293 KERNEL=="sda1", GOTO="does-not-exist"
1294 KERNEL=="sda1", SYMLINK+="right",
1295 LABEL="exists"
1296 EOF
1297 },
1298 {
1299 desc => "SYMLINK+ compare test",
1300 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1301 exp_name => "right",
1302 not_exp_name => "wrong",
1303 rules => <<EOF
1304 KERNEL=="sda1", SYMLINK+="link"
1305 KERNEL=="sda1", SYMLINK=="link*", SYMLINK+="right"
1306 KERNEL=="sda1", SYMLINK=="nolink*", SYMLINK+="wrong"
1307 EOF
1308 },
1309 {
1310 desc => "invalid key operation",
1311 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1312 exp_name => "yes",
1313 rules => <<EOF
1314 KERNEL="sda1", SYMLINK+="no"
1315 KERNEL=="sda1", SYMLINK+="yes"
1316 EOF
1317 },
1318 {
1319 desc => "operator chars in attribute",
1320 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1321 exp_name => "yes",
1322 rules => <<EOF
1323 KERNEL=="sda", ATTR{test:colon+plus}=="?*", SYMLINK+="yes"
1324 EOF
1325 },
1326 {
1327 desc => "overlong comment line",
1328 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1329 exp_name => "yes",
1330 rules => <<EOF
1331 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
1332 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
1333 KERNEL=="sda1", SYMLINK+=="no"
1334 KERNEL=="sda1", SYMLINK+="yes"
1335 EOF
1336 },
1337 {
1338 desc => "magic subsys/kernel lookup",
1339 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1340 exp_name => "00:16:41:e2:8d:ff",
1341 rules => <<EOF
1342 KERNEL=="sda", SYMLINK+="\$attr{[net/eth0]address}"
1343 EOF
1344 },
1345 {
1346 desc => "TEST absolute path",
1347 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1348 exp_name => "there",
1349 rules => <<EOF
1350 TEST=="/etc/machine-id", SYMLINK+="there"
1351 TEST!="/etc/machine-id", SYMLINK+="notthere"
1352 EOF
1353 },
1354 {
1355 desc => "TEST subsys/kernel lookup",
1356 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1357 exp_name => "yes",
1358 rules => <<EOF
1359 KERNEL=="sda", TEST=="[net/eth0]", SYMLINK+="yes"
1360 EOF
1361 },
1362 {
1363 desc => "TEST relative path",
1364 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1365 exp_name => "relative",
1366 rules => <<EOF
1367 KERNEL=="sda", TEST=="size", SYMLINK+="relative"
1368 EOF
1369 },
1370 {
1371 desc => "TEST wildcard substitution (find queue/nr_requests)",
1372 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1373 exp_name => "found-subdir",
1374 rules => <<EOF
1375 KERNEL=="sda", TEST=="*/nr_requests", SYMLINK+="found-subdir"
1376 EOF
1377 },
1378 {
1379 desc => "TEST MODE=0000",
1380 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1381 exp_name => "sda",
1382 exp_perms => "0:0:0000",
1383 exp_rem_error => "yes",
1384 rules => <<EOF
1385 KERNEL=="sda", MODE="0000"
1386 EOF
1387 },
1388 {
1389 desc => "TEST PROGRAM feeds OWNER, GROUP, MODE",
1390 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1391 exp_name => "sda",
1392 exp_perms => "1:1:0400",
1393 exp_rem_error => "yes",
1394 rules => <<EOF
1395 KERNEL=="sda", MODE="666"
1396 KERNEL=="sda", PROGRAM=="/bin/echo 1 1 0400", OWNER="%c{1}", GROUP="%c{2}", MODE="%c{3}"
1397 EOF
1398 },
1399 {
1400 desc => "TEST PROGRAM feeds MODE with overflow",
1401 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1402 exp_name => "sda",
1403 exp_perms => "0:0:0440",
1404 exp_rem_error => "yes",
1405 rules => <<EOF
1406 KERNEL=="sda", MODE="440"
1407 KERNEL=="sda", PROGRAM=="/bin/echo 0 0 0400letsdoabuffferoverflow0123456789012345789012345678901234567890", OWNER="%c{1}", GROUP="%c{2}", MODE="%c{3}"
1408 EOF
1409 },
1410 {
1411 desc => "magic [subsys/sysname] attribute substitution",
1412 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1413 exp_name => "sda-8741C4G-end",
1414 exp_perms => "0:0:0600",
1415 rules => <<EOF
1416 KERNEL=="sda", PROGRAM="/bin/true create-envp"
1417 KERNEL=="sda", ENV{TESTENV}="change-envp"
1418 KERNEL=="sda", SYMLINK+="%k-%s{[dmi/id]product_name}-end"
1419 EOF
1420 },
1421 {
1422 desc => "builtin path_id",
1423 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1424 exp_name => "disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0",
1425 rules => <<EOF
1426 KERNEL=="sda", IMPORT{builtin}="path_id"
1427 KERNEL=="sda", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/\$env{ID_PATH}"
1428 EOF
1429 },
1430 {
1431 desc => "add and match tag",
1432 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1433 exp_name => "found",
1434 not_exp_name => "bad" ,
1435 rules => <<EOF
1436 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", TAG+="green"
1437 TAGS=="green", SYMLINK+="found"
1438 TAGS=="blue", SYMLINK+="bad"
1439 EOF
1440 },
1441 {
1442 desc => "don't crash with lots of tags",
1443 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1444 exp_name => "found",
1445 rules => $rules_10k_tags . <<EOF
1446 TAGS=="test1", TAGS=="test500", TAGS=="test1234", TAGS=="test9999", TAGS=="test10000", SYMLINK+="found"
1447 EOF
1448 },
1449 );
1450
1451 sub udev {
1452 my ($action, $devpath, $rules) = @_;
1453
1454 # create temporary rules
1455 system("mkdir", "-p", "$udev_rules_dir");
1456 open CONF, ">$udev_rules" || die "unable to create rules file: $udev_rules";
1457 print CONF $$rules;
1458 close CONF;
1459
1460 if ($valgrind > 0) {
1461 return system("$udev_bin_valgrind $action $devpath");
1462 } elsif ($gdb > 0) {
1463 return system("$udev_bin_gdb $action $devpath");
1464 } elsif ($strace > 0) {
1465 return system("$udev_bin_strace $action $devpath");
1466 } else {
1467 return system("$udev_bin", "$action", "$devpath");
1468 }
1469 }
1470
1471 my $error = 0;
1472
1473 sub permissions_test {
1474 my($rules, $uid, $gid, $mode) = @_;
1475
1476 my $wrong = 0;
1477 my $userid;
1478 my $groupid;
1479
1480 $rules->{exp_perms} =~ m/^(.*):(.*):(.*)$/;
1481 if ($1 ne "") {
1482 if (defined(getpwnam($1))) {
1483 $userid = int(getpwnam($1));
1484 } else {
1485 $userid = $1;
1486 }
1487 if ($uid != $userid) { $wrong = 1; }
1488 }
1489 if ($2 ne "") {
1490 if (defined(getgrnam($2))) {
1491 $groupid = int(getgrnam($2));
1492 } else {
1493 $groupid = $2;
1494 }
1495 if ($gid != $groupid) { $wrong = 1; }
1496 }
1497 if ($3 ne "") {
1498 if (($mode & 07777) != oct($3)) { $wrong = 1; };
1499 }
1500 if ($wrong == 0) {
1501 print "permissions: ok\n";
1502 } else {
1503 printf " expected permissions are: %s:%s:%#o\n", $1, $2, oct($3);
1504 printf " created permissions are : %i:%i:%#o\n", $uid, $gid, $mode & 07777;
1505 print "permissions: error\n";
1506 $error++;
1507 sleep(1);
1508 }
1509 }
1510
1511 sub major_minor_test {
1512 my($rules, $rdev) = @_;
1513
1514 my $major = ($rdev >> 8) & 0xfff;
1515 my $minor = ($rdev & 0xff) | (($rdev >> 12) & 0xfff00);
1516 my $wrong = 0;
1517
1518 $rules->{exp_majorminor} =~ m/^(.*):(.*)$/;
1519 if ($1 ne "") {
1520 if ($major != $1) { $wrong = 1; };
1521 }
1522 if ($2 ne "") {
1523 if ($minor != $2) { $wrong = 1; };
1524 }
1525 if ($wrong == 0) {
1526 print "major:minor: ok\n";
1527 } else {
1528 printf " expected major:minor is: %i:%i\n", $1, $2;
1529 printf " created major:minor is : %i:%i\n", $major, $minor;
1530 print "major:minor: error\n";
1531 $error++;
1532 sleep(1);
1533 }
1534 }
1535
1536 sub udev_setup {
1537 system("umount", $udev_tmpfs);
1538 rmdir($udev_tmpfs);
1539 mkdir($udev_tmpfs) || die "unable to create udev_tmpfs: $udev_tmpfs\n";
1540 system("mount", "-o", "rw,mode=755,nosuid,noexec", "-t", "tmpfs", "tmpfs", $udev_tmpfs) && die "unable to mount tmpfs";
1541
1542 mkdir($udev_dev) || die "unable to create udev_dev: $udev_dev\n";
1543 # setting group and mode of udev_dev ensures the tests work
1544 # even if the parent directory has setgid bit enabled.
1545 chown (0, 0, $udev_dev) || die "unable to chown $udev_dev\n";
1546 chmod (0755, $udev_dev) || die "unable to chmod $udev_dev\n";
1547 system("mknod", $udev_dev . "/null", "c", "1", "3") && die "unable to create $udev_dev/null";
1548
1549 system("cp", "-r", "test/sys/", $udev_sys) && die "unable to copy test/sys";
1550
1551 system("rm", "-rf", "$udev_run");
1552 }
1553
1554 sub run_test {
1555 my ($rules, $number) = @_;
1556 my $rc;
1557
1558 print "TEST $number: $rules->{desc}\n";
1559 print "device \'$rules->{devpath}\' expecting node/link \'$rules->{exp_name}\'\n";
1560
1561 $rc = udev("add", $rules->{devpath}, \$rules->{rules});
1562 if ($rc != 0) {
1563 print "$udev_bin add failed with code $rc\n";
1564 $error++;
1565 }
1566 if (defined($rules->{not_exp_name})) {
1567 if ((-e "$udev_dev/$rules->{not_exp_name}") ||
1568 (-l "$udev_dev/$rules->{not_exp_name}")) {
1569 print "nonexistent: error \'$rules->{not_exp_name}\' not expected to be there\n";
1570 $error++;
1571 sleep(1);
1572 }
1573 }
1574
1575 if ((-e "$udev_dev/$rules->{exp_name}") ||
1576 (-l "$udev_dev/$rules->{exp_name}")) {
1577
1578 my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
1579 $atime, $mtime, $ctime, $blksize, $blocks) = stat("$udev_dev/$rules->{exp_name}");
1580
1581 if (defined($rules->{exp_perms})) {
1582 permissions_test($rules, $uid, $gid, $mode);
1583 }
1584 if (defined($rules->{exp_majorminor})) {
1585 major_minor_test($rules, $rdev);
1586 }
1587 print "add: ok\n";
1588 } else {
1589 print "add: error";
1590 if ($rules->{exp_add_error}) {
1591 print " as expected\n";
1592 } else {
1593 print "\n";
1594 system("tree", "$udev_dev");
1595 print "\n";
1596 $error++;
1597 sleep(1);
1598 }
1599 }
1600
1601 if (defined($rules->{option}) && $rules->{option} eq "keep") {
1602 print "\n\n";
1603 return;
1604 }
1605
1606 $rc = udev("remove", $rules->{devpath}, \$rules->{rules});
1607 if ($rc != 0) {
1608 print "$udev_bin remove failed with code $rc\n";
1609 $error++;
1610 }
1611 if ((-e "$udev_dev/$rules->{exp_name}") ||
1612 (-l "$udev_dev/$rules->{exp_name}")) {
1613 print "remove: error";
1614 if ($rules->{exp_rem_error}) {
1615 print " as expected\n";
1616 } else {
1617 print "\n";
1618 system("tree", "$udev_dev");
1619 print "\n";
1620 $error++;
1621 sleep(1);
1622 }
1623 } else {
1624 print "remove: ok\n";
1625 }
1626
1627 print "\n";
1628
1629 if (defined($rules->{option}) && $rules->{option} eq "clean") {
1630 udev_setup();
1631 }
1632
1633 }
1634
1635 # only run if we have root permissions
1636 # due to mknod restrictions
1637 if (!($<==0)) {
1638 print "Must have root permissions to run properly.\n";
1639 exit($EXIT_TEST_SKIP);
1640 }
1641
1642 # skip the test when running in a chroot
1643 system("systemd-detect-virt", "-r", "-q");
1644 if ($? >> 8 == 0) {
1645 print "Running in a chroot, skipping the test.\n";
1646 exit($EXIT_TEST_SKIP);
1647 }
1648
1649 udev_setup();
1650
1651 my $test_num = 1;
1652 my @list;
1653
1654 foreach my $arg (@ARGV) {
1655 if ($arg =~ m/--valgrind/) {
1656 $valgrind = 1;
1657 printf("using valgrind\n");
1658 } elsif ($arg =~ m/--gdb/) {
1659 $gdb = 1;
1660 printf("using gdb\n");
1661 } elsif ($arg =~ m/--strace/) {
1662 $strace = 1;
1663 printf("using strace\n");
1664 } else {
1665 push(@list, $arg);
1666 }
1667 }
1668
1669 if ($list[0]) {
1670 foreach my $arg (@list) {
1671 if (defined($tests[$arg-1]->{desc})) {
1672 print "udev-test will run test number $arg:\n\n";
1673 run_test($tests[$arg-1], $arg);
1674 } else {
1675 print "test does not exist.\n";
1676 }
1677 }
1678 } else {
1679 # test all
1680 print "\nudev-test will run ".($#tests + 1)." tests:\n\n";
1681
1682 foreach my $rules (@tests) {
1683 run_test($rules, $test_num);
1684 $test_num++;
1685 }
1686 }
1687
1688 print "$error errors occurred\n\n";
1689
1690 # cleanup
1691 system("rm", "-rf", "$udev_run");
1692 system("umount", "$udev_tmpfs");
1693 rmdir($udev_tmpfs);
1694
1695 if ($error > 0) {
1696 exit(1);
1697 }
1698 exit(0);