github.com/damirazo/docker@v1.9.0/pkg/chrootarchive/diff_unix.go (about) 1 //+build !windows 2 3 package chrootarchive 4 5 import ( 6 "bytes" 7 "encoding/json" 8 "flag" 9 "fmt" 10 "io/ioutil" 11 "os" 12 "path/filepath" 13 "runtime" 14 15 "github.com/docker/docker/pkg/archive" 16 "github.com/docker/docker/pkg/reexec" 17 "github.com/docker/docker/pkg/system" 18 ) 19 20 type applyLayerResponse struct { 21 LayerSize int64 `json:"layerSize"` 22 } 23 24 // applyLayer is the entry-point for docker-applylayer on re-exec. This is not 25 // used on Windows as it does not support chroot, hence no point sandboxing 26 // through chroot and rexec. 27 func applyLayer() { 28 29 var ( 30 tmpDir = "" 31 err error 32 options *archive.TarOptions 33 ) 34 runtime.LockOSThread() 35 flag.Parse() 36 37 if err := chroot(flag.Arg(0)); err != nil { 38 fatal(err) 39 } 40 41 // We need to be able to set any perms 42 oldmask, err := system.Umask(0) 43 defer system.Umask(oldmask) 44 if err != nil { 45 fatal(err) 46 } 47 48 if err := json.Unmarshal([]byte(os.Getenv("OPT")), &options); err != nil { 49 fatal(err) 50 } 51 52 if tmpDir, err = ioutil.TempDir("/", "temp-docker-extract"); err != nil { 53 fatal(err) 54 } 55 56 os.Setenv("TMPDIR", tmpDir) 57 size, err := archive.UnpackLayer("/", os.Stdin, options) 58 os.RemoveAll(tmpDir) 59 if err != nil { 60 fatal(err) 61 } 62 63 encoder := json.NewEncoder(os.Stdout) 64 if err := encoder.Encode(applyLayerResponse{size}); err != nil { 65 fatal(fmt.Errorf("unable to encode layerSize JSON: %s", err)) 66 } 67 68 flush(os.Stdout) 69 flush(os.Stdin) 70 os.Exit(0) 71 } 72 73 // applyLayerHandler parses a diff in the standard layer format from `layer`, and 74 // applies it to the directory `dest`. Returns the size in bytes of the 75 // contents of the layer. 76 func applyLayerHandler(dest string, layer archive.Reader, options *archive.TarOptions, decompress bool) (size int64, err error) { 77 dest = filepath.Clean(dest) 78 if decompress { 79 decompressed, err := archive.DecompressStream(layer) 80 if err != nil { 81 return 0, err 82 } 83 defer decompressed.Close() 84 85 layer = decompressed 86 } 87 if options == nil { 88 options = &archive.TarOptions{} 89 } 90 if options.ExcludePatterns == nil { 91 options.ExcludePatterns = []string{} 92 } 93 94 data, err := json.Marshal(options) 95 if err != nil { 96 return 0, fmt.Errorf("ApplyLayer json encode: %v", err) 97 } 98 99 cmd := reexec.Command("docker-applyLayer", dest) 100 cmd.Stdin = layer 101 cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data)) 102 103 outBuf, errBuf := new(bytes.Buffer), new(bytes.Buffer) 104 cmd.Stdout, cmd.Stderr = outBuf, errBuf 105 106 if err = cmd.Run(); err != nil { 107 return 0, fmt.Errorf("ApplyLayer %s stdout: %s stderr: %s", err, outBuf, errBuf) 108 } 109 110 // Stdout should be a valid JSON struct representing an applyLayerResponse. 111 response := applyLayerResponse{} 112 decoder := json.NewDecoder(outBuf) 113 if err = decoder.Decode(&response); err != nil { 114 return 0, fmt.Errorf("unable to decode ApplyLayer JSON response: %s", err) 115 } 116 117 return response.LayerSize, nil 118 }