zinit 0.3.8

Process supervisor with dependency management
Documentation
//! Filesystem creation (mkfs.vfat, mkfs.btrfs)

use super::boot::BootMode;
use super::cmd;
use super::error::StorageError;
use super::partition::PartitionInfo;
use std::path::Path;

/// Labels for MOS filesystems
pub const MOSBOOT_LABEL: &str = "MOSBOOT";
pub const MOSDATA_LABEL: &str = "mosdata";

/// Format the partitions with appropriate filesystems
///
/// For EFI mode:
/// - Boot partition: FAT32 with MOSBOOT label
/// - Data partition: btrfs with mosdata label
///
/// For BIOS mode:
/// - Boot partition: no formatting (BIOS boot partition)
/// - Data partition: btrfs with mosdata label
pub fn format_partitions(
    partitions: &PartitionInfo,
    boot_mode: BootMode,
) -> Result<(), StorageError> {
    // Format boot partition (EFI only)
    if boot_mode.is_efi() {
        format_esp(&partitions.boot.path)?;
    } else {
        log::info!("skipping BIOS boot partition format (not needed)");
    }

    // Format data partition
    format_btrfs(&partitions.data.path)?;

    Ok(())
}

/// Format the ESP partition as FAT32
fn format_esp(device: &Path) -> Result<(), StorageError> {
    let dev_path = device.to_string_lossy();
    log::info!("formatting ESP as FAT32: {}", dev_path);

    cmd::run("mkfs.vfat", &["-F", "32", "-n", MOSBOOT_LABEL, &dev_path]).map_err(|e| {
        StorageError::FormatFailed {
            device: device.to_path_buf(),
            error: format!("mkfs.vfat failed: {}", e),
        }
    })?;

    Ok(())
}

/// Format the data partition as btrfs
fn format_btrfs(device: &Path) -> Result<(), StorageError> {
    let dev_path = device.to_string_lossy();
    log::info!("formatting data partition as btrfs: {}", dev_path);

    cmd::run("mkfs.btrfs", &["-L", MOSDATA_LABEL, &dev_path]).map_err(|e| {
        StorageError::FormatFailed {
            device: device.to_path_buf(),
            error: format!("mkfs.btrfs failed: {}", e),
        }
    })?;

    Ok(())
}

/// Find a device by its filesystem label using blkid
pub fn find_by_label(label: &str) -> Option<std::path::PathBuf> {
    let output = cmd::run_allow_fail("blkid", &["-L", label])?;

    if output.status.success() {
        let path = String::from_utf8_lossy(&output.stdout).trim().to_string();
        if !path.is_empty() {
            return Some(std::path::PathBuf::from(path));
        }
    }

    None
}

/// Check if MOS data storage exists (by label)
pub fn mosdata_exists() -> bool {
    find_by_label(MOSDATA_LABEL).is_some()
}

/// Check if MOS boot storage exists (by label)
pub fn mosboot_exists() -> bool {
    find_by_label(MOSBOOT_LABEL).is_some()
}