1# 2# Copyright (c) 2007 Diomidis Spinellis 3# Copyright (c) 2023 Klara, Inc. 4# 5# SPDX-License-Identifier: BSD-2-Clause 6# 7 8mv_setup() { 9 atf_check mkdir fs 10 atf_check mount -t tmpfs -o size=1m tmp fs 11} 12 13mv_cleanup() { 14 umount fs || true 15} 16 17# Make a file that can later be verified 18mv_makefile() { 19 local cn="${1##*/}" 20 echo "$cn-$cn" >"$1" 21} 22 23# Verify that the file specified is correct 24mv_checkfile() { 25 atf_check -o inline:"$1-$1\n" cat "$2" 26} 27 28# Make a fifo that can later be verified 29mv_makepipe() { 30 atf_check mkfifo $1 31} 32 33# Verify that the file specified is correct 34mv_checkpipe() { 35 atf_check test -p "$2" 36} 37 38# Make a directory that can later be verified 39mv_makedir() { 40 local cn="${1##*/}" 41 atf_check mkdir -p "$1/$cn-$cn" 42} 43 44# Verify that the directory specified is correct 45mv_checkdir() { 46 atf_check test -d "$2/$1-$1" 47} 48 49# Verify that the specified file does not exist 50# (is not there) 51mv_checkabsent() { 52 atf_check -s exit:1 test -r "$1" 53} 54 55atf_test_case rename_file cleanup 56rename_file_head() { 57 atf_set "descr" "Rename file" 58 atf_set "require.user" "root" 59} 60rename_file_body() { 61 mv_setup 62 for FS in "" "fs/" ; do 63 mv_makefile fa 64 atf_check mv fa ${FS}fb 65 mv_checkfile fa ${FS}fb 66 mv_checkabsent fa 67 done 68} 69rename_file_cleanup() { 70 mv_cleanup 71} 72 73atf_test_case file_into_dir cleanup 74file_into_dir_head() { 75 atf_set "descr" "Move files into directory" 76 atf_set "require.user" "root" 77} 78file_into_dir_body() { 79 mv_setup 80 for FS in "" "fs/" ; do 81 mv_makefile fa 82 mv_makefile fb 83 atf_check mkdir -p ${FS}1/2/3 84 atf_check mv fa fb ${FS}1/2/3 85 mv_checkfile fa ${FS}1/2/3/fa 86 mv_checkfile fb ${FS}1/2/3/fb 87 mv_checkabsent fa 88 mv_checkabsent fb 89 done 90} 91file_into_dir_cleanup() { 92 mv_cleanup 93} 94 95atf_test_case file_from_dir cleanup 96file_from_dir_head() { 97 atf_set "descr" "Move file from directory to file" 98 atf_set "require.user" "root" 99} 100file_from_dir_body() { 101 mv_setup 102 atf_check mkdir -p 1/2/3 103 for FS in "" "fs/" ; do 104 mv_makefile 1/2/3/fa 105 atf_check mv 1/2/3/fa ${FS}fb 106 mv_checkfile fa ${FS}fb 107 mv_checkabsent 1/2/3/fa 108 done 109} 110file_from_dir_cleanup() { 111 mv_cleanup 112} 113 114atf_test_case file_from_dir_replace cleanup 115file_from_dir_replace_head() { 116 atf_set "descr" "Move file from directory to existing file" 117 atf_set "require.user" "root" 118} 119file_from_dir_replace_body() { 120 mv_setup 121 atf_check mkdir -p 1/2/3 122 for FS in "" "fs/" ; do 123 mv_makefile 1/2/3/fa 124 :> ${FS}fb 125 atf_check mv 1/2/3/fa ${FS}fb 126 mv_checkfile fa ${FS}fb 127 mv_checkabsent 1/2/3/fa 128 done 129} 130file_from_dir_replace_cleanup() { 131 mv_cleanup 132} 133 134atf_test_case file_to_dir cleanup 135file_to_dir_head() { 136 atf_set "descr" "Move file from directory to existing directory" 137 atf_set "require.user" "root" 138} 139file_to_dir_body() { 140 mv_setup 141 atf_check mkdir -p 1/2/3 142 for FS in "" "fs/" ; do 143 mv_makefile 1/2/3/fa 144 atf_check mkdir -p ${FS}db/fa 145 # Should fail per POSIX step 3a: 146 # Destination path is a file of type directory and 147 # source_file is not a file of type directory 148 atf_check -s not-exit:0 -e match:"Is a directory" \ 149 mv 1/2/3/fa ${FS}db 150 mv_checkfile fa 1/2/3/fa 151 done 152} 153file_to_dir_cleanup() { 154 mv_cleanup 155} 156 157atf_test_case file_from_rename_dir cleanup 158file_from_rename_dir_head() { 159 atf_set "descr" "Move file from directory to directory" 160 atf_set "require.user" "root" 161} 162file_from_rename_dir_body() { 163 mv_setup 164 atf_check mkdir -p da1/da2/da3 165 for FS in "" "fs/" ; do 166 atf_check mkdir -p ${FS}db1/db2/db3 167 mv_makefile da1/da2/da3/fa 168 atf_check mv da1/da2/da3/fa ${FS}db1/db2/db3/fb 169 mv_checkfile fa ${FS}db1/db2/db3/fb 170 mv_checkabsent da1/da2/da3/fa 171 done 172} 173file_from_rename_dir_cleanup() { 174 mv_cleanup 175} 176 177atf_test_case rename_dir cleanup 178rename_dir_head() { 179 atf_set "descr" "Rename directory" 180 atf_set "require.user" "root" 181} 182rename_dir_body() { 183 mv_setup 184 for FS in "" "fs/" ; do 185 mv_makedir da 186 atf_check mv da ${FS}db 187 mv_checkdir da ${FS}db 188 mv_checkabsent da 189 done 190} 191rename_dir_cleanup() { 192 mv_cleanup 193} 194 195atf_test_case dir_to_dir cleanup 196dir_to_dir_head() { 197 atf_set "descr" "Move directory to directory name" 198 atf_set "require.user" "root" 199} 200dir_to_dir_body() { 201 mv_setup 202 for FS in "" "fs/" ; do 203 mv_makedir da1/da2/da3/da 204 atf_check mkdir -p ${FS}db1/db2/db3 205 atf_check mv da1/da2/da3/da ${FS}db1/db2/db3/db 206 mv_checkdir da ${FS}db1/db2/db3/db 207 mv_checkabsent da1/da2/da3/da 208 done 209} 210dir_to_dir_cleanup() { 211 mv_cleanup 212} 213 214atf_test_case dir_into_dir cleanup 215dir_into_dir_head() { 216 atf_set "descr" "Move directory to directory" 217 atf_set "require.user" "root" 218} 219dir_into_dir_body() { 220 mv_setup 221 for FS in "" "fs/" ; do 222 mv_makedir da1/da2/da3/da 223 atf_check mkdir -p ${FS}db1/db2/db3 224 atf_check mv da1/da2/da3/da ${FS}db1/db2/db3 225 mv_checkdir da ${FS}db1/db2/db3/da 226 mv_checkabsent da1/da2/da3/da 227 done 228} 229dir_into_dir_cleanup() { 230 mv_cleanup 231} 232 233atf_test_case dir_to_empty_dir cleanup 234dir_to_empty_dir_head() { 235 atf_set "descr" "Move directory to existing empty directory" 236 atf_set "require.user" "root" 237} 238dir_to_empty_dir_body() { 239 mv_setup 240 for FS in "" "fs/" ; do 241 mv_makedir da1/da2/da3/da 242 atf_check mkdir -p ${FS}db1/db2/db3/da 243 atf_check mv da1/da2/da3/da ${FS}db1/db2/db3 244 mv_checkdir da ${FS}db1/db2/db3/da 245 mv_checkabsent da1/da2/da3/da 246 done 247} 248dir_to_empty_dir_cleanup() { 249 mv_cleanup 250} 251 252atf_test_case dir_to_nonempty_dir cleanup 253dir_to_nonempty_dir_head() { 254 atf_set "descr" "Move directory to existing non-empty directory" 255 atf_set "require.user" "root" 256} 257dir_to_nonempty_dir_body() { 258 mv_setup 259 for FS in "" "fs/" ; do 260 mv_makedir da1/da2/da3/da 261 atf_check mkdir -p ${FS}db1/db2/db3/da/full 262 # Should fail (per the semantics of rename(2)) 263 atf_check -s not-exit:0 -e match:"Directory not empty" \ 264 mv da1/da2/da3/da ${FS}db1/db2/db3 265 mv_checkdir da da1/da2/da3/da 266 done 267} 268dir_to_nonempty_dir_cleanup() { 269 mv_cleanup 270} 271 272atf_test_case dir_to_file cleanup 273dir_to_file_head() { 274 atf_set "descr" "Move directory to existing file" 275 atf_set "require.user" "root" 276} 277dir_to_file_body() { 278 mv_setup 279 for FS in "" "fs/" ; do 280 mv_makedir da1/da2/da3/da 281 atf_check mkdir -p ${FS}db1/db2/db3 282 :> ${FS}db1/db2/db3/da 283 # Should fail per POSIX step 3b: 284 # Destination path is a file not of type directory 285 # and source_file is a file of type directory 286 atf_check -s not-exit:0 -e match:"Not a directory" \ 287 mv da1/da2/da3/da ${FS}db1/db2/db3/da 288 mv_checkdir da da1/da2/da3/da 289 done 290} 291dir_to_file_cleanup() { 292 mv_cleanup 293} 294 295atf_test_case rename_fifo cleanup 296rename_fifo_head() { 297 atf_set "descr" "Rename fifo" 298 atf_set "require.user" "root" 299} 300rename_fifo_body() { 301 mv_setup 302 for FS in "" "fs/" ; do 303 mv_makepipe fa 304 atf_check mv fa ${FS}fb 305 mv_checkpipe fa ${FS}fb 306 mv_checkabsent fa 307 done 308} 309rename_fifo_cleanup() { 310 mv_cleanup 311} 312 313atf_test_case fifo_into_dir cleanup 314fifo_into_dir_head() { 315 atf_set "descr" "Move fifos into directory" 316 atf_set "require.user" "root" 317} 318fifo_into_dir_body() { 319 mv_setup 320 for FS in "" "fs/" ; do 321 mv_makepipe fa 322 mv_makepipe fb 323 atf_check mkdir -p ${FS}1/2/3 324 atf_check mv fa fb ${FS}1/2/3 325 mv_checkpipe fa ${FS}1/2/3/fa 326 mv_checkpipe fb ${FS}1/2/3/fb 327 mv_checkabsent fa 328 mv_checkabsent fb 329 done 330} 331fifo_into_dir_cleanup() { 332 mv_cleanup 333} 334 335atf_test_case fifo_from_dir cleanup 336fifo_from_dir_head() { 337 atf_set "descr" "Move fifo from directory to fifo" 338 atf_set "require.user" "root" 339} 340fifo_from_dir_body() { 341 mv_setup 342 atf_check mkdir -p 1/2/3 343 for FS in "" "fs/" ; do 344 mv_makepipe 1/2/3/fa 345 atf_check mv 1/2/3/fa ${FS}fb 346 mv_checkpipe fa ${FS}fb 347 mv_checkabsent 1/2/3/fa 348 done 349} 350fifo_from_dir_cleanup() { 351 mv_cleanup 352} 353 354atf_test_case fifo_from_dir_into_dir cleanup 355fifo_from_dir_into_dir_head() { 356 atf_set "descr" "Move fifo from directory to directory" 357 atf_set "require.user" "root" 358} 359fifo_from_dir_into_dir_body() { 360 mv_setup 361 atf_check mkdir -p da1/da2/da3 362 for FS in "" "fs/" ; do 363 atf_check mkdir -p ${FS}db1/db2/db3 364 mv_makepipe da1/da2/da3/fa 365 atf_check mv da1/da2/da3/fa ${FS}db1/db2/db3/fb 366 mv_checkpipe fa ${FS}db1/db2/db3/fb 367 mv_checkabsent da1/da2/da3/fa 368 done 369} 370fifo_from_dir_into_dir_cleanup() { 371 mv_cleanup 372} 373 374atf_test_case mv_f cleanup 375mv_f_head() { 376 atf_set "descr" "Force replacement" 377 atf_set "require.user" "root" 378} 379mv_f_body() { 380 mv_setup 381 for FS in "" "fs/" ; do 382 mv_makefile fa 383 atf_check mv fa ${FS}fb 384 mv_checkfile fa ${FS}fb 385 mv_checkabsent fa 386 mv_makefile fa 387 :> ${FS}fb 388 atf_check mv -i -n -f fa ${FS}fb 389 mv_checkfile fa ${FS}fb 390 mv_checkabsent fa 391 done 392} 393mv_f_cleanup() { 394 mv_cleanup 395} 396 397atf_test_case mv_h cleanup 398mv_h_head() { 399 atf_set "descr" "Replace symbolic link" 400 atf_set "require.user" "root" 401} 402mv_h_body() { 403 mv_setup 404 for FS in "" "fs/" ; do 405 atf_check mkdir ${FS}da 406 atf_check ln -s da ${FS}db 407 # First test without -h, file goes into symlink target 408 mv_makefile fa 409 atf_check mv fa ${FS}db 410 mv_checkfile fa ${FS}da/fa 411 # Second test with -h, file replaces symlink 412 mv_makefile fa 413 atf_check mv -h fa ${FS}db 414 mv_checkfile fa ${FS}db 415 done 416} 417mv_h_cleanup() { 418 mv_cleanup 419} 420 421atf_test_case mv_i cleanup 422mv_i_head() { 423 atf_set "descr" "Confirm replacement" 424 atf_set "require.user" "root" 425} 426mv_i_body() { 427 mv_setup 428 echo n >n 429 echo y >y 430 for FS in "" "fs/" ; do 431 mv_makefile fa 432 mv_makefile ${FS}fb 433 # First test, answer no, file is not replaced 434 atf_check -e match:"^overwrite ${FS}fb\\?" \ 435 mv -i fa ${FS}fb <n 436 mv_checkfile fa fa 437 mv_checkfile fb ${FS}fb 438 # Second test, answer yes, file is replaced 439 atf_check -e match:"^overwrite ${FS}fb\\?" \ 440 mv -i fa ${FS}fb <y 441 mv_checkabsent fa 442 mv_checkfile fa ${FS}fb 443 done 444} 445mv_i_cleanup() { 446 mv_cleanup 447} 448 449atf_test_case mv_n cleanup 450mv_n_head() { 451 atf_set "descr" "Decline replacement" 452 atf_set "require.user" "root" 453} 454mv_n_body() { 455 mv_setup 456 for FS in "" "fs/" ; do 457 mv_makefile fa 458 mv_makefile ${FS}fb 459 atf_check mv -n fa ${FS}fb 460 mv_checkfile fa fa 461 mv_checkfile fb ${FS}fb 462 done 463} 464mv_n_cleanup() { 465 mv_cleanup 466} 467 468atf_test_case mv_v cleanup 469mv_v_head() { 470 atf_set "descr" "Verbose mode" 471 atf_set "require.user" "root" 472} 473mv_v_body() { 474 mv_setup 475 for FS in "" "fs/" ; do 476 mv_makefile fa 477 atf_check mkdir ${FS}da 478 atf_check -o inline:"fa -> ${FS}da/fa\n" \ 479 mv -v fa ${FS}da 480 done 481} 482mv_v_cleanup() { 483 mv_cleanup 484} 485 486atf_init_test_cases() { 487 atf_add_test_case rename_file 488 atf_add_test_case file_into_dir 489 atf_add_test_case file_from_dir 490 atf_add_test_case file_from_dir_replace 491 atf_add_test_case file_to_dir 492 atf_add_test_case file_from_rename_dir 493 atf_add_test_case rename_dir 494 atf_add_test_case dir_to_dir 495 atf_add_test_case dir_into_dir 496 atf_add_test_case dir_to_empty_dir 497 atf_add_test_case dir_to_nonempty_dir 498 atf_add_test_case dir_to_file 499 atf_add_test_case rename_fifo 500 atf_add_test_case fifo_into_dir 501 atf_add_test_case fifo_from_dir 502 atf_add_test_case fifo_from_dir_into_dir 503 atf_add_test_case mv_f 504 atf_add_test_case mv_h 505 atf_add_test_case mv_i 506 atf_add_test_case mv_n 507 atf_add_test_case mv_v 508} 509