From 25fffdb74f142c57a3727da82a316592969e7088 Mon Sep 17 00:00:00 2001 From: Ed Santiago Date: Thu, 25 Jul 2024 11:29:31 -0600 Subject: [PATCH] CI: cp tests: use safename Continuing efforts to make system tests parallel-safe Signed-off-by: Ed Santiago --- test/system/065-cp.bats | 452 +++++++++++++++++++++------------------- 1 file changed, 239 insertions(+), 213 deletions(-) diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats index 191cc885b5..33dc8dd10f 100644 --- a/test/system/065-cp.bats +++ b/test/system/065-cp.bats @@ -22,11 +22,12 @@ load helpers mkdir -p $srcdir/subdir echo "${randomcontent[2]}" > $srcdir/subdir/dotfile. - run_podman run -d --name destrunning --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir; echo READY; sleep infinity" - wait_for_ready destrunning + local destrunning="c-destrun-$(safename)" + run_podman run -d --name $destrunning --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir; echo READY; sleep infinity" + wait_for_ready $destrunning # Commit the image for testing non-running containers - run_podman commit -q destrunning + run_podman commit -q $destrunning cpimage="$output" # format is: | | | @@ -52,36 +53,37 @@ load helpers # RUNNING container while read id dest dest_fullname description; do - run_podman cp $srcdir/hostfile$id destrunning:$dest - run_podman exec destrunning cat $dest_fullname + run_podman cp $srcdir/hostfile$id $destrunning:$dest + run_podman exec $destrunning 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. destrunning:/tmp - run_podman exec destrunning cat /tmp/dotfile. + run_podman cp $srcdir/subdir/dotfile. $destrunning:/tmp + run_podman exec $destrunning cat /tmp/dotfile. is "$output" "${randomcontent[2]}" "$description (cp -> ctr:$dest)" # Host path does not exist. - run_podman 125 cp $srcdir/IdoNotExist destrunning:/tmp + run_podman 125 cp $srcdir/IdoNotExist $destrunning:/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 destrunning:/IdoNotExist/ - is "$output" 'Error: "/IdoNotExist/" could not be found on container destrunning: no such file or directory' \ + run_podman 125 cp $srcdir/hostfile0 $destrunning:/IdoNotExist/ + is "$output" "Error: \"/IdoNotExist/\" could not be found on container $destrunning: no such file or directory" \ "copy into nonexistent path in container" - run_podman rm -t 0 -f destrunning + run_podman rm -t 0 -f $destrunning # CREATED container while read id dest dest_fullname description; do - run_podman create --name destcreated --workdir=/srv $cpimage sleep infinity - run_podman cp $srcdir/hostfile$id destcreated:$dest - run_podman start destcreated - run_podman exec destcreated cat $dest_fullname + local destcreated="c-destcreated-$(safename)" + run_podman create --name $destcreated --workdir=/srv $cpimage sleep infinity + run_podman cp $srcdir/hostfile$id $destcreated:$dest + run_podman start $destcreated + run_podman exec $destcreated cat $dest_fullname is "$output" "${randomcontent[$id]}" "$description (cp -> ctr:$dest)" - run_podman rm -t 0 -f destcreated + run_podman rm -t 0 -f $destcreated done < <(parse_table "$tests") run_podman rmi -f $cpimage @@ -95,19 +97,21 @@ load helpers echo $content > $srcdir/file # RUNNING container - run_podman run -d --mount type=tmpfs,dst=/tmp --name destrunning $IMAGE sleep infinity - run_podman cp $srcdir/file destrunning:/tmp - run_podman exec destrunning cat /tmp/file + local destrunning="c-destrun-$(safename)" + run_podman run -d --mount type=tmpfs,dst=/tmp --name $destrunning $IMAGE sleep infinity + run_podman cp $srcdir/file $destrunning:/tmp + run_podman exec $destrunning cat /tmp/file is "$output" "${content}" "cp to running container's tmpfs" - run_podman rm -t 0 -f destrunning + run_podman rm -t 0 -f $destrunning # CREATED container (with copy up) - run_podman create --mount type=tmpfs,dst=/tmp --name destcreated $IMAGE sleep infinity - run_podman cp $srcdir/file destcreated:/tmp - run_podman start destcreated - run_podman exec destcreated cat /tmp/file + local destcreated=cdestcreated$(safename) + run_podman create --mount type=tmpfs,dst=/tmp --name $destcreated $IMAGE sleep infinity + run_podman cp $srcdir/file $destcreated:/tmp + run_podman start $destcreated + run_podman exec $destcreated cat /tmp/file is "$output" "${content}" "cp to created container's tmpfs" - run_podman rm -t 0 -f destcreated + run_podman rm -t 0 -f $destcreated } @@ -120,11 +124,12 @@ load helpers keepid="--userns=keep-id" is_rootless || keepid="" - run_podman run --user=$userid ${keepid} -d --name destrunning $IMAGE sleep infinity - run_podman cp $srcdir/hostfile destrunning:/tmp/hostfile - run_podman exec destrunning stat -c "%u" /tmp/hostfile + local destrunning="c-destrun-$(safename)" + run_podman run --user=$userid ${keepid} -d --name $destrunning $IMAGE sleep infinity + run_podman cp $srcdir/hostfile $destrunning:/tmp/hostfile + run_podman exec $destrunning stat -c "%u" /tmp/hostfile is "$output" "$userid" "copied file is chowned to the container user" - run_podman rm -t 0 -f destrunning + run_podman rm -t 0 -f $destrunning } @test "podman cp (-a=false) file from host to container and check ownership" { @@ -140,14 +145,14 @@ load helpers keepid="--userns=keep-id" is_rootless || keepid="" - run_podman run --user=$userid ${keepid} -d --name destrunning $IMAGE sleep infinity - run_podman cp -a=false - destrunning:/tmp/ < "${tmpdir}/a.tar" - run_podman exec destrunning stat -c "%u:%g" /tmp/a.txt + local destrunning="c-destrun-$(safename)" + run_podman run --user=$userid ${keepid} -d --name $destrunning $IMAGE sleep infinity + run_podman cp -a=false - $destrunning:/tmp/ < "${tmpdir}/a.tar" + run_podman exec $destrunning stat -c "%u:%g" /tmp/a.txt is "$output" "1042:1043" "copied file retains uid/gid from the tar" - run_podman rm -t 0 -f destrunning + run_podman rm -t 0 -f $destrunning } - @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" @@ -157,10 +162,11 @@ load helpers 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 rm -t 0 -f cpcontainer + local cpcontainer="cpctr-$(safename)" + 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 rm -t 0 -f $cpcontainer } @test "podman cp file from container to host" { @@ -173,17 +179,18 @@ load helpers random-1-$(random_string 15) random-2-$(random_string 20) ) - run_podman run -d --name srcrunning --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir; + local srcrunning="c-srcrun-$(safename)" + run_podman run -d --name $srcrunning --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; echo READY; sleep infinity" - wait_for_ready srcrunning + wait_for_ready $srcrunning # Commit the image for testing non-running containers - run_podman commit -q srcrunning + run_podman commit -q $srcrunning cpimage="$output" # format is: | | | | @@ -205,29 +212,29 @@ load helpers if [[ $dest == "''" ]];then unset dest fi - run_podman cp srcrunning:$src "$srcdir$dest" + run_podman cp $srcrunning:$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 srcrunning + run_podman rm -t 0 -f $srcrunning # Created container - run_podman create --name srccreated --workdir=/srv $cpimage + local srccreated="c-src-crt-$(safename)" + run_podman create --name $srccreated --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 srccreated:$src "$srcdir$dest" + run_podman cp $srccreated:$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 srccreated + run_podman rm -t 0 -f $srccreated 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=( @@ -236,17 +243,18 @@ load helpers random-2-$(random_string 20) ) - run_podman run -d --name srcrunning --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir; + local srcrunning="c-src-run-$(safename)" + run_podman run -d --name $srcrunning --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; echo READY; sleep infinity" - wait_for_ready srcrunning + wait_for_ready $srcrunning # Commit the image for testing non-running containers - run_podman commit -q srcrunning + run_podman commit -q $srcrunning cpimage="$output" # format is: | | | | @@ -274,7 +282,7 @@ load helpers run_podman run -d $IMAGE sleep infinity destcontainer="$output" destcontainers+=($destcontainer) - run_podman cp srcrunning:$src $destcontainer:"$dest" + run_podman cp $srcrunning:$src $destcontainer:"$dest" run_podman exec $destcontainer cat "$dest_fullname" is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to $dest - RUNNING)" @@ -282,16 +290,17 @@ load helpers run_podman create $IMAGE sleep infinity destcontainer="$output" destcontainers+=($destcontainer) - run_podman cp srcrunning:$src $destcontainer:"$dest" + run_podman cp $srcrunning:$src $destcontainer:"$dest" run_podman start $destcontainer run_podman exec $destcontainer cat "$dest_fullname" is "$output" "${randomcontent[$id]}" "$description (cp ctr:$src to $dest - CREATED)" done < <(parse_table "$tests") - run_podman rm -t 0 -f srcrunning ${destcontainers[@]} + run_podman rm -t 0 -f $srcrunning ${destcontainers[@]} # From CREATED container destcontainers=() - run_podman create --name srccreated --workdir=/srv $cpimage + local srccreated="c-src-crt-$(safename)" + run_podman create --name $srccreated --workdir=/srv $cpimage while read id src dest dest_fullname description; do # dest may be "''" for empty table cells if [[ $dest == "''" ]];then @@ -302,23 +311,22 @@ load helpers run_podman run -d $IMAGE sleep infinity destcontainer="$output" destcontainers+=($destcontainer) - run_podman cp srccreated:$src $destcontainer:"$dest" + run_podman cp $srccreated:$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 srccreated:$src $destcontainer:"$dest" + run_podman cp $srccreated:$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 rm -t 0 -f srccreated ${destcontainers[@]} + run_podman rm -t 0 -f $srccreated ${destcontainers[@]} run_podman rmi -f $cpimage } - @test "podman cp dir from host to container" { srcdir=$PODMAN_TMPDIR mkdir -p $srcdir/dir/sub @@ -334,11 +342,12 @@ load helpers mkdir -p $srcdir/dir. cp -r $srcdir/dir/* $srcdir/dir. - run_podman run -d --name destrunning --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir; echo READY;sleep infinity" - wait_for_ready destrunning + local destrunning="c-destrun-$(safename)" + run_podman run -d --name $destrunning --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir; echo READY;sleep infinity" + wait_for_ready $destrunning # Commit the image for testing non-running containers - run_podman commit -q destrunning + run_podman commit -q $destrunning cpimage="$output" # format is: | | | @@ -358,37 +367,38 @@ load helpers # RUNNING container while read src dest dest_fullname description; do - run_podman cp $srcdir/$src destrunning:$dest - run_podman exec destrunning cat $dest_fullname/hostfile0 $dest_fullname/hostfile1 + run_podman cp $srcdir/$src $destrunning:$dest + run_podman exec $destrunning cat $dest_fullname/hostfile0 $dest_fullname/hostfile1 is "${lines[*]}" "${randomcontent[*]}" "$description (cp -> ctr:$dest - RUNNING)" done < <(parse_table "$tests") - run_podman rm -t 0 -f destrunning + run_podman rm -t 0 -f $destrunning # CREATED container - run_podman create --name destcreated --workdir=/srv $cpimage sleep infinity + local destcreated="c-dest-created-$(safename)" + run_podman create --name $destcreated --workdir=/srv $cpimage sleep infinity while read src dest dest_fullname description; do - run_podman cp $srcdir/$src destcreated:$dest + run_podman cp $srcdir/$src $destcreated:$dest # tests checks are done below done < <(parse_table "$tests") # Now do the test checks, it is a bit ugly that we do this over two loops but this # makes the test faster as we do not have to start/stop the container on every iteration. - run_podman start destcreated + run_podman start $destcreated while read src dest dest_fullname description; do - run_podman exec destcreated cat $dest_fullname/hostfile0 $dest_fullname/hostfile1 + run_podman exec $destcreated cat $dest_fullname/hostfile0 $dest_fullname/hostfile1 is "${lines[*]}" "${randomcontent[*]}" "$description (cp -> ctr:$dest - CREATED)" done < <(parse_table "$tests") - run_podman rm -t 0 -f destcreated + run_podman rm -t 0 -f $destcreated - run_podman create --name destnotdir --workdir=/srv $cpimage sleep infinity - run_podman 125 cp $srcdir destnotdir:/etc/os-release + local destnotdir="c-destnotdir-$(safename)" + run_podman create --name $destnotdir --workdir=/srv $cpimage sleep infinity + run_podman 125 cp $srcdir $destnotdir:/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 destnotdir + run_podman rm -t 0 -f $destnotdir 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 @@ -399,16 +409,17 @@ load helpers random-1-$(random_string 15) ) - run_podman run -d --name srcrunning --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir; + local srcrunning="c-src-run-$(safename)" + run_podman run -d --name $srcrunning --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./; \ echo READY; sleep infinity" - wait_for_ready srcrunning + wait_for_ready $srcrunning # Commit the image for testing non-running containers - run_podman commit -q srcrunning + run_podman commit -q $srcrunning cpimage="$output" # format is: | | | @@ -432,15 +443,16 @@ load helpers if [[ $dest_fullname == "''" ]];then unset dest_fullname fi - run_podman cp srcrunning:$src $destdir$dest + run_podman cp $srcrunning:$src $destdir$dest is "$(< $destdir$dest_fullname/containerfile0)" "${randomcontent[0]}" "$description RUNNING (containerfile0)" is "$(< $destdir$dest_fullname/containerfile1)" "${randomcontent[1]}" "$description RUNNING (containerfile1)" rm -rf ${destdir:?}/* done < <(parse_table "$tests") - run_podman rm -t 0 -f srcrunning + run_podman rm -t 0 -f $srcrunning # CREATED container - run_podman create --name srccreated --workdir=/srv $cpimage + local srccreated="c-src-crt-$(safename)" + run_podman create --name $srccreated --workdir=/srv $cpimage while read src dest dest_fullname description; do if [[ $dest == "''" ]];then unset dest @@ -448,21 +460,20 @@ load helpers if [[ $dest_fullname == "''" ]];then unset dest_fullname fi - run_podman cp srccreated:$src $destdir$dest + run_podman cp $srccreated:$src $destdir$dest is "$(< $destdir$dest_fullname/containerfile0)" "${randomcontent[0]}" "$description CREATED (containerfile0)" is "$(< $destdir$dest_fullname/containerfile1)" "${randomcontent[1]}" "$description CREATED (containerfile1)" rm -rf ${destdir:?}/* done < <(parse_table "$tests") touch $destdir/testfile - run_podman 125 cp srccreated:/etc/ $destdir/testfile + run_podman 125 cp $srccreated:/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 srccreated + run_podman rm -t 0 -f $srccreated 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=( @@ -470,16 +481,17 @@ load helpers random-1-$(random_string 15) ) - run_podman run -d --name srcrunning --workdir=/srv $IMAGE sh -c "mkdir /srv/subdir; + local srcrunning="c-src-run-$(safename)" + run_podman run -d --name $srcrunning --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./; \ echo READY; sleep infinity" - wait_for_ready srcrunning + wait_for_ready $srcrunning # Commit the image for testing non-running containers - run_podman commit -q srcrunning + run_podman commit -q $srcrunning cpimage="$output" # format is: | | | @@ -506,7 +518,7 @@ load helpers run_podman run -d $IMAGE sleep infinity destcontainer="$output" destcontainers+=($destcontainer) - run_podman cp srcrunning:$src $destcontainer:"$dest" + run_podman cp $srcrunning:$src $destcontainer:"$dest" run_podman exec $destcontainer cat "$dest_fullname/containerfile0" "$dest_fullname/containerfile1" is "$(echo $output)" "${randomcontent[*]}" "$description - from RUNNING to RUNNING" @@ -514,16 +526,17 @@ load helpers run_podman create $IMAGE sleep infinity destcontainer="$output" destcontainers+=($destcontainer) - run_podman cp srcrunning:$src $destcontainer:"$dest" + run_podman cp $srcrunning:$src $destcontainer:"$dest" run_podman start $destcontainer run_podman exec $destcontainer cat "$dest_fullname/containerfile0" "$dest_fullname/containerfile1" is "$(echo $output)" "${randomcontent[*]}" "$description - from RUNNING to CREATED/STARTED" done < <(parse_table "$tests") - run_podman rm -t 0 -f srcrunning ${destcontainers[@]} + run_podman rm -t 0 -f $srcrunning ${destcontainers[@]} # From CREATED container destcontainers=() - run_podman create --name srccreated --workdir=/srv $cpimage + local srccreated="c-src-crt-$(safename)" + run_podman create --name $srccreated --workdir=/srv $cpimage while read src dest dest_fullname description; do if [[ $dest_fullname == "''" ]];then unset dest_fullname @@ -533,7 +546,7 @@ load helpers run_podman run -d $IMAGE sleep infinity destcontainer="$output" destcontainers+=($destcontainer) - run_podman cp srccreated:$src $destcontainer:"$dest" + run_podman cp $srccreated:$src $destcontainer:"$dest" run_podman exec $destcontainer cat "$dest_fullname/containerfile0" "$dest_fullname/containerfile1" is "$(echo $output)" "${randomcontent[*]}" "$description - from CREATED to RUNNING" @@ -542,16 +555,15 @@ load helpers destcontainer="$output" destcontainers+=($destcontainer) run_podman start $destcontainer - run_podman cp srccreated:$src $destcontainer:"$dest" + run_podman cp $srccreated:$src $destcontainer:"$dest" run_podman exec $destcontainer cat "$dest_fullname/containerfile0" "$dest_fullname/containerfile1" is "$(echo $output)" "${randomcontent[*]}" "$description - from CREATED to CREATED" done < <(parse_table "$tests") - run_podman rm -t 0 -f srccreated ${destcontainers[@]} + run_podman rm -t 0 -f $srccreated ${destcontainers[@]} run_podman rmi -f $cpimage } - @test "podman cp symlinked directory from container" { destdir=$PODMAN_TMPDIR/cp-weird-symlink mkdir -p $destdir @@ -562,46 +574,47 @@ load helpers random-1-$(random_string 15) ) - run_podman run -d --name srcrunning $IMAGE sh -c "echo ${randomcontent[0]} > /tmp/containerfile0; \ + local srcrunning="c-src-run-$(safename)" + run_podman run -d --name $srcrunning $IMAGE sh -c "echo ${randomcontent[0]} > /tmp/containerfile0; \ echo ${randomcontent[1]} > /tmp/containerfile1; \ mkdir /tmp/sub && cd /tmp/sub && ln -s .. weirdlink; \ echo READY; sleep infinity" - wait_for_ready srcrunning + wait_for_ready $srcrunning # Commit the image for testing non-running containers - run_podman commit -q srcrunning + run_podman commit -q $srcrunning cpimage="$output" # RUNNING container # NOTE: /dest does not exist yet but is expected to be created during copy - run_podman cp srcrunning:/tmp/sub/weirdlink $destdir/dest + run_podman cp $srcrunning:/tmp/sub/weirdlink $destdir/dest for i in 0 1; do assert "$(< $destdir/dest/containerfile$i)" = "${randomcontent[$i]}" \ "eval symlink - running container - file $i/1" done - run_podman rm -t 0 -f srcrunning + run_podman rm -t 0 -f $srcrunning rm -rf $srcdir/dest # CREATED container - run_podman create --name srccreated $cpimage - run_podman cp srccreated:/tmp/sub/weirdlink $destdir/dest + local srccreated="c-src-crt-$(safename)" + run_podman create --name $srccreated $cpimage + run_podman cp $srccreated:/tmp/sub/weirdlink $destdir/dest for i in 0 1; do assert "$(< $destdir/dest/containerfile$i)" = "${randomcontent[$i]}" \ "eval symlink - created container - file $i/1" done - run_podman rm -t 0 -f srccreated + run_podman rm -t 0 -f $srccreated 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) + volume1="vol1-$(safename)" + volume2="vol2-$(safename)" run_podman volume create $volume1 run_podman volume inspect $volume1 --format "{{.Mountpoint}}" @@ -616,16 +629,17 @@ load helpers # 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 + local cpcontainer="c-cp_$(safename)" + 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 + 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 rm -t 0 -f $cpcontainer run_podman volume rm $volume1 $volume2 } @@ -636,16 +650,17 @@ load helpers mkdir -p $srcdir $mountdir echo "This file should be in the mount" > $srcdir/hostfile - volume=$(random_string 20) + volume="v-$(safename)" 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 + local cpcontainer="c-cp-$(safename)" + run_podman create --name $cpcontainer -v $volume:/tmp/volume -v $mountdir:/tmp/volume/mount $IMAGE - run_podman cp $srcdir/hostfile cpcontainer:/tmp/volume/mount + 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 rm -t 0 -f $cpcontainer run_podman volume rm $volume } @@ -664,14 +679,15 @@ load helpers rand_filename2=$(random_string 20) rand_content2=$(random_string 50) - run_podman run --name cpcontainer $IMAGE sh -c \ + local cpcontainer="c-cp-$(safename)" + 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 125 cp '$cpcontainer:/tmp/*' $dstdir - run_podman rm -t 0 -f cpcontainer + run_podman rm -t 0 -f $cpcontainer } @@ -683,11 +699,12 @@ load helpers mkdir -p $srcdir $dstdir echo "this file is on the host" >$srcdir/hostfile - run_podman run --name cpcontainer $IMAGE \ + local cpcontainer="c-cp-$(safename)" + 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/ + 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.*' @@ -695,7 +712,7 @@ load helpers # 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 + run_podman rm -t 0 -f $cpcontainer } @@ -710,16 +727,17 @@ load helpers mkdir -p $srcdir $dstdir echo "This file is on the host" > $srcdir/hostfile - run_podman run --name cpcontainer $IMAGE \ + local cpcontainer="c-cp-$(safename)" + run_podman run --name $cpcontainer $IMAGE \ sh -c "ln -s $srcdir/hostfile file1;ln -s file\* copyme" - run_podman 125 cp cpcontainer:copyme $dstdir + 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 + run_podman rm -t 0 -f $cpcontainer } @@ -730,16 +748,17 @@ load helpers mkdir -p $srcdir $dstdir echo "This file lives on the host" > $srcdir/hostfile - run_podman run --name cpcontainer $IMAGE \ + local cpcontainer="c-cp-$(safename)" + run_podman run --name $cpcontainer $IMAGE \ sh -c "ln -s $srcdir/hostfile /tmp/\*" - run_podman 125 cp 'cpcontainer:/tmp/*' $dstdir + 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 + run_podman rm -t 0 -f $cpcontainer } @@ -763,41 +782,42 @@ load helpers # 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 \ + local cpcontainer="c-cp-$(safename)" + 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;echo READY;while :;do sleep 0.5;done" - wait_for_ready cpcontainer + wait_for_ready $cpcontainer # 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 $srcdir/$rand_filename1 cpcontainer:/tmp/d1/x + run_podman cp $srcdir/$rand_filename1 $cpcontainer:/tmp/d1/x is "$output" "" "output from podman cp 1" - run_podman 125 cp $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 125 cp $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 $srcdir/$rand_filename3 cpcontainer:/tmp/d3/x + run_podman cp $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 + 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 + 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 + run_podman exec $cpcontainer cat /tmp/d3/x is "$output" "$rand_content3" "cp creates file named x" - run_podman rm -t 0 -f cpcontainer + run_podman rm -t 0 -f $cpcontainer } @@ -817,26 +837,26 @@ load helpers graphroot=$output # Create that directory in the container, and keep container running - run_podman run -d --name cpcontainer $IMAGE sh -c \ + local cpcontainer="c-cp-$(safename)" + run_podman run -d --name $cpcontainer $IMAGE sh -c \ "mkdir -p $graphroot; echo READY; top" - wait_for_ready cpcontainer + wait_for_ready $cpcontainer # Copy from host into container. - run_podman cp $srcdir/$rand_filename cpcontainer:$graphroot/$rand_filename + run_podman cp $srcdir/$rand_filename $cpcontainer:$graphroot/$rand_filename # ls, and confirm it's there. - run_podman exec cpcontainer ls -l $graphroot/$rand_filename + 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 + run_podman exec $cpcontainer cat $graphroot/$rand_filename is "$output" "$rand_content" "Contents of file copied into container" - run_podman rm -t 0 -f 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 @@ -850,38 +870,39 @@ load helpers tar_file=$PODMAN_TMPDIR/archive.tar.gz tar -zvcf $tar_file $srcdir - run_podman run -d --name cpcontainer $IMAGE sleep infinity + local cpcontainer="c-cp-$(safename)" + 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 + 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 + 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 + 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 + 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 + 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' "cp from stdin to existing file" # Destination must be a directory (on an absent path). - run_podman 125 cp - cpcontainer:/tmp/IdoNotExist < $tar_file + run_podman 125 cp - $cpcontainer:/tmp/IdoNotExist < $tar_file is "$output" 'Error: destination must be a directory when copying from stdin' "cp from stdin to absent path" - run_podman rm -t 0 -f cpcontainer + run_podman rm -t 0 -f $cpcontainer } @@ -890,13 +911,14 @@ load helpers mkdir -p $srcdir rand_content=$(random_string 50) - run_podman run -d --name cpcontainer $IMAGE sleep infinity + local cpcontainer="c-cp-$(safename)" + 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 + 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 + 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 @@ -908,7 +930,7 @@ load helpers # that podman's stdout is redirected cleanly with no artifacts. # Copy file. - $PODMAN cp cpcontainer:/tmp/file.txt - > $srcdir/stdout.tar + $PODMAN cp $cpcontainer:/tmp/file.txt - > $srcdir/stdout.tar tar xvf $srcdir/stdout.tar -C $srcdir is "$(< $srcdir/file.txt)" "$rand_content" "File contents: file.txt" @@ -918,46 +940,48 @@ load helpers rm -f $srcdir/* # Copy directory. - $PODMAN cp cpcontainer:/tmp - > $srcdir/stdout.tar + $PODMAN cp $cpcontainer:/tmp - > $srcdir/stdout.tar tar xvf $srcdir/stdout.tar -C $srcdir is "$(< $srcdir/tmp/file.txt)" "$rand_content" "file.txt contents" is "$(< $srcdir/tmp/empty.txt)" "" "empty.txt contents" - run_podman rm -t 0 -f cpcontainer + run_podman rm -t 0 -f $cpcontainer } @test "podman cp --overwrite file - ctr/ctr" { rand_content_file=$(random_string 50) rand_content_dir=$(random_string 50) - run_podman run -d --name ctr-file $IMAGE sh -c "echo '$rand_content_file' > /tmp/foo; echo READY; sleep infinity" - run_podman run -d --name ctr-dir $IMAGE sh -c "mkdir /tmp/foo; echo '$rand_content_dir' > /tmp/foo/file.txt; echo READY; sleep infinity" - wait_for_ready ctr-file - wait_for_ready ctr-dir + local ctrfile="c-f-$(safename)" + local ctrdir="c-d-$(safename)" + run_podman run -d --name $ctrfile $IMAGE sh -c "echo '$rand_content_file' > /tmp/foo; echo READY; sleep infinity" + run_podman run -d --name $ctrdir $IMAGE sh -c "mkdir /tmp/foo; echo '$rand_content_dir' > /tmp/foo/file.txt; echo READY; sleep infinity" + wait_for_ready $ctrfile + wait_for_ready $ctrdir # overwrite a directory with a file - run_podman 125 cp ctr-file:/tmp/foo ctr-dir:/tmp + run_podman 125 cp $ctrfile:/tmp/foo $ctrdir:/tmp if ! is_remote; then # remote just returns a 500 is "$output" ".* error creating \"/tmp/foo\": .*: file exists.*" fi - run_podman cp --overwrite ctr-file:/tmp/foo ctr-dir:/tmp - run_podman exec ctr-dir cat /tmp/foo - is "$output" "$rand_content_file" "ctr-dir:/tmp/foo, after cp --overwrite, is a file" + run_podman cp --overwrite $ctrfile:/tmp/foo $ctrdir:/tmp + run_podman exec $ctrdir cat /tmp/foo + is "$output" "$rand_content_file" "$ctrdir:/tmp/foo, after cp --overwrite, is a file" - # reset the ctr-dir container - run_podman exec ctr-dir sh -c "rm -rf /tmp/foo; mkdir /tmp/foo; echo '$rand_content_dir' > /tmp/foo/file.txt" + # reset the $ctrdir container + run_podman exec $ctrdir sh -c "rm -rf /tmp/foo; mkdir /tmp/foo; echo '$rand_content_dir' > /tmp/foo/file.txt" # overwrite a file with a directory - run_podman 125 cp ctr-dir:/tmp/foo ctr-file:/tmp + run_podman 125 cp $ctrdir:/tmp/foo $ctrfile:/tmp if ! is_remote; then # remote just returns a 500 is "$output" ".* error creating \"/tmp/foo\": .*: file exists.*" fi - run_podman cp --overwrite ctr-dir:/tmp/foo ctr-file:/tmp - run_podman exec ctr-file cat /tmp/foo/file.txt + run_podman cp --overwrite $ctrdir:/tmp/foo $ctrfile:/tmp + run_podman exec $ctrfile cat /tmp/foo/file.txt is "$output" "$rand_content_dir" - run_podman rm -t 0 -f ctr-file ctr-dir + run_podman rm -t 0 -f $ctrfile $ctrdir } @test "podman cp --overwrite file - ctr/host" { @@ -967,31 +991,33 @@ load helpers rand_content_file=$(random_string 50) rand_content_dir=$(random_string 50) - run_podman run -d --name ctr-file $IMAGE sh -c "echo '$rand_content_file' > /tmp/foo; echo READY; sleep infinity" - run_podman run -d --name ctr-dir $IMAGE sh -c "mkdir /tmp/foo; echo '$rand_content_dir' > /tmp/foo/file.txt; echo READY; sleep infinity" - wait_for_ready ctr-file - wait_for_ready ctr-dir + local ctrfile="c-f-$(safename)" + local ctrdir="c-d-$(safename)" + run_podman run -d --name $ctrfile $IMAGE sh -c "echo '$rand_content_file' > /tmp/foo; echo READY; sleep infinity" + run_podman run -d --name $ctrdir $IMAGE sh -c "mkdir /tmp/foo; echo '$rand_content_dir' > /tmp/foo/file.txt; echo READY; sleep infinity" + wait_for_ready $ctrfile + wait_for_ready $ctrdir # overwrite a directory with a file mkdir $hostdir/foo - run_podman 125 cp ctr-file:/tmp/foo $hostdir + run_podman 125 cp $ctrfile:/tmp/foo $hostdir if ! is_remote; then # remote just returns a 500 is "$output" ".* error creating \"/foo\": .*: file exists.*" fi - run_podman cp --overwrite ctr-file:/tmp/foo $hostdir + run_podman cp --overwrite $ctrfile:/tmp/foo $hostdir is "$(< $hostdir/foo)" "$rand_content_file" # overwrite a file with a directory rm -rf $hostdir/foo touch $hostdir/foo - run_podman 125 cp ctr-dir:/tmp/foo $hostdir + run_podman 125 cp $ctrdir:/tmp/foo $hostdir if ! is_remote; then # remote just returns a 500 is "$output" ".* error creating \"/foo\": .*: file exists.*" fi - run_podman cp --overwrite ctr-dir:/tmp/foo $hostdir + run_podman cp --overwrite $ctrdir:/tmp/foo $hostdir is "$(< $hostdir/foo/file.txt)" "$rand_content_dir" - run_podman rm -t 0 -f ctr-file ctr-dir + run_podman rm -t 0 -f $ctrfile $ctrdir } @test "podman cp --overwrite file - host/ctr" { @@ -1001,34 +1027,36 @@ load helpers rand_content_file=$(random_string 50) rand_content_dir=$(random_string 50) - run_podman run -d --name ctr-dir $IMAGE sh -c "mkdir /tmp/foo; echo READY; sleep infinity" - run_podman run -d --name ctr-file $IMAGE sh -c "touch /tmp/foo; echo READY; sleep infinity" - wait_for_ready ctr-dir - wait_for_ready ctr-file + local ctrfile="c-f-$(safename)" + local ctrdir="c-d-$(safename)" + run_podman run -d --name $ctrdir $IMAGE sh -c "mkdir /tmp/foo; echo READY; sleep infinity" + run_podman run -d --name $ctrfile $IMAGE sh -c "touch /tmp/foo; echo READY; sleep infinity" + wait_for_ready $ctrdir + wait_for_ready $ctrfile # overwrite a directory with a file echo "$rand_content_file" > $hostdir/foo - run_podman 125 cp $hostdir/foo ctr-dir:/tmp + run_podman 125 cp $hostdir/foo $ctrdir:/tmp if ! is_remote; then # remote just returns a 500 is "$output" ".* error creating \"/tmp/foo\": .*: file exists.*" fi - run_podman cp --overwrite $hostdir/foo ctr-dir:/tmp - run_podman exec ctr-dir cat /tmp/foo + run_podman cp --overwrite $hostdir/foo $ctrdir:/tmp + run_podman exec $ctrdir cat /tmp/foo is "$output" "$rand_content_file" # overwrite a file with a directory rm -f $hostdir/foo mkdir $hostdir/foo echo "$rand_content_dir" > $hostdir/foo/file.txt - run_podman 125 cp $hostdir/foo ctr-file:/tmp + run_podman 125 cp $hostdir/foo $ctrfile:/tmp if ! is_remote; then # remote just returns a 500 is "$output" ".* error creating \"/tmp/foo\": .*: file exists.*" fi - run_podman cp --overwrite $hostdir/foo ctr-file:/tmp - run_podman exec ctr-file cat /tmp/foo/file.txt - is "$output" "$rand_content_dir" "ctr-file:/tmp/foo/file.txt, after cp --overwrite" + run_podman cp --overwrite $hostdir/foo $ctrfile:/tmp + run_podman exec $ctrfile cat /tmp/foo/file.txt + is "$output" "$rand_content_dir" "$ctrfile:/tmp/foo/file.txt, after cp --overwrite" - run_podman rm -t 0 -f ctr-file ctr-dir + run_podman rm -t 0 -f $ctrfile $ctrdir } # https://github.com/containers/podman/pull/16498 @@ -1038,45 +1066,43 @@ load helpers mkdir -p $srcdir/test1. $srcdir/test2 touch $srcdir/test1./file1 $srcdir/test2/file2 - run_podman run -d --name=test-ctr --rm $IMAGE sleep infinity - run_podman cp $srcdir/test1. test-ctr:/tmp/foo - run_podman exec test-ctr /bin/ls -1 /tmp/foo/ + local cname="c-$(safename)" + run_podman run -d --name=$cname --rm $IMAGE sleep infinity + run_podman cp $srcdir/test1. $cname:/tmp/foo + run_podman exec $cname /bin/ls -1 /tmp/foo/ assert "$output" = "file1" "ls ctr:/tmp/foo: only file1 exists, nothing more" - run_podman rm -f -t0 test-ctr + run_podman rm -f -t0 $cname } @test "podman cp - dot notation - container to host" { dstdir=$PODMAN_TMPDIR/dst mkdir -p $dstdir - run_podman run -d --name=test-ctr --rm $IMAGE sh -c "mkdir -p /foo/test1. /foo/test2; touch /foo/test1./file1 /foo/test2/file2; echo READY;sleep infinity" - wait_for_ready test-ctr + local cname="c-$(safename)" + run_podman run -d --name=$cname --rm $IMAGE sh -c "mkdir -p /foo/test1. /foo/test2; touch /foo/test1./file1 /foo/test2/file2; echo READY;sleep infinity" + wait_for_ready $cname - run_podman cp test-ctr:/foo/test1. $dstdir/foo + run_podman cp $cname:/foo/test1. $dstdir/foo run /bin/ls -1 $dstdir/foo assert "$output" = "file1" "ls [local]/foo: only file1 was copied, nothing more" - run_podman rm -f -t0 test-ctr + run_podman rm -f -t0 $cname } @test "podman cp - dot notation - container to container" { - run_podman run -d --name=src-ctr --rm $IMAGE sh -c "mkdir -p /foo/test1. /foo/test2; touch /foo/test1./file1 /foo/test2/file2; echo READY;sleep infinity" - wait_for_ready src-ctr + local ctrsrc="c-src-$(safename)" + run_podman run -d --name=$ctrsrc --rm $IMAGE sh -c "mkdir -p /foo/test1. /foo/test2; touch /foo/test1./file1 /foo/test2/file2; echo READY;sleep infinity" + wait_for_ready $ctrsrc - run_podman run -d --name=dest-ctr --rm $IMAGE sleep infinity - run_podman cp src-ctr:/foo/test1. dest-ctr:/foo + local ctrdest="c-test-$(safename)" + run_podman run -d --name=$ctrdest --rm $IMAGE sleep infinity + run_podman cp $ctrsrc:/foo/test1. $ctrdest:/foo - run_podman exec dest-ctr /bin/ls -1 /foo + run_podman exec $ctrdest /bin/ls -1 /foo assert "$output" = "file1" "ls dest-ctr:/foo: only file1 exists, nothing more" - run_podman rm -f -t0 src-ctr dest-ctr -} - -function teardown() { - # In case any test fails, clean up the container we left behind - run_podman rm -t 0 -f --ignore cpcontainer - basic_teardown + run_podman rm -f -t0 $ctrsrc $ctrdest } # vim: filetype=sh