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