aboutsummaryrefslogtreecommitdiff
path: root/test/system/065-cp.bats
blob: 780fc673735db2e88bcee3a09a79c642aa9d01c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
#!/usr/bin/env bats   -*- bats -*-
#
# Tests for 'podman cp'
#
# ASSUMPTION FOR ALL THESE TESTS: /tmp in the container starts off empty
#

load helpers

@test "podman cp file from host to container" {
    srcdir=$PODMAN_TMPDIR/cp-test-file-host-to-ctr
    mkdir -p $srcdir
    local -a randomcontent=(
        random-0-$(random_string 10)
        random-1-$(random_string 15)
        random-2-$(random_string 20)
    )

    echo "${randomcontent[0]}" > $srcdir/hostfile0
    echo "${randomcontent[1]}" > $srcdir/hostfile1
    echo "${randomcontent[2]}" > $srcdir/hostfile2
    mkdir -p $srcdir/subdir
    echo "${randomcontent[2]}" > $srcdir/subdir/dotfile.

    run_podman run -d --name cpcontainer --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir; sleep infinity"

    # Commit the image for testing non-running containers
    run_podman commit -q cpcontainer
    cpimage="$output"

    # format is: <id> | <destination arg to cp> | <full dest path> | <test name>
    # where:
    #    id        is 0-2, one of the random strings/files
    #    dest arg  is the right-hand argument to 'podman cp' (may be implicit)
    #    dest path is the full explicit path we expect to see
    #    test name is a short description of what we're testing here
    tests="
0 | /                    | /hostfile0            | copy to root
0 | /anotherbase.txt     | /anotherbase.txt      | copy to root, new name
0 | /tmp                 | /tmp/hostfile0        | copy to /tmp
1 | /tmp/                | /tmp/hostfile1        | copy to /tmp/
2 | /tmp/.               | /tmp/hostfile2        | copy to /tmp/.
0 | /tmp/anotherbase.txt | /tmp/anotherbase.txt  | copy to /tmp, new name
0 | .                    | /srv/hostfile0        | copy to workdir (rel path), new name
1 | ./                   | /srv/hostfile1        | copy to workdir (rel path), new name
0 | anotherbase.txt      | /srv/anotherbase.txt  | copy to workdir (rel path), new name
0 | subdir               | /srv/subdir/hostfile0 | copy to workdir/subdir
"

    # RUNNING container
    while read id dest dest_fullname description; do
        run_podman cp $srcdir/hostfile$id cpcontainer:$dest
        run_podman exec cpcontainer cat $dest_fullname
        is "$output" "${randomcontent[$id]}" "$description (cp -> ctr:$dest)"
    done < <(parse_table "$tests")

    # Dots are special for dirs not files.
    run_podman cp $srcdir/subdir/dotfile. cpcontainer:/tmp
    run_podman exec cpcontainer cat /tmp/dotfile.
    is "$output" "${randomcontent[2]}" "$description (cp -> ctr:$dest)"

    # Host path does not exist.
    run_podman 125 cp $srcdir/IdoNotExist cpcontainer:/tmp
    is "$output" 'Error: ".*/IdoNotExist" could not be found on the host' \
       "copy nonexistent host path"

    # Container (parent) path does not exist.
    run_podman 125 cp $srcdir/hostfile0 cpcontainer:/IdoNotExist/
    is "$output" 'Error: "/IdoNotExist/" could not be found on container cpcontainer: No such file or directory' \
       "copy into nonexistent path in container"

    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer

    # CREATED container
    while read id dest dest_fullname description; do
        run_podman create --name cpcontainer --workdir=/srv $cpimage sleep infinity
        run_podman cp $srcdir/hostfile$id cpcontainer:$dest
        run_podman start cpcontainer
        run_podman exec cpcontainer cat $dest_fullname
        is "$output" "${randomcontent[$id]}" "$description (cp -> ctr:$dest)"
        run_podman kill cpcontainer
        run_podman rm -t 0 -f cpcontainer
    done < <(parse_table "$tests")

    run_podman rmi -f $cpimage
}


@test "podman cp file from host to container tmpfs mount" {
    srcdir=$PODMAN_TMPDIR/cp-test-file-host-to-ctr
    mkdir -p $srcdir
    content=tmpfile-content$(random_string 20)
    echo $content > $srcdir/file

    # RUNNING container
    run_podman run -d --mount type=tmpfs,dst=/tmp --name cpcontainer $IMAGE sleep infinity
    run_podman cp $srcdir/file cpcontainer:/tmp
    run_podman exec cpcontainer cat /tmp/file
    is "$output" "${content}" "cp to running container's tmpfs"
    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer

    # CREATED container (with copy up)
    run_podman create --mount type=tmpfs,dst=/tmp --name cpcontainer $IMAGE sleep infinity
    run_podman cp $srcdir/file cpcontainer:/tmp
    run_podman start cpcontainer
    run_podman exec cpcontainer cat /tmp/file
    is "$output" "${content}" "cp to created container's tmpfs"
    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer
}


