pub fn resolve_executable(
requested: &Path,
current_dir: &Path,
search_directories: &[PathBuf],
) -> Result<PathBuf, ResolutionError>Expand description
Resolve one executable candidate without reading ambient PATH or running it.
Requests containing / are literal paths, including ./tool; absolute paths
are used directly and relative paths are rooted at current_dir. Other names
search only search_directories, in order. Relative search directories and
explicitly supplied empty entries are rooted at current_dir; an empty list
searches nothing. The working directory must be absolute, even if unused.
No HOME/default installation directory, shell expansion or fallback is added.
Selection requires a regular file with at least one Unix execute permission bit. Search skips missing candidates (including dangling symlinks), directories and nonexecutable files, and stops on other filesystem errors. Once an eligible candidate is observed, canonicalization errors stop selection, including if that candidate disappears. All search directories are checked for NUL before a name search; literal requests ignore the unused search list. Symlinks are followed and the result is canonical and absolute. Permission bits do not prove effective user access or interpreter validity. Caller-owned trusted path trees and exclusion of concurrent writers remain necessary; this path is not a frozen file capability.
A selected path must still undergo super::AdmittedTool::admit with the
consumer’s digest, byte bound and exact version authority before execution.
No candidate is retried or replaced after that admission fails.
§Errors
Returns typed invalid-input, missing/nonexecutable or filesystem failures.
Examples found in repository?
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 use ic_host_tools::tool::resolve_executable;
10 use std::{io, path::PathBuf};
11
12 let mut args = std::env::args_os().skip(1);
13 let mut required = || {
14 args.next().map(PathBuf::from).ok_or_else(|| {
15 io::Error::new(
16 io::ErrorKind::InvalidInput,
17 "usage: resolve_tool REQUEST ABSOLUTE_WORKDIR [SEARCH_DIRECTORY ...]",
18 )
19 })
20 };
21 let requested = required()?;
22 let current_dir = required()?;
23 let directories = args.map(PathBuf::from).collect::<Vec<_>>();
24 let selected = resolve_executable(&requested, ¤t_dir, &directories)?;
25 // Debug quoting preserves non-UTF-8 paths and prevents control characters
26 // from becoming additional terminal lines. This example intentionally prints
27 // the selected path, not a trust or executable identity claim.
28 println!("candidate={:?}", selected.as_os_str());
29 Ok(())
30}