executable_finder/
unix.rs

1use std::{env::VarError, os::unix::fs::PermissionsExt, path::PathBuf};
2
3use crate::Executable;
4
5pub fn search_dir() -> Result<fn(PathBuf) -> Option<Vec<Executable>>, VarError> {
6    Ok(|path: PathBuf| -> Option<Vec<Executable>> {
7        let mut exes = Vec::new();
8        if let Ok(dir) = path.read_dir() {
9            for entry in dir.flatten() {
10                // We need to call metadata on the path to follow symbolic links
11                if let Ok(metadata) = entry.path().metadata() {
12                    if !metadata.is_file() {
13                        continue;
14                    }
15
16                    let path = entry.path();
17                    if let Some(filename) = path.file_name() {
18                        let permissions = metadata.permissions();
19                        if permissions.mode() & 0o111 != 0 {
20                            let exe = Executable {
21                                name: filename.to_string_lossy().to_string(),
22                                path,
23                            };
24
25                            exes.push(exe);
26                        }
27                    }
28                }
29            }
30        }
31
32        if exes.is_empty() {
33            None
34        } else {
35            Some(exes)
36        }
37    })
38}