• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::finder::Checker;
2 #[cfg(unix)]
3 use std::ffi::CString;
4 use std::fs;
5 #[cfg(unix)]
6 use std::os::unix::ffi::OsStrExt;
7 use std::path::Path;
8 
9 pub struct ExecutableChecker;
10 
11 impl ExecutableChecker {
new() -> ExecutableChecker12     pub fn new() -> ExecutableChecker {
13         ExecutableChecker
14     }
15 }
16 
17 impl Checker for ExecutableChecker {
18     #[cfg(unix)]
is_valid(&self, path: &Path) -> bool19     fn is_valid(&self, path: &Path) -> bool {
20         CString::new(path.as_os_str().as_bytes())
21             .map(|c| unsafe { libc::access(c.as_ptr(), libc::X_OK) == 0 })
22             .unwrap_or(false)
23     }
24 
25     #[cfg(windows)]
is_valid(&self, _path: &Path) -> bool26     fn is_valid(&self, _path: &Path) -> bool {
27         true
28     }
29 }
30 
31 pub struct ExistedChecker;
32 
33 impl ExistedChecker {
new() -> ExistedChecker34     pub fn new() -> ExistedChecker {
35         ExistedChecker
36     }
37 }
38 
39 impl Checker for ExistedChecker {
40     #[cfg(target_os = "windows")]
is_valid(&self, path: &Path) -> bool41     fn is_valid(&self, path: &Path) -> bool {
42         fs::symlink_metadata(path)
43             .map(|metadata| {
44                 let file_type = metadata.file_type();
45                 file_type.is_file() || file_type.is_symlink()
46             })
47             .unwrap_or(false)
48     }
49 
50     #[cfg(not(target_os = "windows"))]
is_valid(&self, path: &Path) -> bool51     fn is_valid(&self, path: &Path) -> bool {
52         fs::metadata(path)
53             .map(|metadata| metadata.is_file())
54             .unwrap_or(false)
55     }
56 }
57 
58 pub struct CompositeChecker {
59     checkers: Vec<Box<dyn Checker>>,
60 }
61 
62 impl CompositeChecker {
new() -> CompositeChecker63     pub fn new() -> CompositeChecker {
64         CompositeChecker {
65             checkers: Vec::new(),
66         }
67     }
68 
add_checker(mut self, checker: Box<dyn Checker>) -> CompositeChecker69     pub fn add_checker(mut self, checker: Box<dyn Checker>) -> CompositeChecker {
70         self.checkers.push(checker);
71         self
72     }
73 }
74 
75 impl Checker for CompositeChecker {
is_valid(&self, path: &Path) -> bool76     fn is_valid(&self, path: &Path) -> bool {
77         self.checkers.iter().all(|checker| checker.is_valid(path))
78     }
79 }
80