github.com/rclone/rclone@v1.66.1-0.20240517100346-7b89735ae726/cmd/mountlib/check_linux.go (about) 1 //go:build linux 2 3 package mountlib 4 5 import ( 6 "fmt" 7 "path/filepath" 8 "strings" 9 10 "github.com/moby/sys/mountinfo" 11 ) 12 13 // CheckMountEmpty checks if folder is not already a mountpoint. 14 // On Linux we use the OS-specific /proc/self/mountinfo API so the check won't access the path. 15 // Directories marked as "mounted" by autofs are considered not mounted. 16 func CheckMountEmpty(mountpoint string) error { 17 const msg = "directory already mounted, use --allow-non-empty to mount anyway: %s" 18 19 mountpointAbs, err := filepath.Abs(mountpoint) 20 if err != nil { 21 return fmt.Errorf("cannot get absolute path: %s: %w", mountpoint, err) 22 } 23 24 infos, err := mountinfo.GetMounts(mountinfo.SingleEntryFilter(mountpointAbs)) 25 if err != nil { 26 return fmt.Errorf("cannot get mounts: %w", err) 27 } 28 29 foundAutofs := false 30 for _, info := range infos { 31 if info.FSType != "autofs" { 32 return fmt.Errorf(msg, mountpointAbs) 33 } 34 foundAutofs = true 35 } 36 // It isn't safe to list an autofs in the middle of mounting 37 if foundAutofs { 38 return nil 39 } 40 41 return checkMountEmpty(mountpoint) 42 } 43 44 // singleEntryFilter looks for a specific entry. 45 // 46 // It may appear more than once and we return all of them if so. 47 func singleEntryFilter(mp string) mountinfo.FilterFunc { 48 return func(m *mountinfo.Info) (skip, stop bool) { 49 return m.Mountpoint != mp, false 50 } 51 } 52 53 // CheckMountReady checks whether mountpoint is mounted by rclone. 54 // Only mounts with type "rclone" or "fuse.rclone" count. 55 func CheckMountReady(mountpoint string) error { 56 const msg = "mount not ready: %s" 57 58 mountpointAbs, err := filepath.Abs(mountpoint) 59 if err != nil { 60 return fmt.Errorf("cannot get absolute path: %s: %w", mountpoint, err) 61 } 62 63 infos, err := mountinfo.GetMounts(singleEntryFilter(mountpointAbs)) 64 if err != nil { 65 return fmt.Errorf("cannot get mounts: %w", err) 66 } 67 68 for _, info := range infos { 69 if strings.Contains(info.FSType, "rclone") { 70 return nil 71 } 72 } 73 74 return fmt.Errorf(msg, mountpointAbs) 75 } 76 77 // CanCheckMountReady is set if CheckMountReady is functional 78 var CanCheckMountReady = true