From d9e1b2c47006483300692f39ad553271b5b6eab2 Mon Sep 17 00:00:00 2001
From: Qi Wang <qiwan@redhat.com>
Date: Mon, 4 Mar 2019 16:49:27 -0500
Subject: add flag --extract tar file in podman cp

Signed-off-by: Qi Wang <qiwan@redhat.com>
---
 cmd/podman/cliconfig/create.go |  1 +
 cmd/podman/cp.go               | 21 +++++++++++++++++----
 2 files changed, 18 insertions(+), 4 deletions(-)

(limited to 'cmd/podman')

diff --git a/cmd/podman/cliconfig/create.go b/cmd/podman/cliconfig/create.go
index b5ca1be9c..49ab3d827 100644
--- a/cmd/podman/cliconfig/create.go
+++ b/cmd/podman/cliconfig/create.go
@@ -23,4 +23,5 @@ type BuildValues struct {
 
 type CpValues struct {
 	PodmanCommand
+	Extract bool
 }
diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go
index 5958370b6..a3411b158 100644
--- a/cmd/podman/cp.go
+++ b/cmd/podman/cp.go
@@ -43,6 +43,8 @@ var (
 
 func init() {
 	cpCommand.Command = _cpCommand
+	flags := cpCommand.Flags()
+	flags.BoolVar(&cpCommand.Extract, "extract", false, "Extract the tar file into the destination directory.")
 	rootCmd.AddCommand(cpCommand.Command)
 }
 
@@ -61,10 +63,11 @@ func cpCmd(c *cliconfig.CpValues) error {
 	}
 	defer runtime.Shutdown(false)
 
-	return copyBetweenHostAndContainer(runtime, args[0], args[1])
+	extract := c.Flag("extract").Changed
+	return copyBetweenHostAndContainer(runtime, args[0], args[1], extract)
 }
 
-func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest string) error {
+func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest string, extract bool) error {
 
 	srcCtr, srcPath := parsePath(runtime, src)
 	destCtr, destPath := parsePath(runtime, dest)
@@ -166,7 +169,7 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin
 
 	var lastError error
 	for _, src := range glob {
-		err := copy(src, destPath, dest, idMappingOpts, &containerOwner)
+		err := copy(src, destPath, dest, idMappingOpts, &containerOwner, extract)
 		if lastError != nil {
 			logrus.Error(lastError)
 		}
@@ -219,7 +222,7 @@ func getPathInfo(path string) (string, os.FileInfo, error) {
 	return path, srcfi, nil
 }
 
-func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, chownOpts *idtools.IDPair) error {
+func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, chownOpts *idtools.IDPair, extract bool) error {
 	srcPath, err := filepath.EvalSymlinks(src)
 	if err != nil {
 		return errors.Wrapf(err, "error evaluating symlinks %q", srcPath)
@@ -240,6 +243,7 @@ func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, ch
 	// return functions for copying items
 	copyFileWithTar := chrootarchive.CopyFileWithTarAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap)
 	copyWithTar := chrootarchive.CopyWithTarAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap)
+	untarPath := chrootarchive.UntarPathAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap)
 
 	if srcfi.IsDir() {
 
@@ -263,6 +267,15 @@ func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, ch
 			destPath = filepath.Join(destPath, filepath.Base(srcPath))
 		}
 	}
+
+	if extract {
+		// We're extracting an archive into the destination directory.
+		logrus.Debugf("extracting contents of %q into %q", srcPath, destPath)
+		if err = untarPath(srcPath, destPath); err != nil {
+			return errors.Wrapf(err, "error extracting %q into %q", srcPath, destPath)
+		}
+		return nil
+	}
 	// Copy the file, preserving attributes.
 	logrus.Debugf("copying %q to %q", srcPath, destPath)
 	if err = copyFileWithTar(srcPath, destPath); err != nil {
-- 
cgit v1.2.3-54-g00ecf