Add create_archive function

This commit is contained in:
Nathan Fisher 2023-07-05 13:35:37 -04:00
parent e5cbf16064
commit 8a3bd19185
7 changed files with 48 additions and 20 deletions

View File

@ -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<T: Read>(reader: &mut T) -> Result<Self, Error> {
pub(crate) fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
let mut buf = [0; 1];
reader.read_exact(&mut buf)?;
match buf[0] {
@ -43,7 +51,7 @@ impl Checksum {
}
}
pub fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
pub(crate) fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
match self {
Self::Md5(sum) => {
writer.write_all(&[b'0'])?;

View File

@ -18,7 +18,7 @@ pub struct File {
}
impl File {
pub fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
pub(crate) fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
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<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
pub(crate) fn write<T: 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)?;

View File

@ -25,7 +25,7 @@ pub enum FileType {
}
impl FileType {
pub fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
pub(crate) fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
let mut buf = [0; 1];
reader.read_exact(&mut buf)?;
match buf[0] {
@ -67,7 +67,7 @@ impl FileType {
}
}
pub fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
pub(crate) fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
match self {
Self::Normal(f) => {
writer.write_all(&[0])?;

View File

@ -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(())
}

View File

@ -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() }
}

View File

@ -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<HashMap<u64, String>>,
) -> Result<Self, Error> {
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: {

View File

@ -11,7 +11,7 @@ pub struct Special {
}
impl Special {
pub fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
pub(crate) fn read<T: Read>(reader: &mut T) -> Result<Self, Error> {
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<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
pub(crate) fn write<T: Write>(&self, writer: &mut T) -> Result<(), Error> {
writer.write_all(&self.major.to_le_bytes())?;
writer.write_all(&self.minor.to_le_bytes())?;
Ok(())