Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/bin/cp/tests/cp_test.sh
39507 views
1
#
2
# SPDX-License-Identifier: BSD-2-Clause
3
#
4
# Copyright (c) 2020 Kyle Evans <[email protected]>
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
28
check_size()
29
{
30
file=$1
31
sz=$2
32
33
atf_check -o inline:"$sz\n" stat -f '%z' $file
34
}
35
36
atf_test_case basic
37
basic_head()
38
{
39
atf_set "descr" "Copy a file"
40
}
41
basic_body()
42
{
43
echo "foo" > bar
44
45
atf_check cp bar baz
46
check_size baz 4
47
}
48
49
atf_test_case basic_symlink
50
basic_symlink_head()
51
{
52
atf_set "descr" "Copy a symlink to a file"
53
}
54
basic_symlink_body()
55
{
56
echo "foo" > bar
57
ln -s bar baz
58
59
atf_check cp baz foo
60
atf_check test ! -L foo
61
62
atf_check cmp foo bar
63
}
64
65
atf_test_case chrdev
66
chrdev_head()
67
{
68
atf_set "descr" "Copy a character device"
69
}
70
chrdev_body()
71
{
72
echo "foo" > bar
73
74
check_size bar 4
75
atf_check cp /dev/null trunc
76
check_size trunc 0
77
atf_check cp bar trunc
78
check_size trunc 4
79
atf_check cp /dev/null trunc
80
check_size trunc 0
81
}
82
83
atf_test_case hardlink
84
hardlink_head()
85
{
86
atf_set "descr" "Create a hard link to a file"
87
}
88
hardlink_body()
89
{
90
echo "foo" >foo
91
atf_check cp -l foo bar
92
atf_check -o inline:"foo\n" cat bar
93
atf_check_equal "$(stat -f%d,%i foo)" "$(stat -f%d,%i bar)"
94
}
95
96
atf_test_case hardlink_exists
97
hardlink_exists_head()
98
{
99
atf_set "descr" "Attempt to create a hard link to a file, " \
100
"but the destination already exists"
101
}
102
hardlink_exists_body()
103
{
104
echo "foo" >foo
105
echo "bar" >bar
106
atf_check -s not-exit:0 -e match:exists cp -l foo bar
107
atf_check -o inline:"bar\n" cat bar
108
atf_check_not_equal "$(stat -f%d,%i foo)" "$(stat -f%d,%i bar)"
109
}
110
111
atf_test_case hardlink_exists_force
112
hardlink_exists_force_head()
113
{
114
atf_set "descr" "Force creation of a hard link to a file " \
115
"when the destination already exists"
116
}
117
hardlink_exists_force_body()
118
{
119
echo "foo" >foo
120
echo "bar" >bar
121
atf_check cp -fl foo bar
122
atf_check -o inline:"foo\n" cat bar
123
atf_check_equal "$(stat -f%d,%i foo)" "$(stat -f%d,%i bar)"
124
}
125
126
atf_test_case matching_srctgt
127
matching_srctgt_head()
128
{
129
atf_set "descr" "Avoid infinite loop when copying a directory to itself"
130
}
131
matching_srctgt_body()
132
{
133
# PR235438: `cp -R foo foo` would previously infinitely recurse and
134
# eventually error out.
135
mkdir foo
136
echo "qux" > foo/bar
137
cp foo/bar foo/zoo
138
139
atf_check cp -R foo foo
140
atf_check -o inline:"qux\n" cat foo/foo/bar
141
atf_check -o inline:"qux\n" cat foo/foo/zoo
142
atf_check test ! -e foo/foo/foo
143
}
144
145
atf_test_case matching_srctgt_contained
146
matching_srctgt_contained_head()
147
{
148
atf_set "descr" "Avoid infinite loop when copying a directory " \
149
"into an existing subdirectory of itself"
150
}
151
matching_srctgt_contained_body()
152
{
153
# Let's do the same thing, except we'll try to recursively copy foo into
154
# one of its subdirectories.
155
mkdir foo
156
ln -s foo coo
157
echo "qux" > foo/bar
158
mkdir foo/moo
159
touch foo/moo/roo
160
cp foo/bar foo/zoo
161
162
atf_check cp -R foo foo/moo
163
atf_check cp -RH coo foo/moo
164
atf_check -o inline:"qux\n" cat foo/moo/foo/bar
165
atf_check -o inline:"qux\n" cat foo/moo/coo/bar
166
atf_check -o inline:"qux\n" cat foo/moo/foo/zoo
167
atf_check -o inline:"qux\n" cat foo/moo/coo/zoo
168
169
# We should have copied the contents of foo/moo before foo, coo started
170
# getting copied in.
171
atf_check -o not-empty stat foo/moo/foo/moo/roo
172
atf_check -o not-empty stat foo/moo/coo/moo/roo
173
atf_check -e not-empty -s not-exit:0 stat foo/moo/foo/moo/foo
174
atf_check -e not-empty -s not-exit:0 stat foo/moo/coo/moo/coo
175
}
176
177
atf_test_case matching_srctgt_link
178
matching_srctgt_link_head()
179
{
180
atf_set "descr" "Avoid infinite loop when recursively copying a " \
181
"symlink to a directory into the directory it links to"
182
}
183
matching_srctgt_link_body()
184
{
185
mkdir foo
186
echo "qux" > foo/bar
187
cp foo/bar foo/zoo
188
189
atf_check ln -s foo roo
190
atf_check cp -RH roo foo
191
atf_check -o inline:"qux\n" cat foo/roo/bar
192
atf_check -o inline:"qux\n" cat foo/roo/zoo
193
}
194
195
atf_test_case matching_srctgt_nonexistent
196
matching_srctgt_nonexistent_head()
197
{
198
atf_set "descr" "Avoid infinite loop when recursively copying a " \
199
"directory into a new subdirectory of itself"
200
}
201
matching_srctgt_nonexistent_body()
202
{
203
# We'll copy foo to a nonexistent subdirectory; ideally, we would
204
# skip just the directory and end up with a layout like;
205
#
206
# foo/
207
# bar
208
# dne/
209
# bar
210
# zoo
211
# zoo
212
#
213
mkdir foo
214
echo "qux" > foo/bar
215
cp foo/bar foo/zoo
216
217
atf_check cp -R foo foo/dne
218
atf_check -o inline:"qux\n" cat foo/dne/bar
219
atf_check -o inline:"qux\n" cat foo/dne/zoo
220
atf_check -e not-empty -s not-exit:0 stat foo/dne/foo
221
}
222
223
atf_test_case pflag_acls
224
pflag_acls_head()
225
{
226
atf_set "descr" "Verify that -p preserves access control lists"
227
}
228
pflag_acls_body()
229
{
230
mkdir dir
231
ln -s dir lnk
232
echo "hello" >dir/file
233
if ! setfacl -m g:staff:D::allow dir ||
234
! setfacl -m g:staff:d::allow dir/file ; then
235
atf_skip "file system does not support ACLs"
236
fi
237
atf_check -o match:"group:staff:-+D-+" getfacl dir
238
atf_check -o match:"group:staff:-+d-+" getfacl dir/file
239
# file-to-file copy without -p
240
atf_check cp dir/file dst1
241
atf_check -o not-match:"group:staff:-+d-+" getfacl dst1
242
# file-to-file copy with -p
243
atf_check cp -p dir/file dst2
244
atf_check -o match:"group:staff:-+d-+" getfacl dst2
245
# recursive copy without -p
246
atf_check cp -r dir dst3
247
atf_check -o not-match:"group:staff:-+D-+" getfacl dst3
248
atf_check -o not-match:"group:staff:-+d-+" getfacl dst3/file
249
# recursive copy with -p
250
atf_check cp -rp dir dst4
251
atf_check -o match:"group:staff:-+D-+" getfacl dst4
252
atf_check -o match:"group:staff:-+d-+" getfacl dst4/file
253
# source is a link without -p
254
atf_check cp -r lnk dst5
255
atf_check -o not-match:"group:staff:-+D-+" getfacl dst5
256
atf_check -o not-match:"group:staff:-+d-+" getfacl dst5/file
257
# source is a link with -p
258
atf_check cp -rp lnk dst6
259
atf_check -o match:"group:staff:-+D-+" getfacl dst6
260
atf_check -o match:"group:staff:-+d-+" getfacl dst6/file
261
}
262
263
atf_test_case pflag_flags
264
pflag_flags_head()
265
{
266
atf_set "descr" "Verify that -p preserves file flags"
267
}
268
pflag_flags_body()
269
{
270
mkdir dir
271
ln -s dir lnk
272
echo "hello" >dir/file
273
if ! chflags nodump dir ||
274
! chflags nodump dir/file ; then
275
atf_skip "file system does not support flags"
276
fi
277
atf_check -o match:"nodump" stat -f%Sf dir
278
atf_check -o match:"nodump" stat -f%Sf dir/file
279
# file-to-file copy without -p
280
atf_check cp dir/file dst1
281
atf_check -o not-match:"nodump" stat -f%Sf dst1
282
# file-to-file copy with -p
283
atf_check cp -p dir/file dst2
284
atf_check -o match:"nodump" stat -f%Sf dst2
285
# recursive copy without -p
286
atf_check cp -r dir dst3
287
atf_check -o not-match:"nodump" stat -f%Sf dst3
288
atf_check -o not-match:"nodump" stat -f%Sf dst3/file
289
# recursive copy with -p
290
atf_check cp -rp dir dst4
291
atf_check -o match:"nodump" stat -f%Sf dst4
292
atf_check -o match:"nodump" stat -f%Sf dst4/file
293
# source is a link without -p
294
atf_check cp -r lnk dst5
295
atf_check -o not-match:"nodump" stat -f%Sf dst5
296
atf_check -o not-match:"nodump" stat -f%Sf dst5/file
297
# source is a link with -p
298
atf_check cp -rp lnk dst6
299
atf_check -o match:"nodump" stat -f%Sf dst6
300
atf_check -o match:"nodump" stat -f%Sf dst6/file
301
}
302
303
recursive_link_setup()
304
{
305
extra_cpflag=$1
306
307
mkdir -p foo/bar
308
ln -s bar foo/baz
309
310
mkdir foo-mirror
311
eval "cp -R $extra_cpflag foo foo-mirror"
312
}
313
314
atf_test_case recursive_link_dflt
315
recursive_link_dflt_head()
316
{
317
atf_set "descr" "Copy a directory containing a subdirectory and a " \
318
"symlink to that subdirectory"
319
}
320
recursive_link_dflt_body()
321
{
322
recursive_link_setup
323
324
# -P is the default, so this should work and preserve the link.
325
atf_check cp -R foo foo-mirror
326
atf_check test -L foo-mirror/foo/baz
327
atf_check test -d foo-mirror/foo/baz
328
}
329
330
atf_test_case recursive_link_Hflag
331
recursive_link_Hflag_head()
332
{
333
atf_set "descr" "Copy a directory containing a subdirectory and a " \
334
"symlink to that subdirectory"
335
}
336
recursive_link_Hflag_body()
337
{
338
recursive_link_setup
339
340
# -H will not follow either, so this should also work and preserve the
341
# link.
342
atf_check cp -RH foo foo-mirror
343
atf_check test -L foo-mirror/foo/baz
344
atf_check test -d foo-mirror/foo/baz
345
}
346
347
atf_test_case recursive_link_Lflag
348
recursive_link_Lflag_head()
349
{
350
atf_set "descr" "Copy a directory containing a subdirectory and a " \
351
"symlink to that subdirectory"
352
}
353
recursive_link_Lflag_body()
354
{
355
recursive_link_setup -L
356
357
# -L will work, but foo/baz ends up expanded to a directory.
358
atf_check test ! -L foo-mirror/foo/baz
359
atf_check test -d foo-mirror/foo/baz
360
atf_check cp -RL foo foo-mirror
361
atf_check test ! -L foo-mirror/foo/baz
362
atf_check test -d foo-mirror/foo/baz
363
}
364
365
atf_test_case samefile
366
samefile_head()
367
{
368
atf_set "descr" "Copy a file to itself"
369
}
370
samefile_body()
371
{
372
echo "foo" >foo
373
ln foo bar
374
ln -s bar baz
375
atf_check -e match:"baz and baz are identical" \
376
-s exit:1 cp baz baz
377
atf_check -e match:"bar and baz are identical" \
378
-s exit:1 cp baz bar
379
atf_check -e match:"foo and baz are identical" \
380
-s exit:1 cp baz foo
381
atf_check -e match:"bar and foo are identical" \
382
-s exit:1 cp foo bar
383
}
384
385
file_is_sparse()
386
{
387
atf_check -o match:"^[0-9]+-[0-9]" stat -h "$1"
388
}
389
390
files_are_equal()
391
{
392
atf_check_not_equal "$(stat -f%d,%i "$1")" "$(stat -f%d,%i "$2")"
393
atf_check cmp "$1" "$2"
394
}
395
396
atf_test_case sparse_leading_hole
397
sparse_leading_hole_head()
398
{
399
atf_set "descr" "Copy a sparse file stat starts with a hole"
400
}
401
sparse_leading_hole_body()
402
{
403
# A 16-megabyte hole followed by one megabyte of data
404
truncate -s 16M foo
405
seq -f%015g 65536 >>foo
406
file_is_sparse foo
407
408
atf_check cp foo bar
409
files_are_equal foo bar
410
file_is_sparse bar
411
}
412
413
atf_test_case sparse_multiple_holes
414
sparse_multiple_hole_head()
415
{
416
atf_set "descr" "Copy a sparse file with multiple holes"
417
}
418
sparse_multiple_holes_body()
419
{
420
# Three one-megabyte blocks of data preceded, separated, and
421
# followed by 16-megabyte holes
422
truncate -s 16M foo
423
seq -f%015g 65536 >>foo
424
truncate -s 33M foo
425
seq -f%015g 65536 >>foo
426
truncate -s 50M foo
427
seq -f%015g 65536 >>foo
428
truncate -s 67M foo
429
file_is_sparse foo
430
431
atf_check cp foo bar
432
files_are_equal foo bar
433
file_is_sparse bar
434
}
435
436
atf_test_case sparse_only_hole
437
sparse_only_hole_head()
438
{
439
atf_set "descr" "Copy a sparse file consisting entirely of a hole"
440
}
441
sparse_only_hole_body()
442
{
443
# A 16-megabyte hole
444
truncate -s 16M foo
445
file_is_sparse foo
446
447
atf_check cp foo bar
448
files_are_equal foo bar
449
file_is_sparse bar
450
}
451
452
atf_test_case sparse_to_dev
453
sparse_to_dev_head()
454
{
455
atf_set "descr" "Copy a sparse file to a device"
456
}
457
sparse_to_dev_body()
458
{
459
# Three one-megabyte blocks of data preceded, separated, and
460
# followed by 16-megabyte holes
461
truncate -s 16M foo
462
seq -f%015g 65536 >>foo
463
truncate -s 33M foo
464
seq -f%015g 65536 >>foo
465
truncate -s 50M foo
466
seq -f%015g 65536 >>foo
467
truncate -s 67M foo
468
file_is_sparse foo
469
470
atf_check -o file:foo cp foo /dev/stdout
471
}
472
473
atf_test_case sparse_trailing_hole
474
sparse_trailing_hole_head()
475
{
476
atf_set "descr" "Copy a sparse file that ends with a hole"
477
}
478
sparse_trailing_hole_body()
479
{
480
# One megabyte of data followed by a 16-megabyte hole
481
seq -f%015g 65536 >foo
482
truncate -s 17M foo
483
file_is_sparse foo
484
485
atf_check cp foo bar
486
files_are_equal foo bar
487
file_is_sparse bar
488
}
489
490
atf_test_case standalone_Pflag
491
standalone_Pflag_head()
492
{
493
atf_set "descr" "Test -P without -R"
494
}
495
standalone_Pflag_body()
496
{
497
echo "foo" > bar
498
ln -s bar foo
499
500
atf_check cp -P foo baz
501
atf_check test -L baz
502
}
503
504
atf_test_case symlink
505
symlink_head()
506
{
507
atf_set "descr" "Create a symbolic link to a file"
508
}
509
symlink_body()
510
{
511
echo "foo" >foo
512
atf_check cp -s foo bar
513
atf_check -o inline:"foo\n" cat bar
514
atf_check -o inline:"foo\n" readlink bar
515
}
516
517
atf_test_case symlink_exists
518
symlink_exists_head()
519
{
520
atf_set "descr" "Attempt to create a symbolic link to a file, " \
521
"but the destination already exists"
522
}
523
symlink_exists_body()
524
{
525
echo "foo" >foo
526
echo "bar" >bar
527
atf_check -s not-exit:0 -e match:exists cp -s foo bar
528
atf_check -o inline:"bar\n" cat bar
529
}
530
531
atf_test_case symlink_exists_force
532
symlink_exists_force_head()
533
{
534
atf_set "descr" "Force creation of a symbolic link to a file " \
535
"when the destination already exists"
536
}
537
symlink_exists_force_body()
538
{
539
echo "foo" >foo
540
echo "bar" >bar
541
atf_check cp -fs foo bar
542
atf_check -o inline:"foo\n" cat bar
543
atf_check -o inline:"foo\n" readlink bar
544
}
545
546
atf_test_case directory_to_symlink
547
directory_to_symlink_head()
548
{
549
atf_set "descr" "Attempt to copy a directory to a symlink"
550
}
551
directory_to_symlink_body()
552
{
553
mkdir -p foo
554
ln -s .. foo/bar
555
mkdir bar
556
touch bar/baz
557
atf_check -s not-exit:0 -e match:"Not a directory" \
558
cp -R bar foo
559
atf_check -s not-exit:0 -e match:"Not a directory" \
560
cp -r bar foo
561
}
562
563
atf_test_case overwrite_directory
564
overwrite_directory_head()
565
{
566
atf_set "descr" "Attempt to overwrite a directory with a file"
567
}
568
overwrite_directory_body()
569
{
570
mkdir -p foo/bar/baz
571
touch bar
572
atf_check -s not-exit:0 -e match:"Is a directory" \
573
cp bar foo
574
rm bar
575
mkdir bar
576
touch bar/baz
577
atf_check -s not-exit:0 -e match:"Is a directory" \
578
cp -R bar foo
579
atf_check -s not-exit:0 -e match:"Is a directory" \
580
cp -r bar foo
581
}
582
583
atf_test_case to_dir_dne
584
to_dir_dne_head()
585
{
586
atf_set "descr" "Copy a directory to a nonexistent directory"
587
}
588
to_dir_dne_body()
589
{
590
mkdir dir
591
echo "foo" >dir/foo
592
atf_check cp -r dir dne
593
atf_check test -d dne
594
atf_check test -f dne/foo
595
atf_check cmp dir/foo dne/foo
596
}
597
598
atf_test_case to_nondir
599
to_dir_dne_head()
600
{
601
atf_set "descr" "Copy one or more files to a non-directory"
602
}
603
to_nondir_body()
604
{
605
echo "foo" >foo
606
echo "bar" >bar
607
echo "baz" >baz
608
# This is described as “case 1” in source code comments
609
atf_check cp foo bar
610
atf_check cmp -s foo bar
611
# This is “case 2”, the target must be a directory
612
atf_check -s not-exit:0 -e match:"Not a directory" \
613
cp foo bar baz
614
}
615
616
atf_test_case to_deadlink
617
to_deadlink_head()
618
{
619
atf_set "descr" "Copy a file to a dead symbolic link"
620
}
621
to_deadlink_body()
622
{
623
echo "foo" >foo
624
ln -s bar baz
625
atf_check cp foo baz
626
atf_check cmp -s foo bar
627
}
628
629
atf_test_case to_deadlink_append
630
to_deadlink_append_head()
631
{
632
atf_set "descr" "Copy multiple files to a dead symbolic link"
633
}
634
to_deadlink_append_body()
635
{
636
echo "foo" >foo
637
mkdir bar
638
ln -s baz bar/foo
639
atf_check cp foo bar
640
atf_check cmp -s foo bar/baz
641
rm -f bar/foo bar/baz
642
ln -s baz bar/foo
643
atf_check cp foo bar/
644
atf_check cmp -s foo bar/baz
645
rm -f bar/foo bar/baz
646
ln -s $PWD/baz bar/foo
647
atf_check cp foo bar/
648
atf_check cmp -s foo baz
649
}
650
651
atf_test_case to_dirlink
652
to_dirlink_head()
653
{
654
atf_set "descr" "Copy things to a symbolic link to a directory"
655
}
656
to_dirlink_body()
657
{
658
mkdir src dir
659
echo "foo" >src/file
660
ln -s dir dst
661
atf_check cp -r src dst
662
atf_check cmp -s src/file dir/src/file
663
rm -r dir/*
664
atf_check cp -r src dst/
665
atf_check cmp -s src/file dir/src/file
666
rm -r dir/*
667
# If the source is a directory and ends in a slash, our cp has
668
# traditionally copied the contents of the source rather than
669
# the source itself. It is unclear whether this is intended
670
# or simply a consequence of how FTS handles the situation.
671
# Notably, GNU cp does not behave in this manner.
672
atf_check cp -r src/ dst
673
atf_check cmp -s src/file dir/file
674
rm -r dir/*
675
atf_check cp -r src/ dst/
676
atf_check cmp -s src/file dir/file
677
rm -r dir/*
678
}
679
680
atf_test_case to_deaddirlink
681
to_deaddirlink_head()
682
{
683
atf_set "descr" "Copy things to a symbolic link to a nonexistent " \
684
"directory"
685
}
686
to_deaddirlink_body()
687
{
688
mkdir src
689
echo "foo" >src/file
690
ln -s dir dst
691
# It is unclear which error we should expect in these cases.
692
# Our current implementation always reports ENOTDIR, but one
693
# might be equally justified in expecting EEXIST or ENOENT.
694
# GNU cp reports EEXIST when the destination is given with a
695
# trailing slash and “cannot overwrite non-directory with
696
# directory” otherwise.
697
atf_check -s not-exit:0 -e ignore \
698
cp -r src dst
699
atf_check -s not-exit:0 -e ignore \
700
cp -r src dst/
701
atf_check -s not-exit:0 -e ignore \
702
cp -r src/ dst
703
atf_check -s not-exit:0 -e ignore \
704
cp -r src/ dst/
705
atf_check -s not-exit:0 -e ignore \
706
cp -R src dst
707
atf_check -s not-exit:0 -e ignore \
708
cp -R src dst/
709
atf_check -s not-exit:0 -e ignore \
710
cp -R src/ dst
711
atf_check -s not-exit:0 -e ignore \
712
cp -R src/ dst/
713
}
714
715
atf_test_case to_link_outside
716
to_link_outside_head()
717
{
718
atf_set "descr" "Recursively copy a directory containing a symbolic " \
719
"link that points to somewhere outside the source directory"
720
}
721
to_link_outside_body()
722
{
723
mkdir dir dst dst/dir
724
echo "foo" >dir/file
725
ln -s ../../file dst/dir/file
726
atf_check \
727
-s exit:1 \
728
-e match:"dst/dir/file: Permission denied" \
729
cp -r dir dst
730
}
731
732
atf_test_case dstmode
733
dstmode_head()
734
{
735
atf_set "descr" "Verify that directories are created with the " \
736
"correct permissions"
737
}
738
dstmode_body()
739
{
740
mkdir -m 0755 dir
741
echo "foo" >dir/file
742
umask 0177
743
atf_check cp -R dir dst
744
umask 022
745
atf_check -o inline:"40600\n" stat -f%p dst
746
atf_check chmod 0750 dst
747
atf_check cmp dir/file dst/file
748
}
749
750
atf_test_case to_root cleanup
751
to_root_head()
752
{
753
atf_set "require.user" "unprivileged"
754
}
755
to_root_body()
756
{
757
dst="test.$(atf_get ident).$$"
758
echo "$dst" >dst
759
echo "foo" >"$dst"
760
atf_check -s not-exit:0 \
761
-e match:"^cp: /$dst: (Permission|Read-only)" \
762
cp "$dst" /
763
atf_check -s not-exit:0 \
764
-e match:"^cp: /$dst: (Permission|Read-only)" \
765
cp "$dst" //
766
}
767
to_root_cleanup()
768
{
769
(dst=$(cat dst) && rm "/$dst") 2>/dev/null || true
770
}
771
772
atf_test_case dirloop
773
dirloop_head()
774
{
775
atf_set "descr" "Test cycle detection when recursing"
776
}
777
dirloop_body()
778
{
779
mkdir -p src/a src/b
780
ln -s ../b src/a
781
ln -s ../a src/b
782
atf_check \
783
-s exit:1 \
784
-e match:"src/a/b/a: directory causes a cycle" \
785
-e match:"src/b/a/b: directory causes a cycle" \
786
cp -r src dst
787
atf_check test -d dst
788
atf_check test -d dst/a
789
atf_check test -d dst/b
790
atf_check test -d dst/a/b
791
atf_check test ! -e dst/a/b/a
792
atf_check test -d dst/b/a
793
atf_check test ! -e dst/b/a/b
794
}
795
796
atf_test_case unrdir
797
unrdir_head()
798
{
799
atf_set "descr" "Test handling of unreadable directories"
800
atf_set "require.user" "unprivileged"
801
}
802
unrdir_body()
803
{
804
for d in a b c ; do
805
mkdir -p src/$d
806
echo "$d" >src/$d/f
807
done
808
chmod 0 src/b
809
atf_check \
810
-s exit:1 \
811
-e match:"^cp: src/b: Permission denied" \
812
cp -R --sort src dst
813
atf_check test -d dst/a
814
atf_check cmp src/a/f dst/a/f
815
atf_check test -d dst/b
816
atf_check test ! -e dst/b/f
817
atf_check test -d dst/c
818
atf_check cmp src/c/f dst/c/f
819
}
820
821
atf_test_case unrfile
822
unrfile_head()
823
{
824
atf_set "descr" "Test handling of unreadable files"
825
atf_set "require.user" "unprivileged"
826
}
827
unrfile_body()
828
{
829
mkdir src
830
for d in a b c ; do
831
echo "$d" >src/$d
832
done
833
chmod 0 src/b
834
atf_check \
835
-s exit:1 \
836
-e match:"^cp: src/b: Permission denied" \
837
cp -R --sort src dst
838
atf_check test -d dst
839
atf_check cmp src/a dst/a
840
atf_check test ! -e dst/b
841
atf_check cmp src/c dst/c
842
}
843
844
atf_test_case nopermute
845
nopermute_head()
846
{
847
atf_set descr "Check that getopt_long does not permute options"
848
}
849
nopermute_body()
850
{
851
mkdir src dst
852
atf_check \
853
-s exit:1 \
854
-e match:'cp: -p: No such file' \
855
cp -R src -p dst
856
atf_check test -d dst/src
857
}
858
859
atf_init_test_cases()
860
{
861
atf_add_test_case basic
862
atf_add_test_case basic_symlink
863
atf_add_test_case chrdev
864
atf_add_test_case hardlink
865
atf_add_test_case hardlink_exists
866
atf_add_test_case hardlink_exists_force
867
atf_add_test_case matching_srctgt
868
atf_add_test_case matching_srctgt_contained
869
atf_add_test_case matching_srctgt_link
870
atf_add_test_case matching_srctgt_nonexistent
871
atf_add_test_case pflag_acls
872
atf_add_test_case pflag_flags
873
atf_add_test_case recursive_link_dflt
874
atf_add_test_case recursive_link_Hflag
875
atf_add_test_case recursive_link_Lflag
876
atf_add_test_case samefile
877
atf_add_test_case sparse_leading_hole
878
atf_add_test_case sparse_multiple_holes
879
atf_add_test_case sparse_only_hole
880
atf_add_test_case sparse_to_dev
881
atf_add_test_case sparse_trailing_hole
882
atf_add_test_case standalone_Pflag
883
atf_add_test_case symlink
884
atf_add_test_case symlink_exists
885
atf_add_test_case symlink_exists_force
886
atf_add_test_case directory_to_symlink
887
atf_add_test_case overwrite_directory
888
atf_add_test_case to_dir_dne
889
atf_add_test_case to_nondir
890
atf_add_test_case to_deadlink
891
atf_add_test_case to_deadlink_append
892
atf_add_test_case to_dirlink
893
atf_add_test_case to_deaddirlink
894
atf_add_test_case to_link_outside
895
atf_add_test_case dstmode
896
atf_add_test_case to_root
897
atf_add_test_case dirloop
898
atf_add_test_case unrdir
899
atf_add_test_case unrfile
900
atf_add_test_case nopermute
901
}
902
903