Support detecting mountpoints correctly (#7288)

Currently windows support was relying on Symlink as
a way to detect a drive, this doesn't work in latest
Windows 2016, fix this to use a proper mechanism by
using win32 APIs.

Additionally also add support for detecting bind mounts
on Linux.
This commit is contained in:
Harshavardhana
2019-02-26 18:04:53 -08:00
committed by kannappanr
parent 5085bef397
commit 5e69a107d8
25 changed files with 6925 additions and 32 deletions

View File

@@ -37,24 +37,30 @@ const (
)
// IsLikelyMountPoint determines if a directory is a mountpoint.
// It is fast but not necessarily ALWAYS correct. If the path is in fact
// a bind mount from one part of a mount to another it will not be detected.
// mkdir /tmp/a /tmp/b; mount --bin /tmp/a /tmp/b; IsLikelyMountPoint("/tmp/b")
// will return false. When in fact /tmp/b is a mount point. If this situation
// if of interest to you, don't use this function...
func IsLikelyMountPoint(file string) bool {
stat, err := os.Stat(file)
func IsLikelyMountPoint(path string) bool {
s1, err := os.Lstat(path)
if err != nil {
return false
}
rootStat, err := os.Lstat(filepath.Dir(strings.TrimSuffix(file, "/")))
// A symlink can never be a mount point
if s1.Mode()&os.ModeSymlink != 0 {
return false
}
s2, err := os.Lstat(filepath.Dir(strings.TrimSuffix(path, "/")))
if err != nil {
return false
}
// If the directory has a different device as parent, then it is a mountpoint.
return stat.Sys().(*syscall.Stat_t).Dev != rootStat.Sys().(*syscall.Stat_t).Dev
if s1.Sys().(*syscall.Stat_t).Dev != s2.Sys().(*syscall.Stat_t).Dev {
// path/.. on a different device as path
return true
}
// path/.. is the same i-node as path - this check is for bind mounts.
return s1.Sys().(*syscall.Stat_t).Ino == s2.Sys().(*syscall.Stat_t).Ino
}
// CheckCrossDevice - check if any list of paths has any sub-mounts at /proc/mounts.