few more fixes + clippy

This commit is contained in:
Philipp Schuster 2021-10-04 11:31:11 +02:00
parent 4f314b45f2
commit a2b6cc4f5c
4 changed files with 39 additions and 12 deletions

View File

@ -19,11 +19,24 @@ GNU Extensions such as sparse files, incremental archives, and long filename ext
[This link](https://www.gnu.org/software/tar/manual/html_section/Formats.html) gives a good overview over possible [This link](https://www.gnu.org/software/tar/manual/html_section/Formats.html) gives a good overview over possible
archive formats and their limitations. archive formats and their limitations.
## Example
```rust
fn main() {
// log: not mandatory
std::env::set_var("RUST_LOG", "trace");
env_logger::init();
// also works in no_std environment
let archive = include_bytes!("../tests/gnu_tar_default.tar");
let archive = TarArchive::new(archive);
let entries = archive.entries().collect::<Vec<_>>();
println!("{:#?}", entries);
}
```
## Compression ## Compression
If your tar file is compressed, e.g. bei `gzip`, you need to uncompress the bytes first (e.g. by a *deflate* algorithm), If your tar file is compressed, e.g. bei `.tar.gz`/`gzip`, you need to uncompress the bytes first
before (e.g. by a *gzip* library). Afterwards, this crate can read and write the Tar archive format from the bytes.
## MSRV ## MSRV
The MSRV is 1.51.0 stable. The MSRV is 1.51.0 stable.

View File

@ -30,7 +30,7 @@ use core::fmt::{Debug, Formatter};
use core::ptr; use core::ptr;
use core::str::FromStr; use core::str::FromStr;
/// Describes an entry in a archive. /// Describes an entry in an archive.
/// Currently only supports files but no directories. /// Currently only supports files but no directories.
pub struct ArchiveEntry<'a> { pub struct ArchiveEntry<'a> {
filename: ArrayString<100>, filename: ArrayString<100>,
@ -40,7 +40,7 @@ pub struct ArchiveEntry<'a> {
#[allow(unused)] #[allow(unused)]
impl<'a> ArchiveEntry<'a> { impl<'a> ArchiveEntry<'a> {
pub fn new(filename: ArrayString<100>, data: &'a [u8]) -> Self { pub const fn new(filename: ArrayString<100>, data: &'a [u8]) -> Self {
ArchiveEntry { ArchiveEntry {
filename, filename,
data, data,
@ -49,17 +49,17 @@ impl<'a> ArchiveEntry<'a> {
} }
/// Filename of the entry. Max 99 characters. /// Filename of the entry. Max 99 characters.
pub fn filename(&self) -> ArrayString<100> { pub const fn filename(&self) -> ArrayString<100> {
self.filename self.filename
} }
/// Data of the file. /// Data of the file.
pub fn data(&self) -> &'a [u8] { pub const fn data(&self) -> &'a [u8] {
self.data self.data
} }
/// Filesize in bytes. /// Filesize in bytes.
pub fn size(&self) -> usize { pub const fn size(&self) -> usize {
self.size self.size
} }
} }
@ -95,7 +95,7 @@ impl<'a> TarArchive<'a> {
/// Iterates over all entries of the TAR Archive. /// Iterates over all entries of the TAR Archive.
/// Returns items of type [`ArchiveEntry`]. /// Returns items of type [`ArchiveEntry`].
pub fn entries(&self) -> ArchiveIterator { pub const fn entries(&self) -> ArchiveIterator {
ArchiveIterator::new(self) ArchiveIterator::new(self)
} }
} }
@ -109,7 +109,7 @@ pub struct ArchiveIterator<'a> {
} }
impl<'a> ArchiveIterator<'a> { impl<'a> ArchiveIterator<'a> {
pub fn new(archive: &'a TarArchive<'a>) -> Self { pub const fn new(archive: &'a TarArchive<'a>) -> Self {
Self { Self {
archive, archive,
block_index: 0, block_index: 0,
@ -117,7 +117,7 @@ impl<'a> ArchiveIterator<'a> {
} }
/// Returns a pointer to the next Header. /// Returns a pointer to the next Header.
fn next_hdr(&self, block_index: usize) -> *const PosixHeader { const fn next_hdr(&self, block_index: usize) -> *const PosixHeader {
let hdr_ptr = &self.archive.data[block_index * BLOCKSIZE]; let hdr_ptr = &self.archive.data[block_index * BLOCKSIZE];
let hdr_ptr = hdr_ptr as *const u8; let hdr_ptr = hdr_ptr as *const u8;
hdr_ptr as *const PosixHeader hdr_ptr as *const PosixHeader
@ -157,6 +157,10 @@ impl<'a> Iterator for ArchiveIterator<'a> {
return None; return None;
} }
if hdr.name.is_empty() {
log::warn!("Found empty file name",);
}
// fetch data of file from next block(s) // fetch data of file from next block(s)
let block_count = hdr.payload_block_count(); let block_count = hdr.payload_block_count();
let i_begin = self.block_index * BLOCKSIZE; let i_begin = self.block_index * BLOCKSIZE;

View File

@ -83,7 +83,7 @@ pub struct StaticCString<const N: usize>([u8; N]);
#[allow(unused)] #[allow(unused)]
impl<const N: usize> StaticCString<N> { impl<const N: usize> StaticCString<N> {
/// Constructor. /// Constructor.
fn new(bytes: [u8; N]) -> Self { const fn new(bytes: [u8; N]) -> Self {
Self(bytes) Self(bytes)
} }
@ -93,6 +93,11 @@ impl<const N: usize> StaticCString<N> {
self.as_string().len() self.as_string().len()
} }
/// Returns if the string without NULL-byte is empty.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Returns a string without null bytes. /// Returns a string without null bytes.
pub fn as_string(&self) -> ArrayString<N> { pub fn as_string(&self) -> ArrayString<N> {
let mut string = ArrayString::new(); let mut string = ArrayString::new();
@ -114,7 +119,7 @@ impl<const N: usize> Debug for StaticCString<N> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let mut debug = f.debug_tuple("Name"); let mut debug = f.debug_tuple("Name");
let str = self.as_string(); let str = self.as_string();
if str.len() == 0 { if str.is_empty() {
debug.field(&"<empty>"); debug.field(&"<empty>");
} else { } else {
debug.field(&str); debug.field(&str);

View File

@ -40,6 +40,11 @@ SOFTWARE.
//! archive formats and their limitations. //! archive formats and their limitations.
#![cfg_attr(not(test), no_std)] #![cfg_attr(not(test), no_std)]
#![deny(rustdoc::all)]
#![allow(rustdoc::missing_doc_code_examples)]
#![deny(clippy::all)]
#![deny(clippy::missing_const_for_fn)]
#![deny(missing_debug_implementations)]
#[cfg_attr(test, macro_use)] #[cfg_attr(test, macro_use)]
#[cfg(test)] #[cfg(test)]