mirror of
https://github.com/minio/minio.git
synced 2025-11-10 14:09:48 -05:00
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:
committed by
kannappanr
parent
5085bef397
commit
5e69a107d8
@@ -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.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
package mountinfo
|
||||
|
||||
import (
|
||||
"os"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// CheckCrossDevice - check if any input path has multiple sub-mounts.
|
||||
@@ -28,32 +28,21 @@ func CheckCrossDevice(paths []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// fileExists checks if specified file exists.
|
||||
func fileExists(filename string) (bool, error) {
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
return false, nil
|
||||
} else if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// IsLikelyMountPoint determines if a directory is a mountpoint.
|
||||
func IsLikelyMountPoint(file string) bool {
|
||||
stat, err := os.Lstat(file)
|
||||
if err != nil {
|
||||
func IsLikelyMountPoint(path string) bool {
|
||||
wpath, _ := windows.UTF16PtrFromString(path)
|
||||
wvolume := make([]uint16, len(path)+1)
|
||||
|
||||
if err := windows.GetVolumePathName(wpath, &wvolume[0], uint32(len(wvolume))); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// If current file is a symlink, then it is a mountpoint.
|
||||
if stat.Mode()&os.ModeSymlink != 0 {
|
||||
target, err := os.Readlink(file)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
exists, _ := fileExists(target)
|
||||
return exists
|
||||
switch windows.GetDriveType(&wvolume[0]) {
|
||||
case windows.DRIVE_FIXED, windows.DRIVE_REMOVABLE, windows.DRIVE_REMOTE, windows.DRIVE_RAMDISK:
|
||||
// Recognize "fixed", "removable", "remote" and "ramdisk" drives as proper drives
|
||||
// which can be treated as an actual mount-point, rest can be ignored.
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getdrivetypew
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user