diff --git a/api/client/commands.go b/api/client/commands.go index 6562709f3e..28c1a9c515 100644 --- a/api/client/commands.go +++ b/api/client/commands.go @@ -2058,7 +2058,7 @@ func (cli *DockerCli) CmdCp(args ...string) error { } if statusCode == 200 { - if err := archive.Untar(stream, copyData.Get("HostPath"), nil); err != nil { + if err := archive.Untar(stream, copyData.Get("HostPath"), &archive.TarOptions{NoLchown: true}); err != nil { return err } } diff --git a/archive/archive.go b/archive/archive.go index 160ea0737e..76c6e31289 100644 --- a/archive/archive.go +++ b/archive/archive.go @@ -28,6 +28,7 @@ type ( TarOptions struct { Includes []string Compression Compression + NoLchown bool } ) @@ -179,7 +180,7 @@ func addTarFile(path, name string, tw *tar.Writer) error { return nil } -func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader) error { +func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool) error { // hdr.Mode is in linux format, which we can use for sycalls, // but for os.Foo() calls we need the mode converted to os.FileMode, // so use hdrInfo.Mode() (they differ for e.g. setuid bits) @@ -240,7 +241,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader) e return fmt.Errorf("Unhandled tar header type %d\n", hdr.Typeflag) } - if err := os.Lchown(path, hdr.Uid, hdr.Gid); err != nil { + if err := os.Lchown(path, hdr.Uid, hdr.Gid); err != nil && Lchown { return err } @@ -415,8 +416,7 @@ func Untar(archive io.Reader, dest string, options *TarOptions) error { } } } - - if err := createTarFile(path, dest, hdr, tr); err != nil { + if err := createTarFile(path, dest, hdr, tr, options == nil || !options.NoLchown); err != nil { return err } diff --git a/archive/archive_test.go b/archive/archive_test.go index e959a2b073..72ffd99565 100644 --- a/archive/archive_test.go +++ b/archive/archive_test.go @@ -3,7 +3,6 @@ package archive import ( "bytes" "fmt" - "github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" "io" "io/ioutil" "os" @@ -11,6 +10,8 @@ import ( "path" "testing" "time" + + "github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" ) func TestCmdStreamLargeStderr(t *testing.T) { @@ -132,7 +133,7 @@ func TestTarUntar(t *testing.T) { // Failing prevents the archives from being uncompressed during ADD func TestTypeXGlobalHeaderDoesNotFail(t *testing.T) { hdr := tar.Header{Typeflag: tar.TypeXGlobalHeader} - err := createTarFile("pax_global_header", "some_dir", &hdr, nil) + err := createTarFile("pax_global_header", "some_dir", &hdr, nil, true) if err != nil { t.Fatal(err) } diff --git a/archive/diff.go b/archive/diff.go index 49d8cb4984..d169669126 100644 --- a/archive/diff.go +++ b/archive/diff.go @@ -2,13 +2,14 @@ package archive import ( "fmt" - "github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" "io" "io/ioutil" "os" "path/filepath" "strings" "syscall" + + "github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar" ) // Linux device nodes are a bit weird due to backwards compat with 16 bit device nodes. @@ -79,7 +80,7 @@ func ApplyLayer(dest string, layer ArchiveReader) error { } defer os.RemoveAll(aufsTempdir) } - if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr); err != nil { + if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true); err != nil { return err } } @@ -126,7 +127,7 @@ func ApplyLayer(dest string, layer ArchiveReader) error { srcData = tmpFile } - if err := createTarFile(path, dest, srcHdr, srcData); err != nil { + if err := createTarFile(path, dest, srcHdr, srcData, true); err != nil { return err }