]> git.ipfire.org Git - thirdparty/systemd.git/blob - test/udev-test.pl
Merge pull request #1109 from phomes/man-typos
[thirdparty/systemd.git] / test / udev-test.pl
1 #!/usr/bin/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 (C) 2004-2012 Kay Sievers <kay@vrfy.org>
18 # Copyright (C) 2004 Leann Ogasawara <ogasawara@osdl.org>
19
20 use warnings;
21 use strict;
22
23 my $udev_bin = "./test-udev";
24 my $valgrind = 0;
25 my $gdb = 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_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;
33
34 my @tests = (
35 {
36 desc => "no rules",
37 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
38 exp_name => "sda" ,
39 exp_rem_error => "yes",
40 rules => <<EOF
41 #
42 EOF
43 },
44 {
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" ,
48 rules => <<EOF
49 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
50 KERNEL=="ttyACM0", SYMLINK+="modem"
51 EOF
52 },
53 {
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" ,
57 rules => <<EOF
58 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
59 KERNEL=="ttyACM0", SYMLINK+="modem"
60 EOF
61 },
62 {
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" ,
66 rules => <<EOF
67 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
68 KERNEL=="ttyACM0", SYMLINK+="modem"
69 EOF
70 },
71 {
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" ,
75 rules => <<EOF
76 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
77 EOF
78 },
79 {
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" ,
83 rules => <<EOF
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"
88 EOF
89 },
90 {
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" ,
94 rules => <<EOF
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"
97 EOF
98 },
99 {
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" ,
103 rules => <<EOF
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"
106 EOF
107 },
108 {
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" ,
112 rules => <<EOF
113 KERNEL=="ttyACM*", SYMLINK+="modem/%n"
114 EOF
115 },
116 {
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" ,
120 rules => <<EOF
121 KERNEL=="*ACM1", SYMLINK+="bad"
122 KERNEL=="*ACM0", SYMLINK+="modem/%n"
123 EOF
124 },
125 {
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" ,
129 rules => <<EOF
130 KERNEL=="ttyACM??*", SYMLINK+="modem/%n-1"
131 KERNEL=="ttyACM??", SYMLINK+="modem/%n-2"
132 KERNEL=="ttyACM?", SYMLINK+="modem/%n"
133 EOF
134 },
135 {
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" ,
139 rules => <<EOF
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"
143 EOF
144 },
145 {
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" ,
149 rules => <<EOF
150 KERNEL=="ttyACM0", SYMLINK+="modem"
151 EOF
152 },
153 {
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" ,
157 rules => <<EOF
158 # this is a comment
159 KERNEL=="ttyACM0", SYMLINK+="modem"
160
161 EOF
162 },
163 {
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" ,
167 rules => <<EOF
168 # this is a comment with whitespace before the comment
169 KERNEL=="ttyACM0", SYMLINK+="modem"
170
171 EOF
172 },
173 {
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" ,
177 rules => <<EOF
178
179
180
181 # this is a comment with whitespace before the comment
182 KERNEL=="ttyACM0", SYMLINK+="whitespace"
183
184
185
186 EOF
187 },
188 {
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" ,
192 rules => <<EOF
193
194 KERNEL=="ttyACM0", SYMLINK+="modem"
195
196 EOF
197 },
198 {
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" ,
202 rules => <<EOF
203 KERNEL=="ttyACM0", \\
204 SYMLINK+="modem"
205
206 EOF
207 },
208 {
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",
211 exp_name => "aaa",
212 rules => <<EOF
213 KERNEL=="ttyACM0", PROGRAM=="/bin/echo -e \\101", RESULT=="A", SYMLINK+="aaa"
214 EOF
215 },
216 {
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" ,
220 rules => <<EOF
221
222 #
223 \\
224
225 \\
226
227 #\\
228
229 KERNEL=="ttyACM0", \\
230 SYMLINK+="modem"
231
232 EOF
233 },
234 {
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" ,
238 rules => <<EOF
239 KERNEL=="ttyACM0", SYMLINK+="sub/direct/ory/modem"
240 EOF
241 },
242 {
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" ,
246 rules => <<EOF
247 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="first_disk%n"
248 EOF
249 },
250 {
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" ,
254 rules => <<EOF
255 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:%M:minor:%m:kernelnumber:%n:id:%b"
256 EOF
257 },
258 {
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",
262 rules => <<EOF
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"
265 EOF
266 },
267 {
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" ,
271 rules => <<EOF
272 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="disk-%s{vendor}-%k"
273 KERNEL=="ttyACM0", SYMLINK+="modem"
274 EOF
275 },
276 {
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" ,
281 rules => <<EOF
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"
284 EOF
285 },
286 {
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" ,
290 rules => <<EOF
291 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo test", RESULT=="test", SYMLINK+="newline_removed"
292 EOF
293 },
294 {
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" ,
298 rules => <<EOF
299 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n test-%b", RESULT=="test-0:0*", SYMLINK+="%c"
300 EOF
301 },
302 {
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",
305 exp_name => "foo9" ,
306 rules => <<EOF
307 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="%c{7}"
308 EOF
309 },
310 {
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",
313 exp_name => "bar9" ,
314 rules => <<EOF
315 SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'echo foo3 foo4 foo5 foo6 foo7 foo8 foo9 | sed s/foo9/bar9/'", KERNEL=="sda5", SYMLINK+="%c{7}"
316 EOF
317 },
318 {
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",
321 exp_name => "foo7" ,
322 rules => <<EOF
323 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n 'foo3 foo4' 'foo5 foo6 foo7 foo8'", KERNEL=="sda5", SYMLINK+="%c{5}"
324 EOF
325 },
326 {
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" ,
330 rules => <<EOF
331 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{7}"
332 EOF
333 },
334 {
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" ,
338 rules => <<EOF
339 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{6}"
340 EOF
341 },
342 {
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",
346 rules => <<EOF
347 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:\$major-minor:\$minor-kernelnumber:\$number-id:\$id"
348 EOF
349 },
350 {
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",
354 rules => <<EOF
355 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="Major:\$major-minor:%m-kernelnumber:\$number-id:\$id"
356 EOF
357 },
358 {
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" ,
362 rules => <<EOF
363 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="%M%m%b%n"
364 EOF
365 },
366 {
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",
369 exp_name => "855" ,
370 rules => <<EOF
371 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="\$major\$minor\$number"
372 EOF
373 },
374 {
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" ,
378 rules => <<EOF
379 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="\$major%m%n\$id"
380 EOF
381 },
382 {
383 desc => "non matching SUBSYSTEMS for device with no parent",
384 devpath => "/devices/virtual/tty/console",
385 exp_name => "TTY",
386 rules => <<EOF
387 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo", RESULT=="foo", SYMLINK+="foo"
388 KERNEL=="console", SYMLINK+="TTY"
389 EOF
390 },
391 {
392 desc => "non matching SUBSYSTEMS",
393 devpath => "/devices/virtual/tty/console",
394 exp_name => "TTY" ,
395 rules => <<EOF
396 SUBSYSTEMS=="foo", ATTRS{dev}=="5:1", SYMLINK+="foo"
397 KERNEL=="console", SYMLINK+="TTY"
398 EOF
399 },
400 {
401 desc => "ATTRS match",
402 devpath => "/devices/virtual/tty/console",
403 exp_name => "foo" ,
404 rules => <<EOF
405 KERNEL=="console", SYMLINK+="TTY"
406 ATTRS{dev}=="5:1", SYMLINK+="foo"
407 EOF
408 },
409 {
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" ,
413 rules => <<EOF
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"
418 EOF
419 },
420 {
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" ,
424 rules => <<EOF
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"
431 EOF
432 },
433 {
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" ,
437 rules => <<EOF
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"
441 EOF
442 },
443 {
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" ,
447 rules => <<EOF
448 ATTRS{idProduct}=="007b", SYMLINK+="modem"
449 EOF
450 },
451 {
452 desc => "name test with ! in the name",
453 devpath => "/devices/virtual/block/fake!blockdev0",
454 exp_name => "is/a/fake/blockdev0" ,
455 rules => <<EOF
456 SUBSYSTEMS=="scsi", SYMLINK+="is/not/a/%k"
457 SUBSYSTEM=="block", SYMLINK+="is/a/%k"
458 KERNEL=="ttyACM0", SYMLINK+="modem"
459 EOF
460 },
461 {
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",
466 rules => <<EOF
467 KERNEL=="ttyACM0", SYMLINK+="modem"
468 EOF
469 },
470 {
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",
474 rules => <<EOF
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"
480 EOF
481 },
482 {
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",
486 rules => <<EOF
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"
492 EOF
493 },
494 {
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",
498 rules => <<EOF
499 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
500 SUBSYSTEMS=="scsi", KERNELS=="*:0", SYMLINK+="scsi-0:0:0:0"
501 EOF
502 },
503 {
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",
507 rules => <<EOF
508 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
509 SUBSYSTEMS=="scsi", KERNELS=="*:0:0:0", SYMLINK+="scsi-0:0:0:0"
510 EOF
511 },
512 {
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",
516 rules => <<EOF
517 SUBSYSTEMS=="scsi", SYMLINK+="driver-is-\$attr{driver}"
518 EOF
519 },
520 {
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",
524 rules => <<EOF
525 SUBSYSTEMS=="pci", SYMLINK+="driver-is-\$attr{driver}"
526 EOF
527 },
528 {
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",
532 rules => <<EOF
533 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE", SYMLINK+="ignored"
534 EOF
535 },
536 {
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",
540 rules => <<EOF
541 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE ", SYMLINK+="wrong-to-ignore"
542 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE ", SYMLINK+="matched-with-space"
543 EOF
544 },
545 {
546 desc => "permissions USER=bad GROUP=name",
547 devpath => "/devices/virtual/tty/tty33",
548 exp_name => "tty33",
549 exp_perms => "0:0:0600",
550 rules => <<EOF
551 KERNEL=="tty33", OWNER="bad", GROUP="name"
552 EOF
553 },
554 {
555 desc => "permissions OWNER=1",
556 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
557 exp_name => "node",
558 exp_perms => "1::0600",
559 rules => <<EOF
560 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="1"
561 EOF
562 },
563 {
564 desc => "permissions GROUP=1",
565 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
566 exp_name => "node",
567 exp_perms => ":1:0660",
568 rules => <<EOF
569 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", GROUP="1"
570 EOF
571 },
572 {
573 desc => "textual user id",
574 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
575 exp_name => "node",
576 exp_perms => "nobody::0600",
577 rules => <<EOF
578 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="nobody"
579 EOF
580 },
581 {
582 desc => "textual group id",
583 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
584 exp_name => "node",
585 exp_perms => ":daemon:0660",
586 rules => <<EOF
587 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", GROUP="daemon"
588 EOF
589 },
590 {
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",
593 exp_name => "node",
594 exp_perms => "root:mail:0660",
595 rules => <<EOF
596 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="root", GROUP="mail"
597 EOF
598 },
599 {
600 desc => "permissions MODE=0777",
601 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
602 exp_name => "node",
603 exp_perms => "::0777",
604 rules => <<EOF
605 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", MODE="0777"
606 EOF
607 },
608 {
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",
611 exp_name => "node",
612 exp_perms => "1:1:0777",
613 rules => <<EOF
614 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="1", GROUP="1", MODE="0777"
615 EOF
616 },
617 {
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",
621 exp_perms => "1::",
622 rules => <<EOF
623 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", OWNER="1"
624 EOF
625 },
626 {
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",
631 rules => <<EOF
632 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", GROUP="1"
633 EOF
634 },
635 {
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",
640 rules => <<EOF
641 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", MODE="0060"
642 EOF
643 },
644 {
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",
649 rules => <<EOF
650 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", OWNER="1", GROUP="1", MODE="0777"
651 EOF
652 },
653 {
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",
658 rules => <<EOF
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"
662 EOF
663 },
664 {
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",
669 rules => <<EOF
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"
675 EOF
676 },
677 {
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",
682 rules => <<EOF
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"
688 EOF
689 },
690 {
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",
693 exp_name => "node",
694 exp_majorminor => "8:0",
695 rules => <<EOF
696 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node"
697 EOF
698 },
699 {
700 desc => "big major number test",
701 devpath => "/devices/virtual/misc/misc-fake1",
702 exp_name => "node",
703 exp_majorminor => "4095:1",
704 rules => <<EOF
705 KERNEL=="misc-fake1", SYMLINK+="node"
706 EOF
707 },
708 {
709 desc => "big major and big minor number test",
710 devpath => "/devices/virtual/misc/misc-fake89999",
711 exp_name => "node",
712 exp_majorminor => "4095:89999",
713 rules => <<EOF
714 KERNEL=="misc-fake89999", SYMLINK+="node"
715 EOF
716 },
717 {
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",
721 rules => <<EOF
722 KERNEL=="ttyACM[0-9]*", SYMLINK="symlink1-%n symlink2-%k symlink3-%b"
723 EOF
724 },
725 {
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",
728 exp_name => "one",
729 not_exp_name => " ",
730 rules => <<EOF
731 KERNEL=="ttyACM[0-9]*", SYMLINK=" one two "
732 EOF
733 },
734 {
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",
738 rules => <<EOF
739 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK="modem%n"
740 EOF
741 },
742 {
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" ,
746 rules => <<EOF
747 KERNEL=="ttyACM0", SYMLINK="first-%n second-%n third-%n"
748 EOF
749 },
750 {
751 desc => "symlink name '.'",
752 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
753 exp_name => ".",
754 exp_add_error => "yes",
755 exp_rem_error => "yes",
756 rules => <<EOF
757 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="."
758 EOF
759 },
760 {
761 desc => "symlink node to itself",
762 devpath => "/devices/virtual/tty/tty0",
763 exp_name => "link",
764 exp_add_error => "yes",
765 exp_rem_error => "yes",
766 option => "clean",
767 rules => <<EOF
768 KERNEL=="tty0", SYMLINK+="tty0"
769 EOF
770 },
771 {
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",
775 rules => <<EOF
776 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="symlink%n"
777 EOF
778 },
779 {
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",
783 rules => <<EOF
784 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="symlink-%k"
785 EOF
786 },
787 {
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",
791 rules => <<EOF
792 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="major-%M:%m"
793 EOF
794 },
795 {
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",
799 rules => <<EOF
800 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="symlink-%b"
801 EOF
802 },
803 {
804 desc => "symlink %c substitution",
805 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
806 exp_name => "test",
807 rules => <<EOF
808 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo test", SYMLINK+="%c"
809 EOF
810 },
811 {
812 desc => "symlink %c{N} substitution",
813 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
814 exp_name => "test",
815 rules => <<EOF
816 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo symlink test this", SYMLINK+="%c{2}"
817 EOF
818 },
819 {
820 desc => "symlink %c{N+} substitution",
821 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
822 exp_name => "this",
823 rules => <<EOF
824 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo symlink test this", SYMLINK+="%c{2+}"
825 EOF
826 },
827 {
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",
830 exp_name => "test",
831 rules => <<EOF
832 SUBSYSTEMS=="scsi", KERNEL=="sda", PROGRAM=="/bin/echo link test this" SYMLINK+="%c{2+}"
833 EOF
834 },
835 {
836 desc => "symlink %s{filename} substitution",
837 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
838 exp_name => "166:0",
839 rules => <<EOF
840 KERNEL=="ttyACM[0-9]*", SYMLINK+="%s{dev}"
841 EOF
842 },
843 {
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",
846 exp_name => "link1",
847 rules => <<EOF
848 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n node link1 link2", RESULT=="node *", SYMLINK+="%c{2} %c{3}"
849 EOF
850 },
851 {
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",
854 exp_name => "link4",
855 rules => <<EOF
856 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n node link1 link2 link3 link4", RESULT=="node *", SYMLINK+="%c{2+}"
857 EOF
858 },
859 {
860 desc => "SUBSYSTEM match test",
861 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
862 exp_name => "node",
863 rules => <<EOF
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"
867 EOF
868 },
869 {
870 desc => "DRIVERS match test",
871 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
872 exp_name => "node",
873 rules => <<EOF
874 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match", DRIVERS=="sd-wrong"
875 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", DRIVERS=="sd"
876 EOF
877 },
878 {
879 desc => "devnode substitution test",
880 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
881 exp_name => "node",
882 rules => <<EOF
883 SUBSYSTEMS=="scsi", KERNEL=="sda", PROGRAM=="/usr/bin/test -b %N" SYMLINK+="node"
884 EOF
885 },
886 {
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",
890 rules => <<EOF
891 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="%P-part-1"
892 EOF
893 },
894 {
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",
898 rules => <<EOF
899 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="start-%r-end"
900 EOF
901 },
902 {
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",
905 exp_name => "last",
906 rules => <<EOF
907 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="last", OPTIONS="last_rule"
908 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="very-last"
909 EOF
910 },
911 {
912 desc => "negation KERNEL!=",
913 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
914 exp_name => "match",
915 rules => <<EOF
916 SUBSYSTEMS=="scsi", KERNEL!="sda1", SYMLINK+="matches-but-is-negated"
917 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
918 SUBSYSTEMS=="scsi", KERNEL!="xsda1", SYMLINK+="match"
919 EOF
920 },
921 {
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",
925 rules => <<EOF
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"
929 EOF
930 },
931 {
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",
935 rules => <<EOF
936 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
937 KERNEL=="sda1", PROGRAM!="/bin/false", SYMLINK+="nonzero-program"
938 EOF
939 },
940 {
941 desc => "ENV{} test",
942 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
943 exp_name => "true",
944 rules => <<EOF
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"
949 EOF
950 },
951 {
952 desc => "ENV{} test",
953 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
954 exp_name => "true",
955 rules => <<EOF
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"
961 EOF
962 },
963 {
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",
966 exp_name => "true",
967 rules => <<EOF
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"
972 EOF
973 },
974 {
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",
977 exp_name => "true",
978 rules => <<EOF
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"
984 EOF
985 },
986 {
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",
989 exp_name => "part",
990 rules => <<EOF
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"
996 EOF
997 },
998 {
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",
1001 exp_name => "sane",
1002 rules => <<EOF
1003 SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e name; (/usr/bin/badprogram)", RESULT=="name_ _/usr/bin/badprogram_", SYMLINK+="sane"
1004 EOF
1005 },
1006 {
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",
1009 exp_name => "uber",
1010 rules => <<EOF
1011 SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e \\xc3\\xbcber" RESULT=="\xc3\xbcber", SYMLINK+="uber"
1012 EOF
1013 },
1014 {
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",
1018 rules => <<EOF
1019 SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e \\xef\\xe8garbage", RESULT=="__garbage", SYMLINK+="replaced"
1020 EOF
1021 },
1022 {
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",
1026 rules => <<EOF
1027 KERNEL=="ttyACM*", ATTRS{serial}=="?*", SYMLINK+="serial-%s{serial}"
1028 EOF
1029 },
1030 {
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",
1033 exp_name => "ok",
1034 rules => <<EOF
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"
1039 EOF
1040 },
1041 {
1042 desc => "check ACTION value",
1043 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1044 exp_name => "ok",
1045 rules => <<EOF
1046 ACTION=="unknown", KERNEL=="sda", SYMLINK+="unknown-not-ok"
1047 ACTION=="add", KERNEL=="sda", SYMLINK+="ok"
1048 EOF
1049 },
1050 {
1051 desc => "final assignment",
1052 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1053 exp_name => "ok",
1054 exp_perms => "root:tty:0640",
1055 rules => <<EOF
1056 KERNEL=="sda", GROUP:="tty"
1057 KERNEL=="sda", GROUP="not-ok", MODE="0640", SYMLINK+="ok"
1058 EOF
1059 },
1060 {
1061 desc => "final assignment 2",
1062 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1063 exp_name => "ok",
1064 exp_perms => "root:tty:0640",
1065 rules => <<EOF
1066 KERNEL=="sda", GROUP:="tty"
1067 SUBSYSTEM=="block", MODE:="640"
1068 KERNEL=="sda", GROUP="not-ok", MODE="0666", SYMLINK+="ok"
1069 EOF
1070 },
1071 {
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",
1075 rules => <<EOF
1076 KERNEL=="sda", MODE="0666", SYMLINK+="node-\$env{ACTION}-me"
1077 EOF
1078 },
1079 {
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",
1084 rules => <<EOF
1085 KERNEL=="ttyACM[0-9]*", SYMLINK+="one"
1086 KERNEL=="ttyACM[0-9]*", SYMLINK+="two"
1087 KERNEL=="ttyACM[0-9]*", SYMLINK="three"
1088 EOF
1089 },
1090 {
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",
1095 rules => <<EOF
1096 KERNEL=="ttyACM[0-9]*", SYMLINK+="wrong"
1097 KERNEL=="ttyACM[0-9]*", SYMLINK=""
1098 KERNEL=="ttyACM[0-9]*", SYMLINK+="right"
1099 EOF
1100 },
1101 {
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",
1105 rules => <<EOF
1106 KERNEL=="ttyACM*", SYMLINK+="before"
1107 KERNEL=="ttyACM*|nothing", SYMLINK+="right"
1108 EOF
1109 },
1110 {
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",
1114 rules => <<EOF
1115 KERNEL=="dontknow*|*nothing", SYMLINK+="nomatch"
1116 KERNEL=="ttyACM*", SYMLINK+="before"
1117 KERNEL=="dontknow*|ttyACM*|nothing*", SYMLINK+="right"
1118 EOF
1119 },
1120 {
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",
1124 rules => <<EOF
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"
1129 EOF
1130 },
1131 {
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",
1135 rules => <<EOF
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"
1141 EOF
1142 },
1143 {
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",
1147 option => "keep",
1148 rules => <<EOF
1149 KERNEL=="sda", IMPORT{program}="/bin/echo -e \'PARENT_KEY=parent_right\\nWRONG_PARENT_KEY=parent_wrong'"
1150 KERNEL=="sda", SYMLINK+="parent"
1151 EOF
1152 },
1153 {
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",
1157 option => "clean",
1158 rules => <<EOF
1159 KERNEL=="sda1", IMPORT{parent}="PARENT*", SYMLINK+="parentenv-\$env{PARENT_KEY}\$env{WRONG_PARENT_KEY}"
1160 EOF
1161 },
1162 {
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",
1166 rules => <<EOF
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"
1173 LABEL="end"
1174 EOF
1175 },
1176 {
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",
1180 rules => <<EOF
1181 KERNEL=="sda1", GOTO="does-not-exist"
1182 KERNEL=="sda1", SYMLINK+="right",
1183 LABEL="exists"
1184 EOF
1185 },
1186 {
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",
1191 rules => <<EOF
1192 KERNEL=="sda1", SYMLINK+="link"
1193 KERNEL=="sda1", SYMLINK=="link*", SYMLINK+="right"
1194 KERNEL=="sda1", SYMLINK=="nolink*", SYMLINK+="wrong"
1195 EOF
1196 },
1197 {
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",
1200 exp_name => "yes",
1201 rules => <<EOF
1202 KERNEL="sda1", SYMLINK+="no"
1203 KERNEL=="sda1", SYMLINK+="yes"
1204 EOF
1205 },
1206 {
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",
1209 exp_name => "yes",
1210 rules => <<EOF
1211 KERNEL=="sda", ATTR{test:colon+plus}=="?*", SYMLINK+="yes"
1212 EOF
1213 },
1214 {
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",
1217 exp_name => "yes",
1218 rules => <<EOF
1219 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
1220 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
1221 KERNEL=="sda1", SYMLINK+=="no"
1222 KERNEL=="sda1", SYMLINK+="yes"
1223 EOF
1224 },
1225 {
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",
1229 rules => <<EOF
1230 KERNEL=="sda", SYMLINK+="\$attr{[net/eth0]address}"
1231 EOF
1232 },
1233 {
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",
1237 rules => <<EOF
1238 TEST=="/etc/machine-id", SYMLINK+="there"
1239 TEST!="/etc/machine-id", SYMLINK+="notthere"
1240 EOF
1241 },
1242 {
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",
1245 exp_name => "yes",
1246 rules => <<EOF
1247 KERNEL=="sda", TEST=="[net/eth0]", SYMLINK+="yes"
1248 EOF
1249 },
1250 {
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",
1254 rules => <<EOF
1255 KERNEL=="sda", TEST=="size", SYMLINK+="relative"
1256 EOF
1257 },
1258 {
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",
1262 rules => <<EOF
1263 KERNEL=="sda", TEST=="*/nr_requests", SYMLINK+="found-subdir"
1264 EOF
1265 },
1266 {
1267 desc => "TEST MODE=0000",
1268 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1269 exp_name => "sda",
1270 exp_perms => "0:0:0000",
1271 exp_rem_error => "yes",
1272 rules => <<EOF
1273 KERNEL=="sda", MODE="0000"
1274 EOF
1275 },
1276 {
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",
1279 exp_name => "sda",
1280 exp_perms => "1:1:0400",
1281 exp_rem_error => "yes",
1282 rules => <<EOF
1283 KERNEL=="sda", MODE="666"
1284 KERNEL=="sda", PROGRAM=="/bin/echo 1 1 0400", OWNER="%c{1}", GROUP="%c{2}", MODE="%c{3}"
1285 EOF
1286 },
1287 {
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",
1290 exp_name => "sda",
1291 exp_perms => "0:0:0440",
1292 exp_rem_error => "yes",
1293 rules => <<EOF
1294 KERNEL=="sda", MODE="440"
1295 KERNEL=="sda", PROGRAM=="/bin/echo 0 0 0400letsdoabuffferoverflow0123456789012345789012345678901234567890", OWNER="%c{1}", GROUP="%c{2}", MODE="%c{3}"
1296 EOF
1297 },
1298 {
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",
1303 rules => <<EOF
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"
1307 EOF
1308 },
1309 {
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",
1313 rules => <<EOF
1314 KERNEL=="sda", IMPORT{builtin}="path_id"
1315 KERNEL=="sda", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/\$env{ID_PATH}"
1316 EOF
1317 },
1318 );
1319
1320 sub udev {
1321 my ($action, $devpath, $rules) = @_;
1322
1323 # create temporary rules
1324 system("mkdir", "-p", "$udev_rules_dir");
1325 open CONF, ">$udev_rules" || die "unable to create rules file: $udev_rules";
1326 print CONF $$rules;
1327 close CONF;
1328
1329 if ($valgrind > 0) {
1330 system("$udev_bin_valgrind $action $devpath");
1331 } elsif ($gdb > 0) {
1332 system("$udev_bin_gdb $action $devpath");
1333 } else {
1334 system("$udev_bin", "$action", "$devpath");
1335 }
1336 }
1337
1338 my $error = 0;
1339
1340 sub permissions_test {
1341 my($rules, $uid, $gid, $mode) = @_;
1342
1343 my $wrong = 0;
1344 my $userid;
1345 my $groupid;
1346
1347 $rules->{exp_perms} =~ m/^(.*):(.*):(.*)$/;
1348 if ($1 ne "") {
1349 if (defined(getpwnam($1))) {
1350 $userid = int(getpwnam($1));
1351 } else {
1352 $userid = $1;
1353 }
1354 if ($uid != $userid) { $wrong = 1; }
1355 }
1356 if ($2 ne "") {
1357 if (defined(getgrnam($2))) {
1358 $groupid = int(getgrnam($2));
1359 } else {
1360 $groupid = $2;
1361 }
1362 if ($gid != $groupid) { $wrong = 1; }
1363 }
1364 if ($3 ne "") {
1365 if (($mode & 07777) != oct($3)) { $wrong = 1; };
1366 }
1367 if ($wrong == 0) {
1368 print "permissions: ok\n";
1369 } else {
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";
1373 $error++;
1374 sleep(1);
1375 }
1376 }
1377
1378 sub major_minor_test {
1379 my($rules, $rdev) = @_;
1380
1381 my $major = ($rdev >> 8) & 0xfff;
1382 my $minor = ($rdev & 0xff) | (($rdev >> 12) & 0xfff00);
1383 my $wrong = 0;
1384
1385 $rules->{exp_majorminor} =~ m/^(.*):(.*)$/;
1386 if ($1 ne "") {
1387 if ($major != $1) { $wrong = 1; };
1388 }
1389 if ($2 ne "") {
1390 if ($minor != $2) { $wrong = 1; };
1391 }
1392 if ($wrong == 0) {
1393 print "major:minor: ok\n";
1394 } else {
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";
1398 $error++;
1399 sleep(1);
1400 }
1401 }
1402
1403 sub udev_setup {
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";
1410
1411 system("rm", "-rf", "$udev_run");
1412 }
1413
1414 sub run_test {
1415 my ($rules, $number) = @_;
1416
1417 print "TEST $number: $rules->{desc}\n";
1418 print "device \'$rules->{devpath}\' expecting node/link \'$rules->{exp_name}\'\n";
1419
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";
1425 $error++;
1426 sleep(1);
1427 }
1428 }
1429
1430 if ((-e "$udev_dev/$rules->{exp_name}") ||
1431 (-l "$udev_dev/$rules->{exp_name}")) {
1432
1433 my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
1434 $atime, $mtime, $ctime, $blksize, $blocks) = stat("$udev_dev/$rules->{exp_name}");
1435
1436 if (defined($rules->{exp_perms})) {
1437 permissions_test($rules, $uid, $gid, $mode);
1438 }
1439 if (defined($rules->{exp_majorminor})) {
1440 major_minor_test($rules, $rdev);
1441 }
1442 print "add: ok\n";
1443 } else {
1444 print "add: error";
1445 if ($rules->{exp_add_error}) {
1446 print " as expected\n";
1447 } else {
1448 print "\n";
1449 system("tree", "$udev_dev");
1450 print "\n";
1451 $error++;
1452 sleep(1);
1453 }
1454 }
1455
1456 if (defined($rules->{option}) && $rules->{option} eq "keep") {
1457 print "\n\n";
1458 return;
1459 }
1460
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";
1467 } else {
1468 print "\n";
1469 system("tree", "$udev_dev");
1470 print "\n";
1471 $error++;
1472 sleep(1);
1473 }
1474 } else {
1475 print "remove: ok\n";
1476 }
1477
1478 print "\n";
1479
1480 if (defined($rules->{option}) && $rules->{option} eq "clean") {
1481 udev_setup();
1482 }
1483
1484 }
1485
1486 # only run if we have root permissions
1487 # due to mknod restrictions
1488 if (!($<==0)) {
1489 print "Must have root permissions to run properly.\n";
1490 exit($EXIT_TEST_SKIP);
1491 }
1492
1493 # skip the test when running in a container
1494 system("systemd-detect-virt", "-c", "-q");
1495 if ($? >> 8 == 0) {
1496 print "Running in a container, skipping the test.\n";
1497 exit($EXIT_TEST_SKIP);
1498 }
1499
1500 udev_setup();
1501
1502 my $test_num = 1;
1503 my @list;
1504
1505 foreach my $arg (@ARGV) {
1506 if ($arg =~ m/--valgrind/) {
1507 $valgrind = 1;
1508 printf("using valgrind\n");
1509 } elsif ($arg =~ m/--gdb/) {
1510 $gdb = 1;
1511 printf("using gdb\n");
1512 } else {
1513 push(@list, $arg);
1514 }
1515 }
1516
1517 if ($list[0]) {
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);
1522 } else {
1523 print "test does not exist.\n";
1524 }
1525 }
1526 } else {
1527 # test all
1528 print "\nudev-test will run ".($#tests + 1)." tests:\n\n";
1529
1530 foreach my $rules (@tests) {
1531 run_test($rules, $test_num);
1532 $test_num++;
1533 }
1534 }
1535
1536 print "$error errors occurred\n\n";
1537
1538 # cleanup
1539 system("rm", "-rf", "$udev_dev");
1540 system("rm", "-rf", "$udev_run");
1541
1542 if ($error > 0) {
1543 exit(1);
1544 }
1545 exit(0);