github.com/criyle/go-sandbox@v0.10.3/pkg/mount/mount_linux.go (about) 1 package mount 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "syscall" 8 ) 9 10 // Mount calls mount syscall 11 func (m *Mount) Mount() error { 12 if err := ensureMountTargetExists(m.Source, m.Target); err != nil { 13 return fmt.Errorf("mkdir: %w", err) 14 } 15 if err := syscall.Mount(m.Source, m.Target, m.FsType, m.Flags, m.Data); err != nil { 16 return fmt.Errorf("mount: %w", err) 17 } 18 // Read-only bind mount need to be remounted 19 const bindRo = syscall.MS_BIND | syscall.MS_RDONLY 20 if m.Flags&bindRo == bindRo { 21 if err := syscall.Mount("", m.Target, m.FsType, m.Flags|syscall.MS_REMOUNT, m.Data); err != nil { 22 return fmt.Errorf("remount: %w", err) 23 } 24 } 25 return nil 26 } 27 28 // IsBindMount returns if it is a bind mount 29 func (m Mount) IsBindMount() bool { 30 return m.Flags&syscall.MS_BIND == syscall.MS_BIND 31 } 32 33 // IsReadOnly returns if it is a readonly mount 34 func (m Mount) IsReadOnly() bool { 35 return m.Flags&syscall.MS_RDONLY == syscall.MS_RDONLY 36 } 37 38 // IsTmpFs returns if the fsType is tmpfs 39 func (m Mount) IsTmpFs() bool { 40 return m.FsType == "tmpfs" 41 } 42 43 func ensureMountTargetExists(source, target string) error { 44 isFile := false 45 if fi, err := os.Stat(source); err == nil { 46 isFile = !fi.IsDir() 47 } 48 dir := target 49 if isFile { 50 dir = filepath.Dir(target) 51 } 52 if err := os.MkdirAll(dir, 0755); err != nil { 53 return err 54 } 55 if isFile { 56 if err := syscall.Mknod(target, 0755, 0); err != nil { 57 // double check if file exists 58 f, err1 := os.Lstat(target) 59 if err1 == nil && f.Mode().IsRegular() { 60 return nil 61 } 62 return err 63 } 64 } 65 return nil 66 } 67 68 func (m Mount) String() string { 69 switch { 70 case m.Flags&syscall.MS_BIND == syscall.MS_BIND: 71 flag := "rw" 72 if m.Flags&syscall.MS_RDONLY == syscall.MS_RDONLY { 73 flag = "ro" 74 } 75 return fmt.Sprintf("bind[%s:%s:%s]", m.Source, m.Target, flag) 76 77 case m.FsType == "tmpfs": 78 return fmt.Sprintf("tmpfs[%s]", m.Target) 79 80 case m.FsType == "proc": 81 return "proc[ro]" 82 83 default: 84 return fmt.Sprintf("mount[%s,%s:%s:%x,%s]", m.FsType, m.Source, m.Target, m.Flags, m.Data) 85 } 86 }