2 # SPDX-License-Identifier: LGPL-2.1-or-later
4 # pylint: disable=redefined-outer-name,no-else-return,multiple-imports
5 # pylint: disable=consider-using-with,global-statement
9 # Provides automated testing of the udev binary.
10 # The whole test is self contained in this file, except the matching sysfs tree.
11 # Simply extend RULES to add a new test.
13 # Every test is driven by its own temporary config file.
14 # This program prepares the environment, creates the config and calls udev.
16 # udev parses the rules, looks at the provided sysfs and first creates and then
17 # removes the device node. After creation and removal the result is checked
18 # against the expected value and the result is printed.
29 from pathlib
import Path
30 from typing
import Callable
, Optional
33 import dataclasses
# requires Python >= 3.7
35 except ImportError as e
:
36 print(str(e
), file=sys
.stderr
)
40 SYS_SCRIPT
= Path(__file__
).with_name('sys-script.py')
42 UDEV_BIN
= Path(os
.environ
['UDEV_RULE_RUNNER'])
44 UDEV_BIN
= Path(__file__
).parent
/ 'manual/test-udev-rule-runner'
45 UDEV_BIN
= UDEV_BIN
.absolute()
47 # Those will be set by the udev_setup() fixture
48 UDEV_RUN
= UDEV_RULES
= UDEV_DEV
= UDEV_SYS
= None
50 # Relax sd-device's sysfs verification, since we want to provide a fake sysfs
51 # here that actually is a tmpfs.
52 os
.environ
['SYSTEMD_DEVICE_VERIFY_SYSFS'] = '0'
55 '\n'.join(f
'KERNEL=="sda", TAG+="test{i + 1}"'
56 for i
in range(10_000))
58 rules_10k_tags_continuation
= \
59 ',\\\n'.join(('KERNEL=="sda"',
60 *(f
'TAG+="test{i + 1}"' for i
in range(10_000))))
62 @dataclasses.dataclass
65 devnode
: Optional
[str] = None
66 exp_links
: Optional
[list[str]] = None
67 not_exp_links
: Optional
[list[str]] = None
69 exp_perms
: Optional
[int] = None
70 exp_major_minor
: Optional
[str] = None
72 def check_permissions(self
, st
: os
.stat_result
) -> None:
73 if self
.exp_perms
is None:
76 user
, group
, mode
= self
.exp_perms
.split(':')
80 uid
= pwd
.getpwnam(user
).pw_uid
83 assert uid
== st
.st_uid
87 gid
= grp
.getgrnam(group
).gr_gid
90 assert gid
== st
.st_gid
94 assert stat
.S_IMODE(st
.st_mode
) == mode
96 def check_major_minor(self
, st
: os
.stat_result
) -> None:
97 if not self
.exp_major_minor
:
99 minor
, major
= (int(x
) for x
in self
.exp_major_minor
.split(':'))
100 assert st
.st_rdev
== os
.makedev(minor
, major
)
102 def get_devnode(self
) -> Path
:
103 suffix
= self
.devnode
if self
.devnode
else self
.devpath
.split('/')[-1]
104 return UDEV_DEV
/ suffix
106 def check_link_add(self
, link
: str, devnode
: Path
) -> None:
107 link
= UDEV_DEV
/ link
108 tgt
= link
.parent
/ link
.readlink()
109 assert devnode
.samefile(tgt
)
111 def check_link_nonexistent(self
, link
: str, devnode
: Path
) -> None:
112 link
= UDEV_DEV
/ link
115 tgt
= link
.parent
/ link
.readlink()
116 except FileNotFoundError
:
119 assert not devnode
.samefile(tgt
)
121 def check_add(self
) -> None:
122 print(f
'check_add {self.devpath}')
124 devnode
= self
.get_devnode()
126 assert stat
.S_ISCHR(st
.st_mode
) or stat
.S_ISBLK(st
.st_mode
)
127 self
.check_permissions(st
)
128 self
.check_major_minor(st
)
130 for link
in self
.exp_links
or []:
131 self
.check_link_add(link
, devnode
)
133 for link
in self
.not_exp_links
or []:
134 self
.check_link_nonexistent(link
, devnode
)
136 def check_link_remove(self
, link
: str) -> None:
137 link
= UDEV_DEV
/ link
138 with pytest
.raises(FileNotFoundError
):
141 def check_remove(self
) -> None:
142 devnode
= self
.get_devnode()
143 assert not devnode
.exists()
145 for link
in self
.exp_links
or []:
146 self
.check_link_remove(link
)
150 def wrap(*args
, **kwargs
):
151 return list(f(*args
, **kwargs
))
152 return functools
.update_wrapper(wrap
, f
)
155 def all_block_devs(exp_func
) -> list[Device
]:
156 # Create a device list with all block devices under /sys
157 # (except virtual devices and cd-roms)
158 # the optional argument exp_func returns expected and non-expected
159 # symlinks for the device.
161 for p
in UDEV_SYS
.glob('dev/block/*'):
163 if re
.search('/virtual/ | /sr[0-9]*$', tgt
, re
.VERBOSE
):
166 assert tgt
.startswith('../../')
169 exp
, not_exp
= exp_func(tgt
)
170 yield Device(devpath
=tgt
,
172 not_exp_links
=not_exp
)
175 @dataclasses.dataclass
178 devices
: list[Device
]
180 device_generator
: Callable
= None
182 delay
: Optional
[int] = None
185 def new(cls
, desc
: str, *devices
, rules
=None, device_generator
=None, **kwargs
):
186 assert rules
.startswith('\n')
187 rules
= textwrap
.dedent(rules
[1:]) if rules
else ''
189 assert bool(devices
) ^
bool(device_generator
)
191 return cls(desc
, devices
, rules
, device_generator
=device_generator
, **kwargs
)
193 def generate_devices(self
) -> None:
194 # We can't do this when the class is created, because setup is done later.
195 if self
.device_generator
:
196 self
.devices
= self
.device_generator()
198 def create_rules_file(self
) -> None:
199 # create temporary rules
200 UDEV_RULES
.parent
.mkdir(exist_ok
=True, parents
=True)
201 UDEV_RULES
.write_text(self
.rules
)
207 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
210 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
217 'label test of scsi disc',
219 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
220 exp_links
= ["boot_disk"],
223 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
224 KERNEL=="ttyACM0", SYMLINK+="modem"
228 "label test of scsi disc",
230 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
231 exp_links
= ["boot_disk"],
234 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
235 KERNEL=="ttyACM0", SYMLINK+="modem"
239 "label test of scsi disc",
241 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
242 exp_links
= ["boot_disk"],
245 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
246 KERNEL=="ttyACM0", SYMLINK+="modem"
250 "label test of scsi partition",
252 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
253 exp_links
= ["boot_disk1"],
256 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n"
260 "label test of pattern match",
262 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
263 exp_links
= ["boot_disk1", "boot_disk1-4", "boot_disk1-5"],
264 not_exp_links
= ["boot_disk1-1", "boot_disk1-2", "boot_disk1-3", "boot_disk1-6", "boot_disk1-7"],
268 SUBSYSTEMS=="scsi", ATTRS{vendor}=="?ATA", SYMLINK+="boot_disk%n-1"
269 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA?", SYMLINK+="boot_disk%n-2"
270 SUBSYSTEMS=="scsi", ATTRS{vendor}=="A??", SYMLINK+="boot_disk%n"
271 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATAS", SYMLINK+="boot_disk%n-3"
272 SUBSYSTEMS=="scsi", ATTRS{vendor}=="AT?", SYMLINK+="boot_disk%n-4"
273 SUBSYSTEMS=="scsi", ATTRS{vendor}=="??A", SYMLINK+="boot_disk%n-5"
274 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", GOTO="skip-6"
275 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n-6"
277 SUBSYSTEMS=="scsi", GOTO="skip-7"
278 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="boot_disk%n-7"
283 "label test of multiple sysfs files",
285 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
286 exp_links
= ["boot_disk1"],
287 not_exp_links
= ["boot_diskX1"],
290 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS X ", SYMLINK+="boot_diskX%n"
291 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="boot_disk%n"
295 "label test of max sysfs files (skip invalid rule)",
297 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
298 exp_links
= ["boot_disk1", "boot_diskXY1"],
299 not_exp_links
= ["boot_diskXX1"],
302 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", ATTRS{queue_depth}=="32", SYMLINK+="boot_diskXX%n"
303 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", ATTRS{queue_depth}=="1", SYMLINK+="boot_diskXY%n"
304 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ATTRS{scsi_level}=="6", ATTRS{rev}=="4.06", ATTRS{type}=="0", SYMLINK+="boot_disk%n"
310 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
311 exp_links
= ["link1", "link2/foo", "link3/aaa/bbb",
312 "abs1", "abs2/foo", "abs3/aaa/bbb",
313 "default___replace_test/foo_aaa",
314 "string_escape___replace/foo_bbb",
316 "default/replace/mode_foo__hoge",
317 "replace_env_harder_foo__hoge",
319 not_exp_links
= ["removed1", "removed2", "removed3", "unsafe/../../path", "/nondev/path/will/be/refused"],
322 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="removed1"
323 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK-="removed1"
324 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="/./dev///removed2"
325 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK-="removed2"
326 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="././removed3"
327 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK-="/dev//./removed3/./"
328 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="unsafe/../../path"
329 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="/nondev/path/will/be/refused"
330 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="link1 .///link2/././/foo//./ .///link3/aaa/bbb"
331 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="/dev/abs1 /dev//./abs2///foo/./ ////dev/abs3/aaa/bbb"
332 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK+="default?;;replace%%test/foo'aaa"
333 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", OPTIONS="string_escape=replace", SYMLINK+="string_escape replace/foo%%bbb"
334 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ENV{.HOGE}="env with space", SYMLINK+="%E{.HOGE}"
335 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", ENV{.HOGE}="default/replace/mode?foo;;hoge", SYMLINK+="%E{.HOGE}"
336 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", OPTIONS="string_escape=replace", ENV{.HOGE}="replace/env/harder?foo;;hoge", SYMLINK+="%E{.HOGE}"
337 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK=="link1", SYMLINK+="match"
338 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", ATTRS{model}=="ST910021AS", SYMLINK!="removed1", SYMLINK+="unmatch"
344 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
345 exp_links
= ["modem/0", "catch-all"],
348 KERNEL=="ttyACM*", SYMLINK+="modem/%n"
349 KERNEL=="*", SYMLINK+="catch-all"
353 "catch device by * - take 2",
355 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
356 exp_links
= ["modem/0"],
357 not_exp_links
= ["bad"],
360 KERNEL=="*ACM1", SYMLINK+="bad"
361 KERNEL=="*ACM0", SYMLINK+="modem/%n"
367 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
368 exp_links
= ["modem/0"],
369 not_exp_links
= ["modem/0-1", "modem/0-2"],
372 KERNEL=="ttyACM??*", SYMLINK+="modem/%n-1"
373 KERNEL=="ttyACM??", SYMLINK+="modem/%n-2"
374 KERNEL=="ttyACM?", SYMLINK+="modem/%n"
378 "catch device by character class",
380 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
381 exp_links
= ["modem/0"],
382 not_exp_links
= ["modem/0-1", "modem/0-2"],
385 KERNEL=="ttyACM[A-Z]*", SYMLINK+="modem/%n-1"
386 KERNEL=="ttyACM?[0-9]", SYMLINK+="modem/%n-2"
387 KERNEL=="ttyACM[0-9]*", SYMLINK+="modem/%n"
391 "don't replace kernel name",
393 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
394 exp_links
= ["modem"],
397 KERNEL=="ttyACM0", SYMLINK+="modem"
401 "comment lines in config file (and don't replace kernel name)",
403 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
404 exp_links
= ["modem"],
408 KERNEL=="ttyACM0", SYMLINK+="modem"
413 "comment lines in config file with whitespace (and don't replace kernel name)",
415 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
416 exp_links
= ["modem"],
419 # this is a comment with whitespace before the comment
420 KERNEL=="ttyACM0", SYMLINK+="modem"
425 "whitespace only lines (and don't replace kernel name)",
427 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
428 exp_links
= ["whitespace"],
434 # this is a comment with whitespace before the comment
435 KERNEL=="ttyACM0", SYMLINK+="whitespace"
442 "empty lines in config file (and don't replace kernel name)",
444 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
445 exp_links
= ["modem"],
449 KERNEL=="ttyACM0", SYMLINK+="modem"
454 "backslashed multi lines in config file (and don't replace kernel name)",
456 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
457 exp_links
= ["modem"],
466 "preserve backslashes, if they are not for a newline",
468 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
472 KERNEL=="ttyACM0", PROGRAM=="/bin/echo -e \101", RESULT=="A", SYMLINK+="aaa"
476 "stupid backslashed multi lines in config file (and don't replace kernel name)",
478 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
479 exp_links
= ["modem"],
496 "subdirectory handling",
498 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
499 exp_links
= ["sub/direct/ory/modem"],
502 KERNEL=="ttyACM0", SYMLINK+="sub/direct/ory/modem"
506 "parent device name match of scsi partition",
508 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
509 exp_links
= ["first_disk5"],
512 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="first_disk%n"
516 "test substitution chars",
518 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
519 exp_links
= ["Major:8:minor:5:kernelnumber:5:id:0:0:0:0"],
522 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:%M:minor:%m:kernelnumber:%n:id:%b"
526 "import of shell-value returned from program",
528 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
529 exp_links
= ["node12345678"],
532 SUBSYSTEMS=="scsi", IMPORT{program}="/bin/echo -e ' TEST_KEY=12345678\n TEST_key2=98765'", SYMLINK+="node$env{TEST_KEY}"
533 KERNEL=="ttyACM0", SYMLINK+="modem"
537 "substitution of sysfs value (%s{file})",
539 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
540 exp_links
= ["disk-ATA-sda"],
541 not_exp_links
= ["modem"],
544 SUBSYSTEMS=="scsi", ATTRS{vendor}=="ATA", SYMLINK+="disk-%s{vendor}-%k"
545 KERNEL=="ttyACM0", SYMLINK+="modem"
549 "program result substitution",
551 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
552 exp_links
= ["special-device-5"],
553 not_exp_links
= ["not"],
556 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n special-device", RESULT=="-special-*", SYMLINK+="not"
557 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n special-device", RESULT=="special-*", SYMLINK+="%c-%n"
561 "program result substitution (newline removal)",
563 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
564 exp_links
= ["newline_removed"],
567 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo test", RESULT=="test", SYMLINK+="newline_removed"
571 "program result substitution",
573 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
574 exp_links
= ["test-0:0:0:0"],
577 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n test-%b", RESULT=="test-0:0*", SYMLINK+="%c"
581 "program with lots of arguments",
583 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
584 exp_links
= ["foo9"],
585 not_exp_links
= ["foo3", "foo4", "foo5", "foo6", "foo7", "foo8"],
588 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="%c{7}"
592 "program with subshell",
594 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
595 exp_links
= ["bar9"],
596 not_exp_links
= ["foo3", "foo4", "foo5", "foo6", "foo7", "foo8"],
599 SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'echo foo3 foo4 foo5 foo6 foo7 foo8 foo9 | sed s/foo9/bar9/'", KERNEL=="sda5", SYMLINK+="%c{7}"
603 "program arguments combined with apostrophes",
605 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
606 exp_links
= ["foo7"],
607 not_exp_links
= ["foo3", "foo4", "foo5", "foo6", "foo8"],
610 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n 'foo3 foo4' 'foo5 foo6 foo7 foo8'", KERNEL=="sda5", SYMLINK+="%c{5}"
614 "program arguments combined with escaped double quotes, part 1",
616 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
617 exp_links
= ["foo2"],
618 not_exp_links
= ["foo1"],
621 SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'printf %%s \"foo1 foo2
\" | grep
\"foo1 foo2
\"'", KERNEL=="sda5", SYMLINK+="%c{2}"
625 "program arguments combined with escaped double quotes, part 2",
627 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
628 exp_links = ["foo2"],
629 not_exp_links = ["foo1"],
632 SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c \"printf %%s 'foo1 foo2
' | grep 'foo1 foo2
'\"", KERNEL=="sda5", SYMLINK+="%c{2}"
636 "program arguments combined with escaped double quotes, part 3",
638 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
639 exp_links = ["foo2"],
640 not_exp_links = ["foo1", "foo3"],
643 SUBSYSTEMS=="scsi", PROGRAM=="/bin/sh -c 'printf
\"%%s %%s\" \"foo1 foo2
\" \"foo3
\"| grep
\"foo1 foo2
\"'", KERNEL=="sda5", SYMLINK+="%c{2}"
647 "characters before the %c{N} substitution",
649 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
650 exp_links = ["my-foo9"],
653 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{7}"
657 "substitute the second to last argument",
659 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
660 exp_links = ["my-foo8"],
661 not_exp_links = ["my-foo3", "my-foo4", "my-foo5", "my-foo6", "my-foo7", "my-foo9"],
664 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo3 foo4 foo5 foo6 foo7 foo8 foo9", KERNEL=="sda5", SYMLINK+="my-%c{6}"
668 "test substitution by variable name",
670 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
671 exp_links = ["Major:8-minor:5-kernelnumber:5-id:0:0:0:0"],
674 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="Major:$major-minor:$minor-kernelnumber:$number-id:$id"
678 "test substitution by variable name 2",
680 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
681 exp_links = ["Major:8-minor:5-kernelnumber:5-id:0:0:0:0"],
684 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="Major:$major-minor:%m-kernelnumber:$number-id:$id"
688 "test substitution by variable name 3",
690 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
691 exp_links = ["850:0:0:05"],
694 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="%M%m%b%n"
698 "test substitution by variable name 4",
700 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
704 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="$major$minor$number"
708 "test substitution by variable name 5",
710 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
711 exp_links = ["8550:0:0:0"],
714 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", DEVPATH=="*/sda/*", SYMLINK+="$major%m%n$id"
718 "non matching SUBSYSTEMS for device with no parent",
720 "/devices/virtual/tty/console",
722 not_exp_links = ["foo"],
725 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n foo", RESULT=="foo", SYMLINK+="foo"
726 KERNEL=="console", SYMLINK+="TTY"
730 "non matching SUBSYSTEMS",
732 "/devices/virtual/tty/console",
734 not_exp_links = ["foo"],
737 SUBSYSTEMS=="foo", ATTRS{dev}=="5:1", SYMLINK+="foo"
738 KERNEL=="console", SYMLINK+="TTY"
744 "/devices/virtual/tty/console",
745 exp_links = ["foo", "TTY"],
748 KERNEL=="console", SYMLINK+="TTY"
749 ATTRS{dev}=="5:1", SYMLINK+="foo"
755 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
756 exp_links = ["empty", "not-something"],
757 not_exp_links = ["something", "not-empty"],
760 KERNEL=="sda", ATTR{test_empty_file}=="?*", SYMLINK+="something"
761 KERNEL=="sda", ATTR{test_empty_file}!="", SYMLINK+="not-empty"
762 KERNEL=="sda", ATTR{test_empty_file}=="", SYMLINK+="empty"
763 KERNEL=="sda", ATTR{test_empty_file}!="?*", SYMLINK+="not-something"
767 "ATTR (non-existent file)",
769 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
770 exp_links = ["non-existent", "wrong"],
771 not_exp_links = ["something", "empty", "not-empty",
772 "not-something", "something"],
775 KERNEL=="sda", ATTR{nofile}=="?*", SYMLINK+="something"
776 KERNEL=="sda", ATTR{nofile}!="", SYMLINK+="not-empty"
777 KERNEL=="sda", ATTR{nofile}=="", SYMLINK+="empty"
778 KERNEL=="sda", ATTR{nofile}!="?*", SYMLINK+="not-something"
779 KERNEL=="sda", TEST!="nofile", SYMLINK+="non-existent"
780 KERNEL=="sda", SYMLINK+="wrong"
784 "program and bus type match",
786 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
787 exp_links = ["scsi-0:0:0:0"],
790 SUBSYSTEMS=="usb", PROGRAM=="/bin/echo -n usb-%b", SYMLINK+="%c"
791 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n scsi-%b", SYMLINK+="%c"
792 SUBSYSTEMS=="foo", PROGRAM=="/bin/echo -n foo-%b", SYMLINK+="%c"
796 "sysfs parent hierarchy",
798 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
799 exp_links = ["modem"],
802 ATTRS{idProduct}=="007b", SYMLINK+="modem"
806 "name test with ! in the name",
808 "/devices/virtual/block/fake!blockdev0",
809 devnode = "fake/blockdev0",
810 exp_links = ["is/a/fake/blockdev0"],
811 not_exp_links = ["is/not/a/fake/blockdev0", "modem"],
814 SUBSYSTEMS=="scsi", SYMLINK+="is/not/a/%k"
815 SUBSYSTEM=="block", SYMLINK+="is/a/%k"
816 KERNEL=="ttyACM0", SYMLINK+="modem"
820 "name test with ! in the name, but no matching rule",
822 "/devices/virtual/block/fake!blockdev0",
823 devnode = "fake/blockdev0",
824 not_exp_links = ["modem"],
827 KERNEL=="ttyACM0", SYMLINK+="modem"
833 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
834 exp_links = ["scsi-0:0:0:0"],
835 not_exp_links = ["no-match", "short-id", "not-scsi"],
838 SUBSYSTEMS=="usb", KERNELS=="0:0:0:0", SYMLINK+="not-scsi"
839 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:1", SYMLINK+="no-match"
840 SUBSYSTEMS=="scsi", KERNELS==":0", SYMLINK+="short-id"
841 SUBSYSTEMS=="scsi", KERNELS=="/0:0:0:0", SYMLINK+="no-match"
842 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="scsi-0:0:0:0"
846 "KERNELS wildcard all",
848 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
849 exp_links = ["scsi-0:0:0:0"],
850 not_exp_links = ["no-match", "before"],
853 SUBSYSTEMS=="scsi", KERNELS=="*:1", SYMLINK+="no-match"
854 SUBSYSTEMS=="scsi", KERNELS=="*:0:1", SYMLINK+="no-match"
855 SUBSYSTEMS=="scsi", KERNELS=="*:0:0:1", SYMLINK+="no-match"
856 SUBSYSTEMS=="scsi", KERNEL=="0:0:0:0", SYMLINK+="before"
857 SUBSYSTEMS=="scsi", KERNELS=="*", SYMLINK+="scsi-0:0:0:0"
861 "KERNELS wildcard partial",
863 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
864 exp_links = ["scsi-0:0:0:0", "before"],
867 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
868 SUBSYSTEMS=="scsi", KERNELS=="*:0", SYMLINK+="scsi-0:0:0:0"
872 "KERNELS wildcard partial 2",
874 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
875 exp_links = ["scsi-0:0:0:0", "before"],
878 SUBSYSTEMS=="scsi", KERNELS=="0:0:0:0", SYMLINK+="before"
879 SUBSYSTEMS=="scsi", KERNELS=="*:0:0:0", SYMLINK+="scsi-0:0:0:0"
883 "substitute attr with link target value (first match)",
885 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
886 exp_links = ["driver-is-sd"],
889 SUBSYSTEMS=="scsi", SYMLINK+="driver-is-$attr{driver}"
893 "substitute attr with link target value (currently selected device)",
895 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
896 exp_links = ["driver-is-ahci"],
899 SUBSYSTEMS=="pci", SYMLINK+="driver-is-$attr{driver}"
903 "ignore ATTRS attribute whitespace",
905 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
906 exp_links = ["ignored"],
909 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE", SYMLINK+="ignored"
913 "do not ignore ATTRS attribute whitespace",
915 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
916 exp_links = ["matched-with-space"],
917 not_exp_links = ["wrong-to-ignore"],
920 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE ", SYMLINK+="wrong-to-ignore"
921 SUBSYSTEMS=="scsi", ATTRS{whitespace_test}=="WHITE SPACE ", SYMLINK+="matched-with-space"
925 "permissions USER=bad GROUP=name",
927 "/devices/virtual/tty/tty33",
928 exp_perms = "0:0:0600",
931 KERNEL=="tty33", OWNER="bad", GROUP="name"
935 "permissions OWNER=1",
937 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
938 exp_links = ["node"],
939 exp_perms = "1::0600",
942 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="1"
946 "permissions GROUP=1",
948 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
949 exp_links = ["node"],
950 exp_perms = ":1:0660",
953 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", GROUP="1"
959 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
960 exp_links = ["node"],
961 exp_perms = "daemon::0600",
964 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="daemon"
970 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
971 exp_links = ["node"],
972 exp_perms = ":daemon:0660",
975 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", GROUP="daemon"
979 "textual user/group id",
981 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
982 exp_links = ["node"],
983 exp_perms = "root:audio:0660",
986 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="root", GROUP="audio"
990 "permissions MODE=0777",
992 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
993 exp_links = ["node"],
994 exp_perms = "::0777",
997 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", MODE="0777"
1001 "permissions OWNER=1 GROUP=1 MODE=0777",
1003 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1004 exp_links = ["node"],
1005 exp_perms = "1:1:0777",
1008 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", OWNER="1", GROUP="1", MODE="0777"
1012 "permissions OWNER to 1",
1014 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1018 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", OWNER="1"
1022 "permissions GROUP to 1",
1024 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1025 exp_perms = ":1:0660",
1028 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", GROUP="1"
1032 "permissions MODE to 0060",
1034 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1035 exp_perms = "::0060",
1038 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", MODE="0060"
1042 "permissions OWNER, GROUP, MODE",
1044 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1045 exp_perms = "1:1:0777",
1048 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", OWNER="1", GROUP="1", MODE="0777"
1052 "permissions only rule",
1054 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1055 exp_perms = "1:1:0777",
1058 KERNEL=="ttyACM[0-9]*", OWNER="1", GROUP="1", MODE="0777"
1059 KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
1060 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n"
1064 "multiple permissions only rule",
1066 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1067 exp_perms = "1:1:0777",
1070 SUBSYSTEM=="tty", OWNER="1"
1071 SUBSYSTEM=="tty", GROUP="1"
1072 SUBSYSTEM=="tty", MODE="0777"
1073 KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
1074 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n"
1078 "permissions only rule with override at SYMLINK+ rule",
1080 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1081 exp_perms = "1:2:0777",
1084 SUBSYSTEM=="tty", OWNER="1"
1085 SUBSYSTEM=="tty", GROUP="1"
1086 SUBSYSTEM=="tty", MODE="0777"
1087 KERNEL=="ttyUSX[0-9]*", OWNER="2", GROUP="2", MODE="0444"
1088 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", GROUP="2"
1092 "major/minor number test",
1094 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1095 exp_links = ["node"],
1096 exp_major_minor = "8:0",
1099 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node"
1103 "big major number test",
1105 "/devices/virtual/misc/misc-fake1",
1106 exp_links = ["node"],
1107 exp_major_minor = "4095:1",
1110 KERNEL=="misc-fake1", SYMLINK+="node"
1114 "big major and big minor number test",
1116 "/devices/virtual/misc/misc-fake89999",
1117 exp_links = ["node"],
1118 exp_major_minor = "4095:89999",
1121 KERNEL=="misc-fake89999", SYMLINK+="node"
1125 "multiple symlinks with format char",
1127 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1128 exp_links = ["symlink1-0", "symlink2-ttyACM0", "symlink3-"],
1131 KERNEL=="ttyACM[0-9]*", SYMLINK="symlink1-%n symlink2-%k symlink3-%b"
1135 "multiple symlinks with a lot of s p a c e s",
1137 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1138 exp_links = ["one", "two"],
1139 not_exp_links = [" "],
1142 KERNEL=="ttyACM[0-9]*", SYMLINK=" one two "
1146 "symlink with spaces in substituted variable",
1148 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1149 exp_links = ["name-one_two_three-end"],
1150 not_exp_links = [" "],
1153 ENV{WITH_WS}="one two three"
1154 SYMLINK="name-$env{WITH_WS}-end"
1158 "symlink with leading space in substituted variable",
1160 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1161 exp_links = ["name-one_two_three-end"],
1162 not_exp_links = [" "],
1165 ENV{WITH_WS}=" one two three"
1166 SYMLINK="name-$env{WITH_WS}-end"
1170 "symlink with trailing space in substituted variable",
1172 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1173 exp_links = ["name-one_two_three-end"],
1174 not_exp_links = [" "],
1177 ENV{WITH_WS}="one two three "
1178 SYMLINK="name-$env{WITH_WS}-end"
1182 "symlink with lots of space in substituted variable",
1184 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1185 exp_links = ["name-one_two_three-end"],
1186 not_exp_links = [" "],
1189 ENV{WITH_WS}=" one two three "
1190 SYMLINK="name-$env{WITH_WS}-end"
1194 "symlink with multiple spaces in substituted variable",
1196 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1197 exp_links = ["name-one_two_three-end"],
1198 not_exp_links = [" "],
1201 ENV{WITH_WS}=" one two three "
1202 SYMLINK="name-$env{WITH_WS}-end"
1206 "symlink with space and var with space",
1208 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1209 exp_links = ["first", "name-one_two_three-end",
1210 "another_symlink", "a", "b", "c"],
1211 not_exp_links = [" "],
1214 ENV{WITH_WS}=" one two three "
1215 SYMLINK=" first name-$env{WITH_WS}-end another_symlink a b c "
1219 "symlink with env which contain slash (see #19309)",
1221 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1222 exp_links = ["first", "name-aaa_bbb_ccc-end",
1223 "another_symlink", "a", "b", "c"],
1224 not_exp_links = ["ame-aaa/bbb/ccc-end"],
1227 ENV{WITH_SLASH}="aaa/bbb/ccc"
1228 OPTIONS="string_escape=replace", ENV{REPLACED}="$env{WITH_SLASH}"
1229 SYMLINK=" first name-$env{REPLACED}-end another_symlink a b c "
1233 "symlink creation (same directory)",
1235 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1236 exp_links = ["modem0"],
1239 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK="modem%n"
1243 "multiple symlinks",
1245 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1246 exp_links = ["first-0", "second-0", "third-0"],
1249 KERNEL=="ttyACM0", SYMLINK="first-%n second-%n third-%n"
1255 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1257 # we get a warning, but the process does not fail
1259 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="."
1263 "symlink node to itself",
1265 "/devices/virtual/tty/tty0",
1267 # we get a warning, but the process does not fail
1269 KERNEL=="tty0", SYMLINK+="tty0"
1273 "symlink %n substitution",
1275 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1276 exp_links = ["symlink0"],
1279 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="symlink%n"
1283 "symlink %k substitution",
1285 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1286 exp_links = ["symlink-ttyACM0"],
1289 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="symlink-%k"
1293 "symlink %M:%m substitution",
1295 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1296 exp_links = ["major-166:0"],
1299 KERNEL=="ttyACM[0-9]*", SYMLINK+="ttyACM%n", SYMLINK+="major-%M:%m"
1303 "symlink %b substitution",
1305 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1306 exp_links = ["symlink-0:0:0:0"],
1309 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="symlink-%b"
1313 "symlink %c substitution",
1315 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1316 exp_links = ["test"],
1319 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo test", SYMLINK+="%c"
1323 "symlink %c{N} substitution",
1325 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1326 exp_links = ["test"],
1327 not_exp_links = ["symlink", "this"],
1330 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo symlink test this", SYMLINK+="%c{2}"
1334 "symlink %c{N+} substitution",
1336 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1337 exp_links = ["test", "this"],
1338 not_exp_links = ["symlink"],
1341 KERNEL=="ttyACM[0-9]*", PROGRAM=="/bin/echo symlink test this", SYMLINK+="%c{2+}"
1345 "symlink only rule with %c{N+}",
1347 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1348 exp_links = ["test", "this"],
1349 not_exp_links = ["symlink"],
1352 SUBSYSTEMS=="scsi", KERNEL=="sda", PROGRAM=="/bin/echo link test this" SYMLINK+="%c{2+}"
1356 "symlink %s{filename} substitution",
1358 "/devices/pci0000:00/0000:00:1d.7/usb5/5-2/5-2:1.0/tty/ttyACM0",
1359 exp_links = ["166:0"],
1362 KERNEL=="ttyACM[0-9]*", SYMLINK+="%s{dev}"
1366 "program result substitution (numbered part of)",
1368 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
1369 exp_links = ["link1", "link2"],
1370 not_exp_links = ["node"],
1373 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n node link1 link2", RESULT=="node *", SYMLINK+="%c{2} %c{3}"
1377 "program result substitution (numbered part of+)",
1379 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
1380 exp_links = ["link1", "link2", "link3", "link4"],
1381 not_exp_links = ["node"],
1384 SUBSYSTEMS=="scsi", PROGRAM=="/bin/echo -n node link1 link2 link3 link4", RESULT=="node *", SYMLINK+="%c{2+}"
1388 "SUBSYSTEM match test",
1390 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1391 exp_links = ["node"],
1392 not_exp_links = ["should_not_match", "should_not_match2"],
1395 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match", SUBSYSTEM=="vc"
1396 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", SUBSYSTEM=="block"
1397 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match2", SUBSYSTEM=="vc"
1401 "DRIVERS match test",
1403 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1404 exp_links = ["node"],
1405 not_exp_links = ["should_not_match"]
1408 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="should_not_match", DRIVERS=="sd-wrong"
1409 SUBSYSTEMS=="scsi", KERNEL=="sda", SYMLINK+="node", DRIVERS=="sd"
1413 "devnode substitution test",
1415 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1416 exp_links = ["node"],
1419 SUBSYSTEMS=="scsi", KERNEL=="sda", PROGRAM=="/usr/bin/test -b %N" SYMLINK+="node"
1423 "parent node name substitution test",
1425 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1426 exp_links = ["sda-part-1"],
1429 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="%P-part-%n"
1433 "udev_root substitution",
1435 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1436 exp_links = ["start-/dev-end"],
1439 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="start-%r-end"
1443 # This is not supported any more
1446 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1447 exp_links = ["last", "very-last"],
1450 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="last", OPTIONS="last_rule"
1451 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="very-last"
1455 "negation KERNEL!=",
1457 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1458 exp_links = ["match", "before"],
1459 not_exp_links = ["matches-but-is-negated"],
1462 SUBSYSTEMS=="scsi", KERNEL!="sda1", SYMLINK+="matches-but-is-negated"
1463 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
1464 SUBSYSTEMS=="scsi", KERNEL!="xsda1", SYMLINK+="match"
1468 "negation SUBSYSTEM!=",
1470 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1471 exp_links = ["before", "not-anything"],
1472 not_exp_links = ["matches-but-is-negated"],
1475 SUBSYSTEMS=="scsi", SUBSYSTEM=="block", KERNEL!="sda1", SYMLINK+="matches-but-is-negated"
1476 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
1477 SUBSYSTEMS=="scsi", SUBSYSTEM!="anything", SYMLINK+="not-anything"
1481 "negation PROGRAM!= exit code",
1483 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1484 exp_links = ["before", "nonzero-program"],
1487 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
1488 KERNEL=="sda1", PROGRAM!="/bin/false", SYMLINK+="nonzero-program"
1494 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1495 exp_links = ["true"],
1496 not_exp_links = ["bad", "wrong"],
1499 ENV{ENV_KEY_TEST}="test"
1500 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="go", SYMLINK+="wrong"
1501 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="test", SYMLINK+="true"
1502 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="bad", SYMLINK+="bad"
1508 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1509 exp_links = ["true"],
1510 not_exp_links = ["bad", "wrong", "no"],
1513 ENV{ENV_KEY_TEST}="test"
1514 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="go", SYMLINK+="wrong"
1515 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="yes", ENV{ACTION}=="add", ENV{DEVPATH}=="*/block/sda/sdax1", SYMLINK+="no"
1516 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="test", ENV{ACTION}=="add", ENV{DEVPATH}=="*/block/sda/sda1", SYMLINK+="true"
1517 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ENV_KEY_TEST}=="bad", SYMLINK+="bad"
1521 "ENV{} test (assign)",
1523 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1524 exp_links = ["true", "before"],
1525 not_exp_links = ["no"],
1528 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="true"
1529 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="yes", SYMLINK+="no"
1530 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
1531 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="true", SYMLINK+="true"
1535 "ENV{} test (assign 2 times)",
1537 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1538 exp_links = ["true", "before"],
1539 not_exp_links = ["no", "bad"],
1542 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="true"
1543 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}="absolutely-$env{ASSIGN}"
1544 SUBSYSTEMS=="scsi", KERNEL=="sda1", SYMLINK+="before"
1545 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="yes", SYMLINK+="no"
1546 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="true", SYMLINK+="bad"
1547 SUBSYSTEMS=="scsi", KERNEL=="sda1", ENV{ASSIGN}=="absolutely-true", SYMLINK+="true"
1551 "ENV{} test (assign2)",
1553 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1554 exp_links = ["part"],
1555 not_exp_links = ["disk"],
1558 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
1559 exp_links = ["disk"],
1560 not_exp_links = ["part"],
1563 SUBSYSTEM=="block", KERNEL=="*[0-9]", ENV{PARTITION}="true", ENV{MAINDEVICE}="false"
1564 SUBSYSTEM=="block", KERNEL=="*[!0-9]", ENV{PARTITION}="false", ENV{MAINDEVICE}="true"
1565 ENV{MAINDEVICE}=="true", SYMLINK+="disk"
1566 SUBSYSTEM=="block", SYMLINK+="before"
1567 ENV{PARTITION}=="true", SYMLINK+="part"
1571 "untrusted string sanitize",
1573 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
1574 exp_links = ["sane"],
1577 SUBSYSTEMS=="scsi", KERNEL=="sda1", PROGRAM=="/bin/echo -e name; (/usr/bin/badprogram)", RESULT=="name_ _/usr/bin/badprogram_", SYMLINK+="sane"
1581 "untrusted string sanitize (don't replace utf8
)",
1583 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
/sda1
",
1584 exp_links = ["uber
"],
1587 SUBSYSTEMS=="scsi
", KERNEL=="sda1
", PROGRAM=="/bin
/echo
-e
\xc3\xbcber
" RESULT=="über
", SYMLINK+="uber
"
1591 "untrusted string
sanitize (replace invalid utf8
)",
1593 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
/sda1
",
1594 exp_links = ["replaced
"],
1597 SUBSYSTEMS=="scsi
", KERNEL=="sda1
", PROGRAM=="/bin
/echo
-e
\xef\xe8garbage
", RESULT=="__garbage
", SYMLINK+="replaced
"
1601 "read sysfs value
from parent device
",
1603 "/devices
/pci0000
:00/0000:00:1d
.7/usb5
/5-2/5-2:1.0/tty
/ttyACM0
",
1604 exp_links = ["serial
-354172020305000"],
1607 KERNEL=="ttyACM
*", ATTRS{serial}=="?
*", SYMLINK+="serial
-%s{serial}
"
1611 "match against empty key string
",
1613 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1615 not_exp_links = ["not-1-ok
", "not-2-ok
", "not-3-ok
"],
1618 KERNEL=="sda
", ATTRS{nothing}!="", SYMLINK+="not-1-ok
"
1619 KERNEL=="sda
", ATTRS{nothing}=="", SYMLINK+="not-2-ok
"
1620 KERNEL=="sda
", ATTRS{vendor}!="", SYMLINK+="ok
"
1621 KERNEL=="sda
", ATTRS{vendor}=="", SYMLINK+="not-3-ok
"
1625 "check ACTION value
",
1627 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1629 not_exp_links = ["unknown
-not-ok
"],
1632 ACTION=="unknown
", KERNEL=="sda
", SYMLINK+="unknown
-not-ok
"
1633 ACTION=="add
", KERNEL=="sda
", SYMLINK+="ok
"
1639 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1641 exp_perms = "root
:tty
:0640",
1644 KERNEL=="sda
", GROUP:="tty
"
1645 KERNEL=="sda
", GROUP="root
", MODE="0640", SYMLINK+="ok
"
1649 "final assignment
2",
1651 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1653 exp_perms = "root
:tty
:0640",
1656 KERNEL=="sda
", GROUP:="tty
"
1657 SUBSYSTEM=="block
", MODE:="640"
1658 KERNEL=="sda
", GROUP="root
", MODE="0666", SYMLINK+="ok
"
1664 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1665 exp_links = ["node
-add
-me
"],
1668 KERNEL=="sda
", MODE="0666", SYMLINK+="node
-$env{ACTION}
-me
"
1672 "reset
list to current value
",
1674 "/devices
/pci0000
:00/0000:00:1d
.7/usb5
/5-2/5-2:1.0/tty
/ttyACM0
",
1675 exp_links = ["three
"],
1676 not_exp_links = ["two
", "one
"],
1679 KERNEL=="ttyACM
[0-9]*", SYMLINK+="one
"
1680 KERNEL=="ttyACM
[0-9]*", SYMLINK+="two
"
1681 KERNEL=="ttyACM
[0-9]*", SYMLINK="three
"
1685 "test empty SYMLINK
+ (empty override
)",
1687 "/devices
/pci0000
:00/0000:00:1d
.7/usb5
/5-2/5-2:1.0/tty
/ttyACM0
",
1688 exp_links = ["right
"],
1689 not_exp_links = ["wrong
"],
1692 KERNEL=="ttyACM
[0-9]*", SYMLINK+="wrong
"
1693 KERNEL=="ttyACM
[0-9]*", SYMLINK=""
1694 KERNEL=="ttyACM
[0-9]*", SYMLINK+="right
"
1698 "test multi matches
",
1700 "/devices
/pci0000
:00/0000:00:1d
.7/usb5
/5-2/5-2:1.0/tty
/ttyACM0
",
1701 exp_links = ["right
", "before
"],
1704 KERNEL=="ttyACM
*", SYMLINK+="before
"
1705 KERNEL=="ttyACM
*|nothing
", SYMLINK+="right
"
1709 "test multi matches
2",
1711 "/devices
/pci0000
:00/0000:00:1d
.7/usb5
/5-2/5-2:1.0/tty
/ttyACM0
",
1712 exp_links = ["right
", "before
"],
1713 not_exp_links = ["nomatch
"],
1716 KERNEL=="dontknow
*|
*nothing
", SYMLINK+="nomatch
"
1717 KERNEL=="ttyACM
*", SYMLINK+="before
"
1718 KERNEL=="dontknow
*|ttyACM
*|nothing
*", SYMLINK+="right
"
1722 "test multi matches
3",
1724 "/devices
/pci0000
:00/0000:00:1d
.7/usb5
/5-2/5-2:1.0/tty
/ttyACM0
",
1725 exp_links = ["right
"],
1726 not_exp_links = ["nomatch
", "wrong1
", "wrong2
"],
1729 KERNEL=="dontknow|nothing
", SYMLINK+="nomatch
"
1730 KERNEL=="dontknow|ttyACM0a|nothing|attyACM0
", SYMLINK+="wrong1
"
1731 KERNEL=="X|attyACM0|dontknow|ttyACM0a|nothing|attyACM0
", SYMLINK+="wrong2
"
1732 KERNEL=="dontknow|ttyACM0|nothing
", SYMLINK+="right
"
1736 "test multi matches
4",
1738 "/devices
/pci0000
:00/0000:00:1d
.7/usb5
/5-2/5-2:1.0/tty
/ttyACM0
",
1739 exp_links = ["right
"],
1740 not_exp_links = ["nomatch
", "wrong1
", "wrong2
", "wrong3
"],
1743 KERNEL=="dontknow|nothing
", SYMLINK+="nomatch
"
1744 KERNEL=="dontknow|ttyACM0a|nothing|attyACM0
", SYMLINK+="wrong1
"
1745 KERNEL=="X|attyACM0|dontknow|ttyACM0a|nothing|attyACM0
", SYMLINK+="wrong2
"
1746 KERNEL=="all|dontknow|ttyACM0
", SYMLINK+="right
"
1747 KERNEL=="ttyACM0a|nothing
", SYMLINK+="wrong3
"
1751 "test multi matches
5",
1753 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1754 exp_links = ["found
"],
1755 not_exp_links = ["bad
"],
1758 KERNEL=="sda
", TAG="foo
"
1759 TAGS=="|foo
", SYMLINK+="found
"
1760 TAGS=="|aaa
", SYMLINK+="bad
"
1764 "test multi matches
6",
1766 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1767 exp_links = ["found
"],
1768 not_exp_links = ["bad
"],
1771 KERNEL=="sda
", ENV{HOGE}=""
1772 ENV{HOGE}=="|foo
", SYMLINK+="found
"
1773 ENV{HOGE}=="aaa|bbb
", SYMLINK+="bad
"
1777 "test multi matches
7",
1779 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1780 exp_links = ["found
"],
1781 not_exp_links = ["bad
"],
1784 KERNEL=="sda
", TAG="foo
"
1785 TAGS=="foo||bar
", SYMLINK+="found
"
1786 TAGS=="aaa||bbb
", SYMLINK+="bad
"
1790 "test multi matches
8",
1792 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1793 exp_links = ["found
"],
1794 not_exp_links = ["bad
"],
1797 KERNEL=="sda
", ENV{HOGE}=""
1798 ENV{HOGE}=="foo||bar
", SYMLINK+="found
"
1799 ENV{HOGE}=="aaa|bbb
", SYMLINK+="bad
"
1803 "test multi matches
9",
1805 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1806 exp_links = ["found
", "found2
"],
1807 not_exp_links = ["bad
"],
1810 KERNEL=="sda
", TAG="foo
"
1811 TAGS=="foo|
", SYMLINK+="found
"
1812 TAGS=="aaa|
", SYMLINK+="bad
"
1813 KERNEL=="sda
", TAGS!="hoge
", SYMLINK+="found2
"
1814 KERNEL=="sda
", TAGS!="foo
", SYMLINK+="bad2
"
1818 "test multi matches
10",
1820 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1821 exp_links = ["found
"],
1822 not_exp_links = ["bad
"],
1825 KERNEL=="sda
", ENV{HOGE}=""
1826 ENV{HOGE}=="foo|
", SYMLINK+="found
"
1827 ENV{HOGE}=="aaa|bbb
", SYMLINK+="bad
"
1831 "test multi matches
11",
1833 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1834 exp_links = ["found
"],
1835 not_exp_links = ["bad
"],
1838 KERNEL=="sda
", TAG="c
"
1839 TAGS=="foo||bar||c
", SYMLINK+="found
"
1840 TAGS=="aaa||bbb||ccc
", SYMLINK+="bad
"
1844 "TAG refuses invalid string
",
1846 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1847 exp_links = ["valid
", "found
"],
1848 not_exp_links = ["empty
", "invalid_char
", "path
", "bad
", "bad2
"],
1851 KERNEL=="sda
", TAG+="", TAG+="invalid
.char
", TAG+="path
/is/also
/invalid
", TAG+="valid
"
1852 TAGS=="", SYMLINK+="empty
"
1853 TAGS=="invalid
.char
", SYMLINK+="invalid_char
"
1854 TAGS=="path
/is/also
/invalid
", SYMLINK+="path
"
1855 TAGS=="valid
", SYMLINK+="valid
"
1856 TAGS=="valid|
", SYMLINK+="found
"
1857 TAGS=="aaa|
", SYMLINK+="bad
"
1858 TAGS=="aaa|bbb
", SYMLINK+="bad2
"
1862 "IMPORT parent test
",
1864 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1865 exp_links = ["parent
"],
1868 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
/sda1
",
1869 exp_links = ["parentenv
-parent_right
"],
1871 delay = 500000, # Serialized! We need to sleep here after adding sda
1873 KERNEL=="sda1
", IMPORT{parent}="PARENT
*", SYMLINK+="parentenv
-$env{PARENT_KEY}$env{WRONG_PARENT_KEY}
"
1874 KERNEL=="sda
", IMPORT{program}="/bin
/echo
-e
'PARENT_KEY=parent_right\nWRONG_PARENT_KEY=parent_wrong'"
1875 KERNEL=="sda
", SYMLINK+="parent
"
1881 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
/sda1
",
1882 exp_links = ["right
"],
1883 not_exp_links = ["wrong
", "wrong2
"],
1886 KERNEL=="sda1
", GOTO="TEST
"
1887 KERNEL=="sda1
", SYMLINK+="wrong
"
1888 KERNEL=="sda1
", GOTO="BAD
"
1889 KERNEL=="sda1
", SYMLINK+="", LABEL="NO
"
1890 KERNEL=="sda1
", SYMLINK+="right
", LABEL="TEST
", GOTO="end
"
1891 KERNEL=="sda1
", SYMLINK+="wrong2
", LABEL="BAD
"
1896 "GOTO label does
not exist
",
1898 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
/sda1
",
1899 exp_links = ["right
"],
1902 KERNEL=="sda1
", GOTO="does
-not-exist
"
1903 KERNEL=="sda1
", SYMLINK+="right
",
1908 "SYMLINK
+ compare test
",
1910 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
/sda1
",
1911 exp_links = ["right
", "link
"],
1912 not_exp_links = ["wrong
"],
1915 KERNEL=="sda1
", SYMLINK+="link
"
1916 KERNEL=="sda1
", SYMLINK=="link
*", SYMLINK+="right
"
1917 KERNEL=="sda1
", SYMLINK=="nolink
*", SYMLINK+="wrong
"
1921 "invalid key operation
",
1923 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
/sda1
",
1924 exp_links = ["yes
"],
1925 not_exp_links = ["no
"],
1928 KERNEL="sda1
", SYMLINK+="no
"
1929 KERNEL=="sda1
", SYMLINK+="yes
"
1933 "operator chars
in attribute
",
1935 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1936 exp_links = ["yes
"],
1939 KERNEL=="sda
", ATTR{test:colon+plus}=="?
*", SYMLINK+="yes
"
1943 "overlong comment line
",
1945 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
/sda1
",
1946 exp_links = ["yes
"],
1947 not_exp_links = ["no
"],
1950 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
1951 # 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
1952 KERNEL=="sda1
", SYMLINK+=="no
"
1953 KERNEL=="sda1
", SYMLINK+="yes
"
1957 "magic subsys
/kernel lookup
",
1959 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1960 exp_links = ["00:16:41:e2
:8d
:ff
"],
1963 KERNEL=="sda
", SYMLINK+="$attr
{[net
/eth0
]address
}"
1967 "TEST absolute path
",
1969 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1970 exp_links = ["there
"],
1971 not_exp_links = ["notthere
"],
1974 TEST=="/etc
/passwd
", SYMLINK+="there
"
1975 TEST!="/etc
/passwd
", SYMLINK+="notthere
"
1979 "TEST subsys
/kernel lookup
",
1981 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1982 exp_links = ["yes
"],
1985 KERNEL=="sda
", TEST=="[net
/eth0
]", SYMLINK+="yes
"
1989 "TEST relative path
",
1991 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
1992 exp_links = ["relative
"],
1995 KERNEL=="sda
", TEST=="size
", SYMLINK+="relative
"
1999 "TEST wildcard
substitution (find queue
/nr_requests
)",
2001 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
2002 exp_links = ["found
-subdir
"],
2005 KERNEL=="sda
", TEST=="*/nr_requests
", SYMLINK+="found
-subdir
"
2011 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
2012 exp_perms = "0:0:0000",
2015 KERNEL=="sda
", MODE="0000"
2019 "TEST PROGRAM feeds OWNER
, GROUP
, MODE
",
2021 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
2022 exp_perms = "1:1:0400",
2025 KERNEL=="sda
", MODE="666"
2026 KERNEL=="sda
", PROGRAM=="/bin
/echo
1 1 0400", OWNER="%c{1}
", GROUP="%c{2}
", MODE="%c{3}
"
2030 "TEST PROGRAM feeds MODE with overflow
",
2032 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
2033 exp_perms = "0:0:0440",
2036 KERNEL=="sda
", MODE="440"
2037 KERNEL=="sda
", PROGRAM=="/bin
/echo
0 0 0400letsdoabuffferoverflow
0123456789012345789012345678901234567890", OWNER="%c{1}
", GROUP="%c{2}
", MODE="%c{3}
"
2041 "magic
[subsys
/sysname
] attribute substitution
",
2043 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
2044 exp_links = ["sda
-8741C4G
-end
"],
2045 exp_perms = "0:0:0600",
2048 KERNEL=="sda
", SYMLINK+="%k
-%s{[dmi
/id]product_name
}-end
"
2054 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
2055 exp_links = ["disk
/by
-path
/pci
-0000:00:1f
.2-scsi
-0:0:0:0"],
2058 KERNEL=="sda
", IMPORT{builtin}="path_id
"
2059 KERNEL=="sda
", ENV{ID_PATH}=="?
*", SYMLINK+="disk
/by
-path
/$env{ID_PATH}
"
2063 "add
and match tag
",
2065 "/devices
/pci0000
:00/0000:00:1f
.2/host0
/target0
:0:0/0:0:0:0/block
/sda
",
2066 exp_links = ["found
"],
2067 not_exp_links = ["bad
"],
2070 SUBSYSTEMS=="scsi
", ATTRS{vendor}=="ATA
", TAG+="green
"
2071 TAGS=="green
", SYMLINK+="found
"
2072 TAGS=="blue
", SYMLINK+="bad
"
2076 "don
't crash with lots of tags",
2078 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
2079 exp_links = ["found"],
2083 TAGS=="test1", TAGS=="test500", TAGS=="test1234", TAGS=="test9999", TAGS=="test10000", SYMLINK+="found"
2089 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
2090 exp_links = ["found"],
2091 not_exp_links = ["bad"],
2094 {rules_10k_tags_continuation}
2095 TAGS=="test1", TAGS=="test500", TAGS=="test1234", TAGS=="test9999", TAGS=="test10000", SYMLINK+="bad"
2097 # comment in continuation
2099 # space before comment
2101 # spaces before and after token are dropped
2106 TAGS=="hoge1", TAGS=="hoge2", TAGS=="hoge3", TAGS=="hoge4", SYMLINK+="found"
2110 "continuations with empty line",
2112 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
2113 exp_links = ["found"],
2114 not_exp_links = ["bad"],
2117 # empty line finishes continuation
2118 KERNEL=="sda", TAG+="foo" \
2120 KERNEL=="sdb", TAG+="hoge"
2121 KERNEL=="sda", TAG+="aaa" \
2122 KERNEL=="sdb", TAG+="bbb"
2123 TAGS=="foo", SYMLINK+="found"
2124 TAGS=="aaa", SYMLINK+="bad"
2128 "continuations with space only line",
2130 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda",
2131 exp_links = ["found"],
2132 not_exp_links = ["bad"],
2135 # space only line finishes continuation
2136 KERNEL=="sda", TAG+="foo" \\
2138 KERNEL=="sdb", TAG+="hoge"
2139 KERNEL=="sda", TAG+="aaa" \\
2140 KERNEL=="sdb", TAG+="bbb"
2141 TAGS=="foo", SYMLINK+="found"
2142 TAGS=="aaa", SYMLINK+="bad"
2148 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
2149 exp_links = ["part-1"],
2152 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
2153 exp_links = ["part-5"],
2156 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6",
2157 exp_links = ["part-6"],
2160 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7",
2161 exp_links = ["part-7"],
2164 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8",
2165 exp_links = ["part-8"],
2168 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9",
2169 exp_links = ["part-9"],
2172 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10",
2173 exp_links = ["part-10"],
2176 SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNEL=="sda?*", ENV{DEVTYPE}=="partition", SYMLINK+="part-%n"
2180 "multiple devices, same link name, positive prio",
2182 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
2183 exp_links = ["part-1"],
2184 not_exp_links = ["partition"],
2187 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
2188 exp_links = ["part-5"],
2189 not_exp_links = ["partition"],
2192 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6",
2193 not_exp_links = ["partition"],
2194 exp_links = ["part-6"],
2197 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7",
2198 exp_links = ["part-7", "partition"],
2201 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8",
2202 not_exp_links = ["partition"],
2203 exp_links = ["part-8"],
2206 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9",
2207 not_exp_links = ["partition"],
2208 exp_links = ["part-9"],
2211 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10",
2212 not_exp_links = ["partition"],
2213 exp_links = ["part-10"],
2217 SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNEL=="sda?*", ENV{DEVTYPE}=="partition", SYMLINK+="part-%n"
2218 SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNEL=="sda?*", ENV{DEVTYPE}=="partition", SYMLINK+="partition"
2219 KERNEL=="*7", OPTIONS+="link_priority=10"
2223 "multiple devices, same link name, negative prio",
2225 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
2226 exp_links = ["part-1"],
2227 not_exp_links = ["partition"],
2230 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
2231 exp_links = ["part-5"],
2232 not_exp_links = ["partition"],
2235 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6",
2236 not_exp_links = ["partition"],
2237 exp_links = ["part-6"],
2240 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7",
2241 exp_links = ["part-7", "partition"],
2244 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8",
2245 not_exp_links = ["partition"],
2246 exp_links = ["part-8"],
2249 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9",
2250 not_exp_links = ["partition"],
2251 exp_links = ["part-9"],
2254 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10",
2255 not_exp_links = ["partition"],
2256 exp_links = ["part-10"],
2259 SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNEL=="sda?*", ENV{DEVTYPE}=="partition", SYMLINK+="part-%n"
2260 SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNEL=="sda?*", ENV{DEVTYPE}=="partition", SYMLINK+="partition"
2261 KERNEL!="*7", OPTIONS+="link_priority=-10"
2265 "multiple devices, same link name, positive prio, sleep",
2267 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
2268 exp_links = ["part-1"],
2269 not_exp_links = ["partition"],
2272 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5",
2273 exp_links = ["part-5"],
2274 not_exp_links = ["partition"],
2277 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda6",
2278 not_exp_links = ["partition"],
2279 exp_links = ["part-6"],
2282 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda7",
2283 exp_links = ["part-7", "partition"],
2286 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda8",
2287 not_exp_links = ["partition"],
2288 exp_links = ["part-8"],
2291 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda9",
2292 not_exp_links = ["partition"],
2293 exp_links = ["part-9"],
2296 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda10",
2297 not_exp_links = ["partition"],
2298 exp_links = ["part-10"],
2302 SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNEL=="sda?*", ENV{DEVTYPE}=="partition", SYMLINK+="part-%n"
2303 SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNEL=="sda?*", ENV{DEVTYPE}=="partition", SYMLINK+="partition"
2304 KERNEL=="*7", OPTIONS+="link_priority=10"
2309 device_generator = lambda: \
2310 all_block_devs(lambda name: (["blockdev"], None) if name.endswith('/sda6
') else (None, None)),
2313 SUBSYSTEM=="block", SUBSYSTEMS=="scsi", KERNEL=="sd*", SYMLINK+="blockdev"
2314 KERNEL=="sda6", OPTIONS+="link_priority=10"
2318 "case insensitive match",
2320 "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda1",
2325 KERNEL==i"SDA1", SUBSYSTEMS==i"SCSI", ATTRS{vendor}==i"a?a", SYMLINK+="ok"
2329 def fork_and_run_udev(action: str, rules: Rules) -> None:
2331 for k, device in enumerate(rules.devices):
2332 # TODO: valgrind/gdb/strace
2333 cmd = [UDEV_BIN, action, device.devpath]
2335 cmd += [f'{k
* rules
.delay
}']
2337 kinder += [subprocess.Popen(cmd)]
2342 # once something fails, terminate all workers
2350 def environment_issue():
2351 if os.getuid() != 0:
2352 return 'Must be root to run properly
'
2354 c = subprocess.run(['systemd
-detect
-virt
', '-r
', '-q
'],
2356 if c.returncode == 0:
2357 return 'Running
in a chroot
, skipping the test
'
2359 c = subprocess.run(['systemd
-detect
-virt
', '-c
', '-q
'],
2361 if c.returncode == 0:
2362 return 'Running
in a container
, skipping the test
'
2367 @pytest.fixture(scope='module
')
2369 issue = environment_issue()
2373 global UDEV_RUN, UDEV_RULES, UDEV_DEV, UDEV_SYS
2375 _tmpdir = tempfile.TemporaryDirectory()
2376 tmpdir = Path(_tmpdir.name)
2378 UDEV_RUN = tmpdir / 'run
'
2379 UDEV_RULES = UDEV_RUN / 'udev
-test
.rules
'
2381 udev_tmpfs = tmpdir / 'tmpfs
'
2382 UDEV_DEV = udev_tmpfs / 'dev
'
2383 UDEV_SYS = udev_tmpfs / 'sys
'
2385 subprocess.run(['umount
', udev_tmpfs],
2386 stderr=subprocess.DEVNULL,
2388 udev_tmpfs.mkdir(exist_ok=True, parents=True)
2390 subprocess.check_call(['mount
', '-v
',
2392 '-o
', 'rw
,mode
=0755,nosuid
,noexec
',
2393 'tmpfs
', udev_tmpfs])
2395 UDEV_DEV.mkdir(exist_ok=True)
2396 # setting group and mode of udev_dev ensures the tests work
2397 # even if the parent directory has setgid bit enabled.
2398 os.chmod(UDEV_DEV,0o755)
2399 os.chown(UDEV_DEV, 0, 0)
2401 os.mknod(UDEV_DEV / 'null
', 0o600 | stat.S_IFCHR, os.makedev(1, 3))
2403 # check if we are permitted to create block device nodes
2404 sda = UDEV_DEV / 'sda
'
2405 os.mknod(sda, 0o600 | stat.S_IFBLK, os.makedev(8, 0))
2408 subprocess.check_call([SYS_SCRIPT, UDEV_SYS.parent])
2409 subprocess.check_call(['rm
', '-rf
', UDEV_RUN])
2410 UDEV_RUN.mkdir(parents=True)
2414 if subprocess.run([UDEV_BIN, 'check
'],
2415 check=False).returncode != 0:
2416 pytest.skip(f'{UDEV_BIN} failed to
set up the environment
, skipping the test
',
2417 allow_module_level=True)
2421 subprocess.check_call(['rm
', '-rf
', UDEV_RUN])
2422 subprocess.check_call(['umount
', '-v
', udev_tmpfs])
2426 @pytest.mark.parametrize("rules", RULES, ids=(rule.desc for rule in RULES))
2427 def test_udev(rules: Rules, udev_setup):
2428 assert udev_setup is None
2430 rules.create_rules_file()
2431 rules.generate_devices()
2433 for _ in range(rules.repeat):
2434 fork_and_run_udev('add
', rules)
2436 for device in rules.devices:
2439 fork_and_run_udev('remove
', rules)
2441 for device in rules.devices:
2442 device.check_remove()
2444 if __name__ == '__main__
':
2445 issue = environment_issue()
2447 print(issue, file=sys.stderr)
2449 sys.exit(pytest.main(sys.argv))