sal-virt 0.1.0

SAL Virt - Virtualization and containerization tools including Buildah, Nerdctl, and RFS
Documentation
use super::{cmd::execute_rfs_command, error::RfsError, types::Mount};

/// List all mounted filesystems
///
/// # Returns
///
/// * `Result<Vec<Mount>, RfsError>` - List of mounts or error
pub fn list_mounts() -> Result<Vec<Mount>, RfsError> {
    // Execute the list command
    let result = execute_rfs_command(&["list", "--json"])?;

    // Parse the JSON output
    match serde_json::from_str::<serde_json::Value>(&result.stdout) {
        Ok(json) => {
            if let serde_json::Value::Array(mounts_json) = json {
                let mut mounts = Vec::new();

                for mount_json in mounts_json {
                    // Extract mount ID
                    let id = match mount_json.get("id").and_then(|v| v.as_str()) {
                        Some(id) => id.to_string(),
                        None => return Err(RfsError::ListFailed("Missing mount ID".to_string())),
                    };

                    // Extract source
                    let source = match mount_json.get("source").and_then(|v| v.as_str()) {
                        Some(source) => source.to_string(),
                        None => return Err(RfsError::ListFailed("Missing source".to_string())),
                    };

                    // Extract target
                    let target = match mount_json.get("target").and_then(|v| v.as_str()) {
                        Some(target) => target.to_string(),
                        None => return Err(RfsError::ListFailed("Missing target".to_string())),
                    };

                    // Extract filesystem type
                    let fs_type = match mount_json.get("type").and_then(|v| v.as_str()) {
                        Some(fs_type) => fs_type.to_string(),
                        None => {
                            return Err(RfsError::ListFailed("Missing filesystem type".to_string()))
                        }
                    };

                    // Extract options
                    let options = match mount_json.get("options").and_then(|v| v.as_array()) {
                        Some(options_array) => {
                            let mut options_vec = Vec::new();
                            for option_value in options_array {
                                if let Some(option_str) = option_value.as_str() {
                                    options_vec.push(option_str.to_string());
                                }
                            }
                            options_vec
                        }
                        None => Vec::new(), // Empty vector if no options found
                    };

                    // Create Mount struct and add to vector
                    mounts.push(Mount {
                        id,
                        source,
                        target,
                        fs_type,
                        options,
                    });
                }

                Ok(mounts)
            } else {
                Err(RfsError::ListFailed("Expected JSON array".to_string()))
            }
        }
        Err(e) => Err(RfsError::ListFailed(format!(
            "Failed to parse mount list JSON: {}",
            e
        ))),
    }
}

/// Unmount a filesystem by target path
///
/// # Arguments
///
/// * `target` - Target mount point
///
/// # Returns
///
/// * `Result<(), RfsError>` - Success or error
pub fn unmount(target: &str) -> Result<(), RfsError> {
    // Execute the unmount command
    let result = execute_rfs_command(&["unmount", target])?;

    // Check for errors
    if !result.success {
        return Err(RfsError::UnmountFailed(format!(
            "Failed to unmount {}: {}",
            target, result.stderr
        )));
    }

    Ok(())
}

/// Unmount all filesystems
///
/// # Returns
///
/// * `Result<(), RfsError>` - Success or error
pub fn unmount_all() -> Result<(), RfsError> {
    // Execute the unmount all command
    let result = execute_rfs_command(&["unmount", "--all"])?;

    // Check for errors
    if !result.success {
        return Err(RfsError::UnmountFailed(format!(
            "Failed to unmount all filesystems: {}",
            result.stderr
        )));
    }

    Ok(())
}

/// Get information about a mounted filesystem
///
/// # Arguments
///
/// * `target` - Target mount point
///
/// # Returns
///
/// * `Result<Mount, RfsError>` - Mount information or error
pub fn get_mount_info(target: &str) -> Result<Mount, RfsError> {
    // Get all mounts
    let mounts = list_mounts()?;

    // Find the mount with the specified target
    for mount in mounts {
        if mount.target == target {
            return Ok(mount);
        }
    }

    // Mount not found
    Err(RfsError::Other(format!("No mount found at {}", target)))
}