use error::{Error, Result};
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Mutex;
const BIN_PATHS: [&'static str; 6] = [
"/usr/local/bin",
"/usr/bin",
"/bin",
"/sbin",
"/usr/sbin",
"/usr/local/sbin"
];
lazy_static! {
static ref RESOLVER: Mutex<BinResolver> = Mutex::new(BinResolver::new());
}
pub struct BinResolver {
cache: HashMap<String, PathBuf>,
}
impl BinResolver {
fn new() -> BinResolver {
BinResolver {
cache: HashMap::new(),
}
}
pub fn resolve(bin: &str) -> Result<PathBuf> {
let mut br = RESOLVER.lock().unwrap();
if !br.cache.contains_key(bin) {
for path in BIN_PATHS.into_iter() {
let mut buf = PathBuf::from(path);
if buf.is_dir() {
buf.push(bin);
if buf.is_file() {
br.cache.insert(bin.into(), buf);
break;
}
}
}
}
Ok(br.cache.get(bin)
.ok_or(Error::Generic(format!("No paths contained the requested binary: {}", bin)))?
.to_owned())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_resolve_fail() {
assert!(BinResolver::resolve("i_am_not_a_bin_script").is_err());
}
}