@test "podman cp (-a=true) file from host to container and check ownership" {
    srcdir=$PODMAN_TMPDIR/cp-test-file-host-to-ctr
    mkdir -p $srcdir
    content=cp-user-test-$(random_string 10)
    echo "content" > $srcdir/hostfile
    userid=$(id -u)

    run_podman run --user=$userid --userns=keep-id -d --name cpcontainer $IMAGE sleep infinity
    run_podman cp $srcdir/hostfile cpcontainer:/tmp/hostfile
    run_podman exec cpcontainer stat -c "%u" /tmp/hostfile
    is "$output" "$userid" "copied file is chowned to the container user"
    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer
}

@test "podman cp (-a=false) file from host to container and check ownership" {
    local tmpdir="${PODMAN_TMPDIR}/cp-test-file-host-to-ctr"
    mkdir -p "${tmpdir}"

    pushd "${tmpdir}"
    touch a.txt
    tar --owner=1042 --group=1043 -cf a.tar a.txt
    popd

    userid=$(id -u)

    run_podman run --user="$userid" --userns=keep-id -d --name cpcontainer $IMAGE sleep infinity
    run_podman cp -a=false - cpcontainer:/tmp/ < "${tmpdir}/a.tar"
    run_podman exec cpcontainer stat -c "%u:%g" /tmp/a.txt
    is "$output" "1042:1043" "copied file retains uid/gid from the tar"
    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer
}


@test "podman cp file from/to host while --pid=host" {
    if is_rootless && ! is_cgroupsv2; then
        skip "'podman cp --pid=host' (rootless) only works with cgroups v2"
    fi

    srcdir=$PODMAN_TMPDIR/cp-pid-equals-host
    mkdir -p $srcdir
    touch $srcdir/hostfile

    run_podman run --pid=host -d --name cpcontainer $IMAGE sleep infinity
    run_podman cp $srcdir/hostfile cpcontainer:/tmp/hostfile
    run_podman cp cpcontainer:/tmp/hostfile $srcdir/hostfile1
    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer
}

@test "podman cp file from container to host" {
    srcdir=$PODMAN_TMPDIR/cp-test-file-ctr-to-host
    mkdir -p $srcdir

    # Create 3 files with random content in the container.
    local -a randomcontent=(
        random-0-$(random_string 10)
        random-1-$(random_string 15)
        random-2-$(random_string 20)
    )
    run_podman run -d --name cpcontainer --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir;
         echo ${randomcontent[0]} > /tmp/containerfile;
         echo ${randomcontent[0]} > /tmp/dotfile.;
         echo ${randomcontent[1]} > /srv/containerfile1;
         echo ${randomcontent[2]} > /srv/subdir/containerfile2;
         sleep infinity"

    # Commit the image for testing non-running containers
    run_podman commit -q cpcontainer
    cpimage="$output"

    # format is: <id> | <source arg to cp> | <destination arg (appended to $srcdir) to cp> | <full dest path (appended to $srcdir)> | <test name>
    tests="
0 | /tmp/containerfile    |          | /containerfile  | copy to srcdir/
0 | /tmp/dotfile.         |          | /dotfile.       | copy to srcdir/
0 | /tmp/containerfile    | /        | /containerfile  | copy to srcdir/
0 | /tmp/containerfile    | /.       | /containerfile  | copy to srcdir/.
0 | /tmp/containerfile    | /newfile | /newfile        | copy to srcdir/newfile
1 | containerfile1        | /        | /containerfile1 | copy from workdir (rel path) to srcdir
2 | subdir/containerfile2 | /        | /containerfile2 | copy from workdir/subdir (rel path) to srcdir
"

    # RUNNING container
    while read id src dest dest_fullname description; do
        # dest may be "''" for empty table cells
        if [[ $dest == "''" ]];then
            unset dest
        fi
        run_podman cp cpcontainer:$src "$srcdir$dest"
        is "$(< $srcdir$dest_fullname)" "${randomcontent[$id]}" "$description (cp ctr:$src to \$srcdir$dest)"
        rm $srcdir$dest_fullname
    done < <(parse_table "$tests")
    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer

    # Created container
    run_podman create --name cpcontainer --workdir=/srv $cpimage
    while read id src dest dest_fullname description; do
        # dest may be "''" for empty table cells
        if [[ $dest == "''" ]];then
            unset dest
        fi
        run_podman cp cpcontainer:$src "$srcdir$dest"
        is "$(< $srcdir$dest_fullname)" "${randomcontent[$id]}" "$description (cp ctr:$src to \$srcdir$dest)"
        rm $srcdir$dest_fullname
    done < <(parse_table "$tests")
    run_podman rm -t 0 -f cpcontainer

    run_podman rmi -f $cpimage
}


@test "podman cp file from container to container" {
    # Create 3 files with random content in the container.
    local -a randomcontent=(
        random-0-$(random_string 10)
        random-1-$(random_string 15)
        random-2-$(random_string 20)
    )

    run_podman run -d --name cpcontainer --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir;
         echo ${randomcontent[0]} > /tmp/containerfile;
         echo ${randomcontent[0]} > /tmp/dotfile.;
         echo ${randomcontent[1]} > /srv/containerfile1;
         echo ${randomcontent[2]} > /srv/subdir/containerfile2;
         sleep infinity"

    # Commit the image for testing non-running containers
    run_podman commit -q cpcontainer
    cpimage="$output"

    # format is: <id> | <source arg to cp> | <destination arg (appended to $srcdir) to cp> | <full dest path (appended to $srcdir)> | <test name>
    tests="
0 | /tmp/containerfile    |          | /containerfile  | /
0 | /tmp/dotfile.         |          | /dotfile.       | /
0 | /tmp/containerfile    | /        | /containerfile  | /
0 | /tmp/containerfile    | /.       | /containerfile  | /.
0 | /tmp/containerfile    | /newfile | /newfile        | /newfile
1 | containerfile1        | /        | /containerfile1 | copy from workdir (rel path) to /
2 | subdir/containerfile2 | /        | /containerfile2 | copy from workdir/subdir (rel path) to /
"

    # From RUNNING container
    local -a destcontainers=()
    while read id src dest dest_fullname description; do
        # dest may be "''" for empty table cells
        if [[ $dest == "''" ]];then
            unset dest
        fi

        # To RUNNING container
        run_podman run -d $IMAGE sleep infinity
        destcontainer="$output"
        destcontainers+=($destcontainer)
        run_podman cp cpcontainer:$src $destcontainer:"/$dest"
        run_podman exec $destcontainer cat "/$dest_fullname"
        is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"

	# To CREATED container
        run_podman create $IMAGE sleep infinity
        destcontainer="$output"
        destcontainers+=($destcontainer)
        run_podman cp cpcontainer:$src $destcontainer:"/$dest"
        run_podman start $destcontainer
        run_podman exec $destcontainer cat "/$dest_fullname"
        is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
    done < <(parse_table "$tests")
    run_podman kill cpcontainer ${destcontainers[@]}
    run_podman rm -t 0 -f cpcontainer ${destcontainers[@]}

    # From CREATED container
    destcontainers=()
    run_podman create --name cpcontainer --workdir=/srv $cpimage
    while read id src dest dest_fullname description; do
        # dest may be "''" for empty table cells
        if [[ $dest == "''" ]];then
            unset dest
        fi

        # To RUNNING container
        run_podman run -d $IMAGE sleep infinity
        destcontainer="$output"
        destcontainers+=($destcontainer)
        run_podman cp cpcontainer:$src $destcontainer:"/$dest"
        run_podman exec $destcontainer cat "/$dest_fullname"
        is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
	# To CREATED container
        run_podman create $IMAGE sleep infinity
        destcontainer="$output"
        destcontainers+=($destcontainer)
        run_podman cp cpcontainer:$src $destcontainer:"/$dest"
        run_podman start $destcontainer
        run_podman exec $destcontainer cat "/$dest_fullname"
        is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to /$dest)"
    done < <(parse_table "$tests")
    run_podman kill ${destcontainers[@]}
    run_podman rm -t 0 -f cpcontainer ${destcontainers[@]}
    run_podman rmi -f $cpimage
}


@test "podman cp dir from host to container" {
    srcdir=$PODMAN_TMPDIR
    mkdir -p $srcdir/dir/sub
    local -a randomcontent=(
        random-0-$(random_string 10)
        random-1-$(random_string 15)
    )
    echo "${randomcontent[0]}" > $srcdir/dir/sub/hostfile0
    echo "${randomcontent[1]}" > $srcdir/dir/sub/hostfile1

    # "." and "dir/." will copy the contents, so make sure that a dir ending
    # with dot is treated correctly.
    mkdir -p $srcdir/dir.
    cp -r $srcdir/dir/* $srcdir/dir.

    run_podman run -d --name cpcontainer --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir; sleep infinity"

    # Commit the image for testing non-running containers
    run_podman commit -q cpcontainer
    cpimage="$output"

    # format is: <source arg to cp (appended to srcdir)> | <destination arg to cp> | <full dest path> | <test name>
    tests="
 dir       | /        | /dir/sub     | copy dir  to root
 dir.      | /        | /dir./sub    | copy dir. to root
 dir/      | /tmp     | /tmp/dir/sub | copy dir/ to tmp
 dir/.     | /usr/    | /usr/sub     | copy dir/. usr/
 dir/sub   | .        | /srv/sub     | copy dir/sub to workdir (rel path)
 dir/sub/. | subdir/. | /srv/subdir  | copy dir/sub/. to workdir subdir (rel path)
 dir       | /newdir1 | /newdir1/sub | copy dir to newdir1
 dir/      | /newdir2 | /newdir2/sub | copy dir/ to newdir2
 dir/.     | /newdir3 | /newdir3/sub | copy dir/. to newdir3
"

    # RUNNING container
    while read src dest dest_fullname description; do
        # src may be "''" for empty table cells
        if [[ $src == "''" ]];then
            unset src
        fi
        run_podman cp $srcdir/$src cpcontainer:$dest
        run_podman exec cpcontainer cat $dest_fullname/hostfile0 $dest_fullname/hostfile1
        is "${lines[0]}" "${randomcontent[0]}" "$description (cp -> ctr:$dest)"
        is "${lines[1]}" "${randomcontent[1]}" "$description (cp -> ctr:$dest)"
    done < <(parse_table "$tests")
    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer

    # CREATED container
    while read src dest dest_fullname description; do
        # src may be "''" for empty table cells
        if [[ $src == "''" ]];then
            unset src
        fi
        run_podman create --name cpcontainer --workdir=/srv $cpimage sleep infinity
        run_podman cp $srcdir/$src cpcontainer:$dest
        run_podman start cpcontainer
        run_podman exec cpcontainer cat $dest_fullname/hostfile0 $dest_fullname/hostfile1
        is "${lines[0]}" "${randomcontent[0]}" "$description (cp -> ctr:$dest)"
        is "${lines[1]}" "${randomcontent[1]}" "$description (cp -> ctr:$dest)"
        run_podman kill cpcontainer
        run_podman rm -t 0 -f cpcontainer
    done < <(parse_table "$tests")

    run_podman create --name cpcontainer --workdir=/srv $cpimage sleep infinity
    run_podman 125 cp $srcdir cpcontainer:/etc/os-release
    is "$output" "Error: destination must be a directory when copying a directory" "cannot copy directory to file"
    run_podman rm -t 0 -f cpcontainer

    run_podman rmi -f $cpimage
}


@test "podman cp dir from container to host" {
    destdir=$PODMAN_TMPDIR/cp-test-dir-ctr-to-host
    mkdir -p $destdir

    # Create 2 files with random content in the container.
    local -a randomcontent=(
        random-0-$(random_string 10)
        random-1-$(random_string 15)
    )

    run_podman run -d --name cpcontainer --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir;
         echo ${randomcontent[0]} > /srv/subdir/containerfile0; \
         echo ${randomcontent[1]} > /srv/subdir/containerfile1; \
         mkdir /tmp/subdir.; cp /srv/subdir/* /tmp/subdir./; \
         sleep infinity"

    # Commit the image for testing non-running containers
    run_podman commit -q cpcontainer
    cpimage="$output"

    # format is: <source arg to cp (appended to /srv)> | <dest> | <full dest path> | <test name>
    tests="
/srv          |         | /srv/subdir    | copy /srv
/srv          | /newdir | /newdir/subdir | copy /srv to /newdir
/srv/         |         | /srv/subdir    | copy /srv/
/srv/.        |         | /subdir        | copy /srv/.
/srv/.        | /newdir | /newdir/subdir | copy /srv/. to /newdir
/srv/subdir/. |         |                | copy /srv/subdir/.
/tmp/subdir.  |         | /subdir.       | copy /tmp/subdir.
"

    # RUNNING container
    while read src dest dest_fullname description; do
        if [[ $src == "''" ]];then
            unset src
        fi
        if [[ $dest == "''" ]];then
            unset dest
        fi
        if [[ $dest_fullname == "''" ]];then
            unset dest_fullname
        fi
        run_podman cp cpcontainer:$src $destdir$dest
        is "$(< $destdir$dest_fullname/containerfile0)" "${randomcontent[0]}" "$description"
        is "$(< $destdir$dest_fullname/containerfile1)" "${randomcontent[1]}" "$description"
        rm -rf $destdir/*
    done < <(parse_table "$tests")
    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer

    # CREATED container
    run_podman create --name cpcontainer --workdir=/srv $cpimage
    while read src dest dest_fullname description; do
        if [[ $src == "''" ]];then
            unset src
        fi
        if [[ $dest == "''" ]];then
            unset dest
        fi
        if [[ $dest_fullname == "''" ]];then
            unset dest_fullname
        fi
        run_podman cp cpcontainer:$src $destdir$dest
        is "$(< $destdir$dest_fullname/containerfile0)" "${randomcontent[0]}" "$description"
        is "$(< $destdir$dest_fullname/containerfile1)" "${randomcontent[1]}" "$description"
        rm -rf $destdir/*
    done < <(parse_table "$tests")

    touch $destdir/testfile
    run_podman 125 cp cpcontainer:/etc/ $destdir/testfile
    is "$output" "Error: destination must be a directory when copying a directory" "cannot copy directory to file"
    run_podman rm -t 0 -f cpcontainer

    run_podman rmi -f $cpimage
}


@test "podman cp dir from container to container" {
    # Create 2 files with random content in the container.
    local -a randomcontent=(
        random-0-$(random_string 10)
        random-1-$(random_string 15)
    )

    run_podman run -d --name cpcontainer --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir;
         echo ${randomcontent[0]} > /srv/subdir/containerfile0; \
         echo ${randomcontent[1]} > /srv/subdir/containerfile1; \
         mkdir /tmp/subdir.; cp /srv/subdir/* /tmp/subdir./; \
         sleep infinity"

    # Commit the image for testing non-running containers
    run_podman commit -q cpcontainer
    cpimage="$output"

    # format is: <source arg to cp (appended to /srv)> | <dest> | <full dest path> | <test name>
    tests="
/srv          |         | /srv/subdir    | copy /srv
/srv          | /newdir | /newdir/subdir | copy /srv to /newdir
/srv/         |         | /srv/subdir    | copy /srv/
/srv/.        |         | /subdir        | copy /srv/.
/srv/.        | /newdir | /newdir/subdir | copy /srv/. to /newdir
/srv/subdir/. |         |                | copy /srv/subdir/.
/tmp/subdir.  |         | /subdir.       | copy /tmp/subdir.
"

    # From RUNNING container
    local -a destcontainers=()
    while read src dest dest_fullname description; do
        if [[ $src == "''" ]];then
            unset src
        fi
        if [[ $dest == "''" ]];then
            unset dest
        fi
        if [[ $dest_fullname == "''" ]];then
            unset dest_fullname
        fi

        # To RUNNING container
        run_podman run -d $IMAGE sleep infinity
        destcontainer="$output"
        destcontainers+=($destcontainer)
        run_podman cp cpcontainer:$src $destcontainer:"/$dest"
        run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
        is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"

	# To CREATED container
        run_podman create $IMAGE sleep infinity
        destcontainer="$output"
        destcontainers+=($destcontainer)
        run_podman cp cpcontainer:$src $destcontainer:"/$dest"
        run_podman start $destcontainer
        run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
        is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"
    done < <(parse_table "$tests")
    run_podman kill cpcontainer ${destcontainers[@]}
    run_podman rm -t 0 -f cpcontainer ${destcontainers[@]}

    # From CREATED container
    destcontainers=()
    run_podman create --name cpcontainer --workdir=/srv $cpimage
    while read src dest dest_fullname description; do
        if [[ $src == "''" ]];then
            unset src
        fi
        if [[ $dest == "''" ]];then
            unset dest
        fi
        if [[ $dest_fullname == "''" ]];then
            unset dest_fullname
        fi

	# To RUNNING container
        run_podman run -d $IMAGE sleep infinity
        destcontainer="$output"
        destcontainers+=($destcontainer)
        run_podman cp cpcontainer:$src $destcontainer:"/$dest"
        run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
        is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"

	# To CREATED container
        run_podman create $IMAGE sleep infinity
        destcontainer="$output"
        destcontainers+=($destcontainer)
        run_podman start $destcontainer
        run_podman cp cpcontainer:$src $destcontainer:"/$dest"
        run_podman exec $destcontainer cat "/$dest_fullname/containerfile0" "/$dest_fullname/containerfile1"
        is "$output" "${randomcontent[0]}
${randomcontent[1]}" "$description"
    done < <(parse_table "$tests")

    run_podman kill ${destcontainers[@]}
    run_podman rm -t 0 -f cpcontainer ${destcontainers[@]}
    run_podman rmi -f $cpimage
}


@test "podman cp symlinked directory from container" {
    destdir=$PODMAN_TMPDIR/cp-weird-symlink
    mkdir -p $destdir

    # Create 3 files with random content in the container.
    local -a randomcontent=(
        random-0-$(random_string 10)
        random-1-$(random_string 15)
    )

    run_podman run -d --name cpcontainer $IMAGE sh -c "echo ${randomcontent[0]} > /tmp/containerfile0; \
         echo ${randomcontent[1]} > /tmp/containerfile1; \
         mkdir /tmp/sub && cd /tmp/sub && ln -s .. weirdlink; \
         sleep infinity"

    # Commit the image for testing non-running containers
    run_podman commit -q cpcontainer
    cpimage="$output"

    # RUNNING container
    # NOTE: /dest does not exist yet but is expected to be created during copy
    run_podman cp cpcontainer:/tmp/sub/weirdlink $destdir/dest
    run cat $destdir/dest/containerfile0 $destdir/dest/containerfile1
    is "${lines[0]}" "${randomcontent[0]}" "eval symlink - running container"
    is "${lines[1]}" "${randomcontent[1]}" "eval symlink - running container"

    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer
    run rm -rf $srcdir/dest

    # CREATED container
    run_podman create --name cpcontainer $cpimage
    run_podman cp cpcontainer:/tmp/sub/weirdlink $destdir/dest
    run cat $destdir/dest/containerfile0 $destdir/dest/containerfile1
    is "${lines[0]}" "${randomcontent[0]}" "eval symlink - created container"
    is "${lines[1]}" "${randomcontent[1]}" "eval symlink - created container"
    run_podman rm -t 0 -f cpcontainer
    run_podman rmi $cpimage
}


@test "podman cp file from host to container volume" {
    srcdir=$PODMAN_TMPDIR/cp-test-volume
    mkdir -p $srcdir
    echo "This file should be in volume2" > $srcdir/hostfile
    volume1=$(random_string 20)
    volume2=$(random_string 20)

    run_podman volume create $volume1
    run_podman volume inspect $volume1 --format "{{.Mountpoint}}"
    volume1_mount="$output"
    run_podman volume create $volume2
    run_podman volume inspect $volume2 --format "{{.Mountpoint}}"
    volume2_mount="$output"

    # Create a container using the volume.  Note that copying on not-running
    # containers is allowed, so Podman has to analyze the container paths and
    # check if they are hitting a volume, and eventually resolve to the path on
    # the *host*.
    # This test is extra tricky, as volume2 is mounted into a sub-directory of
    # volume1.  Podman must copy the file into volume2 and not volume1.
    run_podman create --name cpcontainer -v $volume1:/tmp/volume -v $volume2:/tmp/volume/sub-volume $IMAGE

    run_podman cp $srcdir/hostfile cpcontainer:/tmp/volume/sub-volume
    is "$(< $volume2_mount/hostfile)" "This file should be in volume2"

    # Volume 1 must be empty.
    run ls $volume1_mount
    is "$output" ""

    run_podman rm -t 0 -f cpcontainer
    run_podman volume rm $volume1 $volume2
}


@test "podman cp file from host to container mount" {
    srcdir=$PODMAN_TMPDIR/cp-test-mount-src
    mountdir=$PODMAN_TMPDIR/cp-test-mount
    mkdir -p $srcdir $mountdir
    echo "This file should be in the mount" > $srcdir/hostfile

    volume=$(random_string 20)
    run_podman volume create $volume

    # Make it a bit more complex and put the mount on a volume.
    run_podman create --name cpcontainer -v $volume:/tmp/volume -v $mountdir:/tmp/volume/mount $IMAGE

    run_podman cp $srcdir/hostfile cpcontainer:/tmp/volume/mount
    is "$(< $mountdir/hostfile)" "This file should be in the mount"

    run_podman rm -t 0 -f cpcontainer
    run_podman volume rm $volume
}


# Create two random-name random-content files in /tmp in the container
# podman-cp them into the host using '/tmp/*', i.e. asking podman to
# perform wildcard expansion in the container. We should get both
# files copied into the host.
@test "podman cp * - wildcard copy multiple files from container to host" {
    srcdir=$PODMAN_TMPDIR/cp-test-in
    dstdir=$PODMAN_TMPDIR/cp-test-out
    mkdir -p $srcdir $dstdir

    rand_filename1=$(random_string 20)
    rand_content1=$(random_string 50)
    rand_filename2=$(random_string 20)
    rand_content2=$(random_string 50)

    run_podman run --name cpcontainer $IMAGE sh -c \
               "echo $rand_content1 >/tmp/$rand_filename1;
                echo $rand_content2 >/tmp/$rand_filename2"

    # cp no longer supports wildcarding
    run_podman 125 cp 'cpcontainer:/tmp/*' $dstdir

    run_podman rm -t 0 -f cpcontainer
}


# Create a file on the host; make a symlink in the container pointing
# into host-only space. Try to podman-cp that symlink. It should fail.
@test "podman cp - will not recognize symlink pointing into host space" {
    srcdir=$PODMAN_TMPDIR/cp-test-in
    dstdir=$PODMAN_TMPDIR/cp-test-out
    mkdir -p $srcdir $dstdir
    echo "this file is on the host" >$srcdir/hostfile

    run_podman run --name cpcontainer $IMAGE \
               sh -c "ln -s $srcdir/hostfile /tmp/badlink"
    # This should fail because, from the container's perspective, the symlink
    # points to a nonexistent file
    run_podman 125 cp 'cpcontainer:/tmp/*' $dstdir/

    # FIXME: this might not be the exactly correct error message
    is "$output" 'Error: "/tmp/\*" could not be found on container.*'

    # make sure there are no files in dstdir
    is "$(/bin/ls -1 $dstdir)" "" "incorrectly copied symlink from host"

    run_podman rm -t 0 -f cpcontainer
}


# Issue #3829 - like the above, but with a level of indirection in the
# wildcard expansion: create a file on the host; create a symlink in
# the container named 'file1' pointing to this file; then another symlink
# in the container pointing to 'file*' (file star). Try to podman-cp
# this invalid double symlink. It must fail.
@test "podman cp - will not expand globs in host space (#3829)" {
    srcdir=$PODMAN_TMPDIR/cp-test-in
    dstdir=$PODMAN_TMPDIR/cp-test-out
    mkdir -p $srcdir $dstdir
    echo "This file is on the host" > $srcdir/hostfile

    run_podman run --name cpcontainer $IMAGE \
               sh -c "ln -s $srcdir/hostfile file1;ln -s file\* copyme"
    run_podman 125 cp cpcontainer:copyme $dstdir

    is "$output" 'Error: "copyme*" could not be found on container.*'

    # make sure there are no files in dstdir
    is "$(/bin/ls -1 $dstdir)" "" "incorrectly copied symlink from host"

    run_podman rm -t 0 -f cpcontainer
}


# Another symlink into host space, this one named '*' (star). cp should fail.
@test "podman cp - will not expand wildcard" {
    srcdir=$PODMAN_TMPDIR/cp-test-in
    dstdir=$PODMAN_TMPDIR/cp-test-out
    mkdir -p $srcdir $dstdir
    echo "This file lives on the host" > $srcdir/hostfile

    run_podman run --name cpcontainer $IMAGE \
               sh -c "ln -s $srcdir/hostfile /tmp/\*"
    run_podman 125 cp 'cpcontainer:/tmp/*' $dstdir

    is "$output" 'Error: "/tmp/\*" could not be found on container.*'

    # dstdir must be empty
    is "$(/bin/ls -1 $dstdir)" "" "incorrectly copied symlink from host"

    run_podman rm -t 0 -f cpcontainer
}


# THIS IS EXTREMELY WEIRD. Podman expands symlinks in weird ways.
@test "podman cp into container: weird symlink expansion" {
    srcdir=$PODMAN_TMPDIR/cp-test-in
    dstdir=$PODMAN_TMPDIR/cp-test-out
    mkdir -p $srcdir $dstdir

    rand_filename1=$(random_string 20)
    rand_content1=$(random_string 50)
    echo $rand_content1 > $srcdir/$rand_filename1

    rand_filename2=$(random_string 20)
    rand_content2=$(random_string 50)
    echo $rand_content2 > $srcdir/$rand_filename2

    rand_filename3=$(random_string 20)
    rand_content3=$(random_string 50)
    echo $rand_content3 > $srcdir/$rand_filename3

    # Create tmp subdirectories in container, most with an invalid 'x' symlink
    # Keep container running so we can exec into it.
    run_podman run -d --name cpcontainer $IMAGE \
               sh -c "mkdir /tmp/d1;ln -s /tmp/nonesuch1 /tmp/d1/x;
                      mkdir /tmp/d2;ln -s /tmp/nonesuch2 /tmp/d2/x;
                      mkdir /tmp/d3;
                      trap 'exit 0' 15;while :;do sleep 0.5;done"

    # Copy file from host into container, into a file named 'x'
    # Note that the second has a trailing slash, implying a directory.
    # Since that destination directory doesn't exist, the cp will fail
    run_podman cp --pause=false $srcdir/$rand_filename1 cpcontainer:/tmp/d1/x
    is "$output" "" "output from podman cp 1"

    run_podman 125 cp --pause=false $srcdir/$rand_filename2 cpcontainer:/tmp/d2/x/
    is "$output" 'Error: "/tmp/d2/x/" could not be found on container cpcontainer: No such file or directory' "cp will not create nonexistent destination directory"

    run_podman cp --pause=false $srcdir/$rand_filename3 cpcontainer:/tmp/d3/x
    is "$output" "" "output from podman cp 3"

    # Read back.
    # In the first case, podman actually creates the file nonesuch1 (i.e.
    # podman expands 'x -> nonesuch1' and, instead of overwriting x,
    # creates an actual file).
    run_podman exec cpcontainer cat /tmp/nonesuch1
    is "$output" "$rand_content1" "cp creates destination file"


    # cp into nonexistent directory should not mkdir nonesuch2 directory
    run_podman 1 exec cpcontainer test -e /tmp/nonesuch2

    # In the third case, podman (correctly imo) creates a file named 'x'
    run_podman exec cpcontainer cat /tmp/d3/x
    is "$output" "$rand_content3" "cp creates file named x"

    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer
}


# rhbz1741718 : file copied into container:/var/lib/foo appears as /foo
# (docker only, never seems to have affected podman. Make sure it never does).
@test "podman cp into a subdirectory matching GraphRoot" {
    # Create tempfile with random name and content
    srcdir=$PODMAN_TMPDIR/cp-test-in
    mkdir -p $srcdir
    rand_filename=$(random_string 20)
    rand_content=$(random_string 50)
    echo $rand_content > $srcdir/$rand_filename
    chmod 644 $srcdir/$rand_filename

    # Determine path to podman storage (eg /var/lib/c/s, or $HOME/.local/...)
    run_podman info --format '{{.Store.GraphRoot}}'
    graphroot=$output

    # Create that directory in the container, and sleep (to keep container
    # running, so we can exec into it). The trap/while is so podman-rm will
    # run quickly instead of taking 10 seconds.
    run_podman run -d --name cpcontainer $IMAGE sh -c \
               "mkdir -p $graphroot; trap 'exit 0' 15;while :;do sleep 0.5;done"

    # Copy from host into container.
    run_podman cp --pause=false $srcdir/$rand_filename cpcontainer:$graphroot/$rand_filename

    # ls, and confirm it's there.
    run_podman exec cpcontainer ls -l $graphroot/$rand_filename
    is "$output" "-rw-r--r-- .* 1 .* root .* 51 .* $graphroot/$rand_filename" \
       "File is copied into container in the correct (full) path"

    # Confirm it has the expected content (this is unlikely to ever fail)
    run_podman exec cpcontainer cat $graphroot/$rand_filename
    is "$output" "$rand_content" "Contents of file copied into container"

    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer
}


@test "podman cp from stdin to container" {
    # Create tempfile with random name and content
    srcdir=$PODMAN_TMPDIR/cp-test-stdin
    mkdir -p $srcdir
    rand_filename=$(random_string 20)
    rand_content=$(random_string 50)
    echo $rand_content > $srcdir/$rand_filename
    chmod 644 $srcdir/$rand_filename

    # Now tar it up!
    tar_file=$PODMAN_TMPDIR/archive.tar.gz
    tar -zvcf $tar_file $srcdir

    run_podman run -d --name cpcontainer $IMAGE sleep infinity

    # NOTE: podman is supposed to auto-detect the gzip compression and
    # decompress automatically.
    #
    # "-" will evaluate to "/dev/stdin" when used a source.
    run_podman cp - cpcontainer:/tmp < $tar_file
    run_podman exec cpcontainer cat /tmp/$srcdir/$rand_filename
    is "$output" "$rand_content"
    run_podman exec cpcontainer rm -rf /tmp/$srcdir

    # Now for "/dev/stdin".
    # Note: while this works, the content ends up in Nirvana.
    #       Same for Docker.
    run_podman cp /dev/stdin cpcontainer:/tmp < $tar_file

    # Error checks below ...

    # Input stream must be a (compressed) tar archive.
    run_podman 125 cp - cpcontainer:/tmp < $srcdir/$rand_filename
    is "$output" "Error: source must be a (compressed) tar archive when copying from stdin"

    # Destination must be a directory (on an existing file).
    run_podman exec cpcontainer touch /tmp/file.txt
    run_podman 125 cp - cpcontainer:/tmp/file.txt < $tar_file
    is "$output" 'Error: destination must be a directory when copying from stdin'

    # Destination must be a directory (on an absent path).
    run_podman 125 cp - cpcontainer:/tmp/IdoNotExist < $tar_file
    is "$output" 'Error: destination must be a directory when copying from stdin'

    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer
}


@test "podman cp from container to stdout" {
    srcdir=$PODMAN_TMPDIR/cp-test-stdout
    mkdir -p $srcdir
    rand_content=$(random_string 50)

    run_podman run -d --name cpcontainer $IMAGE sleep infinity

    run_podman exec cpcontainer sh -c "echo '$rand_content' > /tmp/file.txt"
    run_podman exec cpcontainer touch /tmp/empty.txt

    # Make sure that only "-" gets special treatment. "/dev/stdout"
    run_podman 125 cp cpcontainer:/tmp/file.txt /dev/stdout
    is "$output" 'Error: invalid destination: "/dev/stdout" must be a directory or a regular file'

    # Copying from stdout will always compress.  So let's copy the previously
    # created file from the container via stdout, untar the archive and make
    # sure the file exists with the expected content.
    #
    # NOTE that we can't use run_podman because that uses the BATS 'run'
    # function which redirects stdout and stderr. Here we need to guarantee
    # that podman's stdout is a pipe, not any other form of redirection.

    # Copy file.
    $PODMAN cp cpcontainer:/tmp/file.txt - > $srcdir/stdout.tar
    if [ $? -ne 0 ]; then
        die "Command failed: podman cp ... - | cat"
    fi

    tar xvf $srcdir/stdout.tar -C $srcdir
    is "$(< $srcdir/file.txt)" "$rand_content"
    run 1 ls $srcdir/empty.txt
    rm -f $srcdir/*

    # Copy directory.
    $PODMAN cp cpcontainer:/tmp - > $srcdir/stdout.tar
    if [ $? -ne 0 ]; then
        die "Command failed: podman cp ... - | cat : $output"
    fi

    tar xvf $srcdir/stdout.tar -C $srcdir
    is "$(< $srcdir/tmp/file.txt)" "$rand_content"
    is "$(< $srcdir/tmp/empty.txt)" ""

    run_podman kill cpcontainer
    run_podman rm -t 0 -f cpcontainer
}

function teardown() {
    # In case any test fails, clean up the container we left behind
    run_podman rm -t 0 f cpcontainer
    basic_teardown
}

# vim: filetype=sh