sal-virt 0.1.0

SAL Virt - Virtualization and containerization tools including Buildah, Nerdctl, and RFS
Documentation
use crate::buildah::{execute_buildah_command, BuildahError};
use sal_process::CommandResult;
use std::fs::File;
use std::io::{Read, Write};
use tempfile::NamedTempFile;

/// Functions for working with file content in buildah containers
pub struct ContentOperations;

impl ContentOperations {
    /// Write content to a file in the container
    ///
    /// # Arguments
    ///
    /// * `container_id` - The container ID
    /// * `content` - The content to write
    /// * `dest_path` - Destination path in the container
    ///
    /// # Returns
    ///
    /// * `Result<CommandResult, BuildahError>` - Command result or error
    pub fn write_content(
        container_id: &str,
        content: &str,
        dest_path: &str,
    ) -> Result<CommandResult, BuildahError> {
        // Create a temporary file
        let mut temp_file = NamedTempFile::new()
            .map_err(|e| BuildahError::Other(format!("Failed to create temporary file: {}", e)))?;

        // Write content to the temporary file
        temp_file.write_all(content.as_bytes()).map_err(|e| {
            BuildahError::Other(format!("Failed to write to temporary file: {}", e))
        })?;

        // Flush the file to ensure content is written
        temp_file
            .flush()
            .map_err(|e| BuildahError::Other(format!("Failed to flush temporary file: {}", e)))?;

        // Copy the temporary file to the container
        let temp_path = temp_file.path().to_string_lossy().to_string();
        // Use add instead of copy for better handling of paths
        execute_buildah_command(&["add", container_id, &temp_path, dest_path])
    }

    /// Read content from a file in the container
    ///
    /// # Arguments
    ///
    /// * `container_id` - The container ID
    /// * `source_path` - Source path in the container
    ///
    /// # Returns
    ///
    /// * `Result<String, BuildahError>` - File content or error
    pub fn read_content(container_id: &str, source_path: &str) -> Result<String, BuildahError> {
        // Create a temporary file
        let temp_file = NamedTempFile::new()
            .map_err(|e| BuildahError::Other(format!("Failed to create temporary file: {}", e)))?;

        let temp_path = temp_file.path().to_string_lossy().to_string();

        // Copy the file from the container to the temporary file
        // Use mount to access the container's filesystem
        let mount_result = execute_buildah_command(&["mount", container_id])?;
        let mount_point = mount_result.stdout.trim();

        // Construct the full path to the file in the container
        let full_source_path = format!("{}{}", mount_point, source_path);

        // Copy the file from the mounted container to the temporary file
        execute_buildah_command(&["copy", container_id, &full_source_path, &temp_path])?;

        // Unmount the container
        execute_buildah_command(&["umount", container_id])?;

        // Read the content from the temporary file
        let mut file = File::open(temp_file.path())
            .map_err(|e| BuildahError::Other(format!("Failed to open temporary file: {}", e)))?;

        let mut content = String::new();
        file.read_to_string(&mut content).map_err(|e| {
            BuildahError::Other(format!("Failed to read from temporary file: {}", e))
        })?;

        Ok(content)
    }
}