Refactor compression into multiple files

This commit is contained in:
Andrew Phillips
2023-09-01 21:01:06 +00:00
parent 6222748901
commit cf352af7d5
5 changed files with 210 additions and 180 deletions

104
src/compression/program.rs Normal file
View File

@@ -0,0 +1,104 @@
use anyhow::{Context, Result, anyhow};
use std::fs::File;
use std::io::Write;
use std::process::{Command,Stdio};
use std::path::PathBuf;
use std::env;
use std::fs;
use std::os::unix::fs::PermissionsExt;
use log::*;
use crate::compression::CompressionEngine;
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct CompressionProgram {
pub program: String,
pub compress: Vec<String>,
pub decompress: Vec<String>,
pub supported: bool
}
impl CompressionProgram {
pub fn new(program: &str, compress: Vec<&str>, decompress: Vec<&str>) -> CompressionProgram {
let program_path = get_program_path(program);
let supported = program_path.is_ok();
CompressionProgram {
program: program_path.unwrap_or(program.to_string()),
compress: compress.iter().map(|s| {s.to_string()}).collect(),
decompress: decompress.iter().map(|s| {s.to_string()}).collect(),
supported
}
}
}
impl CompressionEngine for CompressionProgram {
fn is_supported(&self) -> bool {
self.supported
}
fn cat(&self, file_path: PathBuf) -> Result<()> {
debug!("COMPRESSION: Outputting {:?} to STDOUT using {:?}", file_path, *self);
let program = self.program.clone();
let args = self.decompress.clone();
debug!("COMPRESSION: Executing command: {:?} {:?} writing to {:?}", program, args, file_path);
let file = File::open(file_path).context("Unable to open file for reading")?;
let mut process = Command::new(program.clone())
.args(args.clone())
.stdin(file)
.spawn()
.context(anyhow!("Unable to spawn child process: {:?} {:?}", program, args))?;
let result = process.wait()
.context(anyhow!("Unable to wait for child process: {:?} {:?}", program, args))?;
if result.success() {
Ok(())
} else {
Err(anyhow!("Decompression program returned {}", result))
}
}
fn create(&self, file_path: PathBuf) -> Result<Box<dyn Write>> {
debug!("COMPRESSION: Writting to {:?} using {:?}", file_path, *self);
let program = self.program.clone();
let args = self.compress.clone();
debug!("COMPRESSION: Executing command: {:?} {:?} writing to {:?}", program, args, file_path);
let file = File::create(file_path).context("Unable to open file for writing")?;
let process = Command::new(program.clone())
.args(args.clone())
.stdin(Stdio::piped())
.stdout(file)
.spawn()
.context(anyhow!("Problem spawning child process: {:?} {:?}", program, args))?;
Ok(Box::new(process.stdin.unwrap()))
}
}
fn get_program_path(program: &str) -> Result<String> {
debug!("COMPRESSION: Looking for executable: {}", program);
if let Ok(path) = env::var("PATH") {
for p in path.split(':') {
let p_str = format!("{}/{}", p, program);
let stat = fs::metadata(p_str.clone());
if let Ok(stat) = stat {
let md = stat;
let permissions = md.permissions();
if md.is_file() && permissions.mode() & 0o111 != 0 {
return Ok(p_str);
}
}
}
}
Err(anyhow!("Unable to find binary {} in PATH", program))
}