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_body() 38{ 39 echo "foo" > bar 40 41 atf_check cp bar baz 42 check_size baz 4 43} 44 45atf_test_case basic_symlink 46basic_symlink_body() 47{ 48 echo "foo" > bar 49 ln -s bar baz 50 51 atf_check cp baz foo 52 atf_check test '!' -L foo 53 54 atf_check -e inline:"cp: baz and baz are identical (not copied).\n" \ 55 -s exit:1 cp baz baz 56 atf_check -e inline:"cp: bar and baz are identical (not copied).\n" \ 57 -s exit:1 cp baz bar 58} 59 60atf_test_case chrdev 61chrdev_body() 62{ 63 echo "foo" > bar 64 65 check_size bar 4 66 atf_check cp /dev/null trunc 67 check_size trunc 0 68 atf_check cp bar trunc 69 check_size trunc 4 70 atf_check cp /dev/null trunc 71 check_size trunc 0 72} 73 74atf_test_case matching_srctgt 75matching_srctgt_body() 76{ 77 78 # PR235438: `cp -R foo foo` would previously infinitely recurse and 79 # eventually error out. 80 mkdir foo 81 echo "qux" > foo/bar 82 cp foo/bar foo/zoo 83 84 atf_check cp -R foo foo 85 atf_check -o inline:"qux\n" cat foo/foo/bar 86 atf_check -o inline:"qux\n" cat foo/foo/zoo 87 atf_check -e not-empty -s not-exit:0 stat foo/foo/foo 88} 89 90atf_test_case matching_srctgt_contained 91matching_srctgt_contained_body() 92{ 93 94 # Let's do the same thing, except we'll try to recursively copy foo into 95 # one of its subdirectories. 96 mkdir foo 97 ln -s foo coo 98 echo "qux" > foo/bar 99 mkdir foo/moo 100 touch foo/moo/roo 101 cp foo/bar foo/zoo 102 103 atf_check cp -R foo foo/moo 104 atf_check cp -RH coo foo/moo 105 atf_check -o inline:"qux\n" cat foo/moo/foo/bar 106 atf_check -o inline:"qux\n" cat foo/moo/coo/bar 107 atf_check -o inline:"qux\n" cat foo/moo/foo/zoo 108 atf_check -o inline:"qux\n" cat foo/moo/coo/zoo 109 110 # We should have copied the contents of foo/moo before foo, coo started 111 # getting copied in. 112 atf_check -o not-empty stat foo/moo/foo/moo/roo 113 atf_check -o not-empty stat foo/moo/coo/moo/roo 114 atf_check -e not-empty -s not-exit:0 stat foo/moo/foo/moo/foo 115 atf_check -e not-empty -s not-exit:0 stat foo/moo/coo/moo/coo 116} 117 118atf_test_case matching_srctgt_link 119matching_srctgt_link_body() 120{ 121 122 mkdir foo 123 echo "qux" > foo/bar 124 cp foo/bar foo/zoo 125 126 atf_check ln -s foo roo 127 atf_check cp -RH roo foo 128 atf_check -o inline:"qux\n" cat foo/roo/bar 129 atf_check -o inline:"qux\n" cat foo/roo/zoo 130} 131 132atf_test_case matching_srctgt_nonexistent 133matching_srctgt_nonexistent_body() 134{ 135 136 # We'll copy foo to a nonexistent subdirectory; ideally, we would 137 # skip just the directory and end up with a layout like; 138 # 139 # foo/ 140 # bar 141 # dne/ 142 # bar 143 # zoo 144 # zoo 145 # 146 mkdir foo 147 echo "qux" > foo/bar 148 cp foo/bar foo/zoo 149 150 atf_check cp -R foo foo/dne 151 atf_check -o inline:"qux\n" cat foo/dne/bar 152 atf_check -o inline:"qux\n" cat foo/dne/zoo 153 atf_check -e not-empty -s not-exit:0 stat foo/dne/foo 154} 155 156recursive_link_setup() 157{ 158 extra_cpflag=$1 159 160 mkdir -p foo/bar 161 ln -s bar foo/baz 162 163 mkdir foo-mirror 164 eval "cp -R $extra_cpflag foo foo-mirror" 165} 166 167atf_test_case recursive_link_dflt 168recursive_link_dflt_body() 169{ 170 recursive_link_setup 171 172 # -P is the default, so this should work and preserve the link. 173 atf_check cp -R foo foo-mirror 174 atf_check test -L foo-mirror/foo/baz 175} 176 177atf_test_case recursive_link_Hflag 178recursive_link_Hflag_body() 179{ 180 recursive_link_setup 181 182 # -H will not follow either, so this should also work and preserve the 183 # link. 184 atf_check cp -RH foo foo-mirror 185 atf_check test -L foo-mirror/foo/baz 186} 187 188atf_test_case recursive_link_Lflag 189recursive_link_Lflag_body() 190{ 191 recursive_link_setup -L 192 193 # -L will work, but foo/baz ends up expanded to a directory. 194 atf_check test -d foo-mirror/foo/baz -a \ 195 '(' ! -L foo-mirror/foo/baz ')' 196 atf_check cp -RL foo foo-mirror 197 atf_check test -d foo-mirror/foo/baz -a \ 198 '(' ! -L foo-mirror/foo/baz ')' 199} 200 201file_is_sparse() 202{ 203 atf_check ${0%/*}/sparse "$1" 204} 205 206files_are_equal() 207{ 208 atf_check test "$(stat -f "%d %i" "$1")" != "$(stat -f "%d %i" "$2")" 209 atf_check cmp "$1" "$2" 210} 211 212atf_test_case sparse_leading_hole 213sparse_leading_hole_body() 214{ 215 # A 16-megabyte hole followed by one megabyte of data 216 truncate -s 16M foo 217 seq -f%015g 65536 >>foo 218 file_is_sparse foo 219 220 atf_check cp foo bar 221 files_are_equal foo bar 222 file_is_sparse bar 223} 224 225atf_test_case sparse_multiple_holes 226sparse_multiple_holes_body() 227{ 228 # Three one-megabyte blocks of data preceded, separated, and 229 # followed by 16-megabyte holes 230 truncate -s 16M foo 231 seq -f%015g 65536 >>foo 232 truncate -s 33M foo 233 seq -f%015g 65536 >>foo 234 truncate -s 50M foo 235 seq -f%015g 65536 >>foo 236 truncate -s 67M foo 237 file_is_sparse foo 238 239 atf_check cp foo bar 240 files_are_equal foo bar 241 file_is_sparse bar 242} 243 244atf_test_case sparse_only_hole 245sparse_only_hole_body() 246{ 247 # A 16-megabyte hole 248 truncate -s 16M foo 249 file_is_sparse foo 250 251 atf_check cp foo bar 252 files_are_equal foo bar 253 file_is_sparse bar 254} 255 256atf_test_case sparse_to_dev 257sparse_to_dev_body() 258{ 259 # Three one-megabyte blocks of data preceded, separated, and 260 # followed by 16-megabyte holes 261 truncate -s 16M foo 262 seq -f%015g 65536 >>foo 263 truncate -s 33M foo 264 seq -f%015g 65536 >>foo 265 truncate -s 50M foo 266 seq -f%015g 65536 >>foo 267 truncate -s 67M foo 268 file_is_sparse foo 269 270 atf_check -o file:foo cp foo /dev/stdout 271} 272 273atf_test_case sparse_trailing_hole 274sparse_trailing_hole_body() 275{ 276 # One megabyte of data followed by a 16-megabyte hole 277 seq -f%015g 65536 >foo 278 truncate -s 17M foo 279 file_is_sparse foo 280 281 atf_check cp foo bar 282 files_are_equal foo bar 283 file_is_sparse bar 284} 285 286atf_test_case standalone_Pflag 287standalone_Pflag_body() 288{ 289 echo "foo" > bar 290 ln -s bar foo 291 292 atf_check cp -P foo baz 293 atf_check -o inline:'Symbolic Link\n' stat -f %SHT baz 294} 295 296atf_init_test_cases() 297{ 298 atf_add_test_case basic 299 atf_add_test_case basic_symlink 300 atf_add_test_case chrdev 301 atf_add_test_case matching_srctgt 302 atf_add_test_case matching_srctgt_contained 303 atf_add_test_case matching_srctgt_link 304 atf_add_test_case matching_srctgt_nonexistent 305 atf_add_test_case recursive_link_dflt 306 atf_add_test_case recursive_link_Hflag 307 atf_add_test_case recursive_link_Lflag 308 atf_add_test_case sparse_leading_hole 309 atf_add_test_case sparse_multiple_holes 310 atf_add_test_case sparse_only_hole 311 atf_add_test_case sparse_to_dev 312 atf_add_test_case sparse_trailing_hole 313 atf_add_test_case standalone_Pflag 314} 315