82 lines
1.4 KiB
Go
82 lines
1.4 KiB
Go
|
package fs
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"io/fs"
|
||
|
"os"
|
||
|
"os/exec"
|
||
|
"path/filepath"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
func lookupDirs(extraDirs []string) []string {
|
||
|
pathVar := os.Getenv("path")
|
||
|
dirs := filepath.SplitList(pathVar)
|
||
|
for _, ep := range extraDirs {
|
||
|
dirs = append(dirs, ep)
|
||
|
}
|
||
|
return dirs
|
||
|
}
|
||
|
|
||
|
func findFile(dirs []string, file string, f fileCheckFunc) (string, error) {
|
||
|
for _, dir := range dirs {
|
||
|
path := filepath.Join(dir, file)
|
||
|
if err := f(path); err == nil {
|
||
|
return path, nil
|
||
|
}
|
||
|
}
|
||
|
return "", fmt.Errorf("%s: %w", file, exec.ErrNotFound)
|
||
|
}
|
||
|
|
||
|
func checkExecutable(file string) error {
|
||
|
var exts []string
|
||
|
x := os.Getenv(`PATHEXT`)
|
||
|
if x != "" {
|
||
|
for _, e := range strings.Split(strings.ToLower(x), `;`) {
|
||
|
if e == "" {
|
||
|
continue
|
||
|
}
|
||
|
if e[0] != '.' {
|
||
|
e = "." + e
|
||
|
}
|
||
|
exts = append(exts, e)
|
||
|
}
|
||
|
} else {
|
||
|
exts = []string{".com", ".exe", ".bat", ".cmd"}
|
||
|
}
|
||
|
|
||
|
if len(exts) == 0 {
|
||
|
return chkStat(file)
|
||
|
}
|
||
|
if hasExt(file) {
|
||
|
if chkStat(file) == nil {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
for _, e := range exts {
|
||
|
if f := file + e; chkStat(f) == nil {
|
||
|
return nil
|
||
|
}
|
||
|
}
|
||
|
return fs.ErrNotExist
|
||
|
}
|
||
|
|
||
|
func chkStat(file string) error {
|
||
|
d, err := os.Stat(file)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if d.IsDir() {
|
||
|
return fs.ErrPermission
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func hasExt(file string) bool {
|
||
|
i := strings.LastIndex(file, ".")
|
||
|
if i < 0 {
|
||
|
return false
|
||
|
}
|
||
|
return strings.LastIndexAny(file, `:\/`) < i
|
||
|
}
|