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