Skip to main content

leviso_elf/
paths.rs

1//! Library and binary path searching.
2
3use std::path::{Path, PathBuf};
4
5/// Find a library in standard paths within a rootfs.
6///
7/// Searches lib64, lib, and systemd private library paths.
8/// The `extra_paths` parameter allows callers to add additional search paths
9/// (e.g., `/usr/libexec/sudo` for rootfs builds).
10///
11/// Returns `None` if the library is not found in any search path.
12#[must_use = "found library path should be used"]
13pub fn find_library(source_root: &Path, lib_name: &str, extra_paths: &[&str]) -> Option<PathBuf> {
14    // Standard library paths
15    let mut candidates = vec![
16        source_root.join("usr/lib64").join(lib_name),
17        source_root.join("lib64").join(lib_name),
18        source_root.join("usr/lib").join(lib_name),
19        source_root.join("lib").join(lib_name),
20        // Systemd private libraries
21        source_root.join("usr/lib64/systemd").join(lib_name),
22        source_root.join("usr/lib/systemd").join(lib_name),
23    ];
24
25    // Add extra paths from caller
26    for extra in extra_paths {
27        candidates.push(source_root.join(extra).join(lib_name));
28    }
29
30    candidates
31        .into_iter()
32        .find(|p| p.exists() || p.is_symlink())
33}
34
35/// Find a binary in standard bin/sbin directories.
36///
37/// Returns `None` if the binary is not found in any search path.
38#[must_use = "found binary path should be used"]
39pub fn find_binary(source_root: &Path, binary: &str) -> Option<PathBuf> {
40    let bin_candidates = [
41        source_root.join("usr/bin").join(binary),
42        source_root.join("bin").join(binary),
43        source_root.join("usr/sbin").join(binary),
44        source_root.join("sbin").join(binary),
45    ];
46
47    bin_candidates.into_iter().find(|p| p.exists())
48}
49
50/// Find a binary, prioritizing sbin directories.
51///
52/// Returns `None` if the binary is not found in any search path.
53#[must_use = "found binary path should be used"]
54pub fn find_sbin_binary(source_root: &Path, binary: &str) -> Option<PathBuf> {
55    let sbin_candidates = [
56        source_root.join("usr/sbin").join(binary),
57        source_root.join("sbin").join(binary),
58        source_root.join("usr/bin").join(binary),
59        source_root.join("bin").join(binary),
60    ];
61
62    sbin_candidates.into_iter().find(|p| p.exists())
63}