github.com/endophage/docker@v1.4.2-0.20161027011718-242853499895/pkg/chrootarchive/archive_unix.go (about) 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 }