diff --git a/pkg/fsutils/fsutils.go b/pkg/fsutils/fsutils.go index 80bb9c5b44f4..91d12e5cd341 100644 --- a/pkg/fsutils/fsutils.go +++ b/pkg/fsutils/fsutils.go @@ -61,7 +61,7 @@ func EvalSymlinks(path string) (string, error) { } var er evalSymlinkRes - er.path, er.err = filepath.EvalSymlinks(path) + er.path, er.err = evalSymlinks(path) evalSymlinkCache.Store(path, er) return er.path, er.err diff --git a/pkg/fsutils/fsutils_unix.go b/pkg/fsutils/fsutils_unix.go new file mode 100644 index 000000000000..68e762cf4bab --- /dev/null +++ b/pkg/fsutils/fsutils_unix.go @@ -0,0 +1,9 @@ +//go:build !windows + +package fsutils + +import "path/filepath" + +func evalSymlinks(path string) (string, error) { + return filepath.EvalSymlinks(path) +} diff --git a/pkg/fsutils/fsutils_windows.go b/pkg/fsutils/fsutils_windows.go new file mode 100644 index 000000000000..19efb1cfc245 --- /dev/null +++ b/pkg/fsutils/fsutils_windows.go @@ -0,0 +1,39 @@ +//go:build windows + +package fsutils + +import ( + "errors" + "os" + "path/filepath" + "syscall" +) + +// This is a workaround for the behavior of [filepath.EvalSymlinks], +// which fails with [syscall.ENOTDIR] if the specified path contains a junction on Windows. +// Junctions can occur, for example, when a volume is mounted as a subdirectory inside another drive. +// This can usually happen when using the Dev Drives feature and replacing existing directories. +// See: https://github.com/golang/go/issues/40180 +// +// Since [syscall.ENOTDIR] is only returned when calling [filepath.EvalSymlinks] on Windows +// if part of the presented path is a junction and nothing before was a symlink, +// we simply treat this as NOT symlink, +// because a symlink over the junction makes no sense at all. +func evalSymlinks(path string) (string, error) { + resolved, err := filepath.EvalSymlinks(path) + if err == nil { + return resolved, nil + } + + if !errors.Is(err, syscall.ENOTDIR) { + return "", err + } + + _, err = os.Stat(path) + if err != nil { + return "", err + } + + // If exists, we make the path absolute, to be sure... + return filepath.Abs(path) +}