15 "github.com/docker/docker/pkg/archive"
16 "github.com/docker/docker/pkg/reexec"
19 // untar is the entry-point for docker-untar on re-exec. This is not used on
20 // Windows as it does not support chroot, hence no point sandboxing through
23 runtime.LockOSThread()
26 var options *archive.TarOptions
28 //read the options from the pipe "ExtraFiles"
29 if err := json.NewDecoder(os.NewFile(3, "options")).Decode(&options); err != nil {
33 if err := chroot(flag.Arg(0)); err != nil {
37 if err := archive.Unpack(os.Stdin, "/", options); err != nil {
40 // fully consume stdin in case it is zero padded
41 if _, err := flush(os.Stdin); err != nil {
48 func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions) error {
50 // We can't pass a potentially large exclude list directly via cmd line
51 // because we easily overrun the kernel's max argument/environment size
52 // when the full image list is passed (e.g. when this is used by
53 // `docker load`). We will marshall the options via a pipe to the
55 r, w, err := os.Pipe()
57 return fmt.Errorf("Untar pipe failure: %v", err)
60 cmd := reexec.Command("docker-untar", dest)
61 cmd.Stdin = decompressedArchive
63 cmd.ExtraFiles = append(cmd.ExtraFiles, r)
64 output := bytes.NewBuffer(nil)
68 if err := cmd.Start(); err != nil {
69 return fmt.Errorf("Untar error on re-exec cmd: %v", err)
71 //write the options to the pipe for the untar exec to read
72 if err := json.NewEncoder(w).Encode(options); err != nil {
73 return fmt.Errorf("Untar json encode to pipe failed: %v", err)
77 if err := cmd.Wait(); err != nil {
78 // when `xz -d -c -q | docker-untar ...` failed on docker-untar side,
79 // we need to exhaust `xz`'s output, otherwise the `xz` side will be
80 // pending on write pipe forever
81 io.Copy(ioutil.Discard, decompressedArchive)
83 return fmt.Errorf("Error processing tar file(%v): %s", err, output)