package containerd import ( "os" "os/exec" "strings" "syscall" ) // Mount is the lingua franca of containerd. A mount represents a // serialized mount syscall. Components either emit or consume mounts. type Mount struct { // Type specifies the host-specific of the mount. Type string // Source specifies where to mount from. Depending on the host system, this // can be a source path or device. Source string // Target is the filesystem mount location. Target string // Options contains zero or more fstab-style mount options. Typically, // these are platform specific. Options []string } // MountCommand converts the provided mount into a CLI arguments that can be used to mount the func MountCommand(m Mount) []string { return []string{ "mount", "-t", strings.ToLower(m.Type), m.Source, m.Target, "-o", strings.Join(m.Options, ","), } } func MountAll(mounts ...Mount) error { for _, mount := range mounts { cmd := exec.Command("mount", MountCommand(mount)[1:]...) cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout if err := cmd.Run(); err != nil { return err } } return nil } func MountFS(mounts []Mount, target string) error { for _, m := range mounts { flags, data := parseMountOptions(m.Options) if err := syscall.Mount(m.Source, target, m.Type, uintptr(flags), data); err != nil { return err } } return nil } // parseMountOptions takes fstab style mount options and parses them for // use with a standard mount() syscall func parseMountOptions(options []string) (int, string) { var ( flag int data []string ) flags := map[string]struct { clear bool flag int }{ "async": {true, syscall.MS_SYNCHRONOUS}, "atime": {true, syscall.MS_NOATIME}, "bind": {false, syscall.MS_BIND}, "defaults": {false, 0}, "dev": {true, syscall.MS_NODEV}, "diratime": {true, syscall.MS_NODIRATIME}, "dirsync": {false, syscall.MS_DIRSYNC}, "exec": {true, syscall.MS_NOEXEC}, "mand": {false, syscall.MS_MANDLOCK}, "noatime": {false, syscall.MS_NOATIME}, "nodev": {false, syscall.MS_NODEV}, "nodiratime": {false, syscall.MS_NODIRATIME}, "noexec": {false, syscall.MS_NOEXEC}, "nomand": {true, syscall.MS_MANDLOCK}, "norelatime": {true, syscall.MS_RELATIME}, "nostrictatime": {true, syscall.MS_STRICTATIME}, "nosuid": {false, syscall.MS_NOSUID}, "rbind": {false, syscall.MS_BIND | syscall.MS_REC}, "relatime": {false, syscall.MS_RELATIME}, "remount": {false, syscall.MS_REMOUNT}, "ro": {false, syscall.MS_RDONLY}, "rw": {true, syscall.MS_RDONLY}, "strictatime": {false, syscall.MS_STRICTATIME}, "suid": {true, syscall.MS_NOSUID}, "sync": {false, syscall.MS_SYNCHRONOUS}, } for _, o := range options { // If the option does not exist in the flags table or the flag // is not supported on the platform, // then it is a data value for a specific fs type if f, exists := flags[o]; exists && f.flag != 0 { if f.clear { flag &= ^f.flag } else { flag |= f.flag } } else { data = append(data, o) } } return flag, strings.Join(data, ",") }