github.com/psychoss/docker@v1.9.0/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  }