|
@@ -6,6 +6,8 @@ import (
|
|
|
"github.com/dotcloud/docker/utils"
|
|
|
"os"
|
|
|
"path"
|
|
|
+ "strings"
|
|
|
+ "syscall"
|
|
|
)
|
|
|
|
|
|
type InitFunc func(root string) (Driver, error)
|
|
@@ -31,6 +33,13 @@ type Differ interface {
|
|
|
DiffSize(id string) (bytes int64, err error)
|
|
|
}
|
|
|
|
|
|
+type Mount struct {
|
|
|
+ Device string
|
|
|
+ Target string
|
|
|
+ Type string
|
|
|
+ Options string
|
|
|
+}
|
|
|
+
|
|
|
var (
|
|
|
DefaultDriver string
|
|
|
// All registred drivers
|
|
@@ -88,3 +97,91 @@ func New(root string) (driver Driver, err error) {
|
|
|
}
|
|
|
return nil, err
|
|
|
}
|
|
|
+
|
|
|
+func (m *Mount) Mount(root string) error {
|
|
|
+ var (
|
|
|
+ flag int
|
|
|
+ data []string
|
|
|
+ target = path.Join(root, m.Target)
|
|
|
+ )
|
|
|
+
|
|
|
+ if mounted, err := Mounted(target); err != nil || mounted {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ flags := map[string]struct {
|
|
|
+ clear bool
|
|
|
+ flag int
|
|
|
+ }{
|
|
|
+ "defaults": {false, 0},
|
|
|
+ "ro": {false, syscall.MS_RDONLY},
|
|
|
+ "rw": {true, syscall.MS_RDONLY},
|
|
|
+ "suid": {true, syscall.MS_NOSUID},
|
|
|
+ "nosuid": {false, syscall.MS_NOSUID},
|
|
|
+ "dev": {true, syscall.MS_NODEV},
|
|
|
+ "nodev": {false, syscall.MS_NODEV},
|
|
|
+ "exec": {true, syscall.MS_NOEXEC},
|
|
|
+ "noexec": {false, syscall.MS_NOEXEC},
|
|
|
+ "sync": {false, syscall.MS_SYNCHRONOUS},
|
|
|
+ "async": {true, syscall.MS_SYNCHRONOUS},
|
|
|
+ "dirsync": {false, syscall.MS_DIRSYNC},
|
|
|
+ "remount": {false, syscall.MS_REMOUNT},
|
|
|
+ "mand": {false, syscall.MS_MANDLOCK},
|
|
|
+ "nomand": {true, syscall.MS_MANDLOCK},
|
|
|
+ "atime": {true, syscall.MS_NOATIME},
|
|
|
+ "noatime": {false, syscall.MS_NOATIME},
|
|
|
+ "diratime": {true, syscall.MS_NODIRATIME},
|
|
|
+ "nodiratime": {false, syscall.MS_NODIRATIME},
|
|
|
+ "bind": {false, syscall.MS_BIND},
|
|
|
+ "rbind": {false, syscall.MS_BIND | syscall.MS_REC},
|
|
|
+ "relatime": {false, syscall.MS_RELATIME},
|
|
|
+ "norelatime": {true, syscall.MS_RELATIME},
|
|
|
+ "strictatime": {false, syscall.MS_STRICTATIME},
|
|
|
+ "nostrictatime": {true, syscall.MS_STRICTATIME},
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, o := range strings.Split(m.Options, ",") {
|
|
|
+ // If the option does not exist in the flags table then it is a
|
|
|
+ // data value for a specific fs type
|
|
|
+ if f, exists := flags[o]; exists {
|
|
|
+ if f.clear {
|
|
|
+ flag &= ^f.flag
|
|
|
+ } else {
|
|
|
+ flag |= f.flag
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ data = append(data, o)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := syscall.Mount(m.Device, target, m.Type, uintptr(flag), strings.Join(data, ",")); err != nil {
|
|
|
+ panic(err)
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func (m *Mount) Unmount(root string) error {
|
|
|
+ target := path.Join(root, m.Target)
|
|
|
+ if mounted, err := Mounted(target); err != nil || !mounted {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ return syscall.Unmount(target, 0)
|
|
|
+}
|
|
|
+
|
|
|
+func Mounted(mountpoint string) (bool, error) {
|
|
|
+ mntpoint, err := os.Stat(mountpoint)
|
|
|
+ if err != nil {
|
|
|
+ if os.IsNotExist(err) {
|
|
|
+ return false, nil
|
|
|
+ }
|
|
|
+ return false, err
|
|
|
+ }
|
|
|
+ parent, err := os.Stat(path.Join(mountpoint, ".."))
|
|
|
+ if err != nil {
|
|
|
+ return false, err
|
|
|
+ }
|
|
|
+ mntpointSt := mntpoint.Sys().(*syscall.Stat_t)
|
|
|
+ parentSt := parent.Sys().(*syscall.Stat_t)
|
|
|
+
|
|
|
+ return mntpointSt.Dev != parentSt.Dev, nil
|
|
|
+}
|