pathsearch-0.2.0/Cargo.toml.orig010064400017500001750000000004561364444271700147640ustar0000000000000000[package] name = "pathsearch" version = "0.2.0" authors = ["Wez Furlong"] edition = "2018" repository = "https://github.com/wez/wzsh" description = "Search for files in PATH" license = "MIT" documentation = "https://docs.rs/pathsearch" readme = "README.md" [dependencies] anyhow = "1.0" libc = "0.2" pathsearch-0.2.0/Cargo.toml0000644000000015311364444275500112670ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "pathsearch" version = "0.2.0" authors = ["Wez Furlong"] description = "Search for files in PATH" documentation = "https://docs.rs/pathsearch" readme = "README.md" license = "MIT" repository = "https://github.com/wez/wzsh" [dependencies.anyhow] version = "1.0" [dependencies.libc] version = "0.2" pathsearch-0.2.0/README.md010066400017500001750000000024751364444266500133630ustar0000000000000000# pathsearch This crate provides functions that can be used to search for an executable based on the PATH environment on both POSIX and Windows systems. `find_executable_in_path` is the most convenient function exported by this crate; given the name of an executable, it will yield the absolute path of the first matching file. ```rust use pathsearch::find_executable_in_path; if let Some(exe) = find_executable_in_path("ls") { println!("Found ls at {}", exe.display()); } ``` `PathSearcher` is platform-independent struct that encompasses the path searching algorithm used by `find_executable_in_path`. Construct it by passing in the PATH and PATHEXT (for Windows) environment variables and iterate it to incrementally produce all candidate results. This is useful when implementing utilities such as `which` that want to show all possible paths. ```rust use pathsearch::PathSearcher; use std::ffi::OsString; let path = std::env::var_os("PATH"); let path_ext = std::env::var_os("PATHEXT"); for exe in PathSearcher::new( "zsh", path.as_ref().map(OsString::as_os_str), path_ext.as_ref().map(OsString::as_os_str), ) { println!("{}", exe.display()); } ``` `SimplePathSearcher` is a simple iterator that can be used to search an arbitrary path for an arbitrary file that doesn't have to be executable. License: MIT pathsearch-0.2.0/src/lib.rs010064400017500001750000000071611364444266200137770ustar0000000000000000//! This crate provides functions that can be used to search for an //! executable based on the PATH environment on both POSIX and Windows //! systems. //! //! `find_executable_in_path` is the most convenient function exported //! by this crate; given the name of an executable, it will yield the //! absolute path of the first matching file. //! //! ``` //! use pathsearch::find_executable_in_path; //! //! if let Some(exe) = find_executable_in_path("ls") { //! println!("Found ls at {}", exe.display()); //! } //! ``` //! //! `PathSearcher` is platform-independent struct that encompasses the //! path searching algorithm used by `find_executable_in_path`. Construct //! it by passing in the PATH and PATHEXT (for Windows) environment variables //! and iterate it to incrementally produce all candidate results. This //! is useful when implementing utilities such as `which` that want to show //! all possible paths. //! //! ``` //! use pathsearch::PathSearcher; //! use std::ffi::OsString; //! //! let path = std::env::var_os("PATH"); //! let path_ext = std::env::var_os("PATHEXT"); //! //! for exe in PathSearcher::new( //! "zsh", //! path.as_ref().map(OsString::as_os_str), //! path_ext.as_ref().map(OsString::as_os_str), //! ) { //! println!("{}", exe.display()); //! } //! ``` //! //! `SimplePathSearcher` is a simple iterator that can be used to search //! an arbitrary path for an arbitrary file that doesn't have to be executable. use std::ffi::{OsStr, OsString}; use std::path::PathBuf; #[cfg(unix)] pub mod unix; #[cfg(windows)] pub mod windows; /// SimplePathSearcher is an iterator that yields candidate PathBuf inthstances /// generated from searching the supplied path string following the /// standard rules: explode path by the system path separator character /// and then for each entry, concatenate the candidate command and test /// whether that is a file. pub struct SimplePathSearcher<'a> { path_iter: std::env::SplitPaths<'a>, command: &'a OsStr, } impl<'a> SimplePathSearcher<'a> { /// Create a new SimplePathSearcher that will yield candidate paths for /// the specified command pub fn new + ?Sized>(command: &'a T, path: Option<&'a OsStr>) -> Self { let path = path.unwrap_or_else(|| OsStr::new("")); let path_iter = std::env::split_paths(path); let command = command.as_ref(); Self { path_iter, command } } } impl<'a> Iterator for SimplePathSearcher<'a> { type Item = PathBuf; /// Returns the next candidate path fn next(&mut self) -> Option { loop { let entry = self.path_iter.next()?; let candidate = entry.join(self.command); if candidate.is_file() { return Some(candidate); } } } } #[cfg(unix)] pub type PathSearcher<'a> = unix::ExecutablePathSearcher<'a>; #[cfg(windows)] pub type PathSearcher<'a> = windows::WindowsPathSearcher<'a>; /// Resolves the first matching candidate command from the current /// process environment using the platform appropriate rules. /// On Unix systems this will search the PATH environment variable /// for an executable file. /// On Windows systems this will search each entry in PATH and /// return the first file that has an extension listed in the PATHEXT /// environment variable. pub fn find_executable_in_path + ?Sized>(command: &O) -> Option { let path = std::env::var_os("PATH"); let path_ext = std::env::var_os("PATHEXT"); PathSearcher::new( command, path.as_ref().map(OsString::as_os_str), path_ext.as_ref().map(OsString::as_os_str), ) .next() } pathsearch-0.2.0/src/unix.rs010064400017500001750000000045051357532721600142130ustar0000000000000000use crate::SimplePathSearcher; use std::ffi::{OsStr, OsString}; use std::os::unix::ffi::{OsStrExt, OsStringExt}; use std::path::{Path, PathBuf}; /// Returns true if the specified path has executable access permissions /// for the current process. The check is made using the access(2) /// syscall. pub fn is_executable(path: &Path) -> anyhow::Result { 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) } /// Returns an OsString composed from `a` with `b` appended 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) } /// ExecutablePathSearcher is an iterator that yields candidate PathBuf instances /// generated from searching the supplied path string following the /// standard rules: explode path by the system path separator character /// and then for each entry, concatenate the candidate command and test /// whether that is an executable file. pub struct ExecutablePathSearcher<'a>(SimplePathSearcher<'a>); impl<'a> ExecutablePathSearcher<'a> { /// Create a new ExecutablePathSearcher that will yield candidate paths for /// the specified command. /// `path` should be the path string to be split and searched. This is typically /// the value of the `PATH` environment variable. /// The `_path_ext` parameter is present for easier cross platform support /// when running on Windows. It is ignored on unix systems, but on /// windows systems this is typically the value of the `PATHEXT` environment variable. pub fn new + ?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; /// Returns the next candidate executable file fn next(&mut self) -> Option { while let Some(candidate) = self.0.next() { if let Ok(true) = is_executable(&candidate) { return Some(candidate); } } None } } pathsearch-0.2.0/src/windows.rs010064400017500001750000000052211357532445600147210ustar0000000000000000use std::ffi::{OsStr, OsString}; use std::os::windows::ffi::{OsStrExt, OsStringExt}; use std::path::PathBuf; /// Returns an OsString composed from `a` with `b` appended pub fn concat_osstr(a: &OsStr, b: &OsStr) -> OsString { let mut res: Vec = a.encode_wide().collect(); for c in b.encode_wide() { res.push(c); } OsStringExt::from_wide(&res) } /// WindowsPathSearcher is an iterator that yields candidate PathBuf instances /// generated from searching the PATH environment variable following the /// standard windows rules: explode PATH by the system path separator character /// and then for each entry, concatenate the candidate command and test /// whether that is a file. Additional candidates are produced by taking /// each of the filename extensions specified by the PATHEXT environment /// variable and concatenating those with the command. pub struct WindowsPathSearcher<'a> { path_ext: &'a OsStr, path_iter: std::env::SplitPaths<'a>, path_ext_iter: Option>, command: &'a OsStr, candidate: Option, } impl<'a> WindowsPathSearcher<'a> { pub fn new + ?Sized>( command: &'a T, path: Option<&'a OsStr>, path_ext: Option<&'a OsStr>, ) -> Self { let path = path.unwrap_or_else(|| OsStr::new("")); let path_ext = path_ext.unwrap_or_else(|| OsStr::new(".EXE")); let path_iter = std::env::split_paths(path); let path_ext_iter = None; let command = command.as_ref(); let candidate = None; Self { path_iter, path_ext, path_ext_iter, command, candidate, } } } impl<'a> Iterator for WindowsPathSearcher<'a> { type Item = PathBuf; /// Returns the next candidate executable file fn next(&mut self) -> Option { loop { if let Some(iter) = self.path_ext_iter.as_mut() { while let Some(ext) = iter.next() { let extended = PathBuf::from(concat_osstr( self.candidate.as_ref().unwrap().as_os_str(), ext.as_os_str(), )); if extended.is_file() { return Some(extended); } } } let entry = self.path_iter.next()?; let candidate = entry.join(self.command); self.candidate = Some(candidate.clone()); self.path_ext_iter = Some(std::env::split_paths(self.path_ext)); if candidate.is_file() { return Some(candidate); } } } } pathsearch-0.2.0/.cargo_vcs_info.json0000644000000001121364444275500132630ustar00{ "git": { "sha1": "b91fa4e4b3aaefa9bcc9cbf9e90e820e82f48449" } }