From c31cc8421cab755fabcd7d6ac0feffb5bca79e86 Mon Sep 17 00:00:00 2001 From: Mehul Arora Date: Sat, 19 Jun 2021 11:27:24 +0530 Subject: [PATCH 1/2] support container to container copy Signed-off-by: Mehul Arora --- cmd/podman/containers/cp.go | 54 ++++++++++++++++++++++++++++++++++++- pkg/copy/parse.go | 12 --------- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/cmd/podman/containers/cp.go b/cmd/podman/containers/cp.go index 2c7d72b205..80493b1284 100644 --- a/cmd/podman/containers/cp.go +++ b/cmd/podman/containers/cp.go @@ -80,11 +80,14 @@ func cp(cmd *cobra.Command, args []string) error { return err } - if len(sourceContainerStr) > 0 { + if len(sourceContainerStr) > 0 && len(destContainerStr) > 0 { + return copyContainerToContainer(sourceContainerStr, sourcePath, destContainerStr, destPath) + } else if len(sourceContainerStr) > 0 { return copyFromContainer(sourceContainerStr, sourcePath, destPath) } return copyToContainer(destContainerStr, destPath, sourcePath) + } // containerMustExist returns an error if the specified container does not @@ -113,6 +116,55 @@ func doCopy(funcA func() error, funcB func() error) error { return errorhandling.JoinErrors(copyErrors) } +func copyContainerToContainer(fromContainer string, sourcePath string, toContainer string, destPath string) error { + if err := containerMustExist(fromContainer); err != nil { + return err + } + + if err := containerMustExist(toContainer); err != nil { + return err + } + + fromContainerInfo, err := registry.ContainerEngine().ContainerStat(registry.GetContext(), fromContainer, sourcePath) + if err != nil { + return errors.Wrapf(err, "%q could not be found on container %s", sourcePath, fromContainer) + } + + toContainerInfo, err := registry.ContainerEngine().ContainerStat(registry.GetContext(), toContainer, destPath) + if err != nil { + return errors.Wrapf(err, "%q could not be found on container %s", destPath, toContainer) + } + + fromContainerTarget, toContainerTarget := fromContainerInfo.LinkTarget, toContainerInfo.LinkTarget + reader, writer := io.Pipe() + + fromContainerCopy := func() error { + defer writer.Close() + copyFunc, err := registry.ContainerEngine().ContainerCopyToArchive(registry.GetContext(), fromContainer, fromContainerTarget, writer) + if err != nil { + return err + } + if err := copyFunc(); err != nil { + return errors.Wrap(err, "error copying from container") + } + return nil + } + + toContainerCopy := func() error { + defer reader.Close() + copyFunc, err := registry.ContainerEngine().ContainerCopyFromArchive(registry.GetContext(), toContainer, toContainerTarget, reader) + if err != nil { + return err + } + if err := copyFunc(); err != nil { + return errors.Wrap(err, "error copying to container") + } + return nil + } + + return doCopy(fromContainerCopy, toContainerCopy) +} + // copyFromContainer copies from the containerPath on the container to hostPath. func copyFromContainer(container string, containerPath string, hostPath string) error { if err := containerMustExist(container); err != nil { diff --git a/pkg/copy/parse.go b/pkg/copy/parse.go index 39e0e15471..93edec5fa6 100644 --- a/pkg/copy/parse.go +++ b/pkg/copy/parse.go @@ -18,18 +18,6 @@ func ParseSourceAndDestination(source, destination string) (string, string, stri sourceContainer, sourcePath := parseUserInput(source) destContainer, destPath := parseUserInput(destination) - numContainers := 0 - if len(sourceContainer) > 0 { - numContainers++ - } - if len(destContainer) > 0 { - numContainers++ - } - - if numContainers != 1 { - return "", "", "", "", errors.Errorf("invalid arguments %q, %q: exactly 1 container expected but %d specified", source, destination, numContainers) - } - if len(sourcePath) == 0 || len(destPath) == 0 { return "", "", "", "", errors.Errorf("invalid arguments %q, %q: you must specify paths", source, destination) } From 67cbb74f38aa8b4cd0639c8895b263dd05161364 Mon Sep 17 00:00:00 2001 From: Mehul Arora Date: Fri, 25 Jun 2021 23:42:08 +0530 Subject: [PATCH 2/2] fix bugs Signed-off-by: Mehul Arora --- cmd/podman/containers/cp.go | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/cmd/podman/containers/cp.go b/cmd/podman/containers/cp.go index 608e869e17..af8739fac4 100644 --- a/cmd/podman/containers/cp.go +++ b/cmd/podman/containers/cp.go @@ -130,12 +130,39 @@ func copyContainerToContainer(fromContainer string, sourcePath string, toContain return errors.Wrapf(err, "%q could not be found on container %s", sourcePath, fromContainer) } + var toContainerBaseName string + _ = toContainerBaseName toContainerInfo, err := registry.ContainerEngine().ContainerStat(registry.GetContext(), toContainer, destPath) if err != nil { - return errors.Wrapf(err, "%q could not be found on container %s", destPath, toContainer) + if strings.HasSuffix(destPath, "/") { + return errors.Wrapf(err, "%q could not be found on container %s", destPath, toContainer) + } + if toContainerInfo != nil { + toContainerBaseName = filepath.Base(toContainerInfo.LinkTarget) + } else { + toContainerBaseName = filepath.Base(destPath) + } + + parentDir, err := containerParentDir(toContainer, destPath) + if err != nil { + return errors.Wrapf(err, "could not determine parent dir of %q on container %s", destPath, toContainer) + } + toContainerInfo, err = registry.ContainerEngine().ContainerStat(registry.GetContext(), toContainer, parentDir) + if err != nil { + return errors.Wrapf(err, "%q could not be found on container %s", destPath, toContainer) + } + } else { + toContainerBaseName = filepath.Base(toContainerInfo.LinkTarget) + } + + if fromContainerInfo.IsDir && !toContainerInfo.IsDir { + return errors.New("destination must be a directory when copying a directory") } fromContainerTarget, toContainerTarget := fromContainerInfo.LinkTarget, toContainerInfo.LinkTarget + if !toContainerInfo.IsDir { + toContainerTarget = filepath.Dir(destPath) + } reader, writer := io.Pipe() fromContainerCopy := func() error {