...
1 package mountinfo
2
3 import (
4 "os"
5 "path/filepath"
6
7 "golang.org/x/sys/unix"
8 )
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 func MountedFast(path string) (mounted, sure bool, err error) {
25
26 if path == string(os.PathSeparator) {
27 return true, true, nil
28 }
29
30 path, err = normalizePath(path)
31 if err != nil {
32 return false, false, err
33 }
34 mounted, sure, err = mountedFast(path)
35 return
36 }
37
38
39
40 func mountedByOpenat2(path string) (bool, error) {
41 dir, last := filepath.Split(path)
42
43 dirfd, err := unix.Openat2(unix.AT_FDCWD, dir, &unix.OpenHow{
44 Flags: unix.O_PATH | unix.O_CLOEXEC,
45 })
46 if err != nil {
47 return false, &os.PathError{Op: "openat2", Path: dir, Err: err}
48 }
49 fd, err := unix.Openat2(dirfd, last, &unix.OpenHow{
50 Flags: unix.O_PATH | unix.O_CLOEXEC | unix.O_NOFOLLOW,
51 Resolve: unix.RESOLVE_NO_XDEV,
52 })
53 _ = unix.Close(dirfd)
54 switch err {
55 case nil:
56 _ = unix.Close(fd)
57 return false, nil
58 case unix.EXDEV:
59 return true, nil
60 }
61
62 return false, &os.PathError{Op: "openat2", Path: path, Err: err}
63 }
64
65
66 func mountedFast(path string) (mounted, sure bool, err error) {
67
68 if path == string(os.PathSeparator) {
69 return true, true, nil
70 }
71
72
73 mounted, err = mountedByOpenat2(path)
74 if err == nil {
75 return mounted, true, nil
76 }
77
78
79 mounted, err = mountedByStat(path)
80
81
82 if mounted && err == nil {
83 return true, true, nil
84 }
85
86 return
87 }
88
89 func mounted(path string) (bool, error) {
90 path, err := normalizePath(path)
91 if err != nil {
92 return false, err
93 }
94 mounted, sure, err := mountedFast(path)
95 if sure && err == nil {
96 return mounted, nil
97 }
98
99
100 return mountedByMountinfo(path)
101 }
102
View as plain text