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