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:
parent
79b559bc05
commit
1036313f03
2 changed files with 41 additions and 39 deletions
|
@ -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})
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue