Tizen_4.0 base
[platform/upstream/docker-engine.git] / pkg / chrootarchive / archive_unix.go
1 // +build !windows
2
3 package chrootarchive
4
5 import (
6         "bytes"
7         "encoding/json"
8         "flag"
9         "fmt"
10         "io"
11         "io/ioutil"
12         "os"
13         "runtime"
14
15         "github.com/docker/docker/pkg/archive"
16         "github.com/docker/docker/pkg/reexec"
17 )
18
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
21 // chroot and rexec.
22 func untar() {
23         runtime.LockOSThread()
24         flag.Parse()
25
26         var options *archive.TarOptions
27
28         //read the options from the pipe "ExtraFiles"
29         if err := json.NewDecoder(os.NewFile(3, "options")).Decode(&options); err != nil {
30                 fatal(err)
31         }
32
33         if err := chroot(flag.Arg(0)); err != nil {
34                 fatal(err)
35         }
36
37         if err := archive.Unpack(os.Stdin, "/", options); err != nil {
38                 fatal(err)
39         }
40         // fully consume stdin in case it is zero padded
41         if _, err := flush(os.Stdin); err != nil {
42                 fatal(err)
43         }
44
45         os.Exit(0)
46 }
47
48 func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions) error {
49
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
54         // child
55         r, w, err := os.Pipe()
56         if err != nil {
57                 return fmt.Errorf("Untar pipe failure: %v", err)
58         }
59
60         cmd := reexec.Command("docker-untar", dest)
61         cmd.Stdin = decompressedArchive
62
63         cmd.ExtraFiles = append(cmd.ExtraFiles, r)
64         output := bytes.NewBuffer(nil)
65         cmd.Stdout = output
66         cmd.Stderr = output
67
68         if err := cmd.Start(); err != nil {
69                 return fmt.Errorf("Untar error on re-exec cmd: %v", err)
70         }
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)
74         }
75         w.Close()
76
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)
82
83                 return fmt.Errorf("Error processing tar file(%v): %s", err, output)
84         }
85         return nil
86 }