blob: 2c9983e078750fed63c3a65206571b5e537cd5b1 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package envvar
import (
"io/ioutil"
"path/filepath"
"sort"
"strings"
)
// LookPath returns the absolute path of the executable with the given name,
// based on the given dirs. If multiple exectuables match the name, the first
// match in dirs is returned. Invalid dirs are silently ignored.
func LookPath(dirs []string, name string) string {
if strings.Contains(name, string(filepath.Separator)) {
return ""
}
for _, dir := range dirs {
fileInfos, err := ioutil.ReadDir(dir)
if err != nil {
continue
}
for _, fileInfo := range fileInfos {
if m := fileInfo.Mode(); !m.IsRegular() || (m&0111 == 0) {
continue
}
if fileInfo.Name() == name {
return filepath.Join(dir, name)
}
}
}
return ""
}
// LookPathAll returns the absolute paths of all executables with the given name
// prefix, based on the given dirs. If multiple exectuables match the prefix
// with the same name, the first match in dirs is returned. Invalid dirs are
// silently ignored. Returns a list of paths sorted by name.
//
// The names are filled in as the method runs, to ensure the first matching
// property. As a consequence, you may pass in a pre-populated names map to
// prevent matching those names. It is fine to pass in a nil names map.
func LookPathAll(dirs []string, prefix string, names map[string]bool) []string {
if strings.Contains(prefix, string(filepath.Separator)) {
return nil
}
if names == nil {
names = make(map[string]bool)
}
var all []string
for _, dir := range dirs {
fileInfos, err := ioutil.ReadDir(dir)
if err != nil {
continue
}
for _, fileInfo := range fileInfos {
if m := fileInfo.Mode(); !m.IsRegular() || (m&0111 == 0) {
continue
}
name, prefixLen := fileInfo.Name(), len(prefix)
if len(name) < prefixLen || name[:prefixLen] != prefix {
continue
}
if names[name] {
continue
}
names[name] = true
all = append(all, filepath.Join(dir, name))
}
}
sort.Sort(byBase(all))
return all
}
type byBase []string
func (x byBase) Len() int { return len(x) }
func (x byBase) Less(i, j int) bool { return filepath.Base(x[i]) < filepath.Base(x[j]) }
func (x byBase) Swap(i, j int) { x[i], x[j] = x[j], x[i] }