1 # $NetBSD: t_mtree.sh,v 1.10 2023/12/02 16:18:17 christos Exp $ 2 # 3 # Copyright (c) 2009, 2012 The NetBSD Foundation, Inc. 4 # All rights reserved. 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 # POSSIBILITY OF SUCH DAMAGE. 26 # 27 28 # Postprocess mtree output, canonicalising portions that 29 # are expected to differ from one run to another. 30 # 31 32 h_postprocess() 33 { 34 sed -e ' 35 /^# user: /s/:.*/: x/ 36 /^# machine: /s/:.*/: x/ 37 /^# tree: /s/:.*/: x/ 38 /^# date: /s/:.*/: x/ 39 ' \ 40 -e '/type=dir/s/ size=[0-9]*//' 41 } 42 43 h_check() 44 { 45 diff -Nru "$1" "$2" || atf_fail "files $1 and $2 differ" 46 } 47 48 49 atf_test_case mtree_create 50 atf_test_case netbsd6_create 51 create_head() 52 { 53 atf_set "descr" "Create a specfile describing a directory tree" 54 } 55 56 create_setup() 57 { 58 # create some directories 59 rm -fr create 60 mkdir -p create/a/1 create/a/2 create/b 61 # create some files 62 for file in create/top.file.1 \ 63 create/a/a.file.1 \ 64 create/a/a.file.2 \ 65 create/a/1/a1.file.1 \ 66 create/b/b.file.1 \ 67 create/b/b.file.2 68 do 69 echo "$file" >$file 70 done 71 # hard link to file in same dir 72 ln create/b/b.file.1 create/b/b.hardlink.1 73 # hard link to file in another dir 74 ln create/b/b.file.2 create/a/a.hardlink.b2 75 # symlink to file 76 ln -s a.file.1 create/a.symlink.1 77 # symlink to dir 78 ln -s b create/top.symlink.b 79 # dangling symlink 80 ln -s nonexistent create/top.dangling 81 } 82 83 create_body() 84 { 85 create_setup 86 87 # run mtree and check output 88 ( cd create && mtree -F ${FLAVOR} -c -k type,nlink,link,size,sha256 ) >output.raw \ 89 || atf_fail "mtree exit status $?" 90 h_postprocess <output.raw >output 91 h_check "$(atf_get_srcdir)/${FLAVOR}_d_create.out" output 92 } 93 94 mtree_create_head() 95 { 96 FLAVOR=mtree create_head 97 } 98 netbsd6_create_head() 99 { 100 FLAVOR=netbsd6 create_head 101 } 102 103 mtree_create_body() 104 { 105 FLAVOR=mtree create_body 106 } 107 netbsd6_create_body() 108 { 109 FLAVOR=netbsd6 create_body 110 } 111 112 113 atf_test_case mtree_check 114 atf_test_case netbsd6_check 115 check_head() 116 { 117 atf_set "descr" "Check a directory tree against a specfile" 118 } 119 120 check_body() 121 { 122 # we use the same directory tree and specfile as in the "create" test 123 create_setup 124 125 # run mtree and check output 126 ( cd create && mtree -F ${FLAVOR} ) <"$(atf_get_srcdir)/${FLAVOR}_d_create.out" >output \ 127 || atf_fail "mtree exit status $?" 128 h_check /dev/null output 129 } 130 131 mtree_check_head() 132 { 133 FLAVOR=mtree check_head 134 } 135 netbsd6_check_head() 136 { 137 FLAVOR=netbsd6 check_head 138 } 139 140 mtree_check_body() 141 { 142 FLAVOR=mtree check_body 143 } 144 netbsd6_check_body() 145 { 146 FLAVOR=netbsd6 check_body 147 } 148 149 150 atf_test_case mtree_convert_C 151 atf_test_case netbsd6_convert_C 152 convert_C_head() 153 { 154 atf_set "descr" "Convert a specfile to mtree -C format, unsorted" 155 } 156 157 convert_C_body() 158 { 159 mtree -F ${FLAVOR} -C -K all <"$(atf_get_srcdir)/d_convert.in" >output 160 h_check "$(atf_get_srcdir)/d_convert_C.out" output 161 } 162 163 mtree_convert_C_head() 164 { 165 FLAVOR=mtree convert_C_head 166 } 167 netbsd6_convert_C_head() 168 { 169 FLAVOR=netbsd6 convert_C_head 170 } 171 172 mtree_convert_C_body() 173 { 174 FLAVOR=mtree convert_C_body 175 } 176 netbsd6_convert_C_body() 177 { 178 FLAVOR=netbsd6 convert_C_body 179 } 180 181 182 atf_test_case mtree_convert_C_S 183 atf_test_case netbsd6_convert_C_S 184 convert_C_S_head() 185 { 186 atf_set "descr" "Convert a specfile to mtree -C format, sorted" 187 } 188 189 convert_C_S_body() 190 { 191 mtree -F ${FLAVOR} -C -S -K all <"$(atf_get_srcdir)/d_convert.in" >output 192 h_check "$(atf_get_srcdir)/d_convert_C_S.out" output 193 } 194 195 mtree_convert_C_S_head() 196 { 197 FLAVOR=mtree convert_C_S_head 198 } 199 netbsd6_convert_C_S_head() 200 { 201 FLAVOR=netbsd6 convert_C_S_head 202 } 203 204 mtree_convert_C_S_body() 205 { 206 FLAVOR=mtree convert_C_S_body 207 } 208 netbsd6_convert_C_S_body() 209 { 210 FLAVOR=netbsd6 convert_C_S_body 211 } 212 213 214 atf_test_case mtree_convert_D 215 atf_test_case netbsd6_convert_D 216 convert_D_head() 217 { 218 atf_set "descr" "Convert a specfile to mtree -D format, unsorted" 219 } 220 221 convert_D_body() 222 { 223 mtree -F ${FLAVOR} -D -K all <"$(atf_get_srcdir)/d_convert.in" >output 224 h_check "$(atf_get_srcdir)/d_convert_D.out" output 225 } 226 227 mtree_convert_D_head() 228 { 229 FLAVOR=mtree convert_D_head 230 } 231 netbsd6_convert_D_head() 232 { 233 FLAVOR=netbsd6 convert_D_head 234 } 235 236 mtree_convert_D_body() 237 { 238 FLAVOR=mtree convert_D_body 239 } 240 netbsd6_convert_D_body() 241 { 242 FLAVOR=netbsd6 convert_D_body 243 } 244 245 246 atf_test_case mtree_convert_D_S 247 atf_test_case netbsd6_convert_D_S 248 convert_D_S_head() 249 { 250 atf_set "descr" "Convert a specfile to mtree -D format, sorted" 251 } 252 253 convert_D_S_body() 254 { 255 mtree -F ${FLAVOR} -D -S -K all <"$(atf_get_srcdir)/d_convert.in" >output 256 h_check "$(atf_get_srcdir)/d_convert_D_S.out" output 257 } 258 259 mtree_convert_D_S_head() 260 { 261 FLAVOR=mtree convert_D_S_head 262 } 263 netbsd6_convert_D_S_head() 264 { 265 FLAVOR=netbsd6 convert_D_S_head 266 } 267 268 mtree_convert_D_S_body() 269 { 270 FLAVOR=mtree convert_D_S_body 271 } 272 netbsd6_convert_D_S_body() 273 { 274 FLAVOR=netbsd6 convert_D_S_body 275 } 276 277 278 atf_test_case mtree_ignore 279 atf_test_case netbs6_ignore 280 ignore_head() 281 { 282 atf_set "descr" "Test that -d ignores symlinks (PR bin/41061)" 283 } 284 285 ignore_body() 286 { 287 # Kyua 0.11 and above point TMPDIR to our work directory and atf-check 288 # generates a temporary file, which confuses mtree. Put the mtree files 289 # into a subdirectory. 290 # 291 # See https://github.com/jmmv/kyua/issues/133 for details. 292 mkdir root && cd root 293 294 mkdir newdir 295 mtree -F ${FLAVOR} -c | mtree -F ${FLAVOR} -Ck uid,gid,mode > mtree.spec 296 ln -s newdir otherdir 297 298 # This yields "extra: otherdir" even with -d. 299 # (PR bin/41061) 300 atf_check -s ignore -o empty -e empty -x "mtree -F ${FLAVOR} -d < mtree.spec" 301 302 # Delete the symlink and re-verify. 303 # 304 rm otherdir 305 atf_check -s ignore -o empty -e empty -x "mtree -F ${FLAVOR} -d < mtree.spec" 306 } 307 308 mtree_ignore_head() 309 { 310 FLAVOR=mtree ignore_head 311 } 312 netbsd6_ignore_head() 313 { 314 FLAVOR=netbsd6 ignore_head 315 } 316 317 mtree_ignore_body() 318 { 319 FLAVOR=mtree ignore_body 320 } 321 netbsd6_ignore_body() 322 { 323 # Kyua 0.11 and above point TMPDIR to our work directory and atf-check 324 # generates a temporary file, which confuses mtree. Put the mtree files 325 # into a subdirectory. 326 # 327 # See https://github.com/jmmv/kyua/issues/133 for details. 328 mkdir root && cd root 329 330 FLAVOR=netbsd6 ignore_body 331 } 332 333 334 atf_test_case mtree_merge 335 atf_test_case netbsd6_merge 336 merge_head() 337 { 338 atf_set "descr" "Merge records of different type" 339 } 340 341 merge_body() 342 { 343 mtree -F ${FLAVOR} -C -M -K all <"$(atf_get_srcdir)/d_merge.in" >output 344 h_check "$(atf_get_srcdir)/d_merge_C_M.out" output 345 # same again, with sorting 346 mtree -F ${FLAVOR} -C -M -S -K all <"$(atf_get_srcdir)/d_merge.in" >output 347 h_check "$(atf_get_srcdir)/d_merge_C_M_S.out" output 348 } 349 350 mtree_merge_head() 351 { 352 FLAVOR=mtree merge_head 353 } 354 netbsd6_merge_head() 355 { 356 FLAVOR=netbsd6 merge_head 357 } 358 359 mtree_merge_body() 360 { 361 FLAVOR=mtree merge_body 362 } 363 netbsd6_merge_body() 364 { 365 FLAVOR=netbsd6 merge_body 366 } 367 368 369 atf_test_case mtree_nonemptydir 370 atf_test_case netbsd6_nonemptydir 371 nonemptydir_head() 372 { 373 atf_set "descr" "Test that new non-empty " \ 374 "directories are recorded (PR bin/25693)" 375 } 376 377 nonemptydir_body() 378 { 379 mkdir testdir 380 cd testdir 381 382 mtree -F ${FLAVOR} -c > mtree.spec 383 384 if [ ! -f mtree.spec ]; then 385 atf_fail "mtree failed" 386 fi 387 388 touch bar 389 atf_check -s ignore -o save:output -x "mtree -F ${FLAVOR} -f mtree.spec" 390 391 if [ ! -n "$(egrep "extra: bar" output)" ]; then 392 atf_fail "mtree did not record changes (PR bin/25693)" 393 fi 394 } 395 396 mtree_nonemptydir_head() 397 { 398 FLAVOR=mtree nonemptydir_head 399 } 400 netbsd6_nonemptydir_head() 401 { 402 FLAVOR=netbsd6 nonemptydir_head 403 } 404 405 mtree_nonemptydir_body() 406 { 407 FLAVOR=mtree nonemptydir_body 408 } 409 netbsd6_nonemptydir_body() 410 { 411 FLAVOR=netbsd6 nonemptydir_body 412 } 413 414 atf_test_case mtree_specspec_type 415 mtree_specspec_type_head() 416 { 417 atf_set "descr" "Test that spec comparisons detect type changes" 418 } 419 420 mtree_specspec_type_body() 421 { 422 mkdir testdir 423 424 touch testdir/bar 425 mtree -c -p testdir > mtree1.spec 426 427 if [ ! -f mtree1.spec ]; then 428 atf_fail "mtree failed" 429 fi 430 431 rm -f testdir/bar 432 ln -s foo testdir/bar 433 # uid change is expected to be ignored as done in -C 434 chown -h operator testdir/bar 435 mtree -c -p testdir > mtree2.spec 436 437 if [ ! -f mtree2.spec ]; then 438 atf_fail "mtree failed" 439 fi 440 441 atf_check -s ignore -o save:output \ 442 -x "mtree -f mtree1.spec -f mtree2.spec" 443 444 if ! cut -f 3 output | egrep -q "bar file" || \ 445 ! cut -f 3 output | egrep -q "bar link"; then 446 atf_fail "mtree did not detect type change" 447 fi 448 } 449 450 atf_test_case mtree_onlyfile 451 atf_test_case netbsd6_onlyfile 452 onlyfile_head() 453 { 454 atf_set "descr" "Test -O with same hash value in directory and leaf" 455 } 456 457 onlyfile_body() 458 { 459 mkdir -p ab/no 460 echo ./ab/no >onlyfile 461 mtree -F ${FLAVOR} -c -n -O onlyfile >output 462 if [ ! -s output ]; then 463 atf_fail "mtree did not find path in onlyfile" 464 fi 465 } 466 467 mtree_onlyfile_head() 468 { 469 FLAVOR=mtree onlyfile_head 470 } 471 netbsd6_onlyfile_head() 472 { 473 FLAVOR=netbsd6 onlyfile_head 474 } 475 476 mtree_onlyfile_body() 477 { 478 FLAVOR=mtree onlyfile_body 479 } 480 netbsd6_onlyfile_body() 481 { 482 FLAVOR=netbsd6 onlyfile_body 483 } 484 485 486 atf_init_test_cases() 487 { 488 atf_add_test_case mtree_create 489 atf_add_test_case mtree_check 490 atf_add_test_case mtree_convert_C 491 atf_add_test_case mtree_convert_C_S 492 atf_add_test_case mtree_convert_D 493 atf_add_test_case mtree_convert_D_S 494 atf_add_test_case mtree_ignore 495 atf_add_test_case mtree_merge 496 atf_add_test_case mtree_nonemptydir 497 atf_add_test_case mtree_specspec_type 498 atf_add_test_case mtree_onlyfile 499 500 atf_add_test_case netbsd6_create 501 atf_add_test_case netbsd6_check 502 atf_add_test_case netbsd6_convert_C 503 atf_add_test_case netbsd6_convert_C_S 504 atf_add_test_case netbsd6_convert_D 505 atf_add_test_case netbsd6_convert_D_S 506 atf_add_test_case netbsd6_ignore 507 atf_add_test_case netbsd6_merge 508 atf_add_test_case netbsd6_nonemptydir 509 atf_add_test_case netbsd6_onlyfile 510 } 511