fix cp none exists dest path ends with '/'

close #3894
This patch let podman cp return 'no such file or directory' error if DEST_PATH does not exist and ends with / when copying file.

Signed-off-by: Qi Wang <qiwan@redhat.com>
This commit is contained in:
Qi Wang 2019-09-24 11:35:49 -04:00
parent f197ebe851
commit 0144c3796b
4 changed files with 47 additions and 25 deletions

View file

@ -290,7 +290,7 @@ func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, ch
}
destdir := destPath
if !srcfi.IsDir() && !strings.HasSuffix(dest, string(os.PathSeparator)) {
if !srcfi.IsDir() {
destdir = filepath.Dir(destPath)
}
_, err = os.Stat(destdir)
@ -329,7 +329,7 @@ func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, ch
destfi, err := os.Stat(destPath)
if err != nil {
if !os.IsNotExist(err) {
if !os.IsNotExist(err) || strings.HasSuffix(dest, string(os.PathSeparator)) {
return errors.Wrapf(err, "failed to get stat of dest path %s", destPath)
}
}

View file

@ -29,7 +29,7 @@ Assuming a path separator of /, a first argument of **src_path** and second argu
- **dest_path** does not exist
- the file is saved to a file created at **dest_path**
- **dest_path** does not exist and ends with /
- **dest_path** is created as a directory and the file is copied into this directory using the basename from **src_path**
- Error condition: the destination directory must exist.
- **dest_path** exists and is a file
- the destination is overwritten with the source file's contents
- **dest_path** exists and is a directory

View file

@ -51,6 +51,10 @@ var _ = Describe("Podman cp", func() {
err := ioutil.WriteFile(srcPath, fromHostToContainer, 0644)
Expect(err).To(BeNil())
session = podmanTest.Podman([]string{"cp", srcPath, name + ":foo/"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Not(Equal(0)))
session = podmanTest.Podman([]string{"cp", srcPath, name + ":foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@ -65,30 +69,29 @@ var _ = Describe("Podman cp", func() {
})
It("podman cp file to dir", func() {
srcPath := filepath.Join(podmanTest.RunRoot, "cp_test.txt")
dstDir := filepath.Join(podmanTest.RunRoot, "receive")
name := "testctr"
setup := podmanTest.RunTopContainer(name)
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
srcPath := "/tmp/cp_test.txt"
fromHostToContainer := []byte("copy from host to container directory")
session := podmanTest.Podman([]string{"create", ALPINE, "ls", "foodir/"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
name := session.OutputToString()
err := ioutil.WriteFile(srcPath, fromHostToContainer, 0644)
Expect(err).To(BeNil())
err = os.Mkdir(dstDir, 0755)
Expect(err).To(BeNil())
session := podmanTest.Podman([]string{"exec", name, "mkdir", "foodir"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"cp", srcPath, name + ":foodir/"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"cp", name + ":foodir/cp_test.txt", dstDir})
session = podmanTest.Podman([]string{"exec", name, "ls", "foodir/cp_test.txt"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
os.Remove("cp_test.txt")
os.RemoveAll("receive")
os.Remove("/tmp/cp_test.txt")
})
It("podman cp dir to dir", func() {
@ -137,10 +140,18 @@ var _ = Describe("Podman cp", func() {
session = podmanTest.Podman([]string{"cp", name + ":/foo.tar.gz", "-"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
os.RemoveAll(testDirPath)
os.Remove("file.tar.gz")
})
It("podman cp tar", func() {
session := podmanTest.Podman([]string{"create", "--name", "testctr", ALPINE, "ls", "-l", "foo"})
testctr := "testctr"
setup := podmanTest.RunTopContainer(testctr)
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
session := podmanTest.Podman([]string{"exec", testctr, "mkdir", "foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@ -157,7 +168,7 @@ var _ = Describe("Podman cp", func() {
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"start", "-a", "testctr"})
session = podmanTest.Podman([]string{"exec", testctr, "ls", "-l", "foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("file.tar"))
@ -187,6 +198,15 @@ var _ = Describe("Podman cp", func() {
_, err = os.Stat("/tmp/cp_test.txt")
Expect(err).To(Not(BeNil()))
session = podmanTest.Podman([]string{"exec", name, "ln", "-s", "/tmp/nonesuch", "/test1"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
session = podmanTest.Podman([]string{"cp", "--pause=false", srcPath, name + ":/test1/"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Not(Equal(0)))
})
It("podman cp volume", func() {
session := podmanTest.Podman([]string{"volume", "create", "data"})
@ -208,6 +228,9 @@ var _ = Describe("Podman cp", func() {
session = podmanTest.Podman([]string{"cp", "container1" + ":/data/cp_vol1", "cp_vol2"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
os.Remove("cp_vol")
os.Remove("cp_vol2")
})
It("podman cp from ctr chown ", func() {

View file

@ -144,12 +144,13 @@ load helpers
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; this will trigger mkdir
# 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 cp --pause=false $srcdir/$rand_filename2 cpcontainer:/tmp/d2/x/
is "$output" "" "output from podman cp 3"
run_podman 125 cp --pause=false $srcdir/$rand_filename2 cpcontainer:/tmp/d2/x/
is "$output" "Error: failed to get stat of dest path .*stat.* 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"
@ -161,10 +162,8 @@ load helpers
run_podman exec cpcontainer cat /tmp/nonesuch1
is "$output" "$rand_content1" "cp creates destination file"
# In the second case, podman creates a directory nonesuch2, then
# creates a file with the same name as the input file. THIS IS WEIRD!
run_podman exec cpcontainer cat /tmp/nonesuch2/$rand_filename2
is "$output" "$rand_content2" "cp creates destination dir and 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