refactor: update digest engine to use Result and Write, add is_supported method
This commit is contained in:
committed by
Andrew Phillips (aider)
parent
1aba71a3d6
commit
4ee0715e39
@@ -1,15 +1,22 @@
|
|||||||
|
use anyhow::{anyhow, Context, Result};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
|
use log::*;
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
extern crate enum_map;
|
||||||
|
use enum_map::enum_map;
|
||||||
|
use enum_map::{Enum, EnumMap};
|
||||||
|
|
||||||
pub mod none;
|
pub mod none;
|
||||||
pub mod sha2_digest;
|
|
||||||
pub mod program;
|
pub mod program;
|
||||||
|
pub mod sha2;
|
||||||
|
|
||||||
use crate::digest_engine::none::DigestEngineNone;
|
use crate::digest_engine::none::DigestEngineNone;
|
||||||
use crate::digest_engine::sha2_digest::DigestEngineSha256;
|
|
||||||
use crate::digest_engine::program::DigestEngineProgram;
|
use crate::digest_engine::program::DigestEngineProgram;
|
||||||
|
use crate::digest_engine::sha2::DigestEngineSha256;
|
||||||
use enum_map::Enum;
|
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, strum::EnumIter, strum::Display, strum::EnumString, Enum)]
|
#[derive(Debug, Eq, PartialEq, Clone, strum::EnumIter, strum::Display, strum::EnumString, Enum)]
|
||||||
#[strum(ascii_case_insensitive)]
|
#[strum(ascii_case_insensitive)]
|
||||||
@@ -20,17 +27,29 @@ pub enum DigestType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait DigestEngine {
|
pub trait DigestEngine {
|
||||||
fn create(&self) -> Box<dyn DigestEngine>;
|
fn is_supported(&self) -> bool {
|
||||||
|
true
|
||||||
fn update(&mut self, data: &[u8]) -> io::Result<()>;
|
}
|
||||||
|
fn create(&self) -> Result<Box<dyn Write>>;
|
||||||
fn finalize(&mut self) -> io::Result<String>;
|
fn finalize(&mut self) -> io::Result<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref DIGEST_PROGRAMS: EnumMap<DigestType, Option<DigestEngineProgram>> = enum_map! {
|
||||||
|
DigestType::Sha256 => None,
|
||||||
|
DigestType::Md5 => {
|
||||||
|
let program = DigestEngineProgram::new("bzip2", vec![]);
|
||||||
|
if program.supported { Some(program) } else { None }
|
||||||
|
}
|
||||||
|
DigestType::None => None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn get_engine(digest_type: DigestType) -> Box<dyn DigestEngine> {
|
pub fn get_engine(digest_type: DigestType) -> Box<dyn DigestEngine> {
|
||||||
match digest_type {
|
match digest_type {
|
||||||
DigestType::Sha256 => Box::new(DigestEngineSha256::new()),
|
DigestType::Sha256 => Box::new(DigestEngineSha256::new()),
|
||||||
DigestType::Md5 => Box::new(DigestEngineProgram::new("md5sum")),
|
DigestType::Md5 => Box::new(DigestEngineProgram::new("md5sum", vec![])),
|
||||||
DigestType::None => Box::new(DigestEngineNone::new()),
|
DigestType::None => Box::new(DigestEngineNone::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
use std::io;
|
use anyhow::Result;
|
||||||
use crate::digest_engine::DigestEngine;
|
use crate::digest_engine::DigestEngine;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::io;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Default)]
|
#[derive(Debug, Eq, PartialEq, Clone, Default)]
|
||||||
pub struct DigestEngineNone {}
|
pub struct DigestEngineNone {}
|
||||||
@@ -11,14 +13,9 @@ impl DigestEngineNone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl DigestEngine for DigestEngineNone {
|
impl DigestEngine for DigestEngineNone {
|
||||||
fn create(&self) -> Box<dyn DigestEngine> {
|
fn create(&self) -> Result<Box<dyn Write>> {
|
||||||
Box::new(Self::new())
|
Ok(Box::new(Self::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, _data: &[u8]) -> io::Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finalize(&mut self) -> io::Result<String> {
|
fn finalize(&mut self) -> io::Result<String> {
|
||||||
Ok("none".to_string())
|
Ok("none".to_string())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,83 @@
|
|||||||
|
use anyhow::{anyhow, Context, Result};
|
||||||
|
use log::*;
|
||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
use crate::digest_engine::DigestEngine;
|
use crate::digest_engine::DigestEngine;
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||||
pub struct DigestEngineProgram {
|
pub struct DigestEngineProgram {
|
||||||
program: String,
|
pub program: String,
|
||||||
|
pub args: Vec<String>,
|
||||||
|
pub supported: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DigestEngineProgram {
|
impl DigestEngineProgram {
|
||||||
pub fn new(program: &str) -> DigestEngineProgram {
|
pub fn new(program: &str, args: Vec<&str>) -> DigestEngineProgram {
|
||||||
DigestEngineProgram { program: program.to_string() }
|
let program_path = get_program_path(program);
|
||||||
|
let supported = program_path.is_ok();
|
||||||
|
DigestEngineProgram {
|
||||||
|
program: program_path.unwrap_or(program.to_string()),
|
||||||
|
args: args.iter().map(|s| s.to_string()).collect(),
|
||||||
|
supported,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DigestEngine for DigestEngineProgram {
|
impl DigestEngine for DigestEngineProgram {
|
||||||
fn create(&self) -> Box<dyn DigestEngine> {
|
fn is_supported(&self) -> bool {
|
||||||
Box::new(Self::new(&self.program))
|
self.supported
|
||||||
}
|
}
|
||||||
|
fn create(&self) -> Result<Box<dyn Write>> {
|
||||||
|
debug!("DIGEST: Writting using {:?}", *self);
|
||||||
|
|
||||||
fn update(&mut self, _data: &[u8]) -> io::Result<()> {
|
let program = self.program.clone();
|
||||||
Ok(())
|
let args = self.args.clone();
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
"DIGEST: Executing command: {:?} {:?}",
|
||||||
|
program, args
|
||||||
|
);
|
||||||
|
|
||||||
|
let process = Command::new(program.clone())
|
||||||
|
.args(args.clone())
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.context(anyhow!(
|
||||||
|
"Problem spawning child process: {:?} {:?}",
|
||||||
|
program,
|
||||||
|
args
|
||||||
|
))?;
|
||||||
|
|
||||||
|
Ok(Box::new(process.stdin.unwrap()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize(&mut self) -> io::Result<String> {
|
fn finalize(&mut self) -> io::Result<String> {
|
||||||
Ok("program".to_string())
|
Ok("program".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
use std::io;
|
use anyhow::Result;
|
||||||
|
use log::*;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::path::PathBuf;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use crate::digest_engine::DigestEngine;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct DigestEngineSha256 {
|
pub struct DigestEngineSha256 {
|
||||||
@@ -8,42 +15,18 @@ pub struct DigestEngineSha256 {
|
|||||||
|
|
||||||
impl DigestEngineSha256 {
|
impl DigestEngineSha256 {
|
||||||
pub fn new() -> DigestEngineSha256 {
|
pub fn new() -> DigestEngineSha256 {
|
||||||
DigestEngineSha256 { hasher: Sha256::new() }
|
DigestEngineSha256 {
|
||||||
|
hasher: Sha256::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manual implementation of PartialEq
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
let result1 = self.hasher.clone().finalize();
|
|
||||||
let result2 = other.hasher.clone().finalize();
|
|
||||||
result1.as_slice() == result2.as_slice()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manual implementation of Eq
|
|
||||||
fn is_eq(&self) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::digest_engine::DigestEngine;
|
|
||||||
|
|
||||||
impl PartialEq for DigestEngineSha256 {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.eq(other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for DigestEngineSha256 {}
|
|
||||||
|
|
||||||
impl DigestEngine for DigestEngineSha256 {
|
impl DigestEngine for DigestEngineSha256 {
|
||||||
fn create(&self) -> Box<dyn DigestEngine> {
|
fn create(&self) -> Result<Box<dyn Write>> {
|
||||||
Box::new(Self::new())
|
Box::new(Self::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, data: &[u8]) -> io::Result<()> {
|
|
||||||
self.hasher.update(data);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn finalize(&mut self) -> io::Result<String> {
|
fn finalize(&mut self) -> io::Result<String> {
|
||||||
let result = self.hasher.clone().finalize();
|
let result = self.hasher.clone().finalize();
|
||||||
Ok(format!("{:x}", result))
|
Ok(format!("{:x}", result))
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use log::debug;
|
|||||||
use rusqlite::Connection;
|
use rusqlite::Connection;
|
||||||
|
|
||||||
use crate::db::{self};
|
use crate::db::{self};
|
||||||
use crate::digest_engine::{DigestEngine, get_engine, DigestType};
|
use crate::digest_engine::{get_engine, DigestEngine, DigestType};
|
||||||
use crate::modes::common::get_meta_from_env;
|
use crate::modes::common::get_meta_from_env;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
|
|
||||||
@@ -49,7 +49,8 @@ pub fn mode_save(
|
|||||||
|
|
||||||
use gethostname::gethostname;
|
use gethostname::gethostname;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
let compression_type_opt = crate::compression_engine::CompressionType::from_str(&compression_name);
|
let compression_type_opt =
|
||||||
|
crate::compression_engine::CompressionType::from_str(&compression_name);
|
||||||
if compression_type_opt.is_err() {
|
if compression_type_opt.is_err() {
|
||||||
cmd.error(
|
cmd.error(
|
||||||
ErrorKind::InvalidValue,
|
ErrorKind::InvalidValue,
|
||||||
@@ -62,8 +63,7 @@ pub fn mode_save(
|
|||||||
debug!("MAIN: Compression type: {}", compression_type);
|
debug!("MAIN: Compression type: {}", compression_type);
|
||||||
|
|
||||||
// Create a new digest engine
|
// Create a new digest engine
|
||||||
let digest_type = DigestType::from_str(&digest_name)
|
let digest_type = DigestType::from_str(&digest_name).unwrap_or(DigestType::Sha256);
|
||||||
.unwrap_or(DigestType::Sha256);
|
|
||||||
let mut digest_engine = get_engine(digest_type);
|
let mut digest_engine = get_engine(digest_type);
|
||||||
|
|
||||||
let mut item = db::Item {
|
let mut item = db::Item {
|
||||||
|
|||||||
Reference in New Issue
Block a user