github.com/tompao/docker@v1.9.1/daemon/graphdriver/vfs/driver.go (about) 1 // +build daemon 2 3 package vfs 4 5 import ( 6 "fmt" 7 "os" 8 "path/filepath" 9 10 "github.com/docker/docker/daemon/graphdriver" 11 "github.com/docker/docker/pkg/chrootarchive" 12 "github.com/docker/docker/pkg/idtools" 13 14 "github.com/opencontainers/runc/libcontainer/label" 15 ) 16 17 func init() { 18 graphdriver.Register("vfs", Init) 19 } 20 21 // Init returns a new VFS driver. 22 // This sets the home directory for the driver and returns NaiveDiffDriver. 23 func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { 24 d := &Driver{ 25 home: home, 26 uidMaps: uidMaps, 27 gidMaps: gidMaps, 28 } 29 rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) 30 if err != nil { 31 return nil, err 32 } 33 if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil { 34 return nil, err 35 } 36 return graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps), nil 37 } 38 39 // Driver holds information about the driver, home directory of the driver. 40 // Driver implements graphdriver.ProtoDriver. It uses only basic vfs operations. 41 // In order to support layering, files are copied from the parent layer into the new layer. There is no copy-on-write support. 42 // Driver must be wrapped in NaiveDiffDriver to be used as a graphdriver.Driver 43 type Driver struct { 44 home string 45 uidMaps []idtools.IDMap 46 gidMaps []idtools.IDMap 47 } 48 49 func (d *Driver) String() string { 50 return "vfs" 51 } 52 53 // Status is used for implementing the graphdriver.ProtoDriver interface. VFS does not currently have any status information. 54 func (d *Driver) Status() [][2]string { 55 return nil 56 } 57 58 // GetMetadata is used for implementing the graphdriver.ProtoDriver interface. VFS does not currently have any meta data. 59 func (d *Driver) GetMetadata(id string) (map[string]string, error) { 60 return nil, nil 61 } 62 63 // Cleanup is used to implement graphdriver.ProtoDriver. There is no cleanup required for this driver. 64 func (d *Driver) Cleanup() error { 65 return nil 66 } 67 68 // Create prepares the filesystem for the VFS driver and copies the directory for the given id under the parent. 69 func (d *Driver) Create(id, parent string) error { 70 dir := d.dir(id) 71 rootUID, rootGID, err := idtools.GetRootUIDGID(d.uidMaps, d.gidMaps) 72 if err != nil { 73 return err 74 } 75 if err := idtools.MkdirAllAs(filepath.Dir(dir), 0700, rootUID, rootGID); err != nil { 76 return err 77 } 78 if err := idtools.MkdirAs(dir, 0755, rootUID, rootGID); err != nil { 79 return err 80 } 81 opts := []string{"level:s0"} 82 if _, mountLabel, err := label.InitLabels(opts); err == nil { 83 label.SetFileLabel(dir, mountLabel) 84 } 85 if parent == "" { 86 return nil 87 } 88 parentDir, err := d.Get(parent, "") 89 if err != nil { 90 return fmt.Errorf("%s: %s", parent, err) 91 } 92 if err := chrootarchive.CopyWithTar(parentDir, dir); err != nil { 93 return err 94 } 95 return nil 96 } 97 98 func (d *Driver) dir(id string) string { 99 return filepath.Join(d.home, "dir", filepath.Base(id)) 100 } 101 102 // Remove deletes the content from the directory for a given id. 103 func (d *Driver) Remove(id string) error { 104 if _, err := os.Stat(d.dir(id)); err != nil { 105 return err 106 } 107 return os.RemoveAll(d.dir(id)) 108 } 109 110 // Get returns the directory for the given id. 111 func (d *Driver) Get(id, mountLabel string) (string, error) { 112 dir := d.dir(id) 113 if st, err := os.Stat(dir); err != nil { 114 return "", err 115 } else if !st.IsDir() { 116 return "", fmt.Errorf("%s: not a directory", dir) 117 } 118 return dir, nil 119 } 120 121 // Put is a noop for vfs that return nil for the error, since this driver has no runtime resources to clean up. 122 func (d *Driver) Put(id string) error { 123 // The vfs driver has no runtime resources (e.g. mounts) 124 // to clean up, so we don't need anything here 125 return nil 126 } 127 128 // Exists checks to see if the directory exists for the given id. 129 func (d *Driver) Exists(id string) bool { 130 _, err := os.Stat(d.dir(id)) 131 return err == nil 132 }