Skip to content

Commit 6a95cf4

Browse files
committed
Fix windows path handling in docker cp
Signed-off-by: David Negstad <[email protected]>
1 parent a36276f commit 6a95cf4

36 files changed

+466
-291
lines changed

cmd/podman/containers/cp.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,11 @@ func copyToContainer(container string, containerPath string, hostPath string) er
428428
// rename accordingly.
429429
getOptions.Rename = map[string]string{filepath.Base(hostTarget): containerBaseName}
430430
}
431-
if err := buildahCopiah.Get("/", "", getOptions, []string{hostTarget}, writer); err != nil {
431+
432+
// On Windows, the root path needs to be <drive>:\, while otherwise
433+
// it needs to be /. Combining filepath.VolumeName() + string(os.PathSeparator)
434+
// gives us the correct path for the current OS.
435+
if err := buildahCopiah.Get(filepath.VolumeName(hostTarget)+string(os.PathSeparator), "", getOptions, []string{hostTarget}, writer); err != nil {
432436
return fmt.Errorf("copying from host: %w", err)
433437
}
434438
return nil

go.mod

+5-5
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ require (
1313
github.com/checkpoint-restore/checkpointctl v1.3.0
1414
github.com/checkpoint-restore/go-criu/v7 v7.2.0
1515
github.com/containernetworking/plugins v1.6.2
16-
github.com/containers/buildah v1.39.1-0.20250324153001-6d9381d08265
17-
github.com/containers/common v0.62.3-0.20250326101258-442957aa798d
16+
github.com/containers/buildah v1.39.1-0.20250326204000-898fbb2d25c6
17+
github.com/containers/common v0.62.3-0.20250321171839-dbeb17e40c80
1818
github.com/containers/conmon v2.0.20+incompatible
1919
github.com/containers/gvisor-tap-vsock v0.8.5
2020
github.com/containers/image/v5 v5.34.3-0.20250311194052-d84dbab374e7
@@ -29,7 +29,7 @@ require (
2929
github.com/cyphar/filepath-securejoin v0.4.1
3030
github.com/digitalocean/go-qemu v0.0.0-20250212194115-ee9b0668d242
3131
github.com/docker/distribution v2.8.3+incompatible
32-
github.com/docker/docker v28.0.1+incompatible
32+
github.com/docker/docker v28.0.3+incompatible
3333
github.com/docker/go-connections v0.5.0
3434
github.com/docker/go-plugins-helpers v0.0.0-20240701071450-45e2431495c8
3535
github.com/docker/go-units v0.5.0
@@ -61,7 +61,7 @@ require (
6161
github.com/opencontainers/runtime-spec v1.2.1
6262
github.com/opencontainers/runtime-tools v0.9.1-0.20241108202711-f7e3563b0271
6363
github.com/opencontainers/selinux v1.12.0
64-
github.com/openshift/imagebuilder v1.2.16-0.20250220150830-7ebfb09d364e
64+
github.com/openshift/imagebuilder v1.2.16-0.20250224193648-e87e4e105fd8
6565
github.com/rootless-containers/rootlesskit/v2 v2.3.2
6666
github.com/shirou/gopsutil/v4 v4.25.2
6767
github.com/sirupsen/logrus v1.9.3
@@ -170,7 +170,7 @@ require (
170170
github.com/miekg/pkcs11 v1.1.1 // indirect
171171
github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
172172
github.com/mitchellh/mapstructure v1.5.0 // indirect
173-
github.com/moby/buildkit v0.20.1 // indirect
173+
github.com/moby/buildkit v0.20.2 // indirect
174174
github.com/moby/docker-image-spec v1.3.1 // indirect
175175
github.com/moby/patternmatcher v0.6.0 // indirect
176176
github.com/moby/sys/mountinfo v0.7.2 // indirect

go.sum

+10-10
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ github.com/containernetworking/cni v1.2.3 h1:hhOcjNVUQTnzdRJ6alC5XF+wd9mfGIUaj8F
7676
github.com/containernetworking/cni v1.2.3/go.mod h1:DuLgF+aPd3DzcTQTtp/Nvl1Kim23oFKdm2okJzBQA5M=
7777
github.com/containernetworking/plugins v1.6.2 h1:pqP8Mq923TLyef5g97XfJ/xpDeVek4yF8A4mzy9Tc4U=
7878
github.com/containernetworking/plugins v1.6.2/go.mod h1:SP5UG3jDO9LtmfbBJdP+nl3A1atOtbj2MBOYsnaxy64=
79-
github.com/containers/buildah v1.39.1-0.20250324153001-6d9381d08265 h1:3cFRoMP4Up4sN/f2TOcCKSxiX/mbHCN5FwqHc+rw2B8=
80-
github.com/containers/buildah v1.39.1-0.20250324153001-6d9381d08265/go.mod h1:8DuzWORynpU4q7coSL0aElpPVMDZFoCOnz9gzqU8Ics=
81-
github.com/containers/common v0.62.3-0.20250326101258-442957aa798d h1:xvajXgoMD3wfumCQqI3h+950b5areKa8BEBE2SAmZCA=
82-
github.com/containers/common v0.62.3-0.20250326101258-442957aa798d/go.mod h1:jEHYmXVWsev+dizV4Oh2mZrPFAEzlVeUj/zrCx1jse0=
79+
github.com/containers/buildah v1.39.1-0.20250326204000-898fbb2d25c6 h1:13hjkXp5YO7GDMVv1kzEUI/AdObmu4dJ4y79yr7l7kU=
80+
github.com/containers/buildah v1.39.1-0.20250326204000-898fbb2d25c6/go.mod h1:AvIRsFvWfSuMNGoMm8hXFaOGvzhsnujWz1C38rk+mk4=
81+
github.com/containers/common v0.62.3-0.20250321171839-dbeb17e40c80 h1:U605lFaEyA0zsy4+gqZxth9V2Dl1UXBfcamA3cnQ33E=
82+
github.com/containers/common v0.62.3-0.20250321171839-dbeb17e40c80/go.mod h1:IW8fUkTIwJkeclyROeASOV5FvFBpHjtQj/XBXffhuBk=
8383
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
8484
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
8585
github.com/containers/gvisor-tap-vsock v0.8.5 h1:s7PA8znsZ4mamev5nNLsQqduYSlz1Ze5TWjfXnAfpEs=
@@ -133,8 +133,8 @@ github.com/docker/cli v28.0.1+incompatible h1:g0h5NQNda3/CxIsaZfH4Tyf6vpxFth7PYl
133133
github.com/docker/cli v28.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
134134
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
135135
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
136-
github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0=
137-
github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
136+
github.com/docker/docker v28.0.3+incompatible h1:tH0UhLUB03ApG1dLaYDfaz8zUwOglgJzuUftoDKpDtE=
137+
github.com/docker/docker v28.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
138138
github.com/docker/docker-credential-helpers v0.9.2 h1:50JF7ADQiHdAVBRtg/vy883Y4U5+5GmPOBNtUU+X+6A=
139139
github.com/docker/docker-credential-helpers v0.9.2/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
140140
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
@@ -357,8 +357,8 @@ github.com/mistifyio/go-zfs/v3 v3.0.1 h1:YaoXgBePoMA12+S1u/ddkv+QqxcfiZK4prI6HPn
357357
github.com/mistifyio/go-zfs/v3 v3.0.1/go.mod h1:CzVgeB0RvF2EGzQnytKVvVSDwmKJXxkOTUGbNrTja/k=
358358
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
359359
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
360-
github.com/moby/buildkit v0.20.1 h1:sT0ZXhhNo5rVbMcYfgttma3TdUHfO5JjFA0UAL8p9fY=
361-
github.com/moby/buildkit v0.20.1/go.mod h1:Rq9nB/fJImdk6QeM0niKtOHJqwKeYMrK847hTTDVuA4=
360+
github.com/moby/buildkit v0.20.2 h1:qIeR47eQ1tzI1rwz0on3Xx2enRw/1CKjFhoONVcTlMA=
361+
github.com/moby/buildkit v0.20.2/go.mod h1:DhaF82FjwOElTftl0JUAJpH/SUIUx4UvcFncLeOtlDI=
362362
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
363363
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
364364
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
@@ -406,8 +406,8 @@ github.com/opencontainers/runtime-tools v0.9.1-0.20241108202711-f7e3563b0271 h1:
406406
github.com/opencontainers/runtime-tools v0.9.1-0.20241108202711-f7e3563b0271/go.mod h1:oIH6VwKkaDOO+SIYZpdwrC/0wKYqrfO6E1sG1j3UVws=
407407
github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=
408408
github.com/opencontainers/selinux v1.12.0/go.mod h1:BTPX+bjVbWGXw7ZZWUbdENt8w0htPSrlgOOysQaU62U=
409-
github.com/openshift/imagebuilder v1.2.16-0.20250220150830-7ebfb09d364e h1:yKNaeGlH4+h06lkADFa5rAIG7ifxOiV04kLRCL0rct8=
410-
github.com/openshift/imagebuilder v1.2.16-0.20250220150830-7ebfb09d364e/go.mod h1:cK6MLyBl1IHmIYGLY/2SLOG6p0PtEDUOC7khxsFYUXE=
409+
github.com/openshift/imagebuilder v1.2.16-0.20250224193648-e87e4e105fd8 h1:iPRNMpzJ4HEtIXseOxdIkgNYlp7HJShtEk7URm1BUSU=
410+
github.com/openshift/imagebuilder v1.2.16-0.20250224193648-e87e4e105fd8/go.mod h1:gASl6jikVG3bCFnLjG6Ow5TeKwKVvrqUUj8C7EUmqc8=
411411
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
412412
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
413413
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f h1:/UDgs8FGMqwnHagNDPGOlts35QkhAZ8by3DR7nMih7M=

pkg/copy/fileinfo.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -83,20 +83,20 @@ func ResolveHostPath(path string) (*FileInfo, error) {
8383
// is preserved. The filepath API among tends to clean up a bit too much but
8484
// we *must* preserve this data by all means.
8585
func PreserveBasePath(original, resolved string) string {
86-
// Handle "/"
87-
if strings.HasSuffix(original, "/") {
88-
if !strings.HasSuffix(resolved, "/") {
89-
resolved += "/"
86+
// Handle "/" or "\\" on Windows.
87+
if strings.HasSuffix(original, string(os.PathSeparator)) {
88+
if !strings.HasSuffix(resolved, string(os.PathSeparator)) {
89+
resolved += string(os.PathSeparator)
9090
}
9191
return resolved
9292
}
9393

9494
// Handle "/."
95-
if strings.HasSuffix(original, "/.") {
96-
if strings.HasSuffix(resolved, "/") { // could be root!
95+
if strings.HasSuffix(original, string(os.PathSeparator)+".") {
96+
if strings.HasSuffix(resolved, string(os.PathSeparator)) { // could be root!
9797
resolved += "."
98-
} else if !strings.HasSuffix(resolved, "/.") {
99-
resolved += "/."
98+
} else if !strings.HasSuffix(resolved, string(os.PathSeparator)+".") {
99+
resolved += string(os.PathSeparator) + "."
100100
}
101101
return resolved
102102
}

pkg/copy/parse.go

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package copy
22

33
import (
44
"fmt"
5+
"path/filepath"
56
"strings"
67
)
78

@@ -40,6 +41,14 @@ func parseUserInput(input string) (container string, path string) {
4041
return
4142
}
4243

44+
// If the input is an absolute path, it cannot refer to a container.
45+
// This is necessary because absolute paths on Windows will include
46+
// a colon, which would cause the drive letter to be parsed as a
47+
// container name.
48+
if filepath.IsAbs(input) {
49+
return
50+
}
51+
4352
if parsedContainer, parsedPath, ok := strings.Cut(path, ":"); ok {
4453
container = parsedContainer
4554
path = parsedPath

pkg/machine/e2e/basic_test.go

-84
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
package e2e_test
22

33
import (
4-
"archive/tar"
5-
"bytes"
64
"fmt"
75
"io"
8-
"io/fs"
96
"net"
107
"net/http"
118
"net/url"
@@ -262,87 +259,6 @@ var _ = Describe("run basic podman commands", func() {
262259
Expect(run).To(Exit(0))
263260
Expect(build.outputToString()).To(ContainSubstring(name))
264261
})
265-
266-
It("Copy ops", func() {
267-
var (
268-
stdinDirectory = "stdin-dir"
269-
stdinFile = "file.txt"
270-
)
271-
272-
now := time.Now()
273-
274-
tarBuffer := &bytes.Buffer{}
275-
tw := tar.NewWriter(tarBuffer)
276-
277-
// Write a directory header to the tar
278-
err := tw.WriteHeader(&tar.Header{
279-
Name: stdinDirectory,
280-
Mode: int64(0640 | fs.ModeDir),
281-
Gid: 1000,
282-
ModTime: now,
283-
ChangeTime: now,
284-
AccessTime: now,
285-
Typeflag: tar.TypeDir,
286-
})
287-
Expect(err).ToNot(HaveOccurred())
288-
289-
// Write a file header to the tar
290-
err = tw.WriteHeader(&tar.Header{
291-
Name: path.Join(stdinDirectory, stdinFile),
292-
Mode: 0755,
293-
Uid: 1000,
294-
ModTime: now,
295-
ChangeTime: now,
296-
AccessTime: now,
297-
})
298-
Expect(err).ToNot(HaveOccurred())
299-
300-
err = tw.Close()
301-
Expect(err).ToNot(HaveOccurred())
302-
303-
name := randomString()
304-
i := new(initMachine)
305-
session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withNow()).run()
306-
Expect(err).ToNot(HaveOccurred())
307-
Expect(session).To(Exit(0))
308-
309-
bm := basicMachine{}
310-
newImgs, err := mb.setCmd(bm.withPodmanCommand([]string{"pull", TESTIMAGE})).run()
311-
Expect(err).ToNot(HaveOccurred())
312-
Expect(newImgs).To(Exit(0))
313-
Expect(newImgs.outputToStringSlice()).To(HaveLen(1))
314-
315-
createAlp, err := mb.setCmd(bm.withPodmanCommand([]string{"create", TESTIMAGE, "top"})).run()
316-
Expect(err).ToNot(HaveOccurred())
317-
Expect(createAlp).To(Exit(0))
318-
Expect(createAlp.outputToStringSlice()).To(HaveLen(1))
319-
320-
// Testing stdin copy with archive mode disabled (ownership will be determined by the tar file)
321-
containerID := createAlp.outputToStringSlice()[0]
322-
cpTar, err := mb.setCmd(bm.withPodmanCommand([]string{"cp", "-a=false", "-", containerID + ":/tmp"})).setStdin(tarBuffer).run()
323-
Expect(err).ToNot(HaveOccurred())
324-
Expect(cpTar).To(Exit(0))
325-
326-
start, err := mb.setCmd(bm.withPodmanCommand([]string{"start", containerID})).run()
327-
Expect(err).ToNot(HaveOccurred())
328-
Expect(start).To(Exit(0))
329-
330-
// Check the directory is created with the appropriate mode, uid, gid
331-
exec, err := mb.setCmd(bm.withPodmanCommand([]string{"exec", containerID, "stat", "-c", "%a %u %g", "/tmp/stdin-dir"})).run()
332-
Expect(err).ToNot(HaveOccurred())
333-
Expect(exec).To(Exit(0))
334-
execStdOut := exec.outputToStringSlice()
335-
Expect(execStdOut).To(HaveLen(1))
336-
Expect(execStdOut[0]).To(Equal("640 0 1000"))
337-
338-
// Check the file is created with the appropriate mode, uid, gid
339-
exec, err = mb.setCmd(bm.withPodmanCommand([]string{"exec", containerID, "stat", "-c", "%a %u %g", "/tmp/stdin-dir/file.txt"})).run()
340-
Expect(err).ToNot(HaveOccurred())
341-
Expect(exec).To(Exit(0))
342-
execStdOut = exec.outputToStringSlice()
343-
Expect(execStdOut).To(HaveLen(1))
344-
Expect(execStdOut[0]).To(Equal("755 1000 0"))
345-
})
346262
})
347263

348264
func testHTTPServer(port string, shouldErr bool, expectedResponse string) {

0 commit comments

Comments
 (0)