Source file
src/os/exec/lp_windows.go
1
2
3
4
5 package exec
6
7 import (
8 "errors"
9 "io/fs"
10 "os"
11 "path/filepath"
12 "strings"
13 "syscall"
14 )
15
16
17 var ErrNotFound = errors.New("executable file not found in %PATH%")
18
19 func chkStat(file string) error {
20 d, err := os.Stat(file)
21 if err != nil {
22 return err
23 }
24 if d.IsDir() {
25 return fs.ErrPermission
26 }
27 return nil
28 }
29
30 func hasExt(file string) bool {
31 i := strings.LastIndex(file, ".")
32 if i < 0 {
33 return false
34 }
35 return strings.LastIndexAny(file, `:\/`) < i
36 }
37
38 func findExecutable(file string, exts []string) (string, error) {
39 if len(exts) == 0 {
40 return file, chkStat(file)
41 }
42 if hasExt(file) {
43 if chkStat(file) == nil {
44 return file, nil
45 }
46 }
47 for _, e := range exts {
48 if f := file + e; chkStat(f) == nil {
49 return f, nil
50 }
51 }
52 return "", fs.ErrNotExist
53 }
54
55
56
57
58
59
60
61
62
63
64
65 func LookPath(file string) (string, error) {
66 var exts []string
67 x := os.Getenv(`PATHEXT`)
68 if x != "" {
69 for _, e := range strings.Split(strings.ToLower(x), `;`) {
70 if e == "" {
71 continue
72 }
73 if e[0] != '.' {
74 e = "." + e
75 }
76 exts = append(exts, e)
77 }
78 } else {
79 exts = []string{".com", ".exe", ".bat", ".cmd"}
80 }
81
82 if strings.ContainsAny(file, `:\/`) {
83 f, err := findExecutable(file, exts)
84 if err == nil {
85 return f, nil
86 }
87 return "", &Error{file, err}
88 }
89
90
91
92
93
94
95
96
97
98
99 var (
100 dotf string
101 dotErr error
102 )
103 if _, found := syscall.Getenv("NoDefaultCurrentDirectoryInExePath"); !found {
104 if f, err := findExecutable(filepath.Join(".", file), exts); err == nil {
105 if execerrdot.Value() == "0" {
106 execerrdot.IncNonDefault()
107 return f, nil
108 }
109 dotf, dotErr = f, &Error{file, ErrDot}
110 }
111 }
112
113 path := os.Getenv("path")
114 for _, dir := range filepath.SplitList(path) {
115 if f, err := findExecutable(filepath.Join(dir, file), exts); err == nil {
116 if dotErr != nil {
117
118
119
120
121
122
123
124 dotfi, dotfiErr := os.Lstat(dotf)
125 fi, fiErr := os.Lstat(f)
126 if dotfiErr != nil || fiErr != nil || !os.SameFile(dotfi, fi) {
127 return dotf, dotErr
128 }
129 }
130
131 if !filepath.IsAbs(f) {
132 if execerrdot.Value() != "0" {
133 return f, &Error{file, ErrDot}
134 }
135 execerrdot.IncNonDefault()
136 }
137 return f, nil
138 }
139 }
140
141 if dotErr != nil {
142 return dotf, dotErr
143 }
144 return "", &Error{file, ErrNotFound}
145 }
146
View as plain text