File: check_linux.go

package info (click to toggle)
rclone 1.69.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 45,716 kB
  • sloc: sh: 1,115; xml: 857; python: 754; javascript: 612; makefile: 299; ansic: 101; php: 74
file content (78 lines) | stat: -rw-r--r-- 2,055 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//go:build linux

package mountlib

import (
	"fmt"
	"path/filepath"
	"strings"

	"github.com/moby/sys/mountinfo"
)

// CheckMountEmpty checks if folder is not already a mountpoint.
// On Linux we use the OS-specific /proc/self/mountinfo API so the check won't access the path.
// Directories marked as "mounted" by autofs are considered not mounted.
func CheckMountEmpty(mountpoint string) error {
	const msg = "directory already mounted, use --allow-non-empty to mount anyway: %s"

	mountpointAbs, err := filepath.Abs(mountpoint)
	if err != nil {
		return fmt.Errorf("cannot get absolute path: %s: %w", mountpoint, err)
	}

	infos, err := mountinfo.GetMounts(mountinfo.SingleEntryFilter(mountpointAbs))
	if err != nil {
		return fmt.Errorf("cannot get mounts: %w", err)
	}

	foundAutofs := false
	for _, info := range infos {
		if info.FSType != "autofs" {
			return fmt.Errorf(msg, mountpointAbs)
		}
		foundAutofs = true
	}
	// It isn't safe to list an autofs in the middle of mounting
	if foundAutofs {
		return nil
	}

	return checkMountEmpty(mountpoint)
}

// singleEntryFilter looks for a specific entry.
//
// It may appear more than once and we return all of them if so.
func singleEntryFilter(mp string) mountinfo.FilterFunc {
	return func(m *mountinfo.Info) (skip, stop bool) {
		return m.Mountpoint != mp, false
	}
}

// CheckMountReady checks whether mountpoint is mounted by rclone.
// Only mounts with type "rclone" or "fuse.rclone" count.
func CheckMountReady(mountpoint string) error {
	const msg = "mount not ready: %s"

	mountpointAbs, err := filepath.Abs(mountpoint)
	if err != nil {
		return fmt.Errorf("cannot get absolute path: %s: %w", mountpoint, err)
	}

	infos, err := mountinfo.GetMounts(singleEntryFilter(mountpointAbs))
	if err != nil {
		return fmt.Errorf("cannot get mounts: %w", err)
	}

	for _, info := range infos {
		if strings.Contains(info.FSType, "rclone") {
			return nil
		}
	}

	return fmt.Errorf(msg, mountpointAbs)
}

// CanCheckMountReady is set if CheckMountReady is functional
var CanCheckMountReady = true