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  }