1use std::path::Path;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
6pub struct ShmRuntimeContext {
7 pub path: String,
8 pub mount_fstype: Option<String>,
9 pub hugetlbfs: bool,
10}
11
12pub(crate) fn shm_runtime_context(path: &Path) -> ShmRuntimeContext {
13 let mount_fstype = find_mount_fstype(path);
14 let hugetlbfs = mount_fstype.as_deref() == Some("hugetlbfs");
15 ShmRuntimeContext {
16 path: path.display().to_string(),
17 mount_fstype,
18 hugetlbfs,
19 }
20}
21
22pub(crate) fn find_mount_fstype(path: &Path) -> Option<String> {
23 let mounts = std::fs::read_to_string("/proc/mounts").ok()?;
24 let canonical = std::fs::canonicalize(path).ok()?;
25
26 let mut best: Option<(usize, String)> = None;
27 for line in mounts.lines() {
28 let parts: Vec<&str> = line.split_whitespace().collect();
29 if parts.len() < 3 {
30 continue;
31 }
32 let mount_point = parts[1];
33 let fstype = parts[2];
34
35 let mp = Path::new(mount_point);
36 if canonical.starts_with(mp) {
37 let len = mount_point.len();
38 let is_better = best.as_ref().map(|(l, _)| len > *l).unwrap_or(true);
39 if is_better {
40 best = Some((len, fstype.to_string()));
41 }
42 }
43 }
44
45 best.map(|(_, t)| t)
46}
47
48pub(crate) fn probe_shm_dir_writable(dir: &Path) -> Result<(), String> {
49 #[cfg(target_os = "linux")]
50 {
51 indexbus_platform_ops::linux::fs::probe_dir_writable(dir).map_err(|e| e.to_string())
52 }
53
54 #[cfg(not(target_os = "linux"))]
55 {
56 use std::io::Write;
57
58 let path = dir.join(format!(".byteor_shm_probe_{}", std::process::id()));
59 let res = (|| -> Result<(), String> {
60 let mut f = std::fs::OpenOptions::new()
61 .create(true)
62 .write(true)
63 .truncate(true)
64 .open(&path)
65 .map_err(|e| format!("dir not writable (open {}): {e}", path.display()))?;
66 f.write_all(b"probe")
67 .map_err(|e| format!("dir not writable (write {}): {e}", path.display()))?;
68 Ok(())
69 })();
70
71 let _ = std::fs::remove_file(&path);
72 res
73 }
74}