github.com/wulonghui/docker@v1.8.0-rc2/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 ) 33 runtime.LockOSThread() 34 flag.Parse() 35 36 if err := chroot(flag.Arg(0)); err != nil { 37 fatal(err) 38 } 39 40 // We need to be able to set any perms 41 oldmask, err := system.Umask(0) 42 defer system.Umask(oldmask) 43 if err != nil { 44 fatal(err) 45 } 46 47 if tmpDir, err = ioutil.TempDir("/", "temp-docker-extract"); err != nil { 48 fatal(err) 49 } 50 51 os.Setenv("TMPDIR", tmpDir) 52 size, err := archive.UnpackLayer("/", os.Stdin) 53 os.RemoveAll(tmpDir) 54 if err != nil { 55 fatal(err) 56 } 57 58 encoder := json.NewEncoder(os.Stdout) 59 if err := encoder.Encode(applyLayerResponse{size}); err != nil { 60 fatal(fmt.Errorf("unable to encode layerSize JSON: %s", err)) 61 } 62 63 flush(os.Stdout) 64 flush(os.Stdin) 65 os.Exit(0) 66 } 67 68 // ApplyLayer parses a diff in the standard layer format from `layer`, 69 // and applies it to the directory `dest`. The stream `layer` can only be 70 // uncompressed. 71 // Returns the size in bytes of the contents of the layer. 72 func ApplyLayer(dest string, layer archive.ArchiveReader) (size int64, err error) { 73 return applyLayerHandler(dest, layer, true) 74 } 75 76 // ApplyUncompressedLayer parses a diff in the standard layer format from 77 // `layer`, and applies it to the directory `dest`. The stream `layer` 78 // can only be uncompressed. 79 // Returns the size in bytes of the contents of the layer. 80 func ApplyUncompressedLayer(dest string, layer archive.ArchiveReader) (int64, error) { 81 return applyLayerHandler(dest, layer, false) 82 } 83 84 func applyLayerHandler(dest string, layer archive.ArchiveReader, decompress bool) (size int64, err error) { 85 dest = filepath.Clean(dest) 86 if decompress { 87 decompressed, err := archive.DecompressStream(layer) 88 if err != nil { 89 return 0, err 90 } 91 defer decompressed.Close() 92 93 layer = decompressed 94 } 95 96 cmd := reexec.Command("docker-applyLayer", dest) 97 cmd.Stdin = layer 98 99 outBuf, errBuf := new(bytes.Buffer), new(bytes.Buffer) 100 cmd.Stdout, cmd.Stderr = outBuf, errBuf 101 102 if err = cmd.Run(); err != nil { 103 return 0, fmt.Errorf("ApplyLayer %s stdout: %s stderr: %s", err, outBuf, errBuf) 104 } 105 106 // Stdout should be a valid JSON struct representing an applyLayerResponse. 107 response := applyLayerResponse{} 108 decoder := json.NewDecoder(outBuf) 109 if err = decoder.Decode(&response); err != nil { 110 return 0, fmt.Errorf("unable to decode ApplyLayer JSON response: %s", err) 111 } 112 113 return response.LayerSize, nil 114 }