monocoque-core 0.1.0

Core Btrfs logic for monocoque
Documentation
use std::process::Command;

#[derive(Debug, serde::Serialize)]
pub struct BtrfsSpace {
    pub total_bytes: u128,
    pub used_bytes: u128,
    pub free_bytes: u128,
}

pub fn get_space(path: &str) -> Result<BtrfsSpace, String> {
    let output = Command::new("btrfs")
        .args(["filesystem", "usage", "--raw", path])
        .output()
        .map_err(|e| e.to_string())?;

    if !output.status.success() {
        return Err(String::from_utf8_lossy(&output.stderr).to_string());
    }

    let stdout = String::from_utf8_lossy(&output.stdout);

    derive_space(&stdout).ok_or("Failed to parse space info".into())
}

fn derive_space(output: &str) -> Option<BtrfsSpace> {
    let mut used_bytes: Option<u128> = None;
    let mut free_bytes: Option<u128> = None;

    for line in output.lines() {
        let line = line.trim();

        if line.starts_with("Used:") {
            if let Some(value) = line.split(':').nth(1) {
                let number = value.trim().split_whitespace().next()?;
                used_bytes = number.parse().ok();
            }
        }

        if line.starts_with("Free (estimated):") {
            if let Some(value) = line.split(':').nth(1) {
                let number = value.trim().split_whitespace().next()?;
                free_bytes = number.parse().ok();
            }
        }
    }

    Some(BtrfsSpace {
        total_bytes: used_bytes? + free_bytes?,
        used_bytes: used_bytes?,
        free_bytes: free_bytes?,
    })
}