Can perform basic file copy

This commit is contained in:
Pierre HUBERT 2025-05-29 12:15:52 +02:00
parent e017fe96d5
commit 80d6fe0298
2 changed files with 66 additions and 3 deletions

View File

@ -123,3 +123,6 @@ pub const QEMU_IMAGE_PROGRAM: &str = "/usr/bin/qemu-img";
/// IP program path
pub const IP_PROGRAM: &str = "/usr/sbin/ip";
/// Copy program path
pub const COPY_PROGRAM: &str = "/bin/cp";

View File

@ -1,7 +1,8 @@
use crate::app_config::AppConfig;
use crate::constants;
use crate::utils::file_size_utils::FileSize;
use std::os::linux::fs::MetadataExt;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::time::UNIX_EPOCH;
@ -11,9 +12,11 @@ enum DisksError {
Parse(&'static str),
#[error("DiskCreateError")]
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")]
pub enum DiskFileFormat {
Raw {
@ -42,6 +45,7 @@ impl DiskFileFormat {
/// Disk file information
#[derive(serde::Serialize)]
pub struct DiskFileInfo {
pub file_path: PathBuf,
pub file_size: FileSize,
#[serde(flatten)]
pub format: DiskFileFormat,
@ -83,6 +87,7 @@ impl DiskFileInfo {
};
Ok(Self {
file_path: file.to_path_buf(),
name,
file_size: FileSize::from_bytes(metadata.len() as usize),
format,
@ -145,7 +150,62 @@ impl DiskFileInfo {
/// 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<()> {
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(())
}
}