diff --git a/integration-cli/docker_cli_build_test.go b/integration-cli/docker_cli_build_test.go index f6d5fe23f3faf..fadf9ec7c8a42 100644 --- a/integration-cli/docker_cli_build_test.go +++ b/integration-cli/docker_cli_build_test.go @@ -24,6 +24,7 @@ import ( "github.com/docker/docker/internal/test/fakestorage" "github.com/docker/docker/internal/testutil" "github.com/docker/docker/pkg/archive" + "github.com/docker/docker/pkg/system" "github.com/go-check/check" "github.com/moby/buildkit/frontend/dockerfile/command" "github.com/opencontainers/go-digest" @@ -3601,6 +3602,11 @@ func (s *DockerSuite) TestBuildSymlinkBreakout(c *check.C) { name := "testbuildsymlinkbreakout" tmpdir, err := ioutil.TempDir("", name) c.Assert(err, check.IsNil) + + // See https://github.com/moby/moby/pull/37770 for reason for next line. + tmpdir, err = system.GetLongPathName(tmpdir) + c.Assert(err, check.IsNil) + defer os.RemoveAll(tmpdir) ctx := filepath.Join(tmpdir, "context") if err := os.MkdirAll(ctx, 0755); err != nil { diff --git a/pkg/system/path_unix.go b/pkg/system/path_unix.go new file mode 100644 index 0000000000000..b0b93196a15c5 --- /dev/null +++ b/pkg/system/path_unix.go @@ -0,0 +1,10 @@ +// +build !windows + +package system // import "github.com/docker/docker/pkg/system" + +// GetLongPathName converts Windows short pathnames to full pathnames. +// For example C:\Users\ADMIN~1 --> C:\Users\Administrator. +// It is a no-op on non-Windows platforms +func GetLongPathName(path string) (string, error) { + return path, nil +} diff --git a/pkg/system/path_windows.go b/pkg/system/path_windows.go new file mode 100644 index 0000000000000..188f2c2957a48 --- /dev/null +++ b/pkg/system/path_windows.go @@ -0,0 +1,24 @@ +package system // import "github.com/docker/docker/pkg/system" + +import "syscall" + +// GetLongPathName converts Windows short pathnames to full pathnames. +// For example C:\Users\ADMIN~1 --> C:\Users\Administrator. +// It is a no-op on non-Windows platforms +func GetLongPathName(path string) (string, error) { + // See https://groups.google.com/forum/#!topic/golang-dev/1tufzkruoTg + p := syscall.StringToUTF16(path) + b := p // GetLongPathName says we can reuse buffer + n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b))) + if err != nil { + return "", err + } + if n > uint32(len(b)) { + b = make([]uint16, n) + _, err = syscall.GetLongPathName(&p[0], &b[0], uint32(len(b))) + if err != nil { + return "", err + } + } + return syscall.UTF16ToString(b), nil +}