evobench_tools/utillib/
linux_mounts.rs1use std::{
4 collections::HashMap,
5 fs::Metadata,
6 path::{Path, PathBuf},
7 sync::Arc,
8};
9
10use anyhow::{Result, anyhow};
11use kstring::KString;
12
13use crate::{ctx, utillib::into_arc_path::IntoArcPath};
14
15pub struct MountPoint {
16 pub device_name: KString,
17 pub path: KString,
18 pub fstype: KString,
19 pub options: KString,
20 }
22
23impl MountPoint {
24 pub fn is_tmpfs(&self) -> bool {
25 &self.fstype == "tmpfs"
26 }
27
28 pub fn path(&self) -> Arc<Path> {
29 self.path.as_str().into_arc_path()
30 }
31
32 pub fn path_buf(&self) -> PathBuf {
33 self.path.as_str().into()
34 }
35
36 pub fn path_metadata(&self) -> Result<Metadata> {
37 let path: &Path = self.path.as_str().as_ref();
38 path.metadata()
39 .map_err(ctx!("getting metadata for {path:?}"))
40 }
41}
42
43pub struct MountPoints {
44 mount_points: Vec<MountPoint>,
45 by_path: HashMap<KString, usize>,
46}
47
48impl MountPoints {
49 pub fn read() -> Result<Self> {
50 let input =
51 std::fs::read_to_string("/proc/mounts").map_err(ctx!("reading /proc/mounts"))?;
52 let mount_points: Vec<MountPoint> = input
53 .trim_end()
54 .split("\n")
55 .map(|line| -> Result<MountPoint> {
56 let mut items = line.split(" ");
58 macro_rules! let_get {
59 { $name:tt } => {
60 let $name = KString::from_ref(
61 items.next().ok_or_else(
62 || anyhow!("missing value for {:?}", stringify!($name)))?
63 );
64 }
65 }
66 let_get!(device_name);
67 let_get!(path);
68 let_get!(fstype);
69 let_get!(options);
70 Ok(MountPoint {
71 device_name,
72 path,
73 fstype,
74 options,
75 })
76 })
77 .collect::<Result<_>>()?;
78
79 let by_path = mount_points
80 .iter()
81 .enumerate()
82 .map(|(i, p)| (p.path.clone(), i))
83 .collect();
84
85 Ok(MountPoints {
86 mount_points,
87 by_path,
88 })
89 }
90
91 pub fn get_by_path(&self, path: &str) -> Option<&MountPoint> {
92 self.by_path.get(path).map(|i| &self.mount_points[*i])
93 }
94}