github.com/ssdev-go/moby@v17.12.1-ce-rc2+incompatible/pkg/mount/mount.go (about) 1 package mount 2 3 import ( 4 "sort" 5 "strings" 6 7 "github.com/sirupsen/logrus" 8 ) 9 10 // GetMounts retrieves a list of mounts for the current running process. 11 func GetMounts() ([]*Info, error) { 12 return parseMountTable() 13 } 14 15 // Mounted determines if a specified mountpoint has been mounted. 16 // On Linux it looks at /proc/self/mountinfo. 17 func Mounted(mountpoint string) (bool, error) { 18 entries, err := parseMountTable() 19 if err != nil { 20 return false, err 21 } 22 23 // Search the table for the mountpoint 24 for _, e := range entries { 25 if e.Mountpoint == mountpoint { 26 return true, nil 27 } 28 } 29 return false, nil 30 } 31 32 // Mount will mount filesystem according to the specified configuration, on the 33 // condition that the target path is *not* already mounted. Options must be 34 // specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See 35 // flags.go for supported option flags. 36 func Mount(device, target, mType, options string) error { 37 flag, _ := parseOptions(options) 38 if flag&REMOUNT != REMOUNT { 39 if mounted, err := Mounted(target); err != nil || mounted { 40 return err 41 } 42 } 43 return ForceMount(device, target, mType, options) 44 } 45 46 // ForceMount will mount a filesystem according to the specified configuration, 47 // *regardless* if the target path is not already mounted. Options must be 48 // specified like the mount or fstab unix commands: "opt1=val1,opt2=val2". See 49 // flags.go for supported option flags. 50 func ForceMount(device, target, mType, options string) error { 51 flag, data := parseOptions(options) 52 return mount(device, target, mType, uintptr(flag), data) 53 } 54 55 // Unmount lazily unmounts a filesystem on supported platforms, otherwise 56 // does a normal unmount. 57 func Unmount(target string) error { 58 if mounted, err := Mounted(target); err != nil || !mounted { 59 return err 60 } 61 return unmount(target, mntDetach) 62 } 63 64 // RecursiveUnmount unmounts the target and all mounts underneath, starting with 65 // the deepsest mount first. 66 func RecursiveUnmount(target string) error { 67 mounts, err := GetMounts() 68 if err != nil { 69 return err 70 } 71 72 // Make the deepest mount be first 73 sort.Sort(sort.Reverse(byMountpoint(mounts))) 74 75 for i, m := range mounts { 76 if !strings.HasPrefix(m.Mountpoint, target) { 77 continue 78 } 79 logrus.Debugf("Trying to unmount %s", m.Mountpoint) 80 err = Unmount(m.Mountpoint) 81 if err != nil && i == len(mounts)-1 { 82 if mounted, err := Mounted(m.Mountpoint); err != nil || mounted { 83 return err 84 } 85 // Ignore errors for submounts and continue trying to unmount others 86 // The final unmount should fail if there ane any submounts remaining 87 } else if err != nil { 88 logrus.Errorf("Failed to unmount %s: %v", m.Mountpoint, err) 89 } else if err == nil { 90 logrus.Debugf("Unmounted %s", m.Mountpoint) 91 } 92 } 93 return nil 94 }