# # Copyright (c) 2016 Jilles Tjoelker # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # # atf_test_case incompatible_opts incompatible_opts_body() { printf 'test\n123\r456\r\n789\0z' >testf atf_check -s not-exit:0 -e match:"specified together" \ install -s -d dir1 atf_check -s not-exit:0 -e match:"specified together" \ install -s -l s testf copyf } atf_test_case copy_to_empty copy_to_empty_body() { printf 'test\n123\r456\r\n789\0z' >testf atf_check -s not-exit:0 -e match:"empty string" \ install testf "" } atf_test_case copy_to_nonexistent_dir copy_to_nonexistent_dir_body() { local dir="/nonexistent" printf 'test\n123\r456\r\n789\0z' >testf atf_check -s not-exit:0 -e match:$dir": No such file or directory" \ install testf $dir/testf } copy_to_nonexistent_with_opts() { printf 'test\n123\r456\r\n789\0z' >testf atf_check install "$@" testf copyf cmp testf copyf || atf_fail "bad copy" [ ! testf -nt copyf ] || atf_fail "bad timestamp" [ ! -e copyf.bak ] || atf_fail "no backup expected" } atf_test_case copy_to_nonexistent copy_to_nonexistent_body() { copy_to_nonexistent_with_opts } atf_test_case copy_to_nonexistent_safe copy_to_nonexistent_safe_body() { copy_to_nonexistent_with_opts -S } atf_test_case copy_to_nonexistent_comparing copy_to_nonexistent_comparing_body() { copy_to_nonexistent_with_opts -C } atf_test_case copy_to_nonexistent_safe_comparing copy_to_nonexistent_safe_comparing_body() { copy_to_nonexistent_with_opts -S -C } atf_test_case copy_to_nonexistent_backup copy_to_nonexistent_backup_body() { copy_to_nonexistent_with_opts -b -B.bak } atf_test_case copy_to_nonexistent_backup_safe copy_to_nonexistent_backup_safe_body() { copy_to_nonexistent_with_opts -b -B.bak -S } atf_test_case copy_to_nonexistent_preserving copy_to_nonexistent_preserving_body() { copy_to_nonexistent_with_opts -p [ ! testf -ot copyf ] || atf_fail "bad timestamp 2" } copy_self_with_opts() { printf 'test\n123\r456\r\n789\0z' >testf printf 'test\n123\r456\r\n789\0z' >testf2 atf_check -s not-exit:0 -o empty -e match:. install "$@" testf testf cmp testf testf2 || atf_fail "file changed after self-copy attempt" } atf_test_case copy_self copy_self_body() { copy_self_with_opts } atf_test_case copy_self_safe copy_self_safe_body() { copy_self_with_opts -S } atf_test_case copy_self_comparing copy_self_comparing_body() { copy_self_with_opts -C } atf_test_case copy_self_safe_comparing copy_self_safe_comparing_body() { copy_self_with_opts -S -C } overwrite_with_opts() { printf 'test\n123\r456\r\n789\0z' >testf printf 'test\n123\r456\r\n789\0w' >otherf atf_check install "$@" testf otherf cmp testf otherf || atf_fail "bad overwrite" [ ! testf -nt otherf ] || atf_fail "bad timestamp" } atf_test_case overwrite overwrite_body() { overwrite_with_opts } atf_test_case overwrite_safe overwrite_safe_body() { overwrite_with_opts -S } atf_test_case overwrite_comparing overwrite_comparing_body() { overwrite_with_opts -C } atf_test_case overwrite_safe_comparing overwrite_safe_comparing_body() { overwrite_with_opts -S -C } overwrite_eq_with_opts() { printf 'test\n123\r456\r\n789\0z' >testf printf 'test\n123\r456\r\n789\0z' >otherf atf_check install "$@" testf otherf cmp testf otherf || atf_fail "bad overwrite" [ ! testf -nt otherf ] || atf_fail "bad timestamp" } atf_test_case overwrite_eq overwrite_eq_body() { overwrite_eq_with_opts } atf_test_case overwrite_eq_safe overwrite_eq_safe_body() { overwrite_eq_with_opts -S } atf_test_case overwrite_eq_comparing overwrite_eq_comparing_body() { overwrite_eq_with_opts -C } atf_test_case overwrite_eq_safe_comparing overwrite_eq_safe_comparing_body() { overwrite_eq_with_opts -S -C } overwrite_backup_with_opts() { printf 'test\n123\r456\r\n789\0z' >testf printf 'test\n123\r456\r\n789\0w' >otherf printf 'test\n123\r456\r\n789\0w' >otherf2 atf_check install -b -B.bak "$@" testf otherf cmp testf otherf || atf_fail "bad overwrite" [ ! testf -nt otherf ] || atf_fail "bad timestamp" cmp otherf.bak otherf2 || atf_fail "bad backup" } atf_test_case overwrite_backup overwrite_backup_body() { overwrite_backup_with_opts } atf_test_case overwrite_backup_safe overwrite_backup_safe_body() { overwrite_backup_with_opts -S } atf_test_case overwrite_backup_comparing overwrite_backup_comparing_body() { overwrite_backup_with_opts -C } atf_test_case overwrite_backup_safe_comparing overwrite_backup_safe_comparing_body() { overwrite_backup_with_opts -S -C } setup_stripbin() { cat <<\STRIPBIN >stripbin #!/bin/sh [ "$1" = "-o" ] && dst="$2" && shift 2 [ "$1" = "--" ] && shift [ -z "$dst" ] && dst="$1" STRIPBIN [ "$1" = "true" ] && cmd="cat" || cmd="tr z @" echo $cmd '<"$1" >"$1.new" && mv -- "$1.new" "$dst"' >>stripbin chmod 755 stripbin export STRIPBIN="$PWD/stripbin" } strip_changing_with_opts() { setup_stripbin printf 'test\n123\r456\r\n789\0z' >testf atf_check install -s "$@" testf copyf [ ! testf -nt copyf ] || atf_fail "bad timestamp" printf 'test\n123\r456\r\n789\0@' >otherf cmp otherf copyf || atf_fail "bad stripped copy" } atf_test_case strip_changing strip_changing_body() { strip_changing_with_opts } atf_test_case strip_changing_comparing strip_changing_comparing_body() { strip_changing_with_opts -C } strip_changing_overwrite_with_opts() { setup_stripbin printf 'test\n123\r456\r\n789\0z' >testf printf 'test\n123\r456\r\n789\0w' >copyf atf_check install -s "$@" testf copyf [ ! testf -nt copyf ] || atf_fail "bad timestamp" printf 'test\n123\r456\r\n789\0@' >otherf cmp otherf copyf || atf_fail "bad stripped copy" } atf_test_case strip_changing_overwrite strip_changing_overwrite_body() { strip_changing_overwrite_with_opts } atf_test_case strip_changing_overwrite_comparing strip_changing_overwrite_comparing_body() { strip_changing_overwrite_with_opts -C } strip_changing_overwrite_eq_with_opts() { setup_stripbin printf 'test\n123\r456\r\n789\0z' >testf printf 'test\n123\r456\r\n789\0@' >copyf atf_check install -s "$@" testf copyf [ ! testf -nt copyf ] || atf_fail "bad timestamp" printf 'test\n123\r456\r\n789\0@' >otherf cmp otherf copyf || atf_fail "bad stripped copy" } atf_test_case strip_changing_overwrite_eq strip_changing_overwrite_eq_body() { strip_changing_overwrite_eq_with_opts } atf_test_case strip_changing_overwrite_eq_comparing strip_changing_overwrite_eq_comparing_body() { strip_changing_overwrite_eq_with_opts -C } atf_test_case strip_noop strip_noop_body() { setup_stripbin true printf 'test\n123\r456\r\n789\0z' >testf atf_check install -s testf copyf [ ! testf -nt copyf ] || atf_fail "bad timestamp" printf 'test\n123\r456\r\n789\0z' >otherf cmp otherf copyf || atf_fail "bad stripped copy" } atf_test_case hard_link hard_link_body() { printf 'test\n123\r456\r\n789\0z' >testf atf_check install -l h testf copyf [ testf -ef copyf ] || atf_fail "not same file" [ ! -L copyf ] || atf_fail "copy is symlink" } atf_test_case symbolic_link symbolic_link_body() { printf 'test\n123\r456\r\n789\0z' >testf atf_check install -l s testf copyf [ testf -ef copyf ] || atf_fail "not same file" [ -L copyf ] || atf_fail "copy is not symlink" } atf_test_case symbolic_link_absolute symbolic_link_absolute_body() { printf 'test\n123\r456\r\n789\0z' >testf atf_check install -l sa testf copyf [ testf -ef copyf ] || atf_fail "not same file" [ -L copyf ] || atf_fail "copy is not symlink" copyf_path=$(readlink copyf) testf_path="$(pwd -P)/testf" if [ "$copyf_path" != "$testf_path" ]; then atf_fail "unexpected symlink contents ('$copyf_path' != '$testf_path')" fi } atf_test_case symbolic_link_relative symbolic_link_relative_body() { printf 'test\n123\r456\r\n789\0z' >testf atf_check install -l sr testf copyf [ testf -ef copyf ] || atf_fail "not same file" [ -L copyf ] || atf_fail "copy is not symlink" copyf_path=$(readlink copyf) testf_path="testf" if [ "$copyf_path" != "$testf_path" ]; then atf_fail "unexpected symlink contents ('$copyf_path' != '$testf_path')" fi } atf_test_case symbolic_link_relative_absolute_source_and_dest1 symbolic_link_relative_absolute_source_and_dest1_head() { atf_set "descr" "Verify -l rs with absolute paths (.../copyf -> .../a/b/c/testf)" } symbolic_link_relative_absolute_source_and_dest1_body() { src_path=a/b/c/testf src_path_prefixed=$PWD/$src_path dest_path=$PWD/copyf atf_check mkdir -p a/b/c atf_check touch $src_path atf_check install -l sr $src_path_prefixed $dest_path [ $src_path_prefixed -ef $dest_path ] || atf_fail "not same file" [ -L $dest_path ] || atf_fail "copy is not symlink" dest_path_relative=$(readlink $dest_path) src_path_relative="$src_path" if [ "$src_path_relative" != "$dest_path_relative" ]; then atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')" fi } atf_test_case symbolic_link_relative_absolute_source_and_dest1_double_slash symbolic_link_relative_absolute_source_and_dest1_double_slash_head() { atf_set "descr" "Verify -l rs with absolute paths (.../copyf -> .../a/b/c/testf), using double-slashes" } symbolic_link_relative_absolute_source_and_dest1_double_slash_body() { src_path=a//b//c//testf src_path_prefixed=$PWD/$src_path dest_path=$PWD/copyf atf_check mkdir -p a/b/c atf_check touch $src_path atf_check install -l sr $src_path_prefixed $dest_path [ $src_path_prefixed -ef $dest_path ] || atf_fail "not same file" [ -L $dest_path ] || atf_fail "copy is not symlink" dest_path_relative=$(readlink $dest_path) src_path_relative="$(echo $src_path | sed -e 's,//,/,g')" if [ "$src_path_relative" != "$dest_path_relative" ]; then atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')" fi } atf_test_case symbolic_link_relative_absolute_source_and_dest2 symbolic_link_relative_absolute_source_and_dest2_head() { atf_set "descr" "Verify -l rs with absolute paths (.../a/b/c/copyf -> .../testf)" } symbolic_link_relative_absolute_source_and_dest2_body() { src_path=testf src_path_prefixed=$PWD/$src_path dest_path=$PWD/a/b/c/copyf atf_check mkdir -p a/b/c atf_check touch $src_path atf_check install -l sr $src_path_prefixed $dest_path [ $src_path_prefixed -ef $dest_path ] || atf_fail "not same file" [ -L $dest_path ] || atf_fail "copy is not symlink" dest_path_relative=$(readlink $dest_path) src_path_relative="../../../$src_path" if [ "$src_path_relative" != "$dest_path_relative" ]; then atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')" fi } atf_test_case mkdir_simple mkdir_simple_body() { atf_check install -d dir1/dir2 [ -d dir1 ] || atf_fail "dir1 missing" [ -d dir1/dir2 ] || atf_fail "dir2 missing" atf_check install -d dir1/dir2/dir3 [ -d dir1/dir2/dir3 ] || atf_fail "dir3 missing" atf_check install -d dir1 atf_check install -d dir1/dir2/dir3 } atf_test_case symbolic_link_relative_absolute_common symbolic_link_relative_absolute_common_head() { atf_set "descr" "Verify -l rs with absolute paths having common components" } symbolic_link_relative_absolute_common_body() { filename=foo.so src_path=lib src_path_prefixed=$PWD/$src_path dest_path=$PWD/libexec/ src_file=$src_path_prefixed/$filename dest_file=$dest_path/$filename atf_check mkdir $src_path_prefixed $dest_path atf_check touch $src_file atf_check install -l sr $src_file $dest_path dest_path_relative=$(readlink $dest_file) src_path_relative="../lib/$filename" if [ "$src_path_relative" != "$dest_path_relative" ]; then atf_fail "unexpected symlink contents ('$src_path_relative' != '$dest_path_relative')" fi } atf_test_case set_owner_group_mode set_owner_group_mode_head() { atf_set "require.user" "root" } set_owner_group_mode_body() { local fu=65531 fg=65531 local cu=65532 cg=65532 local u="$(id -u)" local g="$(id -g)" local m=0755 cm=4444 printf "test" >testf atf_check chown "$fu:$fg" testf atf_check chmod "$m" testf atf_check install testf testc atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)" atf_check install -o "$cu" testf testc atf_check_equal "$cu:$g:10$m" "$(stat -f"%u:%g:%p" testc)" atf_check install -g "$cg" testf testc atf_check_equal "$u:$cg:10$m" "$(stat -f"%u:%g:%p" testc)" atf_check install -o "$cu" -g "$cg" testf testc atf_check_equal "$cu:$cg:10$m" "$(stat -f"%u:%g:%p" testc)" atf_check install -m "$cm" testf testc atf_check_equal "$u:$g:10$cm" "$(stat -f"%u:%g:%p" testc)" atf_check install -o "$cu" -m "$cm" testf testc atf_check_equal "$cu:$g:10$cm" "$(stat -f"%u:%g:%p" testc)" atf_check install -g "$cg" -m "$cm" testf testc atf_check_equal "$u:$cg:10$cm" "$(stat -f"%u:%g:%p" testc)" atf_check install -o "$cu" -g "$cg" -m "$cm" testf testc atf_check_equal "$cu:$cg:10$cm" "$(stat -f"%u:%g:%p" testc)" } atf_test_case set_owner_group_mode_unpriv set_owner_group_mode_unpriv_head() { atf_set "require.user" "root" } set_owner_group_mode_unpriv_body() { local fu=65531 fg=65531 local cu=65532 cg=65532 local u="$(id -u)" local g="$(id -g)" local m=0755 cm=4444 cM=0444 printf "test" >testf atf_check chown "$fu:$fg" testf atf_check chmod "$m" testf atf_check install -U testf testc atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)" atf_check install -U -o "$cu" testf testc atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)" atf_check install -U -g "$cg" testf testc atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)" atf_check install -U -o "$cu" -g "$cg" testf testc atf_check_equal "$u:$g:10$m" "$(stat -f"%u:%g:%p" testc)" atf_check install -U -m "$cm" testf testc atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)" atf_check install -U -o "$cu" -m "$cm" testf testc atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)" atf_check install -U -g "$cg" -m "$cm" testf testc atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)" atf_check install -U -o "$cu" -g "$cg" -m "$cm" testf testc atf_check_equal "$u:$g:10$cM" "$(stat -f"%u:%g:%p" testc)" } atf_test_case set_optional_exec set_optional_exec_head() { atf_set "require.user" "unprivileged" } set_optional_exec_body() { echo "abc" > testfile.src atf_check install -d -m ug+rX testdir atf_check test -x testdir atf_check install -m ug+rX testfile.src testfile atf_check test ! -x testfile } atf_test_case metalog metalog_head() { atf_set "descr" "Test metalog generation" } metalog_body() { atf_check install -M metalog -D dst -m 0755 -d dst echo ". type=dir mode=0755" >expect atf_check install -M metalog -D dst -m 0705 -d dst/dir echo "./dir type=dir mode=0705" >>expect atf_check -o save:file echo "Hello, world!" atf_check install -M metalog -D dst -m 0604 file dst/dir echo "./dir/file type=file mode=0604 size=14" >>expect atf_check install -M metalog -D dst -lrs dir/file dst/"li nk" echo "./li\040nk type=link mode=0755 link=dir/file" >>expect atf_check mtree -f expect -p dst atf_check -o file:expect cat metalog } atf_test_case digest digest_head() { atf_set "descr" "Compute digest while copying" } digest_body() { atf_check mkdir src dst atf_check -e ignore dd if=/dev/random of=src/file bs=1m count=1 for alg in md5 rmd160 sha1 sha256 sha512 ; do rm -f dst/file digest metalog atf_check -o save:digest $alg -q src/file atf_check install -M metalog -D dst -h $alg -m 0644 src/file dst echo -n "./file type=file mode=0644 size=1048576 $alg=" >expect cat digest >>expect atf_check cmp src/file dst/file atf_check -o file:expect cat metalog done } atf_test_case null null_head() { atf_set "descr" "Install empty file" } null_body() { atf_check mkdir dst atf_check -s exit:71 -e not-empty install /dev/null dst atf_check install /dev/null dst/file atf_check test -f dst/file atf_check test ! -s dst/file # what if target already exists? echo "The Magic Words are Squeamish Ossifrage" >dst/file atf_check test -s dst/file atf_check install /dev/null dst/file atf_check test ! -s dst/file } atf_test_case stdin stdin_head() { atf_set "descr" "Install stdin" } stdin_body() { atf_check mkdir dst echo "The Magic Words are Squeamish Ossifrage" >src atf_check -s exit:71 -e not-empty install - dst