diff --git a/src/file.rs b/src/file.rs index cb8f228..706c11e 100644 --- a/src/file.rs +++ b/src/file.rs @@ -69,7 +69,7 @@ impl File { Err(Error::InvalidChecksum) } } - _ => Ok(Self { + Checksum::Skip => Ok(Self { len, checksum, data, diff --git a/src/filetype.rs b/src/filetype.rs index 5fb81a4..1b1a7f2 100644 --- a/src/filetype.rs +++ b/src/filetype.rs @@ -50,8 +50,8 @@ impl From<&FileType> for Flag { } impl Flag { - pub(crate) fn append_mode(&self, mode: u16) -> u16 { - let mask: u16 = u16::from(*self as u8) << 13; + pub(crate) fn append_mode(self, mode: u16) -> u16 { + let mask: u16 = u16::from(self as u8) << 13; mode | mask } @@ -130,7 +130,7 @@ impl FileType { match self { Self::Normal(f) => f.write(writer)?, Self::HardLink(s) | Self::SoftLink(s) => { - let len = s.len() as u16; + let len = u16::try_from(s.len())?; writer.write_all(&len.to_le_bytes())?; writer.write_all(s.as_bytes())?; } diff --git a/src/lib.rs b/src/lib.rs index 51e8719..d3e97a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +#![warn(clippy::all, clippy::pedantic)] #![doc = include_str!("../README.md")] use std::{ collections::HashMap, @@ -8,7 +9,7 @@ use std::{ #[cfg(feature = "parallel")] use { rayon::prelude::{IntoParallelRefIterator, ParallelIterator}, - std::{ops::DerefMut, sync::mpsc::Sender}, + std::sync::mpsc::Sender, }; mod checksum; @@ -36,7 +37,9 @@ pub use stream::Message as StreamMessage; pub static MAGIC: [u8; 7] = [0x89, b'h', b'a', b'g', b'g', b'i', b's']; /// Creates a haggis archive from a list of files -pub fn create_archive(path: &str, files: Vec, algorithm: Algorithm) -> Result<(), Error> { +/// # Errors +/// Returns `crate::Error` if io fails or several other error conditions +pub fn create_archive(path: &str, files: &[String], algorithm: Algorithm) -> Result<(), Error> { let fd = fs::OpenOptions::new() .create(true) .truncate(true) @@ -47,16 +50,18 @@ pub fn create_archive(path: &str, files: Vec, algorithm: Algorithm) -> R } /// Streams a haggis archive over something which implements `Write` +/// # Errors +/// Returns `crate::Error` if io fails or several other error conditions pub fn stream_archive( mut writer: W, - files: Vec, + files: &[String], algorithm: Algorithm, ) -> Result<(), Error> { writer.write_all(&MAGIC)?; let len = u32::try_from(files.len())?; writer.write_all(&len.to_le_bytes())?; let links = Mutex::new(HashMap::new()); - for f in &files { + for f in files { let node = Node::from_path(f, algorithm, &links)?; node.write(&mut writer)?; } @@ -74,10 +79,12 @@ pub enum Message { } /// Creates a Haggis archive from a list of files, processing each file in parallel +/// # Errors +/// Returns `crate::Error` if io fails or several other error conditions #[cfg(feature = "parallel")] pub fn par_create_archive( path: &str, - files: Vec, + files: &[String], algorithm: Algorithm, sender: &Sender, ) -> Result<(), Error> { @@ -88,10 +95,12 @@ pub fn par_create_archive( } /// Streams a Haggis archive from a list of files, processing each file in parallel +/// # Errors +/// Returns `crate::Error` if io fails or several other error conditions #[cfg(feature = "parallel")] pub fn par_stream_archive( mut writer: W, - files: Vec, + files: &[String], algorithm: Algorithm, sender: &Sender, ) -> Result<(), Error> { @@ -110,7 +119,7 @@ pub fn par_stream_archive( } }; if let Ok(mut writer) = writer.lock() { - let mut writer = writer.deref_mut(); + let mut writer = &mut *writer; if let Err(e) = node.write(&mut writer) { s.send(Message::Err(e)).map_err(|_| Error::SenderError)?; } diff --git a/src/nix/mod.rs b/src/nix/mod.rs index 354ae96..d370346 100644 --- a/src/nix/mod.rs +++ b/src/nix/mod.rs @@ -10,6 +10,7 @@ pub fn geteuid() -> u32 { unsafe { libc::geteuid() } } +#[allow(clippy::similar_names)] pub fn chown(path: &str, uid: u32, gid: u32) -> Result<(), Error> { let ret = unsafe { libc::chown(CString::new(path)?.as_ptr(), uid, gid) }; if ret == 0 { diff --git a/src/node.rs b/src/node.rs index e1ad0bf..3d5548a 100644 --- a/src/node.rs +++ b/src/node.rs @@ -26,13 +26,13 @@ impl From for Kind { fn from(value: u32) -> Self { if value & 0o40000 != 0 { Self::Dir - } else if value & 0o20000 != 0 { + } else if value & 0o20_000 != 0 { Self::Char - } else if value & 0o60000 != 0 { + } else if value & 0o60_000 != 0 { Self::Block - } else if value & 0o10000 != 0 { + } else if value & 0o10_000 != 0 { Self::Pipe - } else if value & 0o100000 != 0 { + } else if value & 0o100_000 != 0 { Self::Normal } else { unreachable!(); @@ -58,16 +58,19 @@ pub struct Node { } impl Node { + #[allow(clippy::similar_names)] /// Reads a `Node` from an archive file or stream of Nodes. /// > Note: this function reads an already created node. To create a new node /// > from a file, use the `from_path` method. + /// # Errors + /// Returns `crate::Error` if io fails or certain other circumstances pub fn read(reader: &mut T) -> Result { let mut len = [0; 2]; reader.read_exact(&mut len)?; let len = u16::from_le_bytes(len); if len == 0 { return Ok(Self { - name: "".to_string(), + name: String::new(), mode: 0, uid: 0, gid: 0, @@ -101,6 +104,8 @@ impl Node { /// > Note: this function saves the data to the archive format's on-disk /// > representation. To extract the contents of a `Node` and write out the /// > file it represents, use the `extract` method instead. + /// # Errors + /// Returns `crate::Error` if io fails or certain other circumstances pub fn write(&self, writer: &mut T) -> Result<(), Error> { let len: u16 = self.name.len().try_into()?; writer.write_all(&len.to_le_bytes())?; @@ -114,6 +119,7 @@ impl Node { Ok(()) } + #[allow(clippy::similar_names)] /// Creates a new node from a file which exists on the filesystem /// ### Parameters /// - path - the path to this file @@ -122,6 +128,8 @@ impl Node { /// - links - this should be passed to each invocation of `from_path` used /// during the creation of a single archive, to identify hard links and to /// avoid writing their data out more than once. + /// # Errors + /// Returns `crate::Error` if io fails or certain other circumstances pub fn from_path( path: &str, algorithm: Algorithm, @@ -150,9 +158,8 @@ impl Node { let inode = meta.ino(); if let Some(target) = list.get(&inode).cloned() { break 'blk FileType::HardLink(target); - } else { - list.insert(inode, name.clone()); } + list.insert(inode, name.clone()); } } let kind = Kind::from(mode); @@ -195,9 +202,8 @@ impl Node { checksum, data, }); - } else { - return Err(Error::UnknownFileType); } + return Err(Error::UnknownFileType); } }; let mode = Flag::from(&filetype).append_mode(u16::try_from(mode & 0o7777)?); @@ -212,15 +218,16 @@ impl Node { } /// Recreates the original file on disk which this node represents + /// # Errors + /// Returns `crate::Error` if io fails or certain other circumstances pub fn extract(&self, prefix: Option<&str>) -> Result<(), Error> { let euid = nix::geteuid(); let path = 'blk: { if let Some(prefix) = prefix { if self.name.starts_with('/') { break 'blk format!("{prefix}{}", self.name); - } else { - break 'blk format!("{prefix}/{}", self.name); } + break 'blk format!("{prefix}/{}", self.name); } self.name.clone() }; diff --git a/src/special.rs b/src/special.rs index f1abed3..a4cb07f 100644 --- a/src/special.rs +++ b/src/special.rs @@ -28,6 +28,7 @@ impl Special { } #[cfg(all(target_os = "freebsd", target_arch = "x86_64"))] + #[allow(clippy::cast_possible_truncation)] pub(super) fn from_rdev(rdev: u64) -> Self { Self { major: ((rdev >> 8) & 0xff) as u32, @@ -36,13 +37,14 @@ impl Special { } #[cfg(target_os = "linux")] + #[allow(clippy::cast_possible_truncation)] pub(super) fn from_rdev(rdev: u64) -> Self { let mut major = 0; - major |= (rdev & 0x00000000000fff00) >> 8; - major |= (rdev & 0xfffff00000000000) >> 32; + major |= (rdev & 0x0000_0000_000f_ff00) >> 8; + major |= (rdev & 0xffff_f000_0000_0000) >> 32; let mut minor = 0; - minor |= rdev & 0x00000000000000ff; - minor |= (rdev & 0x00000ffffff00000) >> 12; + minor |= rdev & 0x0000_0000_0000_00ff; + minor |= (rdev & 0x0000_0fff_fff0_0000) >> 12; Self { major: major as u32, minor: minor as u32, diff --git a/src/stream.rs b/src/stream.rs index 2307ea4..10e2c2a 100644 --- a/src/stream.rs +++ b/src/stream.rs @@ -49,6 +49,9 @@ pub enum Message { } impl Stream { + /// Creates a new archive + /// # Errors + /// Returns `crate::Error` if io fails or several other error conditions pub fn new(mut reader: R) -> Result { let mut buf = [0; 11]; reader.read_exact(&mut buf)?; @@ -60,6 +63,9 @@ impl Stream { } } + /// Extracts and archive + /// # Errors + /// Returns `crate::Error` if io fails or several other error conditions pub fn extract(&mut self, prefix: Option<&str>) -> Result<(), Error> { for node in self { node?.extract(prefix)?; @@ -68,6 +74,9 @@ impl Stream { } #[cfg(feature = "parallel")] + /// Extracts and archive in parallel + /// # Errors + /// Returns `crate::Error` if io fails or several other error conditions pub fn par_extract( &mut self, prefix: Option<&str>,