Explorar o código

Decompress archive before streaming the unpack in a chroot

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>

Conflicts:
	pkg/archive/archive.go
	pkg/chrootarchive/archive.go
Michael Crosby %!s(int64=10) %!d(string=hai) anos
pai
achega
313a1b7620
Modificáronse 2 ficheiros con 41 adicións e 39 borrados
  1. 25 27
      pkg/archive/archive.go
  2. 16 12
      pkg/chrootarchive/archive.go

+ 25 - 27
pkg/archive/archive.go

@@ -432,32 +432,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
 	return pipeReader, nil
 }
 
-// Untar reads a stream of bytes from `archive`, parses it as a tar archive,
-// and unpacks it into the directory at `path`.
-// The archive may be compressed with one of the following algorithms:
-//  identity (uncompressed), gzip, bzip2, xz.
-// FIXME: specify behavior when target path exists vs. doesn't exist.
-func Untar(archive io.Reader, dest string, options *TarOptions) error {
-	dest = filepath.Clean(dest)
-
-	if options == nil {
-		options = &TarOptions{}
-	}
-
-	if archive == nil {
-		return fmt.Errorf("Empty archive")
-	}
-
-	if options.Excludes == nil {
-		options.Excludes = []string{}
-	}
-
-	decompressedArchive, err := DecompressStream(archive)
-	if err != nil {
-		return err
-	}
-	defer decompressedArchive.Close()
-
+func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) error {
 	tr := tar.NewReader(decompressedArchive)
 	trBuf := pools.BufioReader32KPool.Get(nil)
 	defer pools.BufioReader32KPool.Put(trBuf)
@@ -537,10 +512,33 @@ loop:
 			return err
 		}
 	}
-
 	return nil
 }
 
+// Untar reads a stream of bytes from `archive`, parses it as a tar archive,
+// and unpacks it into the directory at `dest`.
+// The archive may be compressed with one of the following algorithms:
+//  identity (uncompressed), gzip, bzip2, xz.
+// FIXME: specify behavior when target path exists vs. doesn't exist.
+func Untar(archive io.Reader, dest string, options *TarOptions) error {
+	if archive == nil {
+		return fmt.Errorf("Empty archive")
+	}
+	dest = filepath.Clean(dest)
+	if options == nil {
+		options = &TarOptions{}
+	}
+	if options.Excludes == nil {
+		options.Excludes = []string{}
+	}
+	decompressedArchive, err := DecompressStream(archive)
+	if err != nil {
+		return err
+	}
+	defer decompressedArchive.Close()
+	return Unpack(decompressedArchive, dest, options)
+}
+
 func (archiver *Archiver) TarUntar(src, dst string) error {
 	log.Debugf("TarUntar(%s %s)", src, dst)
 	archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed})

+ 16 - 12
pkg/chrootarchive/archive.go

@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"io"
 	"os"
+	"path/filepath"
 	"runtime"
 	"strings"
 	"syscall"
@@ -27,19 +28,14 @@ func chroot(path string) error {
 func untar() {
 	runtime.LockOSThread()
 	flag.Parse()
-
-	if err := syscall.Chroot(flag.Arg(0)); err != nil {
-		fatal(err)
-	}
-	if err := syscall.Chdir("/"); err != nil {
+	if err := chroot(flag.Arg(0)); err != nil {
 		fatal(err)
 	}
-	options := new(archive.TarOptions)
-	dec := json.NewDecoder(strings.NewReader(flag.Arg(1)))
-	if err := dec.Decode(options); err != nil {
+	var options *archive.TarOptions
+	if err := json.NewDecoder(strings.NewReader(flag.Arg(1))).Decode(&options); err != nil {
 		fatal(err)
 	}
-	if err := archive.Untar(os.Stdin, "/", options); err != nil {
+	if err := archive.Unpack(os.Stdin, "/", options); err != nil {
 		fatal(err)
 	}
 	os.Exit(0)
@@ -56,8 +52,10 @@ func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error
 		options.Excludes = []string{}
 	}
 
-	var buf bytes.Buffer
-	enc := json.NewEncoder(&buf)
+	var (
+		buf bytes.Buffer
+		enc = json.NewEncoder(&buf)
+	)
 	if err := enc.Encode(options); err != nil {
 		return fmt.Errorf("Untar json encode: %v", err)
 	}
@@ -66,9 +64,15 @@ func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error
 			return err
 		}
 	}
+	dest = filepath.Clean(dest)
+	decompressedArchive, err := archive.DecompressStream(tarArchive)
+	if err != nil {
+		return err
+	}
+	defer decompressedArchive.Close()
 
 	cmd := reexec.Command("docker-untar", dest, buf.String())
-	cmd.Stdin = tarArchive
+	cmd.Stdin = decompressedArchive
 	out, err := cmd.CombinedOutput()
 	if err != nil {
 		return fmt.Errorf("Untar %s %s", err, out)