From 3747caf9352d32b61b1fa9371b7361e8990651f7 Mon Sep 17 00:00:00 2001 From: xzfc <5121426+xzfc@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:36:50 +0000 Subject: [PATCH] fix: Support sparse entries of enormous size (#373) Just like the `GnuHeader::size` field, fields `GnuHeader::realsize` and `GnuSparseHeader::{offset, numbytes}` could be encoded in a binary format for values greater than 8Gi. --- src/header.rs | 6 +++--- tests/all.rs | 12 ++++++++++++ tests/archives/sparse-large.tar | Bin 0 -> 10240 bytes tests/header/mod.rs | 7 +++++++ 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 tests/archives/sparse-large.tar diff --git a/src/header.rs b/src/header.rs index 65f665e0..7683251e 100644 --- a/src/header.rs +++ b/src/header.rs @@ -1250,7 +1250,7 @@ impl GnuHeader { /// This is applicable for sparse files where the returned size here is the /// size of the entire file after the sparse regions have been filled in. pub fn real_size(&self) -> io::Result { - octal_from(&self.realsize).map_err(|err| { + num_field_wrapper_from(&self.realsize).map_err(|err| { io::Error::new( err.kind(), format!( @@ -1322,7 +1322,7 @@ impl GnuSparseHeader { /// /// Returns `Err` for a malformed `offset` field. pub fn offset(&self) -> io::Result { - octal_from(&self.offset).map_err(|err| { + num_field_wrapper_from(&self.offset).map_err(|err| { io::Error::new( err.kind(), format!("{} when getting offset from sparse header", err), @@ -1334,7 +1334,7 @@ impl GnuSparseHeader { /// /// Returns `Err` for a malformed `numbytes` field. pub fn length(&self) -> io::Result { - octal_from(&self.numbytes).map_err(|err| { + num_field_wrapper_from(&self.numbytes).map_err(|err| { io::Error::new( err.kind(), format!("{} when getting length from sparse header", err), diff --git a/tests/all.rs b/tests/all.rs index 6aae6a85..27a6fcf1 100644 --- a/tests/all.rs +++ b/tests/all.rs @@ -1157,6 +1157,18 @@ fn extract_sparse() { assert!(s[0x2fa0 + 6..0x4000].chars().all(|x| x == '\u{0}')); } +#[test] +fn large_sparse() { + let rdr = Cursor::new(tar!("sparse-large.tar")); + let mut ar = Archive::new(rdr); + let mut entries = t!(ar.entries()); + // Only check the header info without extracting, as the file is very large, + // and not all filesystems support sparse files. + let a = t!(entries.next().unwrap()); + let h = a.header().as_gnu().unwrap(); + assert_eq!(h.real_size().unwrap(), 12626929280); +} + #[test] fn sparse_with_trailing() { let rdr = Cursor::new(tar!("sparse-1.tar")); diff --git a/tests/archives/sparse-large.tar b/tests/archives/sparse-large.tar new file mode 100644 index 0000000000000000000000000000000000000000..47525764f556e92853ae5e08e1d3b635b29d0f04 GIT binary patch literal 10240 zcmeIuK@Ng25J1t!lk^DFQs5w-pqd6<$O2*Ej+^Mp^LYeY(CCT;11tY*rtM^Ans?}` zpjHlvQ8=e!GG#6)iy80fm{}2J#1%%Y*eupf>2jy^cIAH!c`H_<9Zup-Xfp(d!LwIF@MkZp!wZ&Ab