]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/udev-test.pl
test-execute: Add tests for new PassEnvironment= directive
[thirdparty/systemd.git] / test / udev-test.pl
CommitLineData
a367f04e
GKH
1#!/usr/bin/perl
2
438d4c3c 3# udev test
a367f04e
GKH
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#
65005a7f 12# udev parses the rules, looks at the provided sysfs and
a367f04e
GKH
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#
1298001e 17# Copyright (C) 2004-2012 Kay Sievers <kay@vrfy.org>
c4edd0ad 18# Copyright (C) 2004 Leann Ogasawara <ogasawara@osdl.org>
a367f04e
GKH
19
20use warnings;
21use strict;
22
9b80f05f 23my $udev_bin = "./test-udev";
912541b0 24my $valgrind = 0;
333e07b7 25my $gdb = 0;
b3f24900 26my $udev_bin_valgrind = "valgrind --tool=memcheck --leak-check=yes --track-origins=yes --quiet $udev_bin";
333e07b7 27my $udev_bin_gdb = "gdb --args $udev_bin";
6ada823a
KS
28my $udev_dev = "test/dev";
29my $udev_run = "test/run";
30my $udev_rules_dir = "$udev_run/udev/rules.d";
31my $udev_rules = "$udev_rules_dir/udev-test.rules";
0eb3cc88 32my $EXIT_TEST_SKIP = 77;
a367f04e 33
a367f04e 34my @tests = (
912541b0
KS
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
5754e74c 41#
bcf44d55 42EOF
912541b0
KS
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
0f52fdee 49SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
5754e74c 50KERNEL=="ttyACM0", SYMLINK+="modem"
c4edd0ad 51EOF
912541b0
KS
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
5754e74c
KS
58SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
59KERNEL=="ttyACM0", SYMLINK+="modem"
c4edd0ad 60EOF
912541b0
KS
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
5754e74c
KS
67SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
68KERNEL=="ttyACM0", SYMLINK+="modem"
a367f04e 69EOF
912541b0
KS
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
5754e74c 76SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
83be97ba 77EOF
912541b0
KS
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
5754e74c
KS
84SUBSYSTEMS=="scsi", ATTRS{vendor}=="?ATA", SYMLINK+="boot_disk%n-1"
85SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA?", SYMLINK+="boot_disk%n-2"
86SUBSYSTEMS=="scsi", ATTRS{vendor}=="A??", SYMLINK+="boot_disk%n"
87SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATAS", SYMLINK+="boot_disk%n-3"
358c8c20 88EOF
912541b0
KS
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
5754e74c
KS
95SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS X ", SYMLINK+="boot_diskX%n"
96SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="boot_disk%n"
358c8c20 97EOF
912541b0
KS
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
5754e74c
KS
104SUBSYSTEMS=="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"
105SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", SYMLINK+="boot_disk%n"
0db6d4cc 106EOF
912541b0
KS
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
5754e74c 113KERNEL=="ttyACM*", SYMLINK+="modem/%n"
2e317184 114EOF
912541b0
KS
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
5754e74c
KS
121KERNEL=="*ACM1", SYMLINK+="bad"
122KERNEL=="*ACM0", SYMLINK+="modem/%n"
9f1da361 123EOF
912541b0
KS
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
5754e74c
KS
130KERNEL=="ttyACM??*", SYMLINK+="modem/%n-1"
131KERNEL=="ttyACM??", SYMLINK+="modem/%n-2"
132KERNEL=="ttyACM?", SYMLINK+="modem/%n"
9f1da361 133EOF
912541b0
KS
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
5754e74c
KS
140KERNEL=="ttyACM[A-Z]*", SYMLINK+="modem/%n-1"
141KERNEL=="ttyACM?[0-9]", SYMLINK+="modem/%n-2"
142KERNEL=="ttyACM[0-9]*", SYMLINK+="modem/%n"
a367f04e 143EOF
912541b0
KS
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
5754e74c 150KERNEL=="ttyACM0", SYMLINK+="modem"
281ff00a 151EOF
912541b0
KS
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
281ff00a 158# this is a comment
5754e74c 159KERNEL=="ttyACM0", SYMLINK+="modem"
281ff00a
GKH
160
161EOF
912541b0
KS
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
d914e445 168 # this is a comment with whitespace before the comment
5754e74c 169KERNEL=="ttyACM0", SYMLINK+="modem"
281ff00a 170
3db7fa27 171EOF
912541b0
KS
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
3db7fa27 178
3db7fa27 179
d914e445
KS
180
181 # this is a comment with whitespace before the comment
5754e74c 182KERNEL=="ttyACM0", SYMLINK+="whitespace"
3db7fa27 183
d914e445 184
3db7fa27 185
281ff00a 186EOF
912541b0
KS
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
281ff00a 193
5754e74c 194KERNEL=="ttyACM0", SYMLINK+="modem"
281ff00a 195
9f8dfa19 196EOF
912541b0
KS
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
c7fcba1b 203KERNEL=="ttyACM0", \\
5754e74c 204SYMLINK+="modem"
9f8dfa19 205
77313cd0 206EOF
912541b0
KS
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
d914e445 213KERNEL=="ttyACM0", PROGRAM=="/bin/echo -e \\101", RESULT=="A", SYMLINK+="aaa"
9f8dfa19 214EOF
912541b0
KS
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
9f8dfa19
KS
221
222#
223\\
224
d960ad15 225\\
9f8dfa19
KS
226
227#\\
228
c7fcba1b 229KERNEL=="ttyACM0", \\
912541b0 230 SYMLINK+="modem"
9f8dfa19 231
5499d319 232EOF
912541b0
KS
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
5754e74c 239KERNEL=="ttyACM0", SYMLINK+="sub/direct/ory/modem"
a367f04e 240EOF
912541b0
KS
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
5754e74c 247SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="first_disk%n"
c4edd0ad 248EOF
912541b0
KS
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
5754e74c 255SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:%M:minor:%m:kernelnumber:%n:id:%b"
319c6700 256EOF
912541b0
KS
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
d914e445 263SUBSYSTEMS=="scsi", IMPORT{program}="/bin/echo -e \' TEST_KEY=12345678\\n TEST_key2=98765\'", SYMLINK+="node\$env{TEST_KEY}"
5754e74c 264KERNEL=="ttyACM0", SYMLINK+="modem"
a27cd06c 265EOF
912541b0
KS
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
5754e74c
KS
272SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="disk-%s{vendor}-%k"
273KERNEL=="ttyACM0", SYMLINK+="modem"
a367f04e 274EOF
912541b0
KS
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
d914e445
KS
282SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n special-device", RESULT=="-special-*", SYMLINK+="not"
283SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n special-device", RESULT=="special-*", SYMLINK+="%c-%n"
bbbe503e 284EOF
912541b0
KS
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
d914e445 291SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo test", RESULT=="test", SYMLINK+="newline_removed"
f3b04a2e 292EOF
912541b0
KS
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
d914e445 299SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n test-%b", RESULT=="test-0:0*", SYMLINK+="%c"
dde05ccb 300EOF
912541b0
KS
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
d914e445 307SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="%c{7}"
35b38379 308EOF
912541b0
KS
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
d914e445 315SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'echo foo3 foo4 foo5 foo6 foo7 foo8 foo9 | sed s/foo9/bar9/'", KERNEL=="sda5", SYMLINK+="%c{7}"
35b38379 316EOF
912541b0
KS
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
d914e445 323SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n 'foo3 foo4' 'foo5 foo6 foo7 foo8'", KERNEL=="sda5", SYMLINK+="%c{5}"
56c963dc 324EOF
912541b0
KS
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
d914e445 331SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{7}"
56c963dc 332EOF
912541b0
KS
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
d914e445 339SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{6}"
bf5d2964 340EOF
912541b0
KS
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
5754e74c 347SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:\$major-minor:\$minor-kernelnumber:\$number-id:\$id"
bf5d2964 348EOF
912541b0
KS
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
5754e74c 355SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="Major:\$major-minor:%m-kernelnumber:\$number-id:\$id"
bf5d2964 356EOF
912541b0
KS
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
5754e74c 363SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="%M%m%b%n"
bf5d2964 364EOF
912541b0
KS
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
5754e74c 371SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="\$major\$minor\$number"
bf5d2964 372EOF
912541b0
KS
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
5754e74c 379SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="\$major%m%n\$id"
8ff8bbba 380EOF
912541b0
KS
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
d914e445 387SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo", RESULT=="foo", SYMLINK+="foo"
5754e74c 388KERNEL=="console", SYMLINK+="TTY"
1d936fbc 389EOF
912541b0
KS
390 },
391 {
392 desc => "non matching SUBSYSTEMS",
393 devpath => "/devices/virtual/tty/console",
394 exp_name => "TTY" ,
395 rules => <<EOF
5754e74c
KS
396SUBSYSTEMS=="foo", ATTRS{dev}=="5:1", SYMLINK+="foo"
397KERNEL=="console", SYMLINK+="TTY"
64682333 398EOF
912541b0
KS
399 },
400 {
401 desc => "ATTRS match",
402 devpath => "/devices/virtual/tty/console",
403 exp_name => "foo" ,
404 rules => <<EOF
5754e74c
KS
405KERNEL=="console", SYMLINK+="TTY"
406ATTRS{dev}=="5:1", SYMLINK+="foo"
a402404f 407EOF
912541b0
KS
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
5754e74c
KS
414KERNEL=="sda", ATTR{test_empty_file}=="?*", SYMLINK+="something"
415KERNEL=="sda", ATTR{test_empty_file}!="", SYMLINK+="not-empty"
416KERNEL=="sda", ATTR{test_empty_file}=="", SYMLINK+="empty"
417KERNEL=="sda", ATTR{test_empty_file}!="?*", SYMLINK+="not-something"
a402404f 418EOF
912541b0
KS
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
5754e74c
KS
425KERNEL=="sda", ATTR{nofile}=="?*", SYMLINK+="something"
426KERNEL=="sda", ATTR{nofile}!="", SYMLINK+="not-empty"
427KERNEL=="sda", ATTR{nofile}=="", SYMLINK+="empty"
428KERNEL=="sda", ATTR{nofile}!="?*", SYMLINK+="not-something"
429KERNEL=="sda", TEST!="nofile", SYMLINK+="non-existent"
430KERNEL=="sda", SYMLINK+="wrong"
772558f4 431EOF
912541b0
KS
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
d914e445
KS
438SUBSYSTEMS=="usb", PROGRAM=="/bin/echo -n usb-%b", SYMLINK+="%c"
439SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n scsi-%b", SYMLINK+="%c"
440SUBSYSTEMS=="foo", PROGRAM=="/bin/echo -n foo-%b", SYMLINK+="%c"
50e5de03 441EOF
912541b0
KS
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
5754e74c 448ATTRS{idProduct}=="007b", SYMLINK+="modem"
f0142622 449EOF
912541b0
KS
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
5754e74c
KS
456SUBSYSTEMS=="scsi", SYMLINK+="is/not/a/%k"
457SUBSYSTEM=="block", SYMLINK+="is/a/%k"
458KERNEL=="ttyACM0", SYMLINK+="modem"
b9fc973b 459EOF
912541b0
KS
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
5754e74c 467KERNEL=="ttyACM0", SYMLINK+="modem"
93656247 468EOF
912541b0
KS
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
5754e74c
KS
475SUBSYSTEMS=="usb", KERNELS=="0:0:0:0", SYMLINK+="not-scsi"
476SUBSYSTEMS=="scsi", KERNELS=="0:0:0:1", SYMLINK+="no-match"
477SUBSYSTEMS=="scsi", KERNELS==":0", SYMLINK+="short-id"
478SUBSYSTEMS=="scsi", KERNELS=="/0:0:0:0", SYMLINK+="no-match"
479SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="scsi-0:0:0:0"
93656247 480EOF
912541b0
KS
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
5754e74c
KS
487SUBSYSTEMS=="scsi", KERNELS=="*:1", SYMLINK+="no-match"
488SUBSYSTEMS=="scsi", KERNELS=="*:0:1", SYMLINK+="no-match"
489SUBSYSTEMS=="scsi", KERNELS=="*:0:0:1", SYMLINK+="no-match"
490SUBSYSTEMS=="scsi", KERNEL=="0:0:0:0", SYMLINK+="before"
491SUBSYSTEMS=="scsi", KERNELS=="*", SYMLINK+="scsi-0:0:0:0"
93656247 492EOF
912541b0
KS
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
5754e74c
KS
499SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
500SUBSYSTEMS=="scsi", KERNELS=="*:0", SYMLINK+="scsi-0:0:0:0"
93656247 501EOF
912541b0
KS
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
5754e74c
KS
508SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
509SUBSYSTEMS=="scsi", KERNELS=="*:0:0:0", SYMLINK+="scsi-0:0:0:0"
eef54479 510EOF
912541b0
KS
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
5754e74c 517SUBSYSTEMS=="scsi", SYMLINK+="driver-is-\$attr{driver}"
eef54479 518EOF
912541b0
KS
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
5754e74c 525SUBSYSTEMS=="pci", SYMLINK+="driver-is-\$attr{driver}"
d5f91372 526EOF
912541b0
KS
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
5754e74c 533SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE", SYMLINK+="ignored"
d5f91372 534EOF
912541b0
KS
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
5754e74c
KS
541SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE ", SYMLINK+="wrong-to-ignore"
542SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE ", SYMLINK+="matched-with-space"
0a5417a0 543EOF
912541b0
KS
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
6ada823a 551KERNEL=="tty33", OWNER="bad", GROUP="name"
b8669191 552EOF
912541b0
KS
553 },
554 {
9158d03e 555 desc => "permissions OWNER=1",
912541b0
KS
556 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
557 exp_name => "node",
9158d03e 558 exp_perms => "1::0600",
912541b0 559 rules => <<EOF
9158d03e 560SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="1"
b8669191 561EOF
912541b0
KS
562 },
563 {
9158d03e 564 desc => "permissions GROUP=1",
912541b0
KS
565 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
566 exp_name => "node",
9158d03e 567 exp_perms => ":1:0660",
912541b0 568 rules => <<EOF
9158d03e 569SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", GROUP="1"
9b434de1 570EOF
912541b0
KS
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
5754e74c 578SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="nobody"
9b434de1 579EOF
912541b0
KS
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
5754e74c 587SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", GROUP="daemon"
c8278763 588EOF
912541b0
KS
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
5754e74c 596SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="root", GROUP="mail"
b8669191 597EOF
912541b0
KS
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
5754e74c 605SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", MODE="0777"
b8669191 606EOF
912541b0
KS
607 },
608 {
9158d03e 609 desc => "permissions OWNER=1 GROUP=1 MODE=0777",
912541b0
KS
610 devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
611 exp_name => "node",
9158d03e 612 exp_perms => "1:1:0777",
912541b0 613 rules => <<EOF
9158d03e 614SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="1", GROUP="1", MODE="0777"
b8669191 615EOF
912541b0
KS
616 },
617 {
9158d03e 618 desc => "permissions OWNER to 1",
912541b0
KS
619 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
620 exp_name => "ttyACM0",
9158d03e 621 exp_perms => "1::",
912541b0 622 rules => <<EOF
9158d03e 623KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", OWNER="1"
b8669191 624EOF
912541b0
KS
625 },
626 {
9158d03e 627 desc => "permissions GROUP to 1",
912541b0
KS
628 devpath => "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
629 exp_name => "ttyACM0",
9158d03e 630 exp_perms => ":1:0660",
912541b0 631 rules => <<EOF
9158d03e 632KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", GROUP="1"
b8669191 633EOF
912541b0
KS
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
5754e74c 641KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", MODE="0060"
b8669191 642EOF
912541b0
KS
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",
9158d03e 648 exp_perms => "1:1:0777",
912541b0 649 rules => <<EOF
9158d03e 650KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", OWNER="1", GROUP="1", MODE="0777"
e9390146 651EOF
912541b0
KS
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",
9158d03e 657 exp_perms => "1:1:0777",
912541b0 658 rules => <<EOF
9158d03e
TG
659KERNEL=="ttyACM[0-9]*", OWNER="1", GROUP="1", MODE="0777"
660KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
5754e74c 661KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n"
eb870090 662EOF
912541b0
KS
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",
9158d03e 668 exp_perms => "1:1:0777",
912541b0 669 rules => <<EOF
9158d03e
TG
670SUBSYSTEM=="tty", OWNER="1"
671SUBSYSTEM=="tty", GROUP="1"
28ce66de 672SUBSYSTEM=="tty", MODE="0777"
9158d03e 673KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
5754e74c 674KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n"
eb870090 675EOF
912541b0
KS
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",
9158d03e 681 exp_perms => "1:2:0777",
912541b0 682 rules => <<EOF
9158d03e
TG
683SUBSYSTEM=="tty", OWNER="1"
684SUBSYSTEM=="tty", GROUP="1"
28ce66de 685SUBSYSTEM=="tty", MODE="0777"
9158d03e
TG
686KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
687KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", GROUP="2"
fa19f181 688EOF
912541b0
KS
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
5754e74c 696SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node"
7d12d4e1 697EOF
912541b0
KS
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
5754e74c 705KERNEL=="misc-fake1", SYMLINK+="node"
7d12d4e1 706EOF
912541b0
KS
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
5754e74c 714KERNEL=="misc-fake89999", SYMLINK+="node"
2b0f835c 715EOF
912541b0
KS
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
5754e74c 722KERNEL=="ttyACM[0-9]*", SYMLINK="symlink1-%n symlink2-%k symlink3-%b"
7b2bdb4b 723EOF
912541b0
KS
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
5754e74c 731KERNEL=="ttyACM[0-9]*", SYMLINK=" one two "
b8669191 732EOF
912541b0
KS
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
5754e74c 739KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK="modem%n"
b8669191 740EOF
912541b0
KS
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
5754e74c 747KERNEL=="ttyACM0", SYMLINK="first-%n second-%n third-%n"
b8669191 748EOF
912541b0
KS
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
5754e74c 757SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="."
b8669191 758EOF
912541b0
KS
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
5754e74c 768KERNEL=="tty0", SYMLINK+="tty0"
b8669191 769EOF
912541b0
KS
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
5754e74c 776KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="symlink%n"
b8669191 777EOF
912541b0
KS
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
5754e74c 784KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="symlink-%k"
b8669191 785EOF
912541b0
KS
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
5754e74c 792KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="major-%M:%m"
b8669191 793EOF
912541b0
KS
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
220893b3 800SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="symlink-%b"
b8669191 801EOF
912541b0
KS
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
d914e445 808KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo test", SYMLINK+="%c"
b8669191 809EOF
912541b0
KS
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
d914e445 816KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo symlink test this", SYMLINK+="%c{2}"
b8669191 817EOF
912541b0
KS
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
d914e445 824KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo symlink test this", SYMLINK+="%c{2+}"
b8669191 825EOF
912541b0
KS
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
d914e445 832SUBSYSTEMS=="scsi", KERNEL=="sda", PROGRAM=="/bin/echo link test this" SYMLINK+="%c{2+}"
b8669191 833EOF
912541b0
KS
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
5754e74c 840KERNEL=="ttyACM[0-9]*", SYMLINK+="%s{dev}"
b8669191 841EOF
912541b0
KS
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
d914e445 848SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n node link1 link2", RESULT=="node *", SYMLINK+="%c{2} %c{3}"
b8669191 849EOF
912541b0
KS
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
d914e445 856SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n node link1 link2 link3 link4", RESULT=="node *", SYMLINK+="%c{2+}"
7efa217d 857EOF
912541b0
KS
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
5754e74c
KS
864SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match", SUBSYSTEM=="vc"
865SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", SUBSYSTEM=="block"
866SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match2", SUBSYSTEM=="vc"
2092fbcd 867EOF
912541b0
KS
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
5754e74c
KS
874SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match", DRIVERS=="sd-wrong"
875SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", DRIVERS=="sd"
c1ab0461 876EOF
912541b0
KS
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
220893b3 883SUBSYSTEMS=="scsi", KERNEL=="sda", PROGRAM=="/usr/bin/test -b %N" SYMLINK+="node"
69aa6dfb 884EOF
912541b0
KS
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
5754e74c 891SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="%P-part-1"
69aa6dfb 892EOF
912541b0
KS
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",
4cb72937 897 exp_name => "start-/dev-end",
912541b0 898 rules => <<EOF
5754e74c 899SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="start-%r-end"
3b6ed8bb 900EOF
912541b0
KS
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
c4edd0ad 907SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="last", OPTIONS="last_rule"
5754e74c 908SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="very-last"
28ce66de 909EOF
912541b0
KS
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
5754e74c
KS
916SUBSYSTEMS=="scsi", KERNEL!="sda1", SYMLINK+="matches-but-is-negated"
917SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
918SUBSYSTEMS=="scsi", KERNEL!="xsda1", SYMLINK+="match"
28ce66de 919EOF
912541b0
KS
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
5754e74c
KS
926SUBSYSTEMS=="scsi", SUBSYSTEM=="block", KERNEL!="sda1", SYMLINK+="matches-but-is-negated"
927SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
928SUBSYSTEMS=="scsi", SUBSYSTEM!="anything", SYMLINK+="not-anything"
28ce66de 929EOF
912541b0
KS
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
5754e74c 936SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
d914e445 937KERNEL=="sda1", PROGRAM!="/bin/false", SYMLINK+="nonzero-program"
3e5958de 938EOF
912541b0
KS
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
a1af6b04 945ENV{ENV_KEY_TEST}="test"
5754e74c
KS
946SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="go", SYMLINK+="wrong"
947SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="test", SYMLINK+="true"
948SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="bad", SYMLINK+="bad"
3e5958de 949EOF
912541b0
KS
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
a1af6b04 956ENV{ENV_KEY_TEST}="test"
5754e74c
KS
957SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="go", SYMLINK+="wrong"
958SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="yes", ENV{ACTION}=="add", ENV{DEVPATH}=="*/block/sda/sdax1", SYMLINK+="no"
959SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="test", ENV{ACTION}=="add", ENV{DEVPATH}=="*/block/sda/sda1", SYMLINK+="true"
960SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="bad", SYMLINK+="bad"
5618b561 961EOF
912541b0
KS
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
c4edd0ad 968SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="true"
5754e74c
KS
969SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="yes", SYMLINK+="no"
970SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
971SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="true", SYMLINK+="true"
ac528431 972EOF
912541b0
KS
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
ac528431
KS
979SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="true"
980SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="absolutely-\$env{ASSIGN}"
5754e74c
KS
981SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
982SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="yes", SYMLINK+="no"
983SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="absolutely-true", SYMLINK+="true"
5618b561 984EOF
912541b0
KS
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
d59c84ef
KS
991SUBSYSTEM=="block", KERNEL=="*[0-9]", ENV{PARTITION}="true", ENV{MAINDEVICE}="false"
992SUBSYSTEM=="block", KERNEL=="*[!0-9]", ENV{PARTITION}="false", ENV{MAINDEVICE}="true"
5754e74c
KS
993ENV{MAINDEVICE}=="true", SYMLINK+="disk"
994SUBSYSTEM=="block", SYMLINK+="before"
995ENV{PARTITION}=="true", SYMLINK+="part"
18614ab2 996EOF
912541b0
KS
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
d914e445 1003SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e name; (/usr/bin/badprogram)", RESULT=="name_ _/usr/bin/badprogram_", SYMLINK+="sane"
764ce7f2 1004EOF
912541b0
KS
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
d914e445 1011SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e \\xc3\\xbcber" RESULT=="\xc3\xbcber", SYMLINK+="uber"
764ce7f2 1012EOF
912541b0
KS
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
d914e445 1019SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e \\xef\\xe8garbage", RESULT=="__garbage", SYMLINK+="replaced"
98bbc835 1020EOF
912541b0
KS
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
5754e74c 1027KERNEL=="ttyACM*", ATTRS{serial}=="?*", SYMLINK+="serial-%s{serial}"
db949b02 1028EOF
912541b0
KS
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
5754e74c
KS
1035KERNEL=="sda", ATTRS{nothing}!="", SYMLINK+="not-1-ok"
1036KERNEL=="sda", ATTRS{nothing}=="", SYMLINK+="not-2-ok"
1037KERNEL=="sda", ATTRS{vendor}!="", SYMLINK+="ok"
1038KERNEL=="sda", ATTRS{vendor}=="", SYMLINK+="not-3-ok"
821d0ec8 1039EOF
912541b0
KS
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
5754e74c
KS
1046ACTION=="unknown", KERNEL=="sda", SYMLINK+="unknown-not-ok"
1047ACTION=="add", KERNEL=="sda", SYMLINK+="ok"
c974742b 1048EOF
912541b0
KS
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
d960ad15 1056KERNEL=="sda", GROUP:="tty"
5754e74c 1057KERNEL=="sda", GROUP="not-ok", MODE="0640", SYMLINK+="ok"
c974742b 1058EOF
912541b0
KS
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
d960ad15 1066KERNEL=="sda", GROUP:="tty"
c974742b 1067SUBSYSTEM=="block", MODE:="640"
5754e74c 1068KERNEL=="sda", GROUP="not-ok", MODE="0666", SYMLINK+="ok"
bd0ed2ff 1069EOF
912541b0
KS
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
5754e74c 1076KERNEL=="sda", MODE="0666", SYMLINK+="node-\$env{ACTION}-me"
995aec87 1077EOF
912541b0
KS
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
c7fcba1b
KS
1085KERNEL=="ttyACM[0-9]*", SYMLINK+="one"
1086KERNEL=="ttyACM[0-9]*", SYMLINK+="two"
1087KERNEL=="ttyACM[0-9]*", SYMLINK="three"
647f7c49 1088EOF
912541b0
KS
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
5754e74c
KS
1096KERNEL=="ttyACM[0-9]*", SYMLINK+="wrong"
1097KERNEL=="ttyACM[0-9]*", SYMLINK=""
1098KERNEL=="ttyACM[0-9]*", SYMLINK+="right"
0cd4ac47 1099EOF
912541b0
KS
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
5754e74c
KS
1106KERNEL=="ttyACM*", SYMLINK+="before"
1107KERNEL=="ttyACM*|nothing", SYMLINK+="right"
0cd4ac47 1108EOF
912541b0
KS
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
5754e74c
KS
1115KERNEL=="dontknow*|*nothing", SYMLINK+="nomatch"
1116KERNEL=="ttyACM*", SYMLINK+="before"
1117KERNEL=="dontknow*|ttyACM*|nothing*", SYMLINK+="right"
91a75e4a 1118EOF
912541b0
KS
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
5754e74c
KS
1125KERNEL=="dontknow|nothing", SYMLINK+="nomatch"
1126KERNEL=="dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong1"
1127KERNEL=="X|attyACM0|dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong2"
1128KERNEL=="dontknow|ttyACM0|nothing", SYMLINK+="right"
91a75e4a 1129EOF
912541b0
KS
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
5754e74c
KS
1136KERNEL=="dontknow|nothing", SYMLINK+="nomatch"
1137KERNEL=="dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong1"
1138KERNEL=="X|attyACM0|dontknow|ttyACM0a|nothing|attyACM0", SYMLINK+="wrong2"
1139KERNEL=="all|dontknow|ttyACM0", SYMLINK+="right"
1140KERNEL=="ttyACM0a|nothing", SYMLINK+="wrong3"
0bfb84e1 1141EOF
912541b0
KS
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
d914e445 1149KERNEL=="sda", IMPORT{program}="/bin/echo -e \'PARENT_KEY=parent_right\\nWRONG_PARENT_KEY=parent_wrong'"
5754e74c 1150KERNEL=="sda", SYMLINK+="parent"
0bfb84e1 1151EOF
912541b0
KS
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
5754e74c 1159KERNEL=="sda1", IMPORT{parent}="PARENT*", SYMLINK+="parentenv-\$env{PARENT_KEY}\$env{WRONG_PARENT_KEY}"
594dd610 1160EOF
912541b0
KS
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
594dd610 1167KERNEL=="sda1", GOTO="TEST"
5754e74c 1168KERNEL=="sda1", SYMLINK+="wrong"
6880b25d 1169KERNEL=="sda1", GOTO="BAD"
5754e74c
KS
1170KERNEL=="sda1", SYMLINK+="", LABEL="NO"
1171KERNEL=="sda1", SYMLINK+="right", LABEL="TEST", GOTO="end"
1172KERNEL=="sda1", SYMLINK+="wrong2", LABEL="BAD"
9dae0e89 1173LABEL="end"
0c377989 1174EOF
912541b0
KS
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
0c377989 1181KERNEL=="sda1", GOTO="does-not-exist"
5754e74c 1182KERNEL=="sda1", SYMLINK+="right",
0c377989 1183LABEL="exists"
d59c84ef 1184EOF
912541b0
KS
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
5754e74c
KS
1192KERNEL=="sda1", SYMLINK+="link"
1193KERNEL=="sda1", SYMLINK=="link*", SYMLINK+="right"
1194KERNEL=="sda1", SYMLINK=="nolink*", SYMLINK+="wrong"
d59c84ef 1195EOF
912541b0
KS
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
5754e74c
KS
1202KERNEL="sda1", SYMLINK+="no"
1203KERNEL=="sda1", SYMLINK+="yes"
864b9b5e 1204EOF
912541b0
KS
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
5754e74c 1211KERNEL=="sda", ATTR{test:colon+plus}=="?*", SYMLINK+="yes"
d4ae9925 1212EOF
912541b0
KS
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
d4ae9925 1219# 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
d960ad15 1220 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
5754e74c
KS
1221KERNEL=="sda1", SYMLINK+=="no"
1222KERNEL=="sda1", SYMLINK+="yes"
4ad47b2d 1223EOF
912541b0
KS
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
5754e74c 1230KERNEL=="sda", SYMLINK+="\$attr{[net/eth0]address}"
03f65fe6 1231EOF
912541b0
KS
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
02cd084d
TG
1238TEST=="/etc/machine-id", SYMLINK+="there"
1239TEST!="/etc/machine-id", SYMLINK+="notthere"
03f65fe6 1240EOF
912541b0
KS
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
5754e74c 1247KERNEL=="sda", TEST=="[net/eth0]", SYMLINK+="yes"
03f65fe6 1248EOF
912541b0
KS
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
5754e74c 1255KERNEL=="sda", TEST=="size", SYMLINK+="relative"
0ea5e96e 1256EOF
912541b0
KS
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
5754e74c 1263KERNEL=="sda", TEST=="*/nr_requests", SYMLINK+="found-subdir"
cf100ca7 1264EOF
912541b0
KS
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
cf100ca7 1273KERNEL=="sda", MODE="0000"
a367f04e 1274EOF
912541b0
KS
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",
9158d03e 1280 exp_perms => "1:1:0400",
912541b0
KS
1281 exp_rem_error => "yes",
1282 rules => <<EOF
6880b25d 1283KERNEL=="sda", MODE="666"
9158d03e 1284KERNEL=="sda", PROGRAM=="/bin/echo 1 1 0400", OWNER="%c{1}", GROUP="%c{2}", MODE="%c{3}"
ff94cec3 1285EOF
912541b0
KS
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
6880b25d 1294KERNEL=="sda", MODE="440"
d914e445 1295KERNEL=="sda", PROGRAM=="/bin/echo 0 0 0400letsdoabuffferoverflow0123456789012345789012345678901234567890", OWNER="%c{1}", GROUP="%c{2}", MODE="%c{3}"
dc4c7e46 1296EOF
912541b0
KS
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
d914e445 1304KERNEL=="sda", PROGRAM="/bin/true create-envp"
427e20b2 1305KERNEL=="sda", ENV{TESTENV}="change-envp"
0f52fdee 1306KERNEL=="sda", SYMLINK+="%k-%s{[dmi/id]product_name}-end"
d7867b31 1307EOF
912541b0
KS
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
d7867b31
KS
1314KERNEL=="sda", IMPORT{builtin}="path_id"
1315KERNEL=="sda", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/\$env{ID_PATH}"
ff94cec3 1316EOF
912541b0 1317 },
a367f04e
GKH
1318);
1319
a367f04e 1320sub udev {
912541b0 1321 my ($action, $devpath, $rules) = @_;
a367f04e 1322
912541b0 1323 # create temporary rules
6ada823a 1324 system("mkdir", "-p", "$udev_rules_dir");
912541b0
KS
1325 open CONF, ">$udev_rules" || die "unable to create rules file: $udev_rules";
1326 print CONF $$rules;
1327 close CONF;
a367f04e 1328
912541b0
KS
1329 if ($valgrind > 0) {
1330 system("$udev_bin_valgrind $action $devpath");
333e07b7
TG
1331 } elsif ($gdb > 0) {
1332 system("$udev_bin_gdb $action $devpath");
912541b0 1333 } else {
83cd6b75 1334 system("$udev_bin", "$action", "$devpath");
912541b0 1335 }
a367f04e
GKH
1336}
1337
e5fbfe0a 1338my $error = 0;
72ffa78d 1339
b8669191 1340sub permissions_test {
912541b0 1341 my($rules, $uid, $gid, $mode) = @_;
b8669191 1342
912541b0
KS
1343 my $wrong = 0;
1344 my $userid;
1345 my $groupid;
9b434de1 1346
912541b0
KS
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 }
b8669191
GKH
1376}
1377
1378sub major_minor_test {
912541b0 1379 my($rules, $rdev) = @_;
b8669191 1380
912541b0
KS
1381 my $major = ($rdev >> 8) & 0xfff;
1382 my $minor = ($rdev & 0xff) | (($rdev >> 12) & 0xfff00);
1383 my $wrong = 0;
b8669191 1384
912541b0
KS
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 }
b8669191
GKH
1401}
1402
6ada823a
KS
1403sub 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
912541b0 1407 # even if the parent directory has setgid bit enabled.
6ada823a
KS
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");
ff94cec3
EK
1412}
1413
2e317184 1414sub run_test {
912541b0 1415 my ($rules, $number) = @_;
fa19f181 1416
912541b0
KS
1417 print "TEST $number: $rules->{desc}\n";
1418 print "device \'$rules->{devpath}\' expecting node/link \'$rules->{exp_name}\'\n";
b8669191 1419
912541b0
KS
1420 udev("add", $rules->{devpath}, \$rules->{rules});
1421 if (defined($rules->{not_exp_name})) {
6ada823a
KS
1422 if ((-e "$udev_dev/$rules->{not_exp_name}") ||
1423 (-l "$udev_dev/$rules->{not_exp_name}")) {
912541b0
KS
1424 print "nonexistent: error \'$rules->{not_exp_name}\' not expected to be there\n";
1425 $error++;
1426 sleep(1);
1427 }
1428 }
647f7c49 1429
6ada823a
KS
1430 if ((-e "$udev_dev/$rules->{exp_name}") ||
1431 (-l "$udev_dev/$rules->{exp_name}")) {
fa19f181 1432
912541b0 1433 my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
6ada823a 1434 $atime, $mtime, $ctime, $blksize, $blocks) = stat("$udev_dev/$rules->{exp_name}");
fa19f181 1435
912541b0
KS
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";
6ada823a 1449 system("tree", "$udev_dev");
912541b0
KS
1450 print "\n";
1451 $error++;
1452 sleep(1);
1453 }
1454 }
a367f04e 1455
912541b0
KS
1456 if (defined($rules->{option}) && $rules->{option} eq "keep") {
1457 print "\n\n";
1458 return;
1459 }
0345b862 1460
912541b0 1461 udev("remove", $rules->{devpath}, \$rules->{rules});
6ada823a
KS
1462 if ((-e "$udev_dev/$rules->{exp_name}") ||
1463 (-l "$udev_dev/$rules->{exp_name}")) {
912541b0
KS
1464 print "remove: error";
1465 if ($rules->{exp_rem_error}) {
1466 print " as expected\n";
1467 } else {
1468 print "\n";
6ada823a 1469 system("tree", "$udev_dev");
912541b0
KS
1470 print "\n";
1471 $error++;
1472 sleep(1);
1473 }
1474 } else {
1475 print "remove: ok\n";
1476 }
0345b862 1477
912541b0 1478 print "\n";
9b434de1 1479
912541b0 1480 if (defined($rules->{option}) && $rules->{option} eq "clean") {
6ada823a 1481 udev_setup();
912541b0 1482 }
0345b862 1483
a367f04e
GKH
1484}
1485
800ab95b
GKH
1486# only run if we have root permissions
1487# due to mknod restrictions
1488if (!($<==0)) {
912541b0 1489 print "Must have root permissions to run properly.\n";
4d55fc5b 1490 exit($EXIT_TEST_SKIP);
800ab95b
GKH
1491}
1492
0eb3cc88
JS
1493# skip the test when running in a container
1494system("systemd-detect-virt", "-c", "-q");
1495if ($? >> 8 == 0) {
1496 print "Running in a container, skipping the test.\n";
1497 exit($EXIT_TEST_SKIP);
1498}
1499
6ada823a 1500udev_setup();
2e317184
GKH
1501
1502my $test_num = 1;
e08109cb 1503my @list;
2e317184 1504
e08109cb 1505foreach my $arg (@ARGV) {
912541b0
KS
1506 if ($arg =~ m/--valgrind/) {
1507 $valgrind = 1;
1508 printf("using valgrind\n");
333e07b7
TG
1509 } elsif ($arg =~ m/--gdb/) {
1510 $gdb = 1;
1511 printf("using gdb\n");
912541b0
KS
1512 } else {
1513 push(@list, $arg);
1514 }
e08109cb
KS
1515}
1516
1517if ($list[0]) {
912541b0
KS
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 }
2e317184 1526} else {
912541b0
KS
1527 # test all
1528 print "\nudev-test will run ".($#tests + 1)." tests:\n\n";
2e317184 1529
912541b0
KS
1530 foreach my $rules (@tests) {
1531 run_test($rules, $test_num);
1532 $test_num++;
1533 }
2e317184
GKH
1534}
1535
ab06eef8 1536print "$error errors occurred\n\n";
a367f04e
GKH
1537
1538# cleanup
6ada823a
KS
1539system("rm", "-rf", "$udev_dev");
1540system("rm", "-rf", "$udev_run");
a367f04e 1541
034b37c8
AJ
1542if ($error > 0) {
1543 exit(1);
1544}
1545exit(0);