1#!/usr/bin/ksh 2# 3# This file and its contents are supplied under the terms of the 4# Common Development and Distribution License ("CDDL"), version 1.0. 5# You may only use this file in accordance with the terms of version 6# 1.0 of the CDDL. 7# 8# A full copy of the text of the CDDL should have accompanied this 9# source. A copy of the CDDL is also available via the Internet at 10# http://www.illumos.org/license/CDDL. 11# 12 13# 14# Copyright 2024 Oxide Computer Company 15# 16 17# 18# This test exercises the various overwriting, interactivity, and related 19# features of cp, mv, and ln (which are all built from the same source). Each 20# program may be set up to operate interactively (-i), to not touch a file if it 21# already exists (-n), and to forcefully remove it anyways (-f). cp implements 22# -i and -n, -f means something different. mv implements all three flags. ln 23# implements -i and -f (-n is a pseudo-default). 24# 25 26unalias -a 27set -o pipefail 28export LANG=C.UTF-8 29 30# 31# Program paths for interposing while testing. 32# 33MV=${MV:-"/usr/bin/mv"} 34XMV=${XMV:-"/usr/xpg4/bin/mv"} 35CP=${CP:-"/usr/bin/cp"} 36XCP=${XCP:-"/usr/xpg4/bin/cp"} 37LN=${LN:-"/usr/bin/ln"} 38XLN=${XLN:-"/usr/xpg4/bin/ln"} 39 40ovr_exit=0 41ovr_arg0=$(basename $0) 42ovr_tdir=$(dirname $0) 43ovr_mkobj="$ovr_tdir/mkobj" 44ovr_check="$ovr_tdir/checker" 45ovr_work="/tmp/$ovr_arg0.$$" 46 47typeset -A ovr_files=( 48 ["a"]=(type="file" path="$ovr_work/a") 49 ["b"]=(type="file" path="$ovr_work/b") 50 ["c"]=(type="noperms" path="$ovr_work/c") 51 ["fifo"]=(type="fifo" path="$ovr_work/fifo") 52 ["door"]=(type="door" path="$ovr_work/door") 53 ["uds"]=(type="uds" path="$ovr_work/uds") 54 ["symlink"]=(type="symlink" path="$ovr_work/symlink") 55 ["dangle"]=(type="dangle" path="$ovr_work/dangle") 56 ["dir"]=(type="dir" path="$ovr_work/dir") 57 ["dir/a"]=(type="file-dm" path="$ovr_work/dir/a") 58 ["dir/b"]=(type="empty" path="$ovr_work/dir/b") 59 ["dir/c"]=(type="noperms-dm" path="$ovr_work/dir/c") 60 ["dir/fifo"]=(type="fifo-dm" path="$ovr_work/dir/fifo") 61 ["dir/door"]=(type="door-dm" path="$ovr_work/dir/door") 62 ["dir/uds"]=(type="uds-dm" path="$ovr_work/dir/uds") 63 ["dir/symlink"]=(type="symlink-dm" path="$ovr_work/dir/symlink") 64 ["dir/dangle"]=(type="dangle-dm" path="$ovr_work/dir/dangle") 65) 66 67function fatal 68{ 69 typeset msg="$*" 70 echo "TEST FAILED: $msg" >&2 71 exit 1 72} 73 74function warn 75{ 76 typeset msg="$*" 77 echo "TEST FAILED: $msg" >&2 78 ovr_exit=1 79} 80 81function cleanup 82{ 83 rm -rf $ovr_work/ 84} 85 86# 87# Make the files that are required for this particular test. 88# 89function setup_files 90{ 91 mkdir "$ovr_work" || fatal "failed to make test directory" 92 for f in $@; do 93 typeset targ=${ovr_files[$f].path} 94 typeset ftype=${ovr_files[$f].type} 95 case $ftype in 96 file) 97 echo $f > $targ || fatal "failed to create $f" 98 ;; 99 empty) 100 touch $targ || fatal "failed to create $f" 101 ;; 102 noperms) 103 echo $f > $targ || fatal "failed to create $f" 104 chmod 0000 $targ || fatal "failed to chmod $f" 105 ;; 106 fifo) 107 $ovr_mkobj -f $targ || fatal "failed to make fifo" 108 ;; 109 door) 110 $ovr_mkobj -d $targ || fatal "failed to make door" 111 ;; 112 uds) 113 $ovr_mkobj -s $targ || fatal "failed to make uds" 114 ;; 115 symlink) 116 ln -s ${ovr_files["b"].path} $targ || \ 117 fatal "failed to make symlink" 118 ;; 119 dangle) 120 ln -s "$ovr_work/enoent" $targ || \ 121 fatal "failed to make dangling symlink" 122 ;; 123 dir) 124 mkdir -p $targ || fatal "failed to make directory" 125 ;; 126 *) 127 fatal "encountered unknown type $f: $ftype" 128 esac 129 done 130} 131 132# 133# Check files remain what we expect at this point. Arguments passed should be 134# the short form. 135# 136function check_files 137{ 138 typeset desc=$1 139 shift 140 for f in $@; do 141 typeset targ=${ovr_files[$f].path} 142 typeset ftype=${ovr_files[$f].type} 143 typeset data= 144 case $ftype in 145 file*) 146 # 147 # A file should have the data that matches its short 148 # name inside of it. 149 # 150 typeset exp=${f##*/} 151 data=$(cat $targ) 152 if [[ $data != $exp ]]; then 153 warn "$desc: found unexpected file data $data" \ 154 "expected $exp" 155 return 1 156 fi 157 ;; 158 noperms*) 159 if ! $ovr_check -n $targ; then 160 warn "$desc: $targ was clobbered" 161 return 1 162 fi 163 ;; 164 fifo*) 165 if [[ ! -p $targ ]]; then 166 warn "$desc: $targ was is somehow no longer" \ 167 "a pipe: $(ls -l $targ)" 168 return 1 169 fi 170 ;; 171 door*) 172 if ! $ovr_check -d $targ; then 173 warn "$desc: $targ was clobbered" 174 return 1 175 fi 176 ;; 177 uds*) 178 if [[ ! -S $targ ]]; then 179 warn "$desc: $targ was is somehow no longer" \ 180 "a socket: $(ls -l $targ)" 181 return 1 182 fi 183 ;; 184 symlink*|dangle*) 185 if [[ ! -L $targ ]]; then 186 warn "$desc: $targ was is somehow no longer" \ 187 "a symlink: $(ls -l $targ)" 188 return 1 189 fi 190 ;; 191 dir) 192 if [[ ! -d $targ ]]; then 193 warn "$desc: directory $targ was removed?!" 194 return 1 195 fi 196 ;; 197 *) 198 fatal "encountered unknown type $f: $ftype" 199 esac 200 done 201 202 return 0 203} 204 205function check_data 206{ 207 typeset desc=$1 208 typeset targ=$2 209 typeset expect=$3 210 typeset data= 211 212 data=$(cat $targ) 213 if [[ $data != $expect ]]; then 214 warn "$desc: $targ wasn't overwritten found $data" 215 return 1; 216 fi 217 218 return 0 219} 220 221# 222# Run a test we expect to fail and verify that files haven't changed. 223# 224function exp_fail 225{ 226 typeset desc="$1" 227 typeset prog="$2" 228 typeset files="$3" 229 typeset -a args 230 231 setup_files $files 232 for f in $files; do 233 args+=(${ovr_files[$f].path}) 234 done 235 236 if $prog ${args[@]} 2>/dev/null; then 237 warn "$desc: command returned 0, but expected failure" 238 cleanup 239 return 240 fi 241 242 check_files "$desc" "$files" && printf "TEST PASSED: %s\n" "$desc" 243 cleanup 244} 245 246# 247# Run a test where we want to check a particular file's contents after the test 248# passes. The optional last pipe argument is used for testing interactive mode 249# (whether or not a prompt appears is a different question). Interactive mode 250# requires we don't have pipefail turned on to avoid propagating an error when 251# the initial program gets EPIPE or a signal. 252# 253function exp_pass 254{ 255 typeset desc="$1" 256 typeset prog="$2" 257 typeset files="$3" 258 typeset expect="$4" 259 typeset pipe="$5" 260 typeset ret= 261 typeset -a args 262 263 setup_files $files 264 for f in $files; do 265 args+=(${ovr_files[$f].path}) 266 done 267 268 if [[ -z "$pipe" ]]; then 269 $prog ${args[@]} 270 ret=$? 271 else 272 set +o pipefail 273 $pipe | $prog ${args[@]} 2>/dev/null 274 ret=$? 275 set -o pipefail 276 fi 277 278 if (( ret != 0 )); then 279 warn "$desc: command failed, but expected success" 280 cleanup 281 return 282 fi 283 284 check_data "$desc" "${args[-1]}" "$expect" && \ 285 printf "TEST PASSED: %s\n" "$desc" 286 cleanup 287} 288 289# 290# Variant on exp_pass that expects all the input files to remain the same. 291# 292function exp_retain 293{ 294 typeset desc="$1" 295 typeset prog="$2" 296 typeset files="$3" 297 typeset -a args 298 299 setup_files $files 300 for f in $files; do 301 args+=(${ovr_files[$f].path}) 302 done 303 304 if ! $prog ${args[@]}; then 305 warn "$desc: command failed, but expected success" 306 cleanup 307 return 308 fi 309 310 if check_files "$desc" "$files"; then 311 printf "TEST PASSED: %s\n" "$desc" 312 fi 313 cleanup 314} 315 316# 317# Tests for a directory. We always set up the files in the directory in addition 318# to what was asked for. Then based on our expectations we make sure that the 319# files were created that we expect. All tests in here should succeed. 320# 321function exp_dir 322{ 323 typeset desc="$1" 324 typeset prog="$2" 325 typeset files="$3" 326 typeset rval="$4" 327 typeset exp="$5" 328 typeset bdata="$6" 329 typeset pipe="$7" 330 typeset pass=0 331 typeset -a args 332 333 setup_files $files dir dir/b 334 for f in $files; do 335 args+=(${ovr_files[$f].path}) 336 done 337 338 if [[ -z "$pipe" ]]; then 339 $prog ${args[@]} 2>/dev/null 340 ret=$? 341 else 342 set +o pipefail 343 $pipe | $prog ${args[@]} 2>/dev/null 344 ret=$? 345 set -o pipefail 346 fi 347 348 if (( ret != rval )); then 349 warn "$desc: command returned $ret, but expected $rval" 350 cleanup 351 return 352 fi 353 354 if (( ret != 0 )); then 355 cleanup 356 return; 357 fi 358 359 check_files "$desc" $exp || pass=1 360 check_data "$desc" "${ovr_files[dir/b].path}" "$bdata" || pass=1 361 (( pass == 0 )) && printf "TEST PASSED: %s\n" "$desc" 362 cleanup 363} 364 365trap cleanup EXIT 366 367# 368# Start with ln which should fail without -f. Same with ln -s (a different code 369# path). 370# 371exp_fail "ln doesn't clobber a file (ln a b)" "$LN" "a b" 372exp_fail "ln doesn't clobber a file without perms (ln a c)" "$LN" "a c" 373exp_fail "ln doesn't clobber a uds (ln a uds)" "$LN" "a uds" 374exp_fail "ln doesn't clobber a fifo (ln a fifo)" "$LN" "a fifo" 375exp_fail "ln doesn't clobber a door (ln a door)" "$LN" "a door" 376exp_fail "ln doesn't clobber a valid symlink (ln a symlink)" "$LN" "a symlink" 377exp_fail "ln doesn't clobber a dangling symlink (ln a dangle)" "$LN" "a dangle" 378 379exp_fail "ln -s doesn't clobber a file (ln -s a b)" "$LN -s" "a b" 380exp_fail "ln -s doesn't clobber a file without perms (ln -s a c)" "$LN -s" "a c" 381exp_fail "ln -s doesn't clobber a uds (ln -s a uds)" "$LN -s" "a uds" 382exp_fail "ln -s doesn't clobber a fifo (ln -s a fifo)" "$LN -s" "a fifo" 383exp_fail "ln -s doesn't clobber a door (ln -s a door)" "$LN -s" "a door" 384exp_fail "ln -s doesn't clobber a valid symlink (ln -s a symlink)" "$LN -s" \ 385 "a symlink" 386exp_fail "ln -s doesn't clobber a dangling symlink (ln -s a dangle)" "$LN -s" \ 387 "a dangle" 388 389# 390# Now basic cp tests. We expect cp to fail on most of these because it doesn't 391# have -f specified and therefore can't open the file without permissions or 392# replace and deal with the socket and door. We don't use the fifo because it 393# will basically just cause us to block. 394# 395exp_pass "cp works on a file (cp a b)" "$CP" "a b" "a" 396exp_pass "XPG cp works on a file (cp a b)" "$XCP" "a b" "a" 397exp_fail "cp fails on a file without perms (cp a c)" "$CP" "a c" 398exp_fail "XPG cp fails on a file without perms (cp a c)" "$XCP" "a c" 399exp_fail "cp fails on a uds (cp a sock)" "$CP" "a uds" 400exp_fail "cp fails on a door (cp a door)" "$CP" "a door" 401exp_pass "cp works on a symlink (cp a symlink)" "$CP" "a symlink" "a" 402exp_pass "cp works on a dangling symlink (cp a dangle)" "$CP" "a dangle" "a" 403 404# 405# Basic mv tests. We expect mv to work on most things, but the door is a bit 406# complicated because rename will fail with EBUSY, but that depends on the file 407# system unfortunately (seems to fail on ZFS but work on tmpfs). 408# 409exp_pass "mv works on a file (mv a b)" "$MV" "a b" "a" 410exp_pass "mv works on a fifo (mv a fifo)" "$MV" "a fifo" "a" 411exp_pass "mv works on a uds (mv a sock)" "$MV" "a uds" "a" 412exp_pass "mv works on a symlink (mv a symlink)" "$MV" "a symlink" "a" 413exp_pass "mv works on a dangling symlink (mv a dangle)" "$MV" "a dangle" "a" 414 415# 416# Now we go into -f versions and cases where -f trumps -i. This should cause 417# everything to work for ln. For cp, the fifo and door will not work because it 418# will not remove them. We don't test the fifo due to hangs. For mv we expect 419# everything expect the door (which we skip) to work. 420# 421exp_pass "ln -f clobbers a file (ln -f a b)" "$LN -f" "a b" "a" 422exp_pass "ln -f clobbers a file without perms (ln -f a c)" "$LN -f" "a c" "a" 423exp_pass "ln -f clobbers a uds (ln -f a uds)" "$LN -f" "a uds" "a" 424exp_pass "ln -f clobbers a fifo (ln -f a fifo)" "$LN -f" "a fifo" "a" 425exp_pass "ln -f clobbers a door (ln -f a door)" "$LN -f" "a door" "a" 426exp_pass "ln -f clobbers a valid symlink (ln -f a symlink)" "$LN -f" \ 427 "a symlink" "a" 428exp_pass "ln -f clobber a dangling symlink (ln -f a dangle)" "$LN -f" \ 429 "a dangle" "a" 430exp_pass "ln -f beats -i on a file (ln -if a b)" "$LN -if" "a b" "a" 431exp_pass "ln -f beats -i on a file (ln -ifif a b)" "$LN -ifif" "a b" "a" 432 433exp_pass "ln -sf clobbers a file (ln -sf a b)" "$LN -sf" "a b" "a" 434exp_pass "ln -sf clobbers a file without perms (ln -sf a c)" "$LN -sf" "a c" "a" 435exp_pass "ln -sf clobbers a uds (ln -sf a uds)" "$LN -sf" "a uds" "a" 436exp_pass "ln -sf clobbers a fifo (ln -sf a fifo)" "$LN -sf" "a fifo" "a" 437exp_pass "ln -sf clobbers a door (ln -sf a door)" "$LN -sf" "a door" "a" 438exp_pass "ln -sf clobbers a valid symlink (ln -sf a symlink)" "$LN -sf" \ 439 "a symlink" "a" 440exp_pass "ln -sf clobber a dangling symlink (ln -sf a dangle)" "$LN -sf" \ 441 "a dangle" "a" 442exp_pass "ln -sf beats -i on a file (ln -s -if a b)" "$LN -s -if" "a b" "a" 443exp_pass "ln -sf beats -i on a file (ln -s -ifif a b)" "$LN -s -ifif" "a b" "a" 444 445 446exp_pass "cp -f clobbers a file (cp -f a b)" "$CP -f" "a b" "a" 447exp_pass "cp -f clobbers a file without perms (cp -f a c)" "$CP -f" "a c" "a" 448exp_pass "cp -f clobbers a uds (cp -f a uds)" "$CP -f" "a uds" "a" 449exp_fail "cp -f leaves a door alone (cp -f a door)" "$CP -f" "a door" "a" 450exp_pass "cp -f clobbers a valid symlink (cp -f a symlink)" "$CP -f" \ 451 "a symlink" "a" 452exp_pass "cp -f clobber a dangling symlink (cp -f a dangle)" "$CP -f" \ 453 "a dangle" "a" 454 455exp_pass "mv -f clobbers a file (mv -f a b)" "$MV -f" "a b" "a" 456exp_pass "mv -f clobbers a file without perms (mv -f a c)" "$MV -f" "a c" "a" 457exp_pass "mv -f clobbers a uds (mv -f a uds)" "$MV -f" "a uds" "a" 458exp_pass "mv -f clobbers a fifo (mv -f a fifo)" "$MV -f" "a fifo" "a" 459exp_pass "mv -f clobbers a valid symlink (mv -f a symlink)" "$MV -f" \ 460 "a symlink" "a" 461exp_pass "mv -f clobber a dangling symlink (mv -f a dangle)" "$MV -f" \ 462 "a dangle" "a" 463 464# 465# Now cp and mv -n tests. These should leave the target file as is, but pass. 466# 467exp_retain "cp -n doesn't clobber a file (cp -n a b)" "$CP -n" "a b" 468exp_retain "cp -n doesn't clobber a file without perms (cp -n a c)" "$CP -n" \ 469 "a c" 470exp_retain "cp -n doesn't clobber a uds (cp -n a uds)" "$CP -n" "a uds" 471exp_retain "cp -n doesn't clobber a fifo (cp -n a fifo)" "$CP -n" "a fifo" 472exp_retain "cp -n doesn't clobber a door (cp -n a door)" "$CP -n" "a door" 473exp_retain "cp -n doesn't clobber a valid symlink (cp -n a symlink)" "$CP -n" \ 474 "a symlink" 475exp_retain "cp -n doesn't clobber a dangling symlink (cp -n a dangle)" \ 476 "$CP -n" "a dangle" 477 478exp_retain "mv -n doesn't clobber a file (mv -n a b)" "$MV -n" "a b" 479exp_retain "mv -n doesn't clobber a file without perms (mv -n a c)" "$MV -n" \ 480 "a c" 481exp_retain "mv -n doesn't clobber a uds (mv -n a uds)" "$MV -n" "a uds" 482exp_retain "mv -n doesn't clobber a fifo (mv -n a fifo)" "$MV -n" "a fifo" 483exp_retain "mv -n doesn't clobber a door (mv -n a door)" "$MV -n" "a door" 484exp_retain "mv -n doesn't clobber a valid symlink (mv -n a symlink)" "$MV -n" \ 485 "a symlink" 486exp_retain "mv -n doesn't clobber a dangling symlink (mv -n a dangle)" \ 487 "$MV -n" "a dangle" 488 489# 490# -n, -f, and -i interleaving. None of these should cause prompts. non-XPG mv -f 491# will trump -i anywhere. XPG mv -i working normally is tested later on. 492# 493exp_retain "cp -n always beats -f (cp -nf a b)" "$CP -nf" "a b" 494exp_retain "cp -n always beats -f (cp -fn a b)" "$CP -fn" "a b" 495exp_retain "cp last -n wins (cp -in a b)" "$CP -in" "a b" 496exp_retain "cp last -n wins (cp -nin a b)" "$CP -nin" "a b" 497 498exp_retain "mv last -n wins (mv -in a b)" "$MV -in" "a b" 499exp_retain "mv last -n wins (mv -fn a b)" "$MV -fn" "a b" 500exp_retain "mv last -n wins (mv -ifn a b)" "$MV -ifn" "a b" 501exp_retain "mv last -n wins (mv -fifn a b)" "$MV -fifn" "a b" 502exp_pass "mv last -f wins (mv -nf a b)" "$MV -nf" "a b" "a" 503exp_pass "mv last -f wins (mv -if a b)" "$MV -if" "a b" "a" 504exp_pass "mv last -f wins (mv -fif a b)" "$MV -fif" "a b" "a" 505exp_pass "mv last -f wins (mv -nif a b)" "$MV -nif" "a b" "a" 506exp_pass "mv -f always beats -i (non-xpg) (mv -fi a b)" "$MV -fi" "a b" "a" 507exp_retain "XPG4 mv last -n wins (mv -in a b)" "$XMV -in" "a b" 508exp_retain "XPG4 mv last -n wins (mv -fn a b)" "$XMV -fn" "a b" 509exp_retain "XPG4 mv last -n wins (mv -ifn a b)" "$XMV -ifn" "a b" 510exp_retain "XPG4 mv last -n wins (mv -fifn a b)" "$XMV -fifn" "a b" 511exp_pass "XPG4 mv last -f wins (mv -nf a b)" "$XMV -nf" "a b" "a" 512exp_pass "XPG4 mv last -f wins (mv -if a b)" "$XMV -if" "a b" "a" 513exp_pass "XPG4 mv last -f wins (mv -fif a b)" "$XMV -fif" "a b" "a" 514exp_pass "XPG4 mv last -f wins (mv -nif a b)" "$XMV -nif" "a b" "a" 515 516 517# 518# Now onto interactive tests. Interactivity is a bit challenging. If stdin is 519# not a tty then a prompt will not appear if we're not in the XPG variant. This 520# means that it'll fall back to the program default (generally speaking to 521# overwrite). 522# 523exp_pass "XPG4 cp -i no normal file (cp -i a b)" "$XCP -i" "a b" "b" \ 524 "cat /dev/zero" 525exp_pass "XPG4 cp -i yes normal file (cp -i a b)" "$XCP -i" "a b" "a" "yes" 526exp_pass "cp -i clobbers normal file regardless (cp -i a b)" "$CP -i" "a b" \ 527 "a" "cat /dev/zero" 528 529exp_pass "XPG4 mv -i no normal file (mv -i a b)" "$XMV -i" "a b" "b" \ 530 "cat /dev/zero" 531exp_pass "XPG4 mv -i yes normal file (mv -i a b)" "$XMV -i" "a b" "a" "yes" 532exp_pass "mv -i clobbers normal file regardless (mv -i a b)" "$MV -i" "a b" \ 533 "a" "cat /dev/zero" 534 535exp_pass "XPG4 ln -i no normal file (ln -i a b)" "$XLN -i" "a b" "b" \ 536 "cat /dev/zero" 537exp_pass "XPG4 ln -i yes normal file (ln -i a b)" "$XLN -i" "a b" "a" "yes" 538exp_pass "ln -i clobbers normal file regardless (ln -i a b)" "$LN -i" "a b" \ 539 "a" "cat /dev/zero" 540 541exp_pass "XPG4 cp -i yes beats -n normal file (cp -ni a b)" "$XCP -ni" "a b" \ 542 "a" "yes" 543exp_pass "cp -i beats -n (cp -ni a b)" "$CP -ni" "a b" "a" "cat /dev/zero" 544 545exp_pass "XPG4 mv -i beats -n (mv -ni a b)" "$XMV -ni" "a b" "a" "yes" 546exp_pass "mv -i beats -n (mv -ni a b)" "$MV -ni" "a b" "a" "cat /dev/zero" 547exp_pass "XPG4 mv -i beats -f (mv -fi a b)" "$XMV -fi" "a b" "a" "yes" 548 549exp_pass "XPG4 ln -fi no normal file (ln -fi a b)" "$XLN -fi" "a b" "b" \ 550 "cat /dev/zero" 551exp_pass "XPG4 ln -fi yes normal file (ln -fi a b)" "$XLN -fi" "a b" "a" "yes" 552exp_pass "ln -fi clobbers normal file regardless (ln -fi a b)" "$LN -fi" \ 553 "a b" "a" "cat /dev/zero" 554 555exp_pass "XPG4 ln -sfi no normal file (ln -sfi a b)" "$XLN -sfi" "a b" "b" \ 556 "cat /dev/zero" 557exp_pass "XPG4 ln -sfi yes normal file (ln -sfi a b)" "$XLN -sfi" "a b" "a" \ 558 "yes" 559exp_pass "ln -sfi clobbers normal file regardless (ln -sfi a b)" "$LN -sfi" \ 560 "a b" "a" "cat /dev/zero" 561 562# 563# Now our last bit here is to do tests that operate on multiple files into a 564# directory and make sure that they end up as expected. 565# 566exp_dir "cp multi-file" "$CP" "a b dir" 0 "dir/a" "b" 567exp_fail "cp multi-file with socket fails" "$CP" "a b uds dir" 568exp_fail "cp multi-file with noperms fails" "$CP" "a b c dir" 569exp_dir "cp multi-file -n" "$CP -n" "a b dir" 0 "dir/a" "" 570exp_dir "XPG4 cp multi-file -i yes" "$XCP -i" "a b dir" 0 "dir/a" "b" "yes" 571exp_dir "XPG4 cp multi-file -i no" "$XCP -i" "a b dir" 0 "dir/a" "" \ 572 "cat /dev/zero" 573exp_dir "cp multi-file -i clobbers anyways" "$CP -i" "a b dir" 0 "dir/a" "b" \ 574 "cat /dev/zero" 575 576exp_dir "ln multi-file" "$LN" "a b dir" 2 577exp_fail "ln multi-file with door fails" "$LN" "a door dir" 578exp_dir "ln multi-file with socket works" "$LN" "a uds dir" 0 "dir/a dir/uds" "" 579exp_dir "ln multi-file with noperms works" "$LN" "a c dir" 0 "dir/a dir/c" "" 580exp_dir "ln multi-file -f" "$LN -f" "a b dir" 0 "dir/a" "b" 581exp_dir "XPG4 ln multi-file -i yes" "$XLN -i" "a b dir" 0 "dir/a" "b" "yes" 582exp_dir "XPG4 ln multi-file -i no" "$XLN -i" "a b dir" 0 "dir/a" "" \ 583 "cat /dev/zero" 584exp_dir "ln multi-file -i clobbers anyways" "$LN -i" "a b dir" 0 "dir/a" "b" \ 585 "cat /dev/zero" 586 587exp_dir "ln -s multi-file" "$LN -s" "a b dir" 2 588exp_dir "ln -s multi-file with door works" "$LN -s" "a door dir" 0 589exp_dir "ln -s multi-file with socket works" "$LN -s" "a uds dir" 0 \ 590 "dir/a dir/uds" "" 591exp_dir "ln -s multi-file with noperms works" "$LN -s" "a c dir" 0 \ 592 "dir/a dir/c" "" 593exp_dir "ln -s multi-file -f" "$LN -s -f" "a b dir" 0 "dir/a" "b" 594exp_dir "XPG4 ln -s multi-file -i yes" "$XLN -s -i" "a b dir" 0 "dir/a" "b" \ 595 "yes" 596exp_dir "XPG4 ln -s multi-file -i no" "$XLN -s -i" "a b dir" 0 "dir/a" "" \ 597 "cat /dev/zero" 598exp_dir "ln -s multi-file -i clobbers anyways" "$LN -s -i" "a b dir" 0 "dir/a" \ 599 "b" "cat /dev/zero" 600 601exp_dir "mv multi-file" "$MV" "a b c fifo door uds symlink dangle dir" 0 \ 602 "dir/a dir/c dir/fifo dir/door dir/uds dir/symlink dir/dangle" "b" 603exp_dir "mv -n multi-file" "$MV -n" "a b c fifo door uds symlink dangle dir" 0 \ 604 "dir/a dir/c dir/fifo dir/door dir/uds dir/symlink dir/dangle" "" 605exp_dir "mv -f multi-file" "$MV -f" "a b c fifo door uds symlink dangle dir" 0 \ 606 "dir/a dir/c dir/fifo dir/door dir/uds dir/symlink dir/dangle" "b" 607exp_dir "mv -i multi-file clobbers" "$MV -i" \ 608 "a b c fifo door uds symlink dangle dir" 0 \ 609 "dir/a dir/c dir/fifo dir/door dir/uds dir/symlink dir/dangle" "b" \ 610 "cat /dev/null" 611exp_dir "XPG4 mv -i multi-file no" "$XMV -i" \ 612 "a b c fifo door uds symlink dangle dir" 0 \ 613 "dir/a dir/c dir/fifo dir/door dir/uds dir/symlink dir/dangle" "" \ 614 "cat /dev/null" 615exp_dir "XPG4 mv -i multi-file yes" "$XMV -i" \ 616 "a b c fifo door uds symlink dangle dir" 0 \ 617 "dir/a dir/c dir/fifo dir/door dir/uds dir/symlink dir/dangle" "b" "yes" 618 619if (( ovr_exit == 0 )); then 620 printf "All tests passed successfully\n" 621fi 622exit $ovr_exit 623