github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/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 "syscall" 15 16 "github.com/docker/docker/pkg/archive" 17 "github.com/docker/docker/pkg/reexec" 18 ) 19 20 func chroot(path string) error { 21 if err := syscall.Chroot(path); err != nil { 22 return err 23 } 24 return syscall.Chdir("/") 25 } 26 27 // untar is the entry-point for docker-untar on re-exec. This is not used on 28 // Windows as it does not support chroot, hence no point sandboxing through 29 // chroot and rexec. 30 func untar() { 31 runtime.LockOSThread() 32 flag.Parse() 33 34 var options *archive.TarOptions 35 36 //read the options from the pipe "ExtraFiles" 37 if err := json.NewDecoder(os.NewFile(3, "options")).Decode(&options); err != nil { 38 fatal(err) 39 } 40 41 if err := chroot(flag.Arg(0)); err != nil { 42 fatal(err) 43 } 44 45 if err := archive.Unpack(os.Stdin, "/", options); err != nil { 46 fatal(err) 47 } 48 // fully consume stdin in case it is zero padded 49 flush(os.Stdin) 50 os.Exit(0) 51 } 52 53 func invokeUnpack(decompressedArchive io.Reader, dest string, options *archive.TarOptions) error { 54 55 // We can't pass a potentially large exclude list directly via cmd line 56 // because we easily overrun the kernel's max argument/environment size 57 // when the full image list is passed (e.g. when this is used by 58 // `docker load`). We will marshall the options via a pipe to the 59 // child 60 r, w, err := os.Pipe() 61 if err != nil { 62 return fmt.Errorf("Untar pipe failure: %v", err) 63 } 64 65 cmd := reexec.Command("docker-untar", dest) 66 cmd.Stdin = decompressedArchive 67 68 cmd.ExtraFiles = append(cmd.ExtraFiles, r) 69 output := bytes.NewBuffer(nil) 70 cmd.Stdout = output 71 cmd.Stderr = output 72 73 if err := cmd.Start(); err != nil { 74 return fmt.Errorf("Untar error on re-exec cmd: %v", err) 75 } 76 //write the options to the pipe for the untar exec to read 77 if err := json.NewEncoder(w).Encode(options); err != nil { 78 return fmt.Errorf("Untar json encode to pipe failed: %v", err) 79 } 80 w.Close() 81 82 if err := cmd.Wait(); err != nil { 83 // when `xz -d -c -q | docker-untar ...` failed on docker-untar side, 84 // we need to exhaust `xz`'s output, otherwise the `xz` side will be 85 // pending on write pipe forever 86 io.Copy(ioutil.Discard, decompressedArchive) 87 88 return fmt.Errorf("Untar re-exec error: %v: output: %s", err, output) 89 } 90 return nil 91 }