1 use crate::finder::Checker; 2 #[cfg(unix)] 3 use libc; 4 #[cfg(unix)] 5 use std::ffi::CString; 6 use std::fs; 7 #[cfg(unix)] 8 use std::os::unix::ffi::OsStrExt; 9 use std::path::Path; 10 11 pub struct ExecutableChecker; 12 13 impl ExecutableChecker { new() -> ExecutableChecker14 pub fn new() -> ExecutableChecker { 15 ExecutableChecker 16 } 17 } 18 19 impl Checker for ExecutableChecker { 20 #[cfg(unix)] is_valid(&self, path: &Path) -> bool21 fn is_valid(&self, path: &Path) -> bool { 22 CString::new(path.as_os_str().as_bytes()) 23 .and_then(|c| Ok(unsafe { libc::access(c.as_ptr(), libc::X_OK) == 0 })) 24 .unwrap_or(false) 25 } 26 27 #[cfg(windows)] is_valid(&self, _path: &Path) -> bool28 fn is_valid(&self, _path: &Path) -> bool { 29 true 30 } 31 } 32 33 pub struct ExistedChecker; 34 35 impl ExistedChecker { new() -> ExistedChecker36 pub fn new() -> ExistedChecker { 37 ExistedChecker 38 } 39 } 40 41 impl Checker for ExistedChecker { 42 #[cfg(target_os = "windows")] is_valid(&self, path: &Path) -> bool43 fn is_valid(&self, path: &Path) -> bool { 44 fs::symlink_metadata(path) 45 .map(|metadata| { 46 let file_type = metadata.file_type(); 47 file_type.is_file() || file_type.is_symlink() 48 }) 49 .unwrap_or(false) 50 } 51 52 #[cfg(not(target_os = "windows"))] is_valid(&self, path: &Path) -> bool53 fn is_valid(&self, path: &Path) -> bool { 54 fs::metadata(path) 55 .map(|metadata| metadata.is_file()) 56 .unwrap_or(false) 57 } 58 } 59 60 pub struct CompositeChecker { 61 checkers: Vec<Box<dyn Checker>>, 62 } 63 64 impl CompositeChecker { new() -> CompositeChecker65 pub fn new() -> CompositeChecker { 66 CompositeChecker { 67 checkers: Vec::new(), 68 } 69 } 70 add_checker(mut self, checker: Box<dyn Checker>) -> CompositeChecker71 pub fn add_checker(mut self, checker: Box<dyn Checker>) -> CompositeChecker { 72 self.checkers.push(checker); 73 self 74 } 75 } 76 77 impl Checker for CompositeChecker { is_valid(&self, path: &Path) -> bool78 fn is_valid(&self, path: &Path) -> bool { 79 self.checkers.iter().all(|checker| checker.is_valid(path)) 80 } 81 } 82