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 func lookPath(file string) (string, error) {
60 if err := validateLookPath(file); err != nil {
61 return "", &Error{file, err}
62 }
63
64 return lookPathExts(file, pathExt())
65 }
66
67
68
69
70
71
72
73
74
75
76 func lookExtensions(path, dir string) (string, error) {
77 if err := validateLookPath(path); err != nil {
78 return "", &Error{path, err}
79 }
80
81 if filepath.Base(path) == path {
82 path = "." + string(filepath.Separator) + path
83 }
84 exts := pathExt()
85 if ext := filepath.Ext(path); ext != "" {
86 for _, e := range exts {
87 if strings.EqualFold(ext, e) {
88
89 return path, nil
90 }
91 }
92 }
93 if dir == "" {
94 return lookPathExts(path, exts)
95 }
96 if filepath.VolumeName(path) != "" {
97 return lookPathExts(path, exts)
98 }
99 if len(path) > 1 && os.IsPathSeparator(path[0]) {
100 return lookPathExts(path, exts)
101 }
102 dirandpath := filepath.Join(dir, path)
103
104 lp, err := lookPathExts(dirandpath, exts)
105 if err != nil {
106 return "", err
107 }
108 ext := strings.TrimPrefix(lp, dirandpath)
109 return path + ext, nil
110 }
111
112 func pathExt() []string {
113 var exts []string
114 x := os.Getenv(`PATHEXT`)
115 if x != "" {
116 for e := range strings.SplitSeq(strings.ToLower(x), `;`) {
117 if e == "" {
118 continue
119 }
120 if e[0] != '.' {
121 e = "." + e
122 }
123 exts = append(exts, e)
124 }
125 } else {
126 exts = []string{".com", ".exe", ".bat", ".cmd"}
127 }
128 return exts
129 }
130
131
132 func lookPathExts(file string, exts []string) (string, error) {
133 if strings.ContainsAny(file, `:\/`) {
134 f, err := findExecutable(file, exts)
135 if err == nil {
136 return f, nil
137 }
138 return "", &Error{file, err}
139 }
140
141
142
143
144
145
146
147
148
149
150 var (
151 dotf string
152 dotErr error
153 )
154 if _, found := os.LookupEnv("NoDefaultCurrentDirectoryInExePath"); !found {
155 if f, err := findExecutable(filepath.Join(".", file), exts); err == nil {
156 if execerrdot.Value() == "0" {
157 execerrdot.IncNonDefault()
158 return f, nil
159 }
160 dotf, dotErr = f, &Error{file, ErrDot}
161 }
162 }
163
164 path := os.Getenv("path")
165 for _, dir := range filepath.SplitList(path) {
166 if dir == "" {
167
168
169 continue
170 }
171
172 if f, err := findExecutable(filepath.Join(dir, file), exts); err == nil {
173 if dotErr != nil {
174
175
176
177
178
179
180
181 dotfi, dotfiErr := os.Lstat(dotf)
182 fi, fiErr := os.Lstat(f)
183 if dotfiErr != nil || fiErr != nil || !os.SameFile(dotfi, fi) {
184 return dotf, dotErr
185 }
186 }
187
188 if !filepath.IsAbs(f) {
189 if execerrdot.Value() != "0" {
190
191
192
193
194 if dotErr == nil {
195 dotf, dotErr = f, &Error{file, ErrDot}
196 }
197 continue
198 }
199 execerrdot.IncNonDefault()
200 }
201 return f, nil
202 }
203 }
204
205 if dotErr != nil {
206 return dotf, dotErr
207 }
208 return "", &Error{file, ErrNotFound}
209 }
210
View as plain text