pathutil_windows.go raw
1 package pathutil
2
3 import (
4 "errors"
5 "io/fs"
6 "os"
7 "path/filepath"
8 "strings"
9
10 "golang.org/x/sys/windows"
11 )
12
13 // UserHomeDir returns the home directory of the current user.
14 func UserHomeDir() string {
15 return KnownFolder(windows.FOLDERID_Profile, []string{"USERPROFILE"}, nil)
16 }
17
18 // Exists returns true if the specified path exists.
19 func Exists(path string) bool {
20 fi, err := os.Lstat(path)
21 if fi != nil && fi.Mode()&os.ModeSymlink != 0 {
22 _, err = filepath.EvalSymlinks(path)
23 }
24
25 return err == nil || errors.Is(err, fs.ErrExist)
26 }
27
28 // ExpandHome substitutes `%USERPROFILE%` at the start of the specified `path`.
29 func ExpandHome(path string) string {
30 home := UserHomeDir()
31 if path == "" || home == "" {
32 return path
33 }
34 if strings.HasPrefix(path, `%USERPROFILE%`) {
35 return filepath.Join(home, path[13:])
36 }
37
38 return path
39 }
40
41 // KnownFolder returns the location of the folder with the specified ID.
42 // If that fails, the folder location is determined by reading the provided
43 // environment variables (the first non-empty read value is returned).
44 // If that fails as well, the first non-empty fallback is returned.
45 // If all of the above fails, the function returns an empty string.
46 func KnownFolder(id *windows.KNOWNFOLDERID, envVars []string, fallbacks []string) string {
47 if id != nil {
48 flags := []uint32{windows.KF_FLAG_DEFAULT, windows.KF_FLAG_DEFAULT_PATH}
49 for _, flag := range flags {
50 p, _ := windows.KnownFolderPath(id, flag|windows.KF_FLAG_DONT_VERIFY)
51 if p != "" {
52 return p
53 }
54 }
55 }
56
57 for _, envVar := range envVars {
58 p := os.Getenv(envVar)
59 if p != "" {
60 return p
61 }
62 }
63
64 for _, fallback := range fallbacks {
65 if fallback != "" {
66 return fallback
67 }
68 }
69
70 return ""
71 }
72