diff --git a/src/checksum.rs b/src/checksum.rs index 5b0d270..8097bf5 100644 --- a/src/checksum.rs +++ b/src/checksum.rs @@ -3,6 +3,14 @@ use { std::io::{Read, Write}, }; +#[derive(Clone, Copy, Debug)] +pub enum Algorithm { + Md5, + Sha1, + Sha256, + Skip, +} + /// Optional checksumming for individual files #[derive(Debug)] pub enum Checksum { @@ -20,7 +28,7 @@ pub enum Checksum { } impl Checksum { - pub fn read(reader: &mut T) -> Result { + pub(crate) fn read(reader: &mut T) -> Result { let mut buf = [0; 1]; reader.read_exact(&mut buf)?; match buf[0] { @@ -43,7 +51,7 @@ impl Checksum { } } - pub fn write(&self, writer: &mut T) -> Result<(), Error> { + pub(crate) fn write(&self, writer: &mut T) -> Result<(), Error> { match self { Self::Md5(sum) => { writer.write_all(&[b'0'])?; diff --git a/src/file.rs b/src/file.rs index 6c1dd32..7fd120b 100644 --- a/src/file.rs +++ b/src/file.rs @@ -18,7 +18,7 @@ pub struct File { } impl File { - pub fn read(reader: &mut T) -> Result { + pub(crate) fn read(reader: &mut T) -> Result { let mut len = [0; 8]; reader.read_exact(&mut len)?; let len = u64::from_le_bytes(len); @@ -77,7 +77,7 @@ impl File { } } - pub fn write(&self, writer: &mut T) -> Result<(), Error> { + pub(crate) fn write(&self, writer: &mut T) -> Result<(), Error> { writer.write_all(&self.len.to_be_bytes())?; Checksum::write(&self.checksum, writer)?; writer.write_all(&self.data)?; diff --git a/src/filetype.rs b/src/filetype.rs index 49d6f73..ffeafb8 100644 --- a/src/filetype.rs +++ b/src/filetype.rs @@ -25,7 +25,7 @@ pub enum FileType { } impl FileType { - pub fn read(reader: &mut T) -> Result { + pub(crate) fn read(reader: &mut T) -> Result { let mut buf = [0; 1]; reader.read_exact(&mut buf)?; match buf[0] { @@ -67,7 +67,7 @@ impl FileType { } } - pub fn write(&self, writer: &mut T) -> Result<(), Error> { + pub(crate) fn write(&self, writer: &mut T) -> Result<(), Error> { match self { Self::Normal(f) => { writer.write_all(&[0])?; diff --git a/src/lib.rs b/src/lib.rs index a82b7fb..527f65a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,30 @@ +#![doc = include_str!("../README.md")] +use std::{fs, collections::HashMap, io::BufWriter, sync::Mutex}; + mod checksum; mod error; mod file; mod filetype; -pub mod nix; +pub(crate) mod nix; mod node; mod special; mod stream; pub use { - checksum::Checksum, error::Error, file::File, filetype::FileType, node::Node, special::Special, + checksum::{Algorithm, Checksum}, error::Error, file::File, filetype::FileType, node::Node, special::Special, stream::Stream, }; + +pub fn create_archive(path: &str, files: Vec<&str>, algorithm: Algorithm) -> Result<(), Error> { + let fd = fs::OpenOptions::new() + .create(true) + .truncate(true) + .open(path)?; + let mut writer = BufWriter::new(fd); + let mut links = Mutex::new(HashMap::new()); + for f in files.iter() { + let node = Node::from_path(f, algorithm, &mut links)?; + node.write(&mut writer)?; + } + Ok(()) +} diff --git a/src/nix/mod.rs b/src/nix/mod.rs index af1afe9..354ae96 100644 --- a/src/nix/mod.rs +++ b/src/nix/mod.rs @@ -1,9 +1,11 @@ #![allow(clippy::must_use_candidate)] +//! Low level Unix api functions use { crate::Error, std::{ffi::CString, io}, }; +/// Get the effective user id of the current process pub fn geteuid() -> u32 { unsafe { libc::geteuid() } } diff --git a/src/node.rs b/src/node.rs index cfa6a3d..f0a6ab9 100644 --- a/src/node.rs +++ b/src/node.rs @@ -1,5 +1,5 @@ use { - crate::{nix, Checksum, Error, File, FileType, Special}, + crate::{nix, Algorithm, Checksum, Error, File, FileType, Special}, md5::{Digest, Md5}, sha1::Sha1, sha2::Sha256, @@ -121,7 +121,7 @@ impl Node { /// avoid writing their data out more than once. pub fn from_path( path: &str, - checksum: Checksum, + algorithm: Algorithm, links: &Mutex>, ) -> Result { let name = String::from(path); @@ -167,26 +167,26 @@ impl Node { let mut len = meta.len(); let mut data = Vec::with_capacity(len.try_into()?); len = reader.read_to_end(&mut data)?.try_into()?; - let checksum = match checksum { - Checksum::Md5(mut cs) => { + let checksum = match algorithm { + Algorithm::Md5 => { let mut hasher = Md5::new(); hasher.update(&data); - cs = hasher.finalize().into(); + let cs = hasher.finalize().into(); Checksum::Md5(cs) } - Checksum::Sha1(mut cs) => { + Algorithm::Sha1 => { let mut hasher = Sha1::new(); hasher.update(&data); - cs = hasher.finalize().into(); + let cs = hasher.finalize().into(); Checksum::Sha1(cs) } - Checksum::Sha256(mut cs) => { + Algorithm::Sha256 => { let mut hasher = Sha256::new(); hasher.update(&data); - cs = hasher.finalize().into(); + let cs = hasher.finalize().into(); Checksum::Sha256(cs) } - Checksum::Skip => checksum, + Algorithm::Skip => Checksum::Skip, }; break 'blk FileType::Normal(File { len, @@ -208,6 +208,7 @@ impl Node { }) } + /// Recreates the original file on disk which this node represents pub fn extract(&self, prefix: Option<&str>) -> Result<(), Error> { let euid = nix::geteuid(); let path = 'blk: { diff --git a/src/special.rs b/src/special.rs index 56368f9..dcf0c4a 100644 --- a/src/special.rs +++ b/src/special.rs @@ -11,7 +11,7 @@ pub struct Special { } impl Special { - pub fn read(reader: &mut T) -> Result { + pub(crate) fn read(reader: &mut T) -> Result { let mut buf = [0; 8]; reader.read_exact(&mut buf)?; let major: [u8; 4] = buf[..4].try_into()?; @@ -21,7 +21,7 @@ impl Special { Ok(Self { major, minor }) } - pub fn write(&self, writer: &mut T) -> Result<(), Error> { + pub(crate) fn write(&self, writer: &mut T) -> Result<(), Error> { writer.write_all(&self.major.to_le_bytes())?; writer.write_all(&self.minor.to_le_bytes())?; Ok(())