Bugfix (v0.1.2)

This commit is contained in:
Philipp Schuster 2021-10-04 12:25:53 +02:00
parent 48bfc67213
commit 47bdfd1f85
5 changed files with 59 additions and 10 deletions

View File

@ -7,7 +7,7 @@ as GNU Longname. The maximum supported file name length is 100 characters includ
The maximum supported file size is 8GiB. Also, directories are not supported yet but only flat The maximum supported file size is 8GiB. Also, directories are not supported yet but only flat
collections of files. collections of files.
""" """
version = "0.1.1" version = "0.1.2"
edition = "2018" edition = "2018"
keywords = ["tar", "tarball", "archive"] keywords = ["tar", "tarball", "archive"]
categories = ["data-structures", "no-std", "parser-implementations"] categories = ["data-structures", "no-std", "parser-implementations"]

View File

@ -26,11 +26,15 @@ fn main() {
std::env::set_var("RUST_LOG", "trace"); std::env::set_var("RUST_LOG", "trace");
env_logger::init(); env_logger::init();
// also works in no_std environment // also works in no_std environment (except the println!, of course)
let archive = include_bytes!("../tests/gnu_tar_default.tar"); let archive = include_bytes!("../tests/gnu_tar_default.tar");
let archive = TarArchive::new(archive); let archive = TarArchive::new(archive);
// Vec needs an allocator of course, but the library itself doesn't need one
let entries = archive.entries().collect::<Vec<_>>(); let entries = archive.entries().collect::<Vec<_>>();
println!("{:#?}", entries); println!("{:#?}", entries);
println!("content of last file:");
let last_file_content = unsafe { core::str::from_utf8_unchecked(entries[2].data()) };
println!("{:#?}", last_file_content);
} }
``` ```

View File

@ -28,9 +28,13 @@ fn main() {
std::env::set_var("RUST_LOG", "trace"); std::env::set_var("RUST_LOG", "trace");
env_logger::init(); env_logger::init();
// also works in no_std environment // also works in no_std environment (except the println!, of course)
let archive = include_bytes!("../tests/gnu_tar_default.tar"); let archive = include_bytes!("../tests/gnu_tar_default.tar");
let archive = TarArchive::new(archive); let archive = TarArchive::new(archive);
// Vec needs an allocator of course, but the library itself doesn't need one
let entries = archive.entries().collect::<Vec<_>>(); let entries = archive.entries().collect::<Vec<_>>();
println!("{:#?}", entries); println!("{:#?}", entries);
println!("content of last file:");
let last_file_content = unsafe { core::str::from_utf8_unchecked(entries[2].data()) };
println!("{:#?}", last_file_content);
} }

View File

@ -162,16 +162,20 @@ impl<'a> Iterator for ArchiveIterator<'a> {
} }
// fetch data of file from next block(s) // fetch data of file from next block(s)
let block_count = hdr.payload_block_count(); let data_block_count = hdr.payload_block_count();
let i_begin = self.block_index * BLOCKSIZE; // +1: skip hdr block itself and start at data!
let i_end = i_begin + block_count * BLOCKSIZE; // i_begin is the byte begin index of this file in the array of the whole archive
debug_assert!(i_end <= self.archive.data.len(), "index ouf of range!"); let i_begin = (self.block_index + 1) * BLOCKSIZE;
// +1: hdr itself + data blocks // i_end is the exclusive byte end index of the data of the current file
self.block_index += block_count + 1; let i_end = i_begin + data_block_count * BLOCKSIZE;
let file_block_bytes = &self.archive.data[i_begin..i_end]; let file_block_bytes = &self.archive.data[i_begin..i_end];
// because each block is 512 bytes long, the file is not necessarily a multiple of 512 bytes
let file_bytes = &file_block_bytes[0..hdr.size.val()]; let file_bytes = &file_block_bytes[0..hdr.size.val()];
// in next iteration: start at next Archive entry header
// +1 for current hdr block itself + all data blocks
self.block_index += data_block_count + 1;
Some(ArchiveEntry::new( Some(ArchiveEntry::new(
ArrayString::from_str(hdr.name.as_string().as_str()).unwrap(), ArrayString::from_str(hdr.name.as_string().as_str()).unwrap(),
file_bytes, file_bytes,
@ -182,6 +186,7 @@ impl<'a> Iterator for ArchiveIterator<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use core::str;
use std::vec::Vec; use std::vec::Vec;
#[test] #[test]
@ -230,11 +235,26 @@ mod tests {
assert_eq!(entries[0].filename().as_str(), "bye_world_513b.txt"); assert_eq!(entries[0].filename().as_str(), "bye_world_513b.txt");
assert_eq!(entries[0].size(), 513); assert_eq!(entries[0].size(), 513);
assert_eq!(entries[0].data().len(), 513); assert_eq!(entries[0].data().len(), 513);
assert_eq!(
unsafe { str::from_utf8_unchecked(entries[0].data) },
include_str!("../tests/bye_world_513b.txt")
);
assert_eq!(entries[1].filename().as_str(), "hello_world_513b.txt"); assert_eq!(entries[1].filename().as_str(), "hello_world_513b.txt");
assert_eq!(entries[1].size(), 513); assert_eq!(entries[1].size(), 513);
assert_eq!(entries[1].data().len(), 513); assert_eq!(entries[1].data().len(), 513);
assert_eq!(
unsafe { str::from_utf8_unchecked(entries[1].data) },
include_str!("../tests/hello_world_513b.txt")
);
assert_eq!(entries[2].filename().as_str(), "hello_world.txt"); assert_eq!(entries[2].filename().as_str(), "hello_world.txt");
assert_eq!(entries[2].size(), 12); assert_eq!(entries[2].size(), 12);
assert_eq!(entries[2].data().len(), 12); assert_eq!(entries[2].data().len(), 12);
assert_eq!(
unsafe { str::from_utf8_unchecked(entries[2].data) },
"Hello World\n",
"file content must match"
);
} }
} }

View File

@ -38,6 +38,27 @@ SOFTWARE.
//! GNU Extensions such as sparse files, incremental archives, and long filename extension are not supported yet. //! GNU Extensions such as sparse files, incremental archives, and long filename extension are not supported yet.
//! [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
//! use tar_no_std::TarArchive;
//!
//! fn main() {
//! // log: not mandatory
//! std::env::set_var("RUST_LOG", "trace");
//! env_logger::init();
//!
//! // also works in no_std environment (except the println!, of course)
//! let archive = include_bytes!("../tests/gnu_tar_default.tar");
//! let archive = TarArchive::new(archive);
//! // Vec needs an allocator of course, but the library itself doesn't need one
//! let entries = archive.entries().collect::<Vec<_>>();
//! println!("{:#?}", entries);
//! println!("content of last file:");
//! let last_file_content = unsafe { core::str::from_utf8_unchecked(entries[2].data()) };
//! println!("{:#?}", last_file_content);
//! }
//! ```
#![cfg_attr(not(test), no_std)] #![cfg_attr(not(test), no_std)]
#![deny(rustdoc::all)] #![deny(rustdoc::all)]