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