Can perform basic file copy
This commit is contained in:
		@@ -123,3 +123,6 @@ pub const QEMU_IMAGE_PROGRAM: &str = "/usr/bin/qemu-img";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// IP program path
 | 
					/// IP program path
 | 
				
			||||||
pub const IP_PROGRAM: &str = "/usr/sbin/ip";
 | 
					pub const IP_PROGRAM: &str = "/usr/sbin/ip";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Copy program path
 | 
				
			||||||
 | 
					pub const COPY_PROGRAM: &str = "/bin/cp";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,8 @@
 | 
				
			|||||||
 | 
					use crate::app_config::AppConfig;
 | 
				
			||||||
use crate::constants;
 | 
					use crate::constants;
 | 
				
			||||||
use crate::utils::file_size_utils::FileSize;
 | 
					use crate::utils::file_size_utils::FileSize;
 | 
				
			||||||
use std::os::linux::fs::MetadataExt;
 | 
					use std::os::linux::fs::MetadataExt;
 | 
				
			||||||
use std::path::Path;
 | 
					use std::path::{Path, PathBuf};
 | 
				
			||||||
use std::process::Command;
 | 
					use std::process::Command;
 | 
				
			||||||
use std::time::UNIX_EPOCH;
 | 
					use std::time::UNIX_EPOCH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11,9 +12,11 @@ enum DisksError {
 | 
				
			|||||||
    Parse(&'static str),
 | 
					    Parse(&'static str),
 | 
				
			||||||
    #[error("DiskCreateError")]
 | 
					    #[error("DiskCreateError")]
 | 
				
			||||||
    Create,
 | 
					    Create,
 | 
				
			||||||
 | 
					    #[error("DiskConvertError: {0}")]
 | 
				
			||||||
 | 
					    Convert(String),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, serde::Serialize, serde::Deserialize, Copy, Clone)]
 | 
					#[derive(Debug, serde::Serialize, serde::Deserialize, Copy, Clone, PartialEq, Eq)]
 | 
				
			||||||
#[serde(tag = "format")]
 | 
					#[serde(tag = "format")]
 | 
				
			||||||
pub enum DiskFileFormat {
 | 
					pub enum DiskFileFormat {
 | 
				
			||||||
    Raw {
 | 
					    Raw {
 | 
				
			||||||
@@ -42,6 +45,7 @@ impl DiskFileFormat {
 | 
				
			|||||||
/// Disk file information
 | 
					/// Disk file information
 | 
				
			||||||
#[derive(serde::Serialize)]
 | 
					#[derive(serde::Serialize)]
 | 
				
			||||||
pub struct DiskFileInfo {
 | 
					pub struct DiskFileInfo {
 | 
				
			||||||
 | 
					    pub file_path: PathBuf,
 | 
				
			||||||
    pub file_size: FileSize,
 | 
					    pub file_size: FileSize,
 | 
				
			||||||
    #[serde(flatten)]
 | 
					    #[serde(flatten)]
 | 
				
			||||||
    pub format: DiskFileFormat,
 | 
					    pub format: DiskFileFormat,
 | 
				
			||||||
@@ -83,6 +87,7 @@ impl DiskFileInfo {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(Self {
 | 
					        Ok(Self {
 | 
				
			||||||
 | 
					            file_path: file.to_path_buf(),
 | 
				
			||||||
            name,
 | 
					            name,
 | 
				
			||||||
            file_size: FileSize::from_bytes(metadata.len() as usize),
 | 
					            file_size: FileSize::from_bytes(metadata.len() as usize),
 | 
				
			||||||
            format,
 | 
					            format,
 | 
				
			||||||
@@ -145,7 +150,62 @@ impl DiskFileInfo {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /// Copy / convert file disk image into a new destination with optionally a new file format
 | 
					    /// Copy / convert file disk image into a new destination with optionally a new file format
 | 
				
			||||||
    pub fn convert(&self, dest_file: &Path, dest_format: DiskFileFormat) -> anyhow::Result<()> {
 | 
					    pub fn convert(&self, dest_file: &Path, dest_format: DiskFileFormat) -> anyhow::Result<()> {
 | 
				
			||||||
        todo!()
 | 
					        // Create a temporary directory to perform the operation
 | 
				
			||||||
 | 
					        let temp_dir = tempfile::tempdir_in(&AppConfig::get().temp_dir)?;
 | 
				
			||||||
 | 
					        let temp_file = temp_dir.path().join("temp_file");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Prepare the conversion
 | 
				
			||||||
 | 
					        let mut cmd = match (self.format, dest_format) {
 | 
				
			||||||
 | 
					            // Dumb copy of file
 | 
				
			||||||
 | 
					            (a, b) if a == b => {
 | 
				
			||||||
 | 
					                let mut cmd = Command::new(constants::COPY_PROGRAM);
 | 
				
			||||||
 | 
					                cmd.arg("--sparse=auto")
 | 
				
			||||||
 | 
					                    .arg(&self.file_path)
 | 
				
			||||||
 | 
					                    .arg(&temp_file);
 | 
				
			||||||
 | 
					                cmd
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // By default, conversion is unsupported
 | 
				
			||||||
 | 
					            (src, dest) => {
 | 
				
			||||||
 | 
					                return Err(DisksError::Convert(format!(
 | 
				
			||||||
 | 
					                    "Conversion from {src:?} to {dest:?} is not supported!"
 | 
				
			||||||
 | 
					                ))
 | 
				
			||||||
 | 
					                .into());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Execute the conversion
 | 
				
			||||||
 | 
					        let command_s = format!(
 | 
				
			||||||
 | 
					            "{} {}",
 | 
				
			||||||
 | 
					            cmd.get_program().display(),
 | 
				
			||||||
 | 
					            cmd.get_args()
 | 
				
			||||||
 | 
					                .map(|a| format!("'{}'", a.display()))
 | 
				
			||||||
 | 
					                .collect::<Vec<String>>()
 | 
				
			||||||
 | 
					                .join(" ")
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        let cmd_output = cmd.output()?;
 | 
				
			||||||
 | 
					        if !cmd_output.status.success() {
 | 
				
			||||||
 | 
					            return Err(DisksError::Convert(format!(
 | 
				
			||||||
 | 
					                "Command failed:\n{command_s}\nStatus: {}\nstdout: {}\nstderr: {}",
 | 
				
			||||||
 | 
					                cmd_output.status,
 | 
				
			||||||
 | 
					                String::from_utf8_lossy(&cmd_output.stdout),
 | 
				
			||||||
 | 
					                String::from_utf8_lossy(&cmd_output.stderr)
 | 
				
			||||||
 | 
					            ))
 | 
				
			||||||
 | 
					            .into());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Check the file was created
 | 
				
			||||||
 | 
					        if !temp_file.is_file() {
 | 
				
			||||||
 | 
					            return Err(DisksError::Convert(
 | 
				
			||||||
 | 
					                "Temporary was not created after execution of command!".to_string(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .into());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Move the file to its final location
 | 
				
			||||||
 | 
					        std::fs::rename(temp_file, dest_file)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user