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