1# 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2020 Kyle Evans <kevans@FreeBSD.org> 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26# 27 28check_size() 29{ 30 file=$1 31 sz=$2 32 33 atf_check -o inline:"$sz\n" stat -f '%z' $file 34} 35 36atf_test_case basic 37basic_head() 38{ 39 atf_set "descr" "Copy a file" 40} 41basic_body() 42{ 43 echo "foo" > bar 44 45 atf_check cp bar baz 46 check_size baz 4 47} 48 49atf_test_case basic_symlink 50basic_symlink_head() 51{ 52 atf_set "descr" "Copy a symlink to a file" 53} 54basic_symlink_body() 55{ 56 echo "foo" > bar 57 ln -s bar baz 58 59 atf_check cp baz foo 60 atf_check test ! -L foo 61 62 atf_check cmp foo bar 63} 64 65atf_test_case chrdev 66chrdev_head() 67{ 68 atf_set "descr" "Copy a character device" 69} 70chrdev_body() 71{ 72 echo "foo" > bar 73 74 check_size bar 4 75 atf_check cp /dev/null trunc 76 check_size trunc 0 77 atf_check cp bar trunc 78 check_size trunc 4 79 atf_check cp /dev/null trunc 80 check_size trunc 0 81} 82 83atf_test_case hardlink 84hardlink_head() 85{ 86 atf_set "descr" "Create a hard link to a file" 87} 88hardlink_body() 89{ 90 echo "foo" >foo 91 atf_check cp -l foo bar 92 atf_check -o inline:"foo\n" cat bar 93 atf_check_equal "$(stat -f%d,%i foo)" "$(stat -f%d,%i bar)" 94} 95 96atf_test_case hardlink_exists 97hardlink_exists_head() 98{ 99 atf_set "descr" "Attempt to create a hard link to a file, " \ 100 "but the destination already exists" 101} 102hardlink_exists_body() 103{ 104 echo "foo" >foo 105 echo "bar" >bar 106 atf_check -s not-exit:0 -e match:exists cp -l foo bar 107 atf_check -o inline:"bar\n" cat bar 108 atf_check_not_equal "$(stat -f%d,%i foo)" "$(stat -f%d,%i bar)" 109} 110 111atf_test_case hardlink_exists_force 112hardlink_exists_force_head() 113{ 114 atf_set "descr" "Force creation of a hard link to a file " \ 115 "when the destination already exists" 116} 117hardlink_exists_force_body() 118{ 119 echo "foo" >foo 120 echo "bar" >bar 121 atf_check cp -fl foo bar 122 atf_check -o inline:"foo\n" cat bar 123 atf_check_equal "$(stat -f%d,%i foo)" "$(stat -f%d,%i bar)" 124} 125 126atf_test_case matching_srctgt 127matching_srctgt_head() 128{ 129 atf_set "descr" "Avoid infinite loop when copying a directory to itself" 130} 131matching_srctgt_body() 132{ 133 # PR235438: `cp -R foo foo` would previously infinitely recurse and 134 # eventually error out. 135 mkdir foo 136 echo "qux" > foo/bar 137 cp foo/bar foo/zoo 138 139 atf_check cp -R foo foo 140 atf_check -o inline:"qux\n" cat foo/foo/bar 141 atf_check -o inline:"qux\n" cat foo/foo/zoo 142 atf_check test ! -e foo/foo/foo 143} 144 145atf_test_case matching_srctgt_contained 146matching_srctgt_contained_head() 147{ 148 atf_set "descr" "Avoid infinite loop when copying a directory " \ 149 "into an existing subdirectory of itself" 150} 151matching_srctgt_contained_body() 152{ 153 # Let's do the same thing, except we'll try to recursively copy foo into 154 # one of its subdirectories. 155 mkdir foo 156 ln -s foo coo 157 echo "qux" > foo/bar 158 mkdir foo/moo 159 touch foo/moo/roo 160 cp foo/bar foo/zoo 161 162 atf_check cp -R foo foo/moo 163 atf_check cp -RH coo foo/moo 164 atf_check -o inline:"qux\n" cat foo/moo/foo/bar 165 atf_check -o inline:"qux\n" cat foo/moo/coo/bar 166 atf_check -o inline:"qux\n" cat foo/moo/foo/zoo 167 atf_check -o inline:"qux\n" cat foo/moo/coo/zoo 168 169 # We should have copied the contents of foo/moo before foo, coo started 170 # getting copied in. 171 atf_check -o not-empty stat foo/moo/foo/moo/roo 172 atf_check -o not-empty stat foo/moo/coo/moo/roo 173 atf_check -e not-empty -s not-exit:0 stat foo/moo/foo/moo/foo 174 atf_check -e not-empty -s not-exit:0 stat foo/moo/coo/moo/coo 175} 176 177atf_test_case matching_srctgt_link 178matching_srctgt_link_head() 179{ 180 atf_set "descr" "Avoid infinite loop when recursively copying a " \ 181 "symlink to a directory into the directory it links to" 182} 183matching_srctgt_link_body() 184{ 185 mkdir foo 186 echo "qux" > foo/bar 187 cp foo/bar foo/zoo 188 189 atf_check ln -s foo roo 190 atf_check cp -RH roo foo 191 atf_check -o inline:"qux\n" cat foo/roo/bar 192 atf_check -o inline:"qux\n" cat foo/roo/zoo 193} 194 195atf_test_case matching_srctgt_nonexistent 196matching_srctgt_nonexistent_head() 197{ 198 atf_set "descr" "Avoid infinite loop when recursively copying a " \ 199 "directory into a new subdirectory of itself" 200} 201matching_srctgt_nonexistent_body() 202{ 203 # We'll copy foo to a nonexistent subdirectory; ideally, we would 204 # skip just the directory and end up with a layout like; 205 # 206 # foo/ 207 # bar 208 # dne/ 209 # bar 210 # zoo 211 # zoo 212 # 213 mkdir foo 214 echo "qux" > foo/bar 215 cp foo/bar foo/zoo 216 217 atf_check cp -R foo foo/dne 218 atf_check -o inline:"qux\n" cat foo/dne/bar 219 atf_check -o inline:"qux\n" cat foo/dne/zoo 220 atf_check -e not-empty -s not-exit:0 stat foo/dne/foo 221} 222 223atf_test_case pflag_acls 224pflag_acls_head() 225{ 226 atf_set "descr" "Verify that -p preserves access control lists" 227} 228pflag_acls_body() 229{ 230 mkdir dir 231 ln -s dir lnk 232 echo "hello" >dir/file 233 if ! setfacl -m g:staff:D::allow dir || 234 ! setfacl -m g:staff:d::allow dir/file ; then 235 atf_skip "file system does not support ACLs" 236 fi 237 atf_check -o match:"group:staff:-+D-+" getfacl dir 238 atf_check -o match:"group:staff:-+d-+" getfacl dir/file 239 # file-to-file copy without -p 240 atf_check cp dir/file dst1 241 atf_check -o not-match:"group:staff:-+d-+" getfacl dst1 242 # file-to-file copy with -p 243 atf_check cp -p dir/file dst2 244 atf_check -o match:"group:staff:-+d-+" getfacl dst2 245 # recursive copy without -p 246 atf_check cp -r dir dst3 247 atf_check -o not-match:"group:staff:-+D-+" getfacl dst3 248 atf_check -o not-match:"group:staff:-+d-+" getfacl dst3/file 249 # recursive copy with -p 250 atf_check cp -rp dir dst4 251 atf_check -o match:"group:staff:-+D-+" getfacl dst4 252 atf_check -o match:"group:staff:-+d-+" getfacl dst4/file 253 # source is a link without -p 254 atf_check cp -r lnk dst5 255 atf_check -o not-match:"group:staff:-+D-+" getfacl dst5 256 atf_check -o not-match:"group:staff:-+d-+" getfacl dst5/file 257 # source is a link with -p 258 atf_check cp -rp lnk dst6 259 atf_check -o match:"group:staff:-+D-+" getfacl dst6 260 atf_check -o match:"group:staff:-+d-+" getfacl dst6/file 261} 262 263atf_test_case pflag_flags 264pflag_flags_head() 265{ 266 atf_set "descr" "Verify that -p preserves file flags" 267} 268pflag_flags_body() 269{ 270 mkdir dir 271 ln -s dir lnk 272 echo "hello" >dir/file 273 if ! chflags nodump dir || 274 ! chflags nodump dir/file ; then 275 atf_skip "file system does not support flags" 276 fi 277 atf_check -o match:"nodump" stat -f%Sf dir 278 atf_check -o match:"nodump" stat -f%Sf dir/file 279 # file-to-file copy without -p 280 atf_check cp dir/file dst1 281 atf_check -o not-match:"nodump" stat -f%Sf dst1 282 # file-to-file copy with -p 283 atf_check cp -p dir/file dst2 284 atf_check -o match:"nodump" stat -f%Sf dst2 285 # recursive copy without -p 286 atf_check cp -r dir dst3 287 atf_check -o not-match:"nodump" stat -f%Sf dst3 288 atf_check -o not-match:"nodump" stat -f%Sf dst3/file 289 # recursive copy with -p 290 atf_check cp -rp dir dst4 291 atf_check -o match:"nodump" stat -f%Sf dst4 292 atf_check -o match:"nodump" stat -f%Sf dst4/file 293 # source is a link without -p 294 atf_check cp -r lnk dst5 295 atf_check -o not-match:"nodump" stat -f%Sf dst5 296 atf_check -o not-match:"nodump" stat -f%Sf dst5/file 297 # source is a link with -p 298 atf_check cp -rp lnk dst6 299 atf_check -o match:"nodump" stat -f%Sf dst6 300 atf_check -o match:"nodump" stat -f%Sf dst6/file 301} 302 303recursive_link_setup() 304{ 305 extra_cpflag=$1 306 307 mkdir -p foo/bar 308 ln -s bar foo/baz 309 310 mkdir foo-mirror 311 eval "cp -R $extra_cpflag foo foo-mirror" 312} 313 314atf_test_case recursive_link_dflt 315recursive_link_dflt_head() 316{ 317 atf_set "descr" "Copy a directory containing a subdirectory and a " \ 318 "symlink to that subdirectory" 319} 320recursive_link_dflt_body() 321{ 322 recursive_link_setup 323 324 # -P is the default, so this should work and preserve the link. 325 atf_check cp -R foo foo-mirror 326 atf_check test -L foo-mirror/foo/baz 327 atf_check test -d foo-mirror/foo/baz 328} 329 330atf_test_case recursive_link_Hflag 331recursive_link_Hflag_head() 332{ 333 atf_set "descr" "Copy a directory containing a subdirectory and a " \ 334 "symlink to that subdirectory" 335} 336recursive_link_Hflag_body() 337{ 338 recursive_link_setup 339 340 # -H will not follow either, so this should also work and preserve the 341 # link. 342 atf_check cp -RH foo foo-mirror 343 atf_check test -L foo-mirror/foo/baz 344 atf_check test -d foo-mirror/foo/baz 345} 346 347atf_test_case recursive_link_Lflag 348recursive_link_Lflag_head() 349{ 350 atf_set "descr" "Copy a directory containing a subdirectory and a " \ 351 "symlink to that subdirectory" 352} 353recursive_link_Lflag_body() 354{ 355 recursive_link_setup -L 356 357 # -L will work, but foo/baz ends up expanded to a directory. 358 atf_check test ! -L foo-mirror/foo/baz 359 atf_check test -d foo-mirror/foo/baz 360 atf_check cp -RL foo foo-mirror 361 atf_check test ! -L foo-mirror/foo/baz 362 atf_check test -d foo-mirror/foo/baz 363} 364 365atf_test_case samefile 366samefile_head() 367{ 368 atf_set "descr" "Copy a file to itself" 369} 370samefile_body() 371{ 372 echo "foo" >foo 373 ln foo bar 374 ln -s bar baz 375 atf_check -e match:"baz and baz are identical" \ 376 -s exit:1 cp baz baz 377 atf_check -e match:"bar and baz are identical" \ 378 -s exit:1 cp baz bar 379 atf_check -e match:"foo and baz are identical" \ 380 -s exit:1 cp baz foo 381 atf_check -e match:"bar and foo are identical" \ 382 -s exit:1 cp foo bar 383} 384 385file_is_sparse() 386{ 387 atf_check ${0%/*}/sparse "$1" 388} 389 390files_are_equal() 391{ 392 atf_check_not_equal "$(stat -f%d,%i "$1")" "$(stat -f%d,%i "$2")" 393 atf_check cmp "$1" "$2" 394} 395 396atf_test_case sparse_leading_hole 397sparse_leading_hole_head() 398{ 399 atf_set "descr" "Copy a sparse file stat starts with a hole" 400} 401sparse_leading_hole_body() 402{ 403 # A 16-megabyte hole followed by one megabyte of data 404 truncate -s 16M foo 405 seq -f%015g 65536 >>foo 406 file_is_sparse foo 407 408 atf_check cp foo bar 409 files_are_equal foo bar 410 file_is_sparse bar 411} 412 413atf_test_case sparse_multiple_holes 414sparse_multiple_hole_head() 415{ 416 atf_set "descr" "Copy a sparse file with multiple holes" 417} 418sparse_multiple_holes_body() 419{ 420 # Three one-megabyte blocks of data preceded, separated, and 421 # followed by 16-megabyte holes 422 truncate -s 16M foo 423 seq -f%015g 65536 >>foo 424 truncate -s 33M foo 425 seq -f%015g 65536 >>foo 426 truncate -s 50M foo 427 seq -f%015g 65536 >>foo 428 truncate -s 67M foo 429 file_is_sparse foo 430 431 atf_check cp foo bar 432 files_are_equal foo bar 433 file_is_sparse bar 434} 435 436atf_test_case sparse_only_hole 437sparse_only_hole_head() 438{ 439 atf_set "descr" "Copy a sparse file consisting entirely of a hole" 440} 441sparse_only_hole_body() 442{ 443 # A 16-megabyte hole 444 truncate -s 16M foo 445 file_is_sparse foo 446 447 atf_check cp foo bar 448 files_are_equal foo bar 449 file_is_sparse bar 450} 451 452atf_test_case sparse_to_dev 453sparse_to_dev_head() 454{ 455 atf_set "descr" "Copy a sparse file to a device" 456} 457sparse_to_dev_body() 458{ 459 # Three one-megabyte blocks of data preceded, separated, and 460 # followed by 16-megabyte holes 461 truncate -s 16M foo 462 seq -f%015g 65536 >>foo 463 truncate -s 33M foo 464 seq -f%015g 65536 >>foo 465 truncate -s 50M foo 466 seq -f%015g 65536 >>foo 467 truncate -s 67M foo 468 file_is_sparse foo 469 470 atf_check -o file:foo cp foo /dev/stdout 471} 472 473atf_test_case sparse_trailing_hole 474sparse_trailing_hole_head() 475{ 476 atf_set "descr" "Copy a sparse file that ends with a hole" 477} 478sparse_trailing_hole_body() 479{ 480 # One megabyte of data followed by a 16-megabyte hole 481 seq -f%015g 65536 >foo 482 truncate -s 17M foo 483 file_is_sparse foo 484 485 atf_check cp foo bar 486 files_are_equal foo bar 487 file_is_sparse bar 488} 489 490atf_test_case standalone_Pflag 491standalone_Pflag_head() 492{ 493 atf_set "descr" "Test -P without -R" 494} 495standalone_Pflag_body() 496{ 497 echo "foo" > bar 498 ln -s bar foo 499 500 atf_check cp -P foo baz 501 atf_check test -L baz 502} 503 504atf_test_case symlink 505symlink_head() 506{ 507 atf_set "descr" "Create a symbolic link to a file" 508} 509symlink_body() 510{ 511 echo "foo" >foo 512 atf_check cp -s foo bar 513 atf_check -o inline:"foo\n" cat bar 514 atf_check -o inline:"foo\n" readlink bar 515} 516 517atf_test_case symlink_exists 518symlink_exists_head() 519{ 520 atf_set "descr" "Attempt to create a symbolic link to a file, " \ 521 "but the destination already exists" 522} 523symlink_exists_body() 524{ 525 echo "foo" >foo 526 echo "bar" >bar 527 atf_check -s not-exit:0 -e match:exists cp -s foo bar 528 atf_check -o inline:"bar\n" cat bar 529} 530 531atf_test_case symlink_exists_force 532symlink_exists_force_head() 533{ 534 atf_set "descr" "Force creation of a symbolic link to a file " \ 535 "when the destination already exists" 536} 537symlink_exists_force_body() 538{ 539 echo "foo" >foo 540 echo "bar" >bar 541 atf_check cp -fs foo bar 542 atf_check -o inline:"foo\n" cat bar 543 atf_check -o inline:"foo\n" readlink bar 544} 545 546atf_test_case directory_to_symlink 547directory_to_symlink_head() 548{ 549 atf_set "descr" "Attempt to copy a directory to a symlink" 550} 551directory_to_symlink_body() 552{ 553 mkdir -p foo 554 ln -s .. foo/bar 555 mkdir bar 556 touch bar/baz 557 atf_check -s not-exit:0 -e match:"Not a directory" \ 558 cp -R bar foo 559 atf_check -s not-exit:0 -e match:"Not a directory" \ 560 cp -r bar foo 561} 562 563atf_test_case overwrite_directory 564overwrite_directory_head() 565{ 566 atf_set "descr" "Attempt to overwrite a directory with a file" 567} 568overwrite_directory_body() 569{ 570 mkdir -p foo/bar/baz 571 touch bar 572 atf_check -s not-exit:0 -e match:"Is a directory" \ 573 cp bar foo 574 rm bar 575 mkdir bar 576 touch bar/baz 577 atf_check -s not-exit:0 -e match:"Is a directory" \ 578 cp -R bar foo 579 atf_check -s not-exit:0 -e match:"Is a directory" \ 580 cp -r bar foo 581} 582 583atf_test_case to_dir_dne 584to_dir_dne_head() 585{ 586 atf_set "descr" "Copy a directory to a nonexistent directory" 587} 588to_dir_dne_body() 589{ 590 mkdir dir 591 echo "foo" >dir/foo 592 atf_check cp -r dir dne 593 atf_check test -d dne 594 atf_check test -f dne/foo 595 atf_check cmp dir/foo dne/foo 596} 597 598atf_test_case to_nondir 599to_dir_dne_head() 600{ 601 atf_set "descr" "Copy one or more files to a non-directory" 602} 603to_nondir_body() 604{ 605 echo "foo" >foo 606 echo "bar" >bar 607 echo "baz" >baz 608 # This is described as “case 1” in source code comments 609 atf_check cp foo bar 610 atf_check cmp -s foo bar 611 # This is “case 2”, the target must be a directory 612 atf_check -s not-exit:0 -e match:"Not a directory" \ 613 cp foo bar baz 614} 615 616atf_test_case to_deadlink 617to_deadlink_head() 618{ 619 atf_set "descr" "Copy a file to a dead symbolic link" 620} 621to_deadlink_body() 622{ 623 echo "foo" >foo 624 ln -s bar baz 625 atf_check cp foo baz 626 atf_check cmp -s foo bar 627} 628 629atf_test_case to_deadlink_append 630to_deadlink_append_head() 631{ 632 atf_set "descr" "Copy multiple files to a dead symbolic link" 633} 634to_deadlink_append_body() 635{ 636 echo "foo" >foo 637 mkdir bar 638 ln -s baz bar/foo 639 atf_check cp foo bar 640 atf_check cmp -s foo bar/baz 641 rm -f bar/foo bar/baz 642 ln -s baz bar/foo 643 atf_check cp foo bar/ 644 atf_check cmp -s foo bar/baz 645 rm -f bar/foo bar/baz 646 ln -s $PWD/baz bar/foo 647 atf_check cp foo bar/ 648 atf_check cmp -s foo baz 649} 650 651atf_test_case to_dirlink 652to_dirlink_head() 653{ 654 atf_set "descr" "Copy things to a symbolic link to a directory" 655} 656to_dirlink_body() 657{ 658 mkdir src dir 659 echo "foo" >src/file 660 ln -s dir dst 661 atf_check cp -r src dst 662 atf_check cmp -s src/file dir/src/file 663 rm -r dir/* 664 atf_check cp -r src dst/ 665 atf_check cmp -s src/file dir/src/file 666 rm -r dir/* 667 # If the source is a directory and ends in a slash, our cp has 668 # traditionally copied the contents of the source rather than 669 # the source itself. It is unclear whether this is intended 670 # or simply a consequence of how FTS handles the situation. 671 # Notably, GNU cp does not behave in this manner. 672 atf_check cp -r src/ dst 673 atf_check cmp -s src/file dir/file 674 rm -r dir/* 675 atf_check cp -r src/ dst/ 676 atf_check cmp -s src/file dir/file 677 rm -r dir/* 678} 679 680atf_test_case to_deaddirlink 681to_deaddirlink_head() 682{ 683 atf_set "descr" "Copy things to a symbolic link to a nonexistent " \ 684 "directory" 685} 686to_deaddirlink_body() 687{ 688 mkdir src 689 echo "foo" >src/file 690 ln -s dir dst 691 # It is unclear which error we should expect in these cases. 692 # Our current implementation always reports ENOTDIR, but one 693 # might be equally justified in expecting EEXIST or ENOENT. 694 # GNU cp reports EEXIST when the destination is given with a 695 # trailing slash and “cannot overwrite non-directory with 696 # directory” otherwise. 697 atf_check -s not-exit:0 -e ignore \ 698 cp -r src dst 699 atf_check -s not-exit:0 -e ignore \ 700 cp -r src dst/ 701 atf_check -s not-exit:0 -e ignore \ 702 cp -r src/ dst 703 atf_check -s not-exit:0 -e ignore \ 704 cp -r src/ dst/ 705 atf_check -s not-exit:0 -e ignore \ 706 cp -R src dst 707 atf_check -s not-exit:0 -e ignore \ 708 cp -R src dst/ 709 atf_check -s not-exit:0 -e ignore \ 710 cp -R src/ dst 711 atf_check -s not-exit:0 -e ignore \ 712 cp -R src/ dst/ 713} 714 715atf_test_case to_link_outside 716to_link_outside_head() 717{ 718 atf_set "descr" "Recursively copy a directory containing a symbolic " \ 719 "link that points to somewhere outside the source directory" 720} 721to_link_outside_body() 722{ 723 mkdir dir dst dst/dir 724 echo "foo" >dir/file 725 ln -s ../../file dst/dir/file 726 atf_check \ 727 -s exit:1 \ 728 -e match:"dst/dir/file: Permission denied" \ 729 cp -r dir dst 730} 731 732atf_test_case dstmode 733dstmode_head() 734{ 735 atf_set "descr" "Verify that directories are created with the " \ 736 "correct permissions" 737} 738dstmode_body() 739{ 740 mkdir -m 0755 dir 741 echo "foo" >dir/file 742 umask 0177 743 atf_check cp -R dir dst 744 umask 022 745 atf_check -o inline:"40600\n" stat -f%p dst 746 atf_check chmod 0750 dst 747 atf_check cmp dir/file dst/file 748} 749 750atf_test_case to_root cleanup 751to_root_head() 752{ 753 atf_set "require.user" "unprivileged" 754} 755to_root_body() 756{ 757 dst="test.$(atf_get ident).$$" 758 echo "$dst" >dst 759 echo "foo" >"$dst" 760 atf_check -s not-exit:0 \ 761 -e match:"^cp: /$dst: (Permission|Read-only)" \ 762 cp "$dst" / 763 atf_check -s not-exit:0 \ 764 -e match:"^cp: /$dst: (Permission|Read-only)" \ 765 cp "$dst" // 766} 767to_root_cleanup() 768{ 769 (dst=$(cat dst) && rm "/$dst") 2>/dev/null || true 770} 771 772atf_test_case dirloop 773dirloop_head() 774{ 775 atf_set "descr" "Test cycle detection when recursing" 776} 777dirloop_body() 778{ 779 mkdir -p src/a src/b 780 ln -s ../b src/a 781 ln -s ../a src/b 782 atf_check \ 783 -s exit:1 \ 784 -e match:"src/a/b/a: directory causes a cycle" \ 785 -e match:"src/b/a/b: directory causes a cycle" \ 786 cp -r src dst 787 atf_check test -d dst 788 atf_check test -d dst/a 789 atf_check test -d dst/b 790 atf_check test -d dst/a/b 791 atf_check test ! -e dst/a/b/a 792 atf_check test -d dst/b/a 793 atf_check test ! -e dst/b/a/b 794} 795 796atf_test_case unrdir 797unrdir_head() 798{ 799 atf_set "descr" "Test handling of unreadable directories" 800 atf_set "require.user" "unprivileged" 801} 802unrdir_body() 803{ 804 for d in a b c ; do 805 mkdir -p src/$d 806 echo "$d" >src/$d/f 807 done 808 chmod 0 src/b 809 atf_check \ 810 -s exit:1 \ 811 -e match:"^cp: src/b: Permission denied" \ 812 cp -R --sort src dst 813 atf_check test -d dst/a 814 atf_check cmp src/a/f dst/a/f 815 atf_check test -d dst/b 816 atf_check test ! -e dst/b/f 817 atf_check test -d dst/c 818 atf_check cmp src/c/f dst/c/f 819} 820 821atf_test_case unrfile 822unrfile_head() 823{ 824 atf_set "descr" "Test handling of unreadable files" 825 atf_set "require.user" "unprivileged" 826} 827unrfile_body() 828{ 829 mkdir src 830 for d in a b c ; do 831 echo "$d" >src/$d 832 done 833 chmod 0 src/b 834 atf_check \ 835 -s exit:1 \ 836 -e match:"^cp: src/b: Permission denied" \ 837 cp -R --sort src dst 838 atf_check test -d dst 839 atf_check cmp src/a dst/a 840 atf_check test ! -e dst/b 841 atf_check cmp src/c dst/c 842} 843 844atf_test_case nopermute 845nopermute_head() 846{ 847 atf_set descr "Check that getopt_long does not permute options" 848} 849nopermute_body() 850{ 851 mkdir src dst 852 atf_check \ 853 -s exit:1 \ 854 -e match:'cp: -p: No such file' \ 855 cp -R src -p dst 856 atf_check test -d dst/src 857} 858 859atf_init_test_cases() 860{ 861 atf_add_test_case basic 862 atf_add_test_case basic_symlink 863 atf_add_test_case chrdev 864 atf_add_test_case hardlink 865 atf_add_test_case hardlink_exists 866 atf_add_test_case hardlink_exists_force 867 atf_add_test_case matching_srctgt 868 atf_add_test_case matching_srctgt_contained 869 atf_add_test_case matching_srctgt_link 870 atf_add_test_case matching_srctgt_nonexistent 871 atf_add_test_case pflag_acls 872 atf_add_test_case pflag_flags 873 atf_add_test_case recursive_link_dflt 874 atf_add_test_case recursive_link_Hflag 875 atf_add_test_case recursive_link_Lflag 876 atf_add_test_case samefile 877 atf_add_test_case sparse_leading_hole 878 atf_add_test_case sparse_multiple_holes 879 atf_add_test_case sparse_only_hole 880 atf_add_test_case sparse_to_dev 881 atf_add_test_case sparse_trailing_hole 882 atf_add_test_case standalone_Pflag 883 atf_add_test_case symlink 884 atf_add_test_case symlink_exists 885 atf_add_test_case symlink_exists_force 886 atf_add_test_case directory_to_symlink 887 atf_add_test_case overwrite_directory 888 atf_add_test_case to_dir_dne 889 atf_add_test_case to_nondir 890 atf_add_test_case to_deadlink 891 atf_add_test_case to_deadlink_append 892 atf_add_test_case to_dirlink 893 atf_add_test_case to_deaddirlink 894 atf_add_test_case to_link_outside 895 atf_add_test_case dstmode 896 atf_add_test_case to_root 897 atf_add_test_case dirloop 898 atf_add_test_case unrdir 899 atf_add_test_case unrfile 900 atf_add_test_case nopermute 901} 902