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
This commit is contained in:
Michael Crosby 2014-12-08 16:19:24 -05:00 committed by Tibor Vass
parent 79b559bc05
commit 1036313f03
2 changed files with 41 additions and 39 deletions

View file

@ -432,32 +432,7 @@ func TarWithOptions(srcPath string, options *TarOptions) (io.ReadCloser, error)
return pipeReader, nil return pipeReader, nil
} }
// Untar reads a stream of bytes from `archive`, parses it as a tar archive, func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) error {
// 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()
tr := tar.NewReader(decompressedArchive) tr := tar.NewReader(decompressedArchive)
trBuf := pools.BufioReader32KPool.Get(nil) trBuf := pools.BufioReader32KPool.Get(nil)
defer pools.BufioReader32KPool.Put(trBuf) defer pools.BufioReader32KPool.Put(trBuf)
@ -537,10 +512,33 @@ loop:
return err return err
} }
} }
return nil 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 { func (archiver *Archiver) TarUntar(src, dst string) error {
log.Debugf("TarUntar(%s %s)", src, dst) log.Debugf("TarUntar(%s %s)", src, dst)
archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed}) archive, err := TarWithOptions(src, &TarOptions{Compression: Uncompressed})

View file

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