github.com/pmorton/docker@v1.5.0/pkg/chrootarchive/diff.go (about) 1 package chrootarchive 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "flag" 7 "fmt" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "runtime" 12 "syscall" 13 14 "github.com/docker/docker/pkg/archive" 15 "github.com/docker/docker/pkg/reexec" 16 ) 17 18 type applyLayerResponse struct { 19 LayerSize int64 `json:"layerSize"` 20 } 21 22 func applyLayer() { 23 runtime.LockOSThread() 24 flag.Parse() 25 26 if err := chroot(flag.Arg(0)); err != nil { 27 fatal(err) 28 } 29 30 // We need to be able to set any perms 31 oldmask := syscall.Umask(0) 32 defer syscall.Umask(oldmask) 33 tmpDir, err := ioutil.TempDir("/", "temp-docker-extract") 34 if err != nil { 35 fatal(err) 36 } 37 38 os.Setenv("TMPDIR", tmpDir) 39 size, err := archive.UnpackLayer("/", os.Stdin) 40 os.RemoveAll(tmpDir) 41 if err != nil { 42 fatal(err) 43 } 44 45 encoder := json.NewEncoder(os.Stdout) 46 if err := encoder.Encode(applyLayerResponse{size}); err != nil { 47 fatal(fmt.Errorf("unable to encode layerSize JSON: %s", err)) 48 } 49 50 flush(os.Stdout) 51 flush(os.Stdin) 52 os.Exit(0) 53 } 54 55 func ApplyLayer(dest string, layer archive.ArchiveReader) (size int64, err error) { 56 dest = filepath.Clean(dest) 57 decompressed, err := archive.DecompressStream(layer) 58 if err != nil { 59 return 0, err 60 } 61 62 defer decompressed.Close() 63 64 cmd := reexec.Command("docker-applyLayer", dest) 65 cmd.Stdin = decompressed 66 67 outBuf, errBuf := new(bytes.Buffer), new(bytes.Buffer) 68 cmd.Stdout, cmd.Stderr = outBuf, errBuf 69 70 if err = cmd.Run(); err != nil { 71 return 0, fmt.Errorf("ApplyLayer %s stdout: %s stderr: %s", err, outBuf, errBuf) 72 } 73 74 // Stdout should be a valid JSON struct representing an applyLayerResponse. 75 response := applyLayerResponse{} 76 decoder := json.NewDecoder(outBuf) 77 if err = decoder.Decode(&response); err != nil { 78 return 0, fmt.Errorf("unable to decode ApplyLayer JSON response: %s", err) 79 } 80 81 return response.LayerSize, nil 82 }