driver.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package vfs
  2. import (
  3. "bytes"
  4. "fmt"
  5. "os"
  6. "os/exec"
  7. "path"
  8. "github.com/docker/docker/daemon/graphdriver"
  9. "github.com/docker/libcontainer/label"
  10. )
  11. func init() {
  12. graphdriver.Register("vfs", Init)
  13. }
  14. func Init(home string, options []string) (graphdriver.Driver, error) {
  15. d := &Driver{
  16. home: home,
  17. }
  18. return d, nil
  19. }
  20. type Driver struct {
  21. home string
  22. }
  23. func (d *Driver) String() string {
  24. return "vfs"
  25. }
  26. func (d *Driver) Status() [][2]string {
  27. return nil
  28. }
  29. func (d *Driver) Cleanup() error {
  30. return nil
  31. }
  32. func isGNUcoreutils() bool {
  33. if stdout, err := exec.Command("cp", "--version").Output(); err == nil {
  34. return bytes.Contains(stdout, []byte("GNU coreutils"))
  35. }
  36. return false
  37. }
  38. func copyDir(src, dst string) error {
  39. argv := make([]string, 0, 4)
  40. if isGNUcoreutils() {
  41. argv = append(argv, "-aT", "--reflink=auto", src, dst)
  42. } else {
  43. argv = append(argv, "-a", src+"/.", dst+"/.")
  44. }
  45. if output, err := exec.Command("cp", argv...).CombinedOutput(); err != nil {
  46. return fmt.Errorf("Error VFS copying directory: %s (%s)", err, output)
  47. }
  48. return nil
  49. }
  50. func (d *Driver) Create(id, parent string) error {
  51. dir := d.dir(id)
  52. if err := os.MkdirAll(path.Dir(dir), 0700); err != nil {
  53. return err
  54. }
  55. if err := os.Mkdir(dir, 0755); err != nil {
  56. return err
  57. }
  58. opts := []string{"level:s0"}
  59. if _, mountLabel, err := label.InitLabels(opts); err == nil {
  60. label.Relabel(dir, mountLabel, "")
  61. }
  62. if parent == "" {
  63. return nil
  64. }
  65. parentDir, err := d.Get(parent, "")
  66. if err != nil {
  67. return fmt.Errorf("%s: %s", parent, err)
  68. }
  69. if err := copyDir(parentDir, dir); err != nil {
  70. return err
  71. }
  72. return nil
  73. }
  74. func (d *Driver) dir(id string) string {
  75. return path.Join(d.home, "dir", path.Base(id))
  76. }
  77. func (d *Driver) Remove(id string) error {
  78. if _, err := os.Stat(d.dir(id)); err != nil {
  79. return err
  80. }
  81. return os.RemoveAll(d.dir(id))
  82. }
  83. func (d *Driver) Get(id, mountLabel string) (string, error) {
  84. dir := d.dir(id)
  85. if st, err := os.Stat(dir); err != nil {
  86. return "", err
  87. } else if !st.IsDir() {
  88. return "", fmt.Errorf("%s: not a directory", dir)
  89. }
  90. return dir, nil
  91. }
  92. func (d *Driver) Put(id string) {
  93. // The vfs driver has no runtime resources (e.g. mounts)
  94. // to clean up, so we don't need anything here
  95. }
  96. func (d *Driver) Exists(id string) bool {
  97. _, err := os.Stat(d.dir(id))
  98. return err == nil
  99. }