Skip to main content

monocoque_core/
lib.rs

1use std::process::Command;
2
3#[derive(Debug, serde::Serialize)]
4pub struct BtrfsSpace {
5    pub total_bytes: u128,
6    pub used_bytes: u128,
7    pub free_bytes: u128,
8}
9
10pub fn get_space(path: &str) -> Result<BtrfsSpace, String> {
11    let output = Command::new("btrfs")
12        .args(["filesystem", "usage", "--raw", path])
13        .output()
14        .map_err(|e| e.to_string())?;
15
16    if !output.status.success() {
17        return Err(String::from_utf8_lossy(&output.stderr).to_string());
18    }
19
20    let stdout = String::from_utf8_lossy(&output.stdout);
21
22    derive_space(&stdout).ok_or("Failed to parse space info".into())
23}
24
25fn derive_space(output: &str) -> Option<BtrfsSpace> {
26    let mut used_bytes: Option<u128> = None;
27    let mut free_bytes: Option<u128> = None;
28
29    for line in output.lines() {
30        let line = line.trim();
31
32        if line.starts_with("Used:") {
33            if let Some(value) = line.split(':').nth(1) {
34                let number = value.trim().split_whitespace().next()?;
35                used_bytes = number.parse().ok();
36            }
37        }
38
39        if line.starts_with("Free (estimated):") {
40            if let Some(value) = line.split(':').nth(1) {
41                let number = value.trim().split_whitespace().next()?;
42                free_bytes = number.parse().ok();
43            }
44        }
45    }
46
47    Some(BtrfsSpace {
48        total_bytes: used_bytes? + free_bytes?,
49        used_bytes: used_bytes?,
50        free_bytes: free_bytes?,
51    })
52}