mirror of
https://github.com/containers/podman.git
synced 2025-09-20 19:24:58 +08:00
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:
@ -290,7 +290,7 @@ func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
destdir := destPath
|
destdir := destPath
|
||||||
if !srcfi.IsDir() && !strings.HasSuffix(dest, string(os.PathSeparator)) {
|
if !srcfi.IsDir() {
|
||||||
destdir = filepath.Dir(destPath)
|
destdir = filepath.Dir(destPath)
|
||||||
}
|
}
|
||||||
_, err = os.Stat(destdir)
|
_, err = os.Stat(destdir)
|
||||||
@ -329,7 +329,7 @@ func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, ch
|
|||||||
|
|
||||||
destfi, err := os.Stat(destPath)
|
destfi, err := os.Stat(destPath)
|
||||||
if err != nil {
|
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)
|
return errors.Wrapf(err, "failed to get stat of dest path %s", destPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ Assuming a path separator of /, a first argument of **src_path** and second argu
|
|||||||
- **dest_path** does not exist
|
- **dest_path** does not exist
|
||||||
- the file is saved to a file created at **dest_path**
|
- the file is saved to a file created at **dest_path**
|
||||||
- **dest_path** does not exist and ends with /
|
- **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
|
- **dest_path** exists and is a file
|
||||||
- the destination is overwritten with the source file's contents
|
- the destination is overwritten with the source file's contents
|
||||||
- **dest_path** exists and is a directory
|
- **dest_path** exists and is a directory
|
||||||
|
@ -51,6 +51,10 @@ var _ = Describe("Podman cp", func() {
|
|||||||
err := ioutil.WriteFile(srcPath, fromHostToContainer, 0644)
|
err := ioutil.WriteFile(srcPath, fromHostToContainer, 0644)
|
||||||
Expect(err).To(BeNil())
|
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 = podmanTest.Podman([]string{"cp", srcPath, name + ":foo"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
@ -65,30 +69,29 @@ var _ = Describe("Podman cp", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
It("podman cp file to dir", func() {
|
It("podman cp file to dir", func() {
|
||||||
srcPath := filepath.Join(podmanTest.RunRoot, "cp_test.txt")
|
name := "testctr"
|
||||||
dstDir := filepath.Join(podmanTest.RunRoot, "receive")
|
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")
|
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)
|
err := ioutil.WriteFile(srcPath, fromHostToContainer, 0644)
|
||||||
Expect(err).To(BeNil())
|
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 = podmanTest.Podman([]string{"cp", srcPath, name + ":foodir/"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
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()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
os.Remove("cp_test.txt")
|
os.Remove("/tmp/cp_test.txt")
|
||||||
os.RemoveAll("receive")
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman cp dir to dir", func() {
|
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 = podmanTest.Podman([]string{"cp", name + ":/foo.tar.gz", "-"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
|
os.RemoveAll(testDirPath)
|
||||||
|
os.Remove("file.tar.gz")
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman cp tar", func() {
|
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()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
@ -157,7 +168,7 @@ var _ = Describe("Podman cp", func() {
|
|||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
session = podmanTest.Podman([]string{"start", "-a", "testctr"})
|
session = podmanTest.Podman([]string{"exec", testctr, "ls", "-l", "foo"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
Expect(session.OutputToString()).To(ContainSubstring("file.tar"))
|
Expect(session.OutputToString()).To(ContainSubstring("file.tar"))
|
||||||
@ -187,6 +198,15 @@ var _ = Describe("Podman cp", func() {
|
|||||||
|
|
||||||
_, err = os.Stat("/tmp/cp_test.txt")
|
_, err = os.Stat("/tmp/cp_test.txt")
|
||||||
Expect(err).To(Not(BeNil()))
|
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() {
|
It("podman cp volume", func() {
|
||||||
session := podmanTest.Podman([]string{"volume", "create", "data"})
|
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 = podmanTest.Podman([]string{"cp", "container1" + ":/data/cp_vol1", "cp_vol2"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
|
os.Remove("cp_vol")
|
||||||
|
os.Remove("cp_vol2")
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman cp from ctr chown ", func() {
|
It("podman cp from ctr chown ", func() {
|
||||||
|
@ -144,12 +144,13 @@ load helpers
|
|||||||
trap 'exit 0' 15;while :;do sleep 0.5;done"
|
trap 'exit 0' 15;while :;do sleep 0.5;done"
|
||||||
|
|
||||||
# Copy file from host into container, into a file named 'x'
|
# 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
|
run_podman cp --pause=false $srcdir/$rand_filename1 cpcontainer:/tmp/d1/x
|
||||||
is "$output" "" "output from podman cp 1"
|
is "$output" "" "output from podman cp 1"
|
||||||
|
|
||||||
run_podman cp --pause=false $srcdir/$rand_filename2 cpcontainer:/tmp/d2/x/
|
run_podman 125 cp --pause=false $srcdir/$rand_filename2 cpcontainer:/tmp/d2/x/
|
||||||
is "$output" "" "output from podman cp 3"
|
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
|
run_podman cp --pause=false $srcdir/$rand_filename3 cpcontainer:/tmp/d3/x
|
||||||
is "$output" "" "output from podman cp 3"
|
is "$output" "" "output from podman cp 3"
|
||||||
@ -161,10 +162,8 @@ load helpers
|
|||||||
run_podman exec cpcontainer cat /tmp/nonesuch1
|
run_podman exec cpcontainer cat /tmp/nonesuch1
|
||||||
is "$output" "$rand_content1" "cp creates destination file"
|
is "$output" "$rand_content1" "cp creates destination file"
|
||||||
|
|
||||||
# In the second case, podman creates a directory nonesuch2, then
|
# cp into nonexistent directory should not mkdir nonesuch2 directory
|
||||||
# creates a file with the same name as the input file. THIS IS WEIRD!
|
run_podman 1 exec cpcontainer test -e /tmp/nonesuch2
|
||||||
run_podman exec cpcontainer cat /tmp/nonesuch2/$rand_filename2
|
|
||||||
is "$output" "$rand_content2" "cp creates destination dir and file"
|
|
||||||
|
|
||||||
# In the third case, podman (correctly imo) creates a file named 'x'
|
# 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
|
||||||
|
Reference in New Issue
Block a user