1use std::path::{Path, PathBuf};
2use std::os::unix::prelude::*;
3use std::collections::HashMap;
4
5pub fn which<'a, 'b>(files: &'a [&'a str],
6 paths: &'a [&'a Path],
7 match_all: bool,
8 mut result: Option<&'b mut HashMap<&'a str, Vec<PathBuf>>>) -> Result<bool, String> {
9 let mut all_matched = true;
10 for f in files {
11 let mut matched = false;
12
13 for p in paths {
14 let mut target = p.to_path_buf();
15 target.push(f);
16
17 if !target.exists() {
19 continue;
20 }
21
22 let metadata =
23 target.metadata().map_err(|e| format!("read metadata failed: {}", e))?;
24 if metadata.mode() & 0o111 == 0 {
25 continue;
27 }
28
29 matched = true;
31 match result {
32 Some(ref mut r) => {
33 r.entry(f).or_insert(Vec::new());
34 if let Some(targets) = r.get_mut(f) {
35 targets.push(target);
36 }
37 }
38 None => {}
39 }
40
41 if !match_all {
42 break;
43 }
44 }
45
46 all_matched &= matched;
47 }
48
49 Ok(all_matched)
50}