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 )
14
15
16 var ErrNotFound = errors.New("executable file not found in %PATH%")
17
18 func chkStat(file string) error {
19 d, err := os.Stat(file)
20 if err != nil {
21 return err
22 }
23 if d.IsDir() {
24 return fs.ErrPermission
25 }
26 return nil
27 }
28
29 func hasExt(file string) bool {
30 i := strings.LastIndex(file, ".")
31 if i < 0 {
32 return false
33 }
34 return strings.LastIndexAny(file, `:\/`) < i
35 }
36
37 func findExecutable(file string, exts []string) (string, error) {
38 if len(exts) == 0 {
39 return file, chkStat(file)
40 }
41 if hasExt(file) {
42 if chkStat(file) == nil {
43 return file, nil
44 }
45
46
47 }
48 for _, e := range exts {
49 if f := file + e; chkStat(f) == nil {
50 return f, nil
51 }
52 }
53 if hasExt(file) {
54 return "", fs.ErrNotExist
55 }
56 return "", ErrNotFound
57 }
58
59
60
61
62
63
64
65
66
67
68
69 func LookPath(file string) (string, error) {
70 if err := validateLookPath(file); err != nil {
71 return "", &Error{file, err}
72 }
73
74 return lookPath(file, pathExt())
75 }
76
77
78
79
80
81
82
83
84
85
86 func lookExtensions(path, dir string) (string, error) {
87 if err := validateLookPath(path); err != nil {
88 return "", &Error{path, err}
89 }
90
91 if filepath.Base(path) == path {
92 path = "." + string(filepath.Separator) + path
93 }
94 exts := pathExt()
95 if ext := filepath.Ext(path); ext != "" {
96 for _, e := range exts {
97 if strings.EqualFold(ext, e) {
98
99 return path, nil
100 }
101 }
102 }
103 if dir == "" {
104 return lookPath(path, exts)
105 }
106 if filepath.VolumeName(path) != "" {
107 return lookPath(path, exts)
108 }
109 if len(path) > 1 && os.IsPathSeparator(path[0]) {
110 return lookPath(path, exts)
111 }
112 dirandpath := filepath.Join(dir, path)
113
114 lp, err := lookPath(dirandpath, exts)
115 if err != nil {
116 return "", err
117 }
118 ext := strings.TrimPrefix(lp, dirandpath)
119 return path + ext, nil
120 }
121
122 func pathExt() []string {
123 var exts []string
124 x := os.Getenv(`PATHEXT`)
125 if x != "" {
126 for _, e := range strings.Split(strings.ToLower(x), `;`) {
127 if e == "" {
128 continue
129 }
130 if e[0] != '.' {
131 e = "." + e
132 }
133 exts = append(exts, e)
134 }
135 } else {
136 exts = []string{".com", ".exe", ".bat", ".cmd"}
137 }
138 return exts
139 }
140
141
142 func lookPath(file string, exts []string) (string, error) {
143 if strings.ContainsAny(file, `:\/`) {
144 f, err := findExecutable(file, exts)
145 if err == nil {
146 return f, nil
147 }
148 return "", &Error{file, err}
149 }
150
151
152
153
154
155
156
157
158
159
160 var (
161 dotf string
162 dotErr error
163 )
164 if _, found := os.LookupEnv("NoDefaultCurrentDirectoryInExePath"); !found {
165 if f, err := findExecutable(filepath.Join(".", file), exts); err == nil {
166 if execerrdot.Value() == "0" {
167 execerrdot.IncNonDefault()
168 return f, nil
169 }
170 dotf, dotErr = f, &Error{file, ErrDot}
171 }
172 }
173
174 path := os.Getenv("path")
175 for _, dir := range filepath.SplitList(path) {
176 if dir == "" {
177
178
179 continue
180 }
181
182 if f, err := findExecutable(filepath.Join(dir, file), exts); err == nil {
183 if dotErr != nil {
184
185
186
187
188
189
190
191 dotfi, dotfiErr := os.Lstat(dotf)
192 fi, fiErr := os.Lstat(f)
193 if dotfiErr != nil || fiErr != nil || !os.SameFile(dotfi, fi) {
194 return dotf, dotErr
195 }
196 }
197
198 if !filepath.IsAbs(f) {
199 if execerrdot.Value() != "0" {
200
201
202
203
204 if dotErr == nil {
205 dotf, dotErr = f, &Error{file, ErrDot}
206 }
207 continue
208 }
209 execerrdot.IncNonDefault()
210 }
211 return f, nil
212 }
213 }
214
215 if dotErr != nil {
216 return dotf, dotErr
217 }
218 return "", &Error{file, ErrNotFound}
219 }
220
View as plain text