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