diff --git a/src/cli.rs b/src/cli.rs index 7bcb0ae..42d1d13 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -2,10 +2,10 @@ use std::{ path::Path, fs::File, str::FromStr, - io::{stdin, stdout, Read, Write}, + io::{stdin, stdout, Read}, }; use clap::{crate_name, crate_version, App, Arg, AppSettings}; -use crate::{Password, crypto::{ArgonParams, CipherAlgorithm}}; +use crate::{LazyWriter, Password, crypto::{ArgonParams, CipherAlgorithm}}; cpufeatures::new!(aes_ni, "aes"); @@ -16,7 +16,7 @@ pub struct CliArgs { pub cipher: CipherAlgorithm, pub block_size: usize, pub reader: Box, - pub writer: Box, + pub writer: LazyWriter, } pub fn parse() -> Option { @@ -133,10 +133,10 @@ pub fn parse() -> Option { eprintln!("WARNING: {} already exists", s); None } else { - Some(Box::new(File::create(s).unwrap()) as Box) + Some(LazyWriter::from_path(s.to_owned())) } }) - .unwrap_or_else(|| Some(Box::new(stdout())))?; + .unwrap_or_else(|| Some(LazyWriter::from_writer(stdout())))?; Some(CliArgs { password: app.value_of("1_password").into(), diff --git a/src/lib.rs b/src/lib.rs index d076a27..64a4f61 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ pub mod cli; pub mod crypto; -use std::io::{self, Read, Write}; +use std::{fs::File, path::Path, io::{self, Read, Write}}; use crypto::{DobyCipher, EncryptionParams}; use zeroize::Zeroize; @@ -33,6 +33,39 @@ impl Zeroize for Password { } } +pub struct LazyWriter> { + path: Option

, + writer: Option>, +} + +impl> LazyWriter

{ + fn from_path(path: P) -> Self { + Self { + path: Some(path), + writer: None, + } + } + fn from_writer(writer: T) -> Self { + Self { + path: None, + writer: Some(Box::new(writer)), + } + } +} + +impl> Write for LazyWriter

{ + fn write(&mut self, buf: &[u8]) -> io::Result { + if self.writer.is_none() { + self.writer = Some(Box::new(File::create(self.path.as_ref().unwrap()).unwrap())); + } + self.writer.as_mut().unwrap().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.writer.as_mut().unwrap().flush() + } +} + pub fn encrypt(reader: &mut R, writer: &mut W, params: &EncryptionParams, mut cipher: DobyCipher, block_size: usize, already_read: Option>) -> io::Result<()> { writer.write_all(MAGIC_BYTES)?; params.write(writer)?;