github.com/criyle/go-sandbox@v0.10.3/container/lookup_linux.go (about) 1 package container 2 3 import ( 4 "errors" 5 "io/fs" 6 "os" 7 "path/filepath" 8 "strings" 9 ) 10 11 var ( 12 errNotFound = errors.New("executable file not found in $PATH") 13 errNoPath = errors.New("no PATH environment variable provided for look up") 14 ) 15 16 func findExecutable(file string) error { 17 d, err := os.Stat(file) 18 if err != nil { 19 return err 20 } 21 if m := d.Mode(); !m.IsDir() && m&0111 != 0 { 22 return nil 23 } 24 return fs.ErrPermission 25 } 26 27 func lookPath(name string, env []string) (string, error) { 28 // don't look if abs path provided 29 if filepath.Base(name) != name { 30 return name, nil 31 } 32 33 // don't look if exist in current dir 34 if err := findExecutable(name); err == nil { 35 return name, nil 36 } 37 38 path, err := findPath(env) 39 if err != nil { 40 return "", err 41 } 42 for _, dir := range path { 43 if dir == "" { 44 dir = "." 45 } 46 p := filepath.Join(dir, name) 47 if err := findExecutable(p); err == nil { 48 return p, nil 49 } 50 } 51 return "", errNotFound 52 } 53 54 func findPath(env []string) ([]string, error) { 55 // find PATH= 56 const pathPrefix = "PATH=" 57 for i := len(env) - 1; i >= 0; i-- { 58 s := env[i] 59 if strings.HasPrefix(s, pathPrefix) { 60 return filepath.SplitList(s[len(pathPrefix):]), nil 61 } 62 } 63 return nil, errNoPath 64 }