116 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package containerd
 | 
						|
 | 
						|
import (
 | 
						|
	"os"
 | 
						|
	"os/exec"
 | 
						|
	"strings"
 | 
						|
	"syscall"
 | 
						|
)
 | 
						|
 | 
						|
// Mount is the lingua franca of the containerkit. 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, ",")
 | 
						|
}
 |