use std::path::PathBuf;
use serde::Serialize;
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct MountEntry {
pub mount_id: u32,
pub device: u64,
pub mountpoint: PathBuf,
pub fs_type: String,
pub options: MountOptions,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct MountOptions {
pub read_only: bool,
pub noexec: bool,
pub nosuid: bool,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct MountTable(pub Vec<MountEntry>);
impl MountTable {
#[must_use]
pub fn find_by_device(&self, dev: u64) -> Option<&MountEntry> {
self.0
.iter()
.filter(|entry| entry.device == dev)
.max_by_key(|entry| entry.mountpoint.as_os_str().len())
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_entry(mount_id: u32, device: u64, mountpoint: &str) -> MountEntry {
MountEntry {
mount_id,
device,
mountpoint: PathBuf::from(mountpoint),
fs_type: String::from("ext4"),
options: MountOptions {
read_only: false,
noexec: false,
nosuid: false,
},
}
}
#[test]
fn find_by_device_single_match() {
let table = MountTable(vec![make_entry(1, 100, "/"), make_entry(2, 200, "/var")]);
let found = table.find_by_device(200);
assert_eq!(found.map(|e| e.mount_id), Some(2));
}
#[test]
fn find_by_device_longest_mountpoint_wins() {
let table = MountTable(vec![
make_entry(1, 100, "/"),
make_entry(2, 100, "/var"),
make_entry(3, 100, "/var/log"),
]);
let found = table.find_by_device(100);
assert_eq!(found.map(|e| e.mount_id), Some(3));
}
#[test]
fn find_by_device_no_match_returns_none() {
let table = MountTable(vec![make_entry(1, 100, "/")]);
assert!(table.find_by_device(999).is_none());
}
#[test]
fn find_by_device_empty_table_returns_none() {
let table = MountTable(vec![]);
assert!(table.find_by_device(100).is_none());
}
}