|
@@ -2,6 +2,7 @@ package util
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
+ "io/fs"
|
|
|
"os"
|
|
|
"path"
|
|
|
"path/filepath"
|
|
@@ -112,3 +113,54 @@ func FindProjectPath(loc string) (string, bool) {
|
|
|
|
|
|
return "", false
|
|
|
}
|
|
|
+
|
|
|
+// ReadLink returns the destination of the named symbolic link recursively.
|
|
|
+func ReadLink(name string) (string, error) {
|
|
|
+ name, err := filepath.Abs(name)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ if name == "/" {
|
|
|
+ return "/", nil
|
|
|
+ }
|
|
|
+
|
|
|
+ isLink, err := isLink(name)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ if !isLink {
|
|
|
+ dir, base := filepath.Split(name)
|
|
|
+ dir = filepath.Clean(dir)
|
|
|
+ dir, err := ReadLink(dir)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ return filepath.Join(dir, base), nil
|
|
|
+ }
|
|
|
+
|
|
|
+ link, err := os.Readlink(name)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ dir, base := filepath.Split(link)
|
|
|
+ dir = filepath.Dir(dir)
|
|
|
+ dir, err = ReadLink(dir)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ return filepath.Join(dir, base), nil
|
|
|
+}
|
|
|
+
|
|
|
+func isLink(name string) (bool, error) {
|
|
|
+ fi, err := os.Lstat(name)
|
|
|
+ if err != nil {
|
|
|
+ return false, err
|
|
|
+ }
|
|
|
+
|
|
|
+ return fi.Mode()&fs.ModeSymlink != 0, nil
|
|
|
+}
|