mount.go 2.5 KB

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