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