diff.go 2.3 KB

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