github.com/sdibtacm/sandbox@v0.0.0-20200320120712-60470cf803dc/exec/lookpath.go (about) 1 //+build linux 2 3 package exec 4 5 import ( 6 "errors" 7 "os" 8 "path/filepath" 9 "strconv" 10 "strings" 11 ) 12 13 type LpError struct { 14 // Name is the file name for which the error occurred. 15 Name string 16 // Err is the underlying error. 17 Err error 18 } 19 20 func (e *LpError) Error() string { 21 return "exec: " + strconv.Quote(e.Name) + ": " + e.Err.Error() 22 } 23 24 // Copyright 2010 The Go Authors. All rights reserved. 25 // Use of this source code is governed by a BSD-style 26 // license that can be found in the LICENSE file. 27 28 // ErrNotFound is the error resulting if a path search failed to find an executable file. 29 var ErrNotFound = errors.New("executable file not found in $PATH") 30 31 func executable(file string) error { 32 d, err := os.Stat(file) 33 if err != nil { 34 return err 35 } 36 if m := d.Mode(); !m.IsDir() && m&0111 != 0 { 37 return nil 38 } 39 return os.ErrPermission 40 } 41 42 // LookPath searches for an executable named file in the 43 // directories named by the PATH environment variable. 44 // If file contains a slash, it is tried directly and the PATH is not consulted. 45 // The result may be an absolute path or a path relative to the current directory. 46 func LookPath(file string) (string, error) { 47 // NOTE(rsc): I wish we could use the Plan 9 behavior here 48 // (only bypass the path if file begins with / or ./ or ../) 49 // but that would not match all the Unix shells. 50 51 if strings.Contains(file, "/") { 52 err := executable(file) 53 if err == nil { 54 return file, nil 55 } 56 return "", &LpError{file, err} 57 } 58 path := os.Getenv("PATH") 59 for _, dir := range filepath.SplitList(path) { 60 if dir == "" { 61 // Unix shell semantics: path element "" means "." 62 dir = "." 63 } 64 path := filepath.Join(dir, file) 65 if err := executable(path); err == nil { 66 return path, nil 67 } 68 } 69 return "", &LpError{file, ErrNotFound} 70 }