diff_unix.go 2.2 KB

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