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