use crate::SimplePathSearcher;
use std::ffi::{OsStr, OsString};
use std::os::unix::ffi::{OsStrExt, OsStringExt};
use std::path::{Path, PathBuf};
pub fn is_executable(path: &Path) -> anyhow::Result<bool> {
use libc::{access, X_OK};
let cstr = std::ffi::CString::new(path.as_os_str().as_bytes().to_vec())?;
let res = unsafe { access(cstr.as_ptr(), X_OK) };
Ok(res == 0)
}
pub fn concat_osstr(a: &OsStr, b: &OsStr) -> OsString {
let a = a.as_bytes();
let b = b.as_bytes();
let mut res = Vec::with_capacity(a.len() + b.len());
res.extend_from_slice(a);
res.extend_from_slice(b);
OsStringExt::from_vec(res)
}
pub struct ExecutablePathSearcher<'a>(SimplePathSearcher<'a>);
impl<'a> ExecutablePathSearcher<'a> {
pub fn new<T: AsRef<OsStr> + ?Sized>(
command: &'a T,
path: Option<&'a OsStr>,
_path_ext: Option<&'a OsStr>,
) -> Self {
Self(SimplePathSearcher::new(command, path))
}
}
impl<'a> Iterator for ExecutablePathSearcher<'a> {
type Item = PathBuf;
fn next(&mut self) -> Option<PathBuf> {
while let Some(candidate) = self.0.next() {
if let Ok(true) = is_executable(&candidate) {
return Some(candidate);
}
}
None
}
}