daemon/archive.go: Fix copy routines to preserve UID.
This changes the long-standing bug of copy operations not preserving the UID/GID information after the files arrive to the container. Signed-off-by: Erik Hollensbe <github@hollensbe.org>
This commit is contained in:
parent
8d96619e5a
commit
8a7ff5ff74
14 changed files with 209 additions and 99 deletions
|
@ -27,7 +27,7 @@ type copyBackend interface {
|
|||
ContainerArchivePath(name string, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error)
|
||||
ContainerCopy(name string, res string) (io.ReadCloser, error)
|
||||
ContainerExport(name string, out io.Writer) error
|
||||
ContainerExtractToDir(name, path string, noOverwriteDirNonDir bool, content io.Reader) error
|
||||
ContainerExtractToDir(name, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) error
|
||||
ContainerStatPath(name string, path string) (stat *types.ContainerPathStat, err error)
|
||||
}
|
||||
|
||||
|
|
|
@ -112,5 +112,7 @@ func (s *containerRouter) putContainersArchive(ctx context.Context, w http.Respo
|
|||
}
|
||||
|
||||
noOverwriteDirNonDir := httputils.BoolValue(r, "noOverwriteDirNonDir")
|
||||
return s.backend.ContainerExtractToDir(v.Name, v.Path, noOverwriteDirNonDir, r.Body)
|
||||
copyUIDGID := httputils.BoolValue(r, "copyUIDGID")
|
||||
|
||||
return s.backend.ContainerExtractToDir(v.Name, v.Path, copyUIDGID, noOverwriteDirNonDir, r.Body)
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@ type ContainerStartOptions struct {
|
|||
// about files to copy into a container
|
||||
type CopyToContainerOptions struct {
|
||||
AllowOverwriteDirWithFile bool
|
||||
CopyUIDGID bool
|
||||
}
|
||||
|
||||
// EventsOptions holds parameters to filter events with.
|
||||
|
|
|
@ -20,6 +20,7 @@ type copyOptions struct {
|
|||
source string
|
||||
destination string
|
||||
followLink bool
|
||||
copyUIDGID bool
|
||||
}
|
||||
|
||||
type copyDirection int
|
||||
|
@ -66,6 +67,7 @@ func NewCopyCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|||
flags := cmd.Flags()
|
||||
|
||||
flags.BoolVarP(&opts.followLink, "follow-link", "L", false, "Always follow symbol link in SRC_PATH")
|
||||
flags.BoolVarP(&opts.copyUIDGID, "archive", "a", false, "Archive mode (copy all uid/gid information)")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -92,7 +94,7 @@ func runCopy(dockerCli *command.DockerCli, opts copyOptions) error {
|
|||
case fromContainer:
|
||||
return copyFromContainer(ctx, dockerCli, srcContainer, srcPath, dstPath, cpParam)
|
||||
case toContainer:
|
||||
return copyToContainer(ctx, dockerCli, srcPath, dstContainer, dstPath, cpParam)
|
||||
return copyToContainer(ctx, dockerCli, srcPath, dstContainer, dstPath, cpParam, opts.copyUIDGID)
|
||||
case acrossContainers:
|
||||
// Copying between containers isn't supported.
|
||||
return errors.New("copying between containers is not supported")
|
||||
|
@ -175,7 +177,7 @@ func copyFromContainer(ctx context.Context, dockerCli *command.DockerCli, srcCon
|
|||
return archive.CopyTo(preArchive, srcInfo, dstPath)
|
||||
}
|
||||
|
||||
func copyToContainer(ctx context.Context, dockerCli *command.DockerCli, srcPath, dstContainer, dstPath string, cpParam *cpConfig) (err error) {
|
||||
func copyToContainer(ctx context.Context, dockerCli *command.DockerCli, srcPath, dstContainer, dstPath string, cpParam *cpConfig, copyUIDGID bool) (err error) {
|
||||
if srcPath != "-" {
|
||||
// Get an absolute source path.
|
||||
srcPath, err = resolveLocalPath(srcPath)
|
||||
|
@ -265,6 +267,7 @@ func copyToContainer(ctx context.Context, dockerCli *command.DockerCli, srcPath,
|
|||
|
||||
options := types.CopyToContainerOptions{
|
||||
AllowOverwriteDirWithFile: false,
|
||||
CopyUIDGID: copyUIDGID,
|
||||
}
|
||||
|
||||
return dockerCli.Client().CopyToContainer(ctx, dstContainer, resolvedDstPath, content, options)
|
||||
|
|
|
@ -38,6 +38,10 @@ func (cli *Client) CopyToContainer(ctx context.Context, container, path string,
|
|||
query.Set("noOverwriteDirNonDir", "true")
|
||||
}
|
||||
|
||||
if options.CopyUIDGID {
|
||||
query.Set("copyUIDGID", "true")
|
||||
}
|
||||
|
||||
apiPath := fmt.Sprintf("/containers/%s/archive", container)
|
||||
|
||||
response, err := cli.putRaw(ctx, apiPath, query, content, nil)
|
||||
|
|
|
@ -83,7 +83,7 @@ func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io
|
|||
// be ErrExtractPointNotDirectory. If noOverwriteDirNonDir is true then it will
|
||||
// be an error if unpacking the given content would cause an existing directory
|
||||
// to be replaced with a non-directory and vice versa.
|
||||
func (daemon *Daemon) ContainerExtractToDir(name, path string, noOverwriteDirNonDir bool, content io.Reader) error {
|
||||
func (daemon *Daemon) ContainerExtractToDir(name, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) error {
|
||||
container, err := daemon.GetContainer(name)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -94,7 +94,7 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, noOverwriteDirNon
|
|||
return err
|
||||
}
|
||||
|
||||
return daemon.containerExtractToDir(container, path, noOverwriteDirNonDir, content)
|
||||
return daemon.containerExtractToDir(container, path, copyUIDGID, noOverwriteDirNonDir, content)
|
||||
}
|
||||
|
||||
// containerStatPath stats the filesystem resource at the specified path in this
|
||||
|
@ -196,7 +196,7 @@ func (daemon *Daemon) containerArchivePath(container *container.Container, path
|
|||
// noOverwriteDirNonDir is true then it will be an error if unpacking the
|
||||
// given content would cause an existing directory to be replaced with a non-
|
||||
// directory and vice versa.
|
||||
func (daemon *Daemon) containerExtractToDir(container *container.Container, path string, noOverwriteDirNonDir bool, content io.Reader) (err error) {
|
||||
func (daemon *Daemon) containerExtractToDir(container *container.Container, path string, copyUIDGID, noOverwriteDirNonDir bool, content io.Reader) (err error) {
|
||||
container.Lock()
|
||||
defer container.Unlock()
|
||||
|
||||
|
@ -279,13 +279,18 @@ func (daemon *Daemon) containerExtractToDir(container *container.Container, path
|
|||
return ErrRootFSReadOnly
|
||||
}
|
||||
|
||||
uid, gid := daemon.GetRemappedUIDGID()
|
||||
options := &archive.TarOptions{
|
||||
NoOverwriteDirNonDir: noOverwriteDirNonDir,
|
||||
ChownOpts: &archive.TarChownOptions{
|
||||
UID: uid, GID: gid, // TODO: should all ownership be set to root (either real or remapped)?
|
||||
},
|
||||
options := daemon.defaultTarCopyOptions(noOverwriteDirNonDir)
|
||||
|
||||
if copyUIDGID {
|
||||
var err error
|
||||
// tarCopyOptions will appropriately pull in the right uid/gid for the
|
||||
// user/group and will set the options.
|
||||
options, err = daemon.tarCopyOptions(container, noOverwriteDirNonDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := chrootarchive.Untar(content, resolvedPath, options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
16
daemon/archive_tarcopyoptions.go
Normal file
16
daemon/archive_tarcopyoptions.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
// defaultTarCopyOptions is the setting that is used when unpacking an archive
|
||||
// for a copy API event.
|
||||
func (daemon *Daemon) defaultTarCopyOptions(noOverwriteDirNonDir bool) *archive.TarOptions {
|
||||
uidMaps, gidMaps := daemon.GetUIDGIDMaps()
|
||||
return &archive.TarOptions{
|
||||
NoOverwriteDirNonDir: noOverwriteDirNonDir,
|
||||
UIDMaps: uidMaps,
|
||||
GIDMaps: gidMaps,
|
||||
}
|
||||
}
|
28
daemon/archive_tarcopyoptions_unix.go
Normal file
28
daemon/archive_tarcopyoptions_unix.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
// +build !windows
|
||||
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) tarCopyOptions(container *container.Container, noOverwriteDirNonDir bool) (*archive.TarOptions, error) {
|
||||
if container.Config.User == "" {
|
||||
return daemon.defaultTarCopyOptions(noOverwriteDirNonDir), nil
|
||||
}
|
||||
|
||||
user, err := idtools.LookupUser(container.Config.User)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &archive.TarOptions{
|
||||
NoOverwriteDirNonDir: noOverwriteDirNonDir,
|
||||
ChownOpts: &archive.TarChownOptions{
|
||||
UID: user.Uid,
|
||||
GID: user.Gid,
|
||||
},
|
||||
}, nil
|
||||
}
|
12
daemon/archive_tarcopyoptions_windows.go
Normal file
12
daemon/archive_tarcopyoptions_windows.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// +build windows
|
||||
|
||||
package daemon
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
func (daemon *Daemon) tarCopyOptions(container *container.Container, noOverwriteDirNonDir bool) (*archive.TarOptions, error) {
|
||||
return daemon.defaultTarCopyOptions(noOverwriteDirNonDir), nil
|
||||
}
|
|
@ -29,7 +29,7 @@ func (s *DockerSuite) TestCpFromErrSrcNotExists(c *check.C) {
|
|||
tmpDir := getTestDir(c, "test-cp-from-err-src-not-exists")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
err := runDockerCp(c, containerCpPath(containerID, "file1"), tmpDir)
|
||||
err := runDockerCp(c, containerCpPath(containerID, "file1"), tmpDir, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
|
||||
|
@ -44,7 +44,7 @@ func (s *DockerSuite) TestCpFromErrSrcNotDir(c *check.C) {
|
|||
tmpDir := getTestDir(c, "test-cp-from-err-src-not-dir")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
err := runDockerCp(c, containerCpPathTrailingSep(containerID, "file1"), tmpDir)
|
||||
err := runDockerCp(c, containerCpPathTrailingSep(containerID, "file1"), tmpDir, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err))
|
||||
|
@ -65,7 +65,7 @@ func (s *DockerSuite) TestCpFromErrDstParentNotExists(c *check.C) {
|
|||
srcPath := containerCpPath(containerID, "/file1")
|
||||
dstPath := cpPath(tmpDir, "notExists", "file1")
|
||||
|
||||
err := runDockerCp(c, srcPath, dstPath)
|
||||
err := runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
|
||||
|
@ -73,7 +73,7 @@ func (s *DockerSuite) TestCpFromErrDstParentNotExists(c *check.C) {
|
|||
// Try with a directory source.
|
||||
srcPath = containerCpPath(containerID, "/dir1")
|
||||
|
||||
err = runDockerCp(c, srcPath, dstPath)
|
||||
err = runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
|
||||
|
@ -94,7 +94,7 @@ func (s *DockerSuite) TestCpFromErrDstNotDir(c *check.C) {
|
|||
srcPath := containerCpPath(containerID, "/file1")
|
||||
dstPath := cpPathTrailingSep(tmpDir, "file1")
|
||||
|
||||
err := runDockerCp(c, srcPath, dstPath)
|
||||
err := runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err))
|
||||
|
@ -102,7 +102,7 @@ func (s *DockerSuite) TestCpFromErrDstNotDir(c *check.C) {
|
|||
// Try with a directory source.
|
||||
srcPath = containerCpPath(containerID, "/dir1")
|
||||
|
||||
err = runDockerCp(c, srcPath, dstPath)
|
||||
err = runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err))
|
||||
|
@ -124,7 +124,7 @@ func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) {
|
|||
srcPath := containerCpPath(containerID, "/file2")
|
||||
dstPath := cpPath(tmpDir, "symlinkToFile1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// The symlink should not have been modified.
|
||||
c.Assert(symlinkTargetEquals(c, dstPath, "file1"), checker.IsNil)
|
||||
|
@ -136,7 +136,7 @@ func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) {
|
|||
// should copy the file into the symlink target directory.
|
||||
dstPath = cpPath(tmpDir, "symlinkToDir1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// The symlink should not have been modified.
|
||||
c.Assert(symlinkTargetEquals(c, dstPath, "dir1"), checker.IsNil)
|
||||
|
@ -149,7 +149,7 @@ func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) {
|
|||
// the contents of the source file.
|
||||
dstPath = cpPath(tmpDir, "brokenSymlinkToFileX")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// The symlink should not have been modified.
|
||||
c.Assert(symlinkTargetEquals(c, dstPath, "fileX"), checker.IsNil)
|
||||
|
@ -163,7 +163,7 @@ func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) {
|
|||
srcPath = containerCpPath(containerID, "/dir2")
|
||||
dstPath = cpPath(tmpDir, "symlinkToDir1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// The symlink should not have been modified.
|
||||
c.Assert(symlinkTargetEquals(c, dstPath, "dir1"), checker.IsNil)
|
||||
|
@ -177,7 +177,7 @@ func (s *DockerSuite) TestCpFromSymlinkDestination(c *check.C) {
|
|||
// should not modify the symlink.
|
||||
dstPath = cpPath(tmpDir, "brokenSymlinkToDirX")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// The symlink should not have been modified.
|
||||
c.Assert(symlinkTargetEquals(c, dstPath, "dirX"), checker.IsNil)
|
||||
|
@ -217,7 +217,7 @@ func (s *DockerSuite) TestCpFromCaseA(c *check.C) {
|
|||
srcPath := containerCpPath(containerID, "/root/file1")
|
||||
dstPath := cpPath(tmpDir, "itWorks.txt")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1\n"), checker.IsNil)
|
||||
}
|
||||
|
@ -235,7 +235,7 @@ func (s *DockerSuite) TestCpFromCaseB(c *check.C) {
|
|||
srcPath := containerCpPath(containerID, "/file1")
|
||||
dstDir := cpPathTrailingSep(tmpDir, "testDir")
|
||||
|
||||
err := runDockerCp(c, srcPath, dstDir)
|
||||
err := runDockerCp(c, srcPath, dstDir, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpDirNotExist(err), checker.True, check.Commentf("expected DirNotExists error, but got %T: %s", err, err))
|
||||
|
@ -260,7 +260,7 @@ func (s *DockerSuite) TestCpFromCaseC(c *check.C) {
|
|||
// Ensure the local file starts with different content.
|
||||
c.Assert(fileContentEquals(c, dstPath, "file2\n"), checker.IsNil)
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1\n"), checker.IsNil)
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ func (s *DockerSuite) TestCpFromCaseD(c *check.C) {
|
|||
_, err := os.Stat(dstPath)
|
||||
c.Assert(os.IsNotExist(err), checker.True, check.Commentf("did not expect dstPath %q to exist", dstPath))
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstDir, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1\n"), checker.IsNil)
|
||||
|
||||
|
@ -299,7 +299,7 @@ func (s *DockerSuite) TestCpFromCaseD(c *check.C) {
|
|||
|
||||
dstDir = cpPathTrailingSep(tmpDir, "dir1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstDir, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1\n"), checker.IsNil)
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ func (s *DockerSuite) TestCpFromCaseE(c *check.C) {
|
|||
dstDir := cpPath(tmpDir, "testDir")
|
||||
dstPath := filepath.Join(dstDir, "file1-1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil)
|
||||
|
||||
|
@ -330,7 +330,7 @@ func (s *DockerSuite) TestCpFromCaseE(c *check.C) {
|
|||
|
||||
dstDir = cpPathTrailingSep(tmpDir, "testDir")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil)
|
||||
}
|
||||
|
@ -351,7 +351,7 @@ func (s *DockerSuite) TestCpFromCaseF(c *check.C) {
|
|||
srcDir := containerCpPath(containerID, "/root/dir1")
|
||||
dstFile := cpPath(tmpDir, "file1")
|
||||
|
||||
err := runDockerCp(c, srcDir, dstFile)
|
||||
err := runDockerCp(c, srcDir, dstFile, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpCannotCopyDir(err), checker.True, check.Commentf("expected ErrCannotCopyDir error, but got %T: %s", err, err))
|
||||
|
@ -376,7 +376,7 @@ func (s *DockerSuite) TestCpFromCaseG(c *check.C) {
|
|||
resultDir := filepath.Join(dstDir, "dir1")
|
||||
dstPath := filepath.Join(resultDir, "file1-1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil)
|
||||
|
||||
|
@ -390,7 +390,7 @@ func (s *DockerSuite) TestCpFromCaseG(c *check.C) {
|
|||
|
||||
dstDir = cpPathTrailingSep(tmpDir, "dir2")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil)
|
||||
}
|
||||
|
@ -410,7 +410,7 @@ func (s *DockerSuite) TestCpFromCaseH(c *check.C) {
|
|||
dstDir := cpPath(tmpDir, "testDir")
|
||||
dstPath := filepath.Join(dstDir, "file1-1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil)
|
||||
|
||||
|
@ -421,7 +421,7 @@ func (s *DockerSuite) TestCpFromCaseH(c *check.C) {
|
|||
|
||||
dstDir = cpPathTrailingSep(tmpDir, "testDir")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil)
|
||||
}
|
||||
|
@ -443,7 +443,7 @@ func (s *DockerSuite) TestCpFromCaseI(c *check.C) {
|
|||
srcDir := containerCpPathTrailingSep(containerID, "/root/dir1") + "."
|
||||
dstFile := cpPath(tmpDir, "file1")
|
||||
|
||||
err := runDockerCp(c, srcDir, dstFile)
|
||||
err := runDockerCp(c, srcDir, dstFile, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpCannotCopyDir(err), checker.True, check.Commentf("expected ErrCannotCopyDir error, but got %T: %s", err, err))
|
||||
|
@ -468,7 +468,7 @@ func (s *DockerSuite) TestCpFromCaseJ(c *check.C) {
|
|||
dstDir := cpPath(tmpDir, "dir2")
|
||||
dstPath := filepath.Join(dstDir, "file1-1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil)
|
||||
|
||||
|
@ -482,7 +482,7 @@ func (s *DockerSuite) TestCpFromCaseJ(c *check.C) {
|
|||
|
||||
dstDir = cpPathTrailingSep(tmpDir, "dir2")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
c.Assert(fileContentEquals(c, dstPath, "file1-1\n"), checker.IsNil)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ const (
|
|||
|
||||
// Ensure that an all-local path case returns an error.
|
||||
func (s *DockerSuite) TestCpLocalOnly(c *check.C) {
|
||||
err := runDockerCp(c, "foo", "bar")
|
||||
err := runDockerCp(c, "foo", "bar", nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(err.Error(), checker.Contains, "must specify at least one container source")
|
||||
|
|
|
@ -31,7 +31,7 @@ func (s *DockerSuite) TestCpToErrSrcNotExists(c *check.C) {
|
|||
srcPath := cpPath(tmpDir, "file1")
|
||||
dstPath := containerCpPath(containerID, "file1")
|
||||
|
||||
err := runDockerCp(c, srcPath, dstPath)
|
||||
err := runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
|
||||
|
@ -50,7 +50,7 @@ func (s *DockerSuite) TestCpToErrSrcNotDir(c *check.C) {
|
|||
srcPath := cpPathTrailingSep(tmpDir, "file1")
|
||||
dstPath := containerCpPath(containerID, "testDir")
|
||||
|
||||
err := runDockerCp(c, srcPath, dstPath)
|
||||
err := runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpNotDir(err), checker.True, check.Commentf("expected IsNotDir error, but got %T: %s", err, err))
|
||||
|
@ -71,7 +71,7 @@ func (s *DockerSuite) TestCpToErrDstParentNotExists(c *check.C) {
|
|||
srcPath := cpPath(tmpDir, "file1")
|
||||
dstPath := containerCpPath(containerID, "/notExists", "file1")
|
||||
|
||||
err := runDockerCp(c, srcPath, dstPath)
|
||||
err := runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
|
||||
|
@ -79,7 +79,7 @@ func (s *DockerSuite) TestCpToErrDstParentNotExists(c *check.C) {
|
|||
// Try with a directory source.
|
||||
srcPath = cpPath(tmpDir, "dir1")
|
||||
|
||||
err = runDockerCp(c, srcPath, dstPath)
|
||||
err = runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpNotExist(err), checker.True, check.Commentf("expected IsNotExist error, but got %T: %s", err, err))
|
||||
|
@ -104,7 +104,7 @@ func (s *DockerSuite) TestCpToErrDstNotDir(c *check.C) {
|
|||
// The client should encounter an error trying to stat the destination
|
||||
// and then be unable to copy since the destination is asserted to be a
|
||||
// directory but does not exist.
|
||||
err := runDockerCp(c, srcPath, dstPath)
|
||||
err := runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpDirNotExist(err), checker.True, check.Commentf("expected DirNotExist error, but got %T: %s", err, err))
|
||||
|
@ -116,7 +116,7 @@ func (s *DockerSuite) TestCpToErrDstNotDir(c *check.C) {
|
|||
// then decide to extract to the parent directory instead with a rebased
|
||||
// name in the source archive, but this directory would overwrite the
|
||||
// existing file with the same name.
|
||||
err = runDockerCp(c, srcPath, dstPath)
|
||||
err = runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCannotOverwriteNonDirWithDir(err), checker.True, check.Commentf("expected CannotOverwriteNonDirWithDir error, but got %T: %s", err, err))
|
||||
|
@ -144,7 +144,7 @@ func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) {
|
|||
srcPath := cpPath(testVol, "file2")
|
||||
dstPath := containerCpPath(containerID, "/vol2/symlinkToFile1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// The symlink should not have been modified.
|
||||
c.Assert(symlinkTargetEquals(c, cpPath(testVol, "symlinkToFile1"), "file1"), checker.IsNil)
|
||||
|
@ -156,7 +156,7 @@ func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) {
|
|||
// This should copy the file into the symlink target directory.
|
||||
dstPath = containerCpPath(containerID, "/vol2/symlinkToDir1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// The symlink should not have been modified.
|
||||
c.Assert(symlinkTargetEquals(c, cpPath(testVol, "symlinkToDir1"), "dir1"), checker.IsNil)
|
||||
|
@ -169,7 +169,7 @@ func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) {
|
|||
// contents of the source file.
|
||||
dstPath = containerCpPath(containerID, "/vol2/brokenSymlinkToFileX")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// The symlink should not have been modified.
|
||||
c.Assert(symlinkTargetEquals(c, cpPath(testVol, "brokenSymlinkToFileX"), "fileX"), checker.IsNil)
|
||||
|
@ -183,7 +183,7 @@ func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) {
|
|||
srcPath = cpPath(testVol, "/dir2")
|
||||
dstPath = containerCpPath(containerID, "/vol2/symlinkToDir1")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// The symlink should not have been modified.
|
||||
c.Assert(symlinkTargetEquals(c, cpPath(testVol, "symlinkToDir1"), "dir1"), checker.IsNil)
|
||||
|
@ -197,7 +197,7 @@ func (s *DockerSuite) TestCpToSymlinkDestination(c *check.C) {
|
|||
// should not modify the symlink.
|
||||
dstPath = containerCpPath(containerID, "/vol2/brokenSymlinkToDirX")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// The symlink should not have been modified.
|
||||
c.Assert(symlinkTargetEquals(c, cpPath(testVol, "brokenSymlinkToDirX"), "dirX"), checker.IsNil)
|
||||
|
@ -238,7 +238,7 @@ func (s *DockerSuite) TestCpToCaseA(c *check.C) {
|
|||
srcPath := cpPath(tmpDir, "file1")
|
||||
dstPath := containerCpPath(containerID, "/root/itWorks.txt")
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil)
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ func (s *DockerSuite) TestCpToCaseB(c *check.C) {
|
|||
srcPath := cpPath(tmpDir, "file1")
|
||||
dstDir := containerCpPathTrailingSep(containerID, "testDir")
|
||||
|
||||
err := runDockerCp(c, srcPath, dstDir)
|
||||
err := runDockerCp(c, srcPath, dstDir, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpDirNotExist(err), checker.True, check.Commentf("expected DirNotExists error, but got %T: %s", err, err))
|
||||
|
@ -285,7 +285,7 @@ func (s *DockerSuite) TestCpToCaseC(c *check.C) {
|
|||
// Ensure the container's file starts with the original content.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file2\n"), checker.IsNil)
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil)
|
||||
|
@ -312,7 +312,7 @@ func (s *DockerSuite) TestCpToCaseD(c *check.C) {
|
|||
// Ensure that dstPath doesn't exist.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstDir, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil)
|
||||
|
@ -330,7 +330,7 @@ func (s *DockerSuite) TestCpToCaseD(c *check.C) {
|
|||
// Ensure that dstPath doesn't exist.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
|
||||
|
||||
c.Assert(runDockerCp(c, srcPath, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcPath, dstDir, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1\n"), checker.IsNil)
|
||||
|
@ -353,7 +353,7 @@ func (s *DockerSuite) TestCpToCaseE(c *check.C) {
|
|||
srcDir := cpPath(tmpDir, "dir1")
|
||||
dstDir := containerCpPath(containerID, "testDir")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1-1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
|
||||
|
@ -367,7 +367,7 @@ func (s *DockerSuite) TestCpToCaseE(c *check.C) {
|
|||
|
||||
dstDir = containerCpPathTrailingSep(containerID, "testDir")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1-1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
|
||||
|
@ -389,7 +389,7 @@ func (s *DockerSuite) TestCpToCaseF(c *check.C) {
|
|||
srcDir := cpPath(tmpDir, "dir1")
|
||||
dstFile := containerCpPath(containerID, "/root/file1")
|
||||
|
||||
err := runDockerCp(c, srcDir, dstFile)
|
||||
err := runDockerCp(c, srcDir, dstFile, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpCannotCopyDir(err), checker.True, check.Commentf("expected ErrCannotCopyDir error, but got %T: %s", err, err))
|
||||
|
@ -416,7 +416,7 @@ func (s *DockerSuite) TestCpToCaseG(c *check.C) {
|
|||
// Ensure that dstPath doesn't exist.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1-1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
|
||||
|
@ -434,7 +434,7 @@ func (s *DockerSuite) TestCpToCaseG(c *check.C) {
|
|||
// Ensure that dstPath doesn't exist.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1-1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
|
||||
|
@ -457,7 +457,7 @@ func (s *DockerSuite) TestCpToCaseH(c *check.C) {
|
|||
srcDir := cpPathTrailingSep(tmpDir, "dir1") + "."
|
||||
dstDir := containerCpPath(containerID, "testDir")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1-1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
|
||||
|
@ -471,7 +471,7 @@ func (s *DockerSuite) TestCpToCaseH(c *check.C) {
|
|||
|
||||
dstDir = containerCpPathTrailingSep(containerID, "testDir")
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1-1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
|
||||
|
@ -494,7 +494,7 @@ func (s *DockerSuite) TestCpToCaseI(c *check.C) {
|
|||
srcDir := cpPathTrailingSep(tmpDir, "dir1") + "."
|
||||
dstFile := containerCpPath(containerID, "/root/file1")
|
||||
|
||||
err := runDockerCp(c, srcDir, dstFile)
|
||||
err := runDockerCp(c, srcDir, dstFile, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpCannotCopyDir(err), checker.True, check.Commentf("expected ErrCannotCopyDir error, but got %T: %s", err, err))
|
||||
|
@ -522,7 +522,7 @@ func (s *DockerSuite) TestCpToCaseJ(c *check.C) {
|
|||
// Ensure that dstPath doesn't exist.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1-1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
|
||||
|
@ -539,7 +539,7 @@ func (s *DockerSuite) TestCpToCaseJ(c *check.C) {
|
|||
// Ensure that dstPath doesn't exist.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, ""), checker.IsNil)
|
||||
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir), checker.IsNil)
|
||||
c.Assert(runDockerCp(c, srcDir, dstDir, nil), checker.IsNil)
|
||||
|
||||
// Should now contain file1-1's contents.
|
||||
c.Assert(containerStartOutputEquals(c, containerID, "file1-1\n"), checker.IsNil)
|
||||
|
@ -563,7 +563,7 @@ func (s *DockerSuite) TestCpToErrReadOnlyRootfs(c *check.C) {
|
|||
srcPath := cpPath(tmpDir, "file1")
|
||||
dstPath := containerCpPath(containerID, "/root/shouldNotExist")
|
||||
|
||||
err := runDockerCp(c, srcPath, dstPath)
|
||||
err := runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpCannotCopyReadOnly(err), checker.True, check.Commentf("expected ErrContainerRootfsReadonly error, but got %T: %s", err, err))
|
||||
|
@ -590,7 +590,7 @@ func (s *DockerSuite) TestCpToErrReadOnlyVolume(c *check.C) {
|
|||
srcPath := cpPath(tmpDir, "file1")
|
||||
dstPath := containerCpPath(containerID, "/vol_ro/shouldNotExist")
|
||||
|
||||
err := runDockerCp(c, srcPath, dstPath)
|
||||
err := runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.NotNil)
|
||||
|
||||
c.Assert(isCpCannotCopyReadOnly(err), checker.True, check.Commentf("expected ErrVolumeReadonly error, but got %T: %s", err, err))
|
||||
|
|
|
@ -14,6 +14,29 @@ import (
|
|||
"github.com/go-check/check"
|
||||
)
|
||||
|
||||
func (s *DockerSuite) TestCpToContainerWithPermissions(c *check.C) {
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
|
||||
tmpDir := getTestDir(c, "test-cp-to-host-with-permissions")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
makeTestContentInDir(c, tmpDir)
|
||||
|
||||
containerName := "permtest"
|
||||
|
||||
_, exc := dockerCmd(c, "create", "--name", containerName, "debian:jessie", "/bin/bash", "-c", "stat -c '%u %g %a' /permdirtest /permdirtest/permtest")
|
||||
c.Assert(exc, checker.Equals, 0)
|
||||
defer dockerCmd(c, "rm", "-f", containerName)
|
||||
|
||||
srcPath := cpPath(tmpDir, "permdirtest")
|
||||
dstPath := containerCpPath(containerName, "/")
|
||||
c.Assert(runDockerCp(c, srcPath, dstPath, []string{"-a"}), checker.IsNil)
|
||||
|
||||
out, err := startContainerGetOutput(c, containerName)
|
||||
c.Assert(err, checker.IsNil, check.Commentf("output: %v", out))
|
||||
c.Assert(strings.TrimSpace(out), checker.Equals, "2 2 700\n65534 65534 400", check.Commentf("output: %v", out))
|
||||
}
|
||||
|
||||
// Check ownership is root, both in non-userns and userns enabled modes
|
||||
func (s *DockerSuite) TestCpCheckDestOwnership(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, SameHostDaemon)
|
||||
|
@ -29,7 +52,7 @@ func (s *DockerSuite) TestCpCheckDestOwnership(c *check.C) {
|
|||
srcPath := cpPath(tmpDir, "file1")
|
||||
dstPath := containerCpPath(containerID, "/tmpvol", "file1")
|
||||
|
||||
err := runDockerCp(c, srcPath, dstPath)
|
||||
err := runDockerCp(c, srcPath, dstPath, nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
stat, err := system.Stat(filepath.Join(tmpVolDir, "file1"))
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
|
@ -26,6 +27,9 @@ type fileData struct {
|
|||
filetype fileType
|
||||
path string
|
||||
contents string
|
||||
uid int
|
||||
gid int
|
||||
mode int
|
||||
}
|
||||
|
||||
func (fd fileData) creationCommand() string {
|
||||
|
@ -55,31 +59,33 @@ func mkFilesCommand(fds []fileData) string {
|
|||
}
|
||||
|
||||
var defaultFileData = []fileData{
|
||||
{ftRegular, "file1", "file1"},
|
||||
{ftRegular, "file2", "file2"},
|
||||
{ftRegular, "file3", "file3"},
|
||||
{ftRegular, "file4", "file4"},
|
||||
{ftRegular, "file5", "file5"},
|
||||
{ftRegular, "file6", "file6"},
|
||||
{ftRegular, "file7", "file7"},
|
||||
{ftDir, "dir1", ""},
|
||||
{ftRegular, "dir1/file1-1", "file1-1"},
|
||||
{ftRegular, "dir1/file1-2", "file1-2"},
|
||||
{ftDir, "dir2", ""},
|
||||
{ftRegular, "dir2/file2-1", "file2-1"},
|
||||
{ftRegular, "dir2/file2-2", "file2-2"},
|
||||
{ftDir, "dir3", ""},
|
||||
{ftRegular, "dir3/file3-1", "file3-1"},
|
||||
{ftRegular, "dir3/file3-2", "file3-2"},
|
||||
{ftDir, "dir4", ""},
|
||||
{ftRegular, "dir4/file3-1", "file4-1"},
|
||||
{ftRegular, "dir4/file3-2", "file4-2"},
|
||||
{ftDir, "dir5", ""},
|
||||
{ftSymlink, "symlinkToFile1", "file1"},
|
||||
{ftSymlink, "symlinkToDir1", "dir1"},
|
||||
{ftSymlink, "brokenSymlinkToFileX", "fileX"},
|
||||
{ftSymlink, "brokenSymlinkToDirX", "dirX"},
|
||||
{ftSymlink, "symlinkToAbsDir", "/root"},
|
||||
{ftRegular, "file1", "file1", 0, 0, 0666},
|
||||
{ftRegular, "file2", "file2", 0, 0, 0666},
|
||||
{ftRegular, "file3", "file3", 0, 0, 0666},
|
||||
{ftRegular, "file4", "file4", 0, 0, 0666},
|
||||
{ftRegular, "file5", "file5", 0, 0, 0666},
|
||||
{ftRegular, "file6", "file6", 0, 0, 0666},
|
||||
{ftRegular, "file7", "file7", 0, 0, 0666},
|
||||
{ftDir, "dir1", "", 0, 0, 0777},
|
||||
{ftRegular, "dir1/file1-1", "file1-1", 0, 0, 0666},
|
||||
{ftRegular, "dir1/file1-2", "file1-2", 0, 0, 0666},
|
||||
{ftDir, "dir2", "", 0, 0, 0666},
|
||||
{ftRegular, "dir2/file2-1", "file2-1", 0, 0, 0666},
|
||||
{ftRegular, "dir2/file2-2", "file2-2", 0, 0, 0666},
|
||||
{ftDir, "dir3", "", 0, 0, 0666},
|
||||
{ftRegular, "dir3/file3-1", "file3-1", 0, 0, 0666},
|
||||
{ftRegular, "dir3/file3-2", "file3-2", 0, 0, 0666},
|
||||
{ftDir, "dir4", "", 0, 0, 0666},
|
||||
{ftRegular, "dir4/file3-1", "file4-1", 0, 0, 0666},
|
||||
{ftRegular, "dir4/file3-2", "file4-2", 0, 0, 0666},
|
||||
{ftDir, "dir5", "", 0, 0, 0666},
|
||||
{ftSymlink, "symlinkToFile1", "file1", 0, 0, 0666},
|
||||
{ftSymlink, "symlinkToDir1", "dir1", 0, 0, 0666},
|
||||
{ftSymlink, "brokenSymlinkToFileX", "fileX", 0, 0, 0666},
|
||||
{ftSymlink, "brokenSymlinkToDirX", "dirX", 0, 0, 0666},
|
||||
{ftSymlink, "symlinkToAbsDir", "/root", 0, 0, 0666},
|
||||
{ftDir, "permdirtest", "", 2, 2, 0700},
|
||||
{ftRegular, "permdirtest/permtest", "perm_test", 65534, 65534, 0400},
|
||||
}
|
||||
|
||||
func defaultMkContentCommand() string {
|
||||
|
@ -91,12 +97,16 @@ func makeTestContentInDir(c *check.C, dir string) {
|
|||
path := filepath.Join(dir, filepath.FromSlash(fd.path))
|
||||
switch fd.filetype {
|
||||
case ftRegular:
|
||||
c.Assert(ioutil.WriteFile(path, []byte(fd.contents+"\n"), os.FileMode(0666)), checker.IsNil)
|
||||
c.Assert(ioutil.WriteFile(path, []byte(fd.contents+"\n"), os.FileMode(fd.mode)), checker.IsNil)
|
||||
case ftDir:
|
||||
c.Assert(os.Mkdir(path, os.FileMode(0777)), checker.IsNil)
|
||||
c.Assert(os.Mkdir(path, os.FileMode(fd.mode)), checker.IsNil)
|
||||
case ftSymlink:
|
||||
c.Assert(os.Symlink(fd.contents, path), checker.IsNil)
|
||||
}
|
||||
|
||||
if fd.filetype != ftSymlink && runtime.GOOS != "windows" {
|
||||
c.Assert(os.Chown(path, fd.uid, fd.gid), checker.IsNil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,10 +188,16 @@ func containerCpPathTrailingSep(containerID string, pathElements ...string) stri
|
|||
return fmt.Sprintf("%s/", containerCpPath(containerID, pathElements...))
|
||||
}
|
||||
|
||||
func runDockerCp(c *check.C, src, dst string) (err error) {
|
||||
c.Logf("running `docker cp %s %s`", src, dst)
|
||||
func runDockerCp(c *check.C, src, dst string, params []string) (err error) {
|
||||
c.Logf("running `docker cp %s %s %s`", strings.Join(params, " "), src, dst)
|
||||
|
||||
args := []string{"cp", src, dst}
|
||||
args := []string{"cp"}
|
||||
|
||||
for _, param := range params {
|
||||
args = append(args, param)
|
||||
}
|
||||
|
||||
args = append(args, src, dst)
|
||||
|
||||
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, args...))
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in a new issue