Skip to content

Commit

Permalink
Merge pull request #33 from fasterthanlime/win11-zip64
Browse files Browse the repository at this point in the history
Correctly parse zip64 files produced by Windows 11
  • Loading branch information
fasterthanlime authored Jan 26, 2024
2 parents ab5e9d1 + 2ee90e1 commit cad55f0
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 11 deletions.
74 changes: 74 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/jean/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ clap = { version = "4.4.18", features = ["derive"] }
humansize = "2.1.3"
positioned-io.workspace = true
indicatif = "0.17.7"
tracing-subscriber = "0.3.18"
9 changes: 9 additions & 0 deletions crates/jean/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ enum Commands {
}

fn main() {
tracing_subscriber::fmt::init();

let cli = Cli::parse();
do_main(cli).unwrap();
}
Expand All @@ -75,6 +77,8 @@ fn do_main(cli: Cli) -> Result<(), Box<dyn std::error::Error>> {
if let Some(comment) = archive.comment() {
println!("Comment:\n{}", comment);
}
let has_zip64 = archive.entries().any(|entry| entry.inner.is_zip64);
println!("{}", if has_zip64 { "Zip64" } else { "Zip32" });

let mut creator_versions = HashSet::<rc_zip::Version>::new();
let mut reader_versions = HashSet::<rc_zip::Version>::new();
Expand Down Expand Up @@ -156,6 +160,11 @@ fn do_main(cli: Cli) -> Result<(), Box<dyn std::error::Error>> {
if let Some(comment) = entry.comment() {
print!("\t{comment}", comment = comment);
}
if entry.inner.is_zip64 {
print!("\tZip64");
} else {
print!("\tZip32");
}
}
println!();
}
Expand Down
5 changes: 3 additions & 2 deletions crates/rc-zip/src/format/directory_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,11 @@ impl DirectoryHeader {
let mut extra_fields: Vec<ExtraField> = Vec::new();

let settings = ExtraFieldSettings {
needs_compressed_size: self.uncompressed_size == !0u32,
needs_uncompressed_size: self.compressed_size == !0u32,
needs_compressed_size: self.compressed_size == !0u32,
needs_uncompressed_size: self.uncompressed_size == !0u32,
needs_header_offset: self.header_offset == !0u32,
};
trace!("extra field settings: {:#?}", settings);

let mut slice = &self.extra.0[..];
while !slice.is_empty() {
Expand Down
4 changes: 4 additions & 0 deletions crates/rc-zip/src/format/eocd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use nom::{
use tracing::trace;

/// 4.3.16 End of central directory record:
#[derive(Debug)]
pub struct EndOfCentralDirectoryRecord {
/// number of this disk
pub disk_nbr: u16,
Expand Down Expand Up @@ -81,6 +82,7 @@ impl EndOfCentralDirectoryRecord {
}

/// 4.3.15 Zip64 end of central directory locator
#[derive(Debug)]
pub struct EndOfCentralDirectory64Locator {
/// number of the disk with the start of the zip64 end of central directory
pub dir_disk_number: u32,
Expand All @@ -107,6 +109,7 @@ impl EndOfCentralDirectory64Locator {
}

/// 4.3.14 Zip64 end of central directory record
#[derive(Debug)]
pub struct EndOfCentralDirectory64Record {
/// size of zip64 end of central directory record
pub record_size: u64,
Expand Down Expand Up @@ -150,6 +153,7 @@ impl EndOfCentralDirectory64Record {
}
}

#[derive(Debug)]
pub struct Located<T> {
pub offset: u64,
pub inner: T,
Expand Down
1 change: 1 addition & 0 deletions crates/rc-zip/src/format/extra_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ impl<'a> ExtraFieldRecord<'a> {
// is created. The order of the fields in the zip64 extended information record
// is fixed, but the fields MUST only appear if the corresponding Local or
// Central directory record field is set to 0xFFFF or 0xFFFFFFFF.
#[derive(Debug)]
pub(crate) struct ExtraFieldSettings {
pub(crate) needs_uncompressed_size: bool,
pub(crate) needs_compressed_size: bool,
Expand Down
17 changes: 17 additions & 0 deletions crates/rc-zip/src/reader/archive_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,21 @@ impl ArchiveReader {
} {
None => Err(FormatError::DirectoryEndSignatureNotFound.into()),
Some(mut eocdr) => {
trace!(
?eocdr,
size = self.size,
"ReadEocd | found end of central directory record"
);
buffer.reset();
eocdr.offset += self.size - haystack_size;

if eocdr.offset < EndOfCentralDirectory64Locator::LENGTH as u64 {
// no room for an EOCD64 locator, definitely not a zip64 file
trace!(
offset = eocdr.offset,
eocd64locator_length = EndOfCentralDirectory64Locator::LENGTH,
"no room for an EOCD64 locator, definitely not a zip64 file"
);
transition!(self.state => (S::ReadEocd { mut buffer, .. }) {
buffer.reset();
S::ReadCentralDirectory {
Expand All @@ -188,6 +198,7 @@ impl ArchiveReader {
});
Ok(R::Continue)
} else {
trace!("ReadEocd | transition to ReadEocd64Locator");
transition!(self.state => (S::ReadEocd { mut buffer, .. }) {
buffer.reset();
S::ReadEocd64Locator { buffer, eocdr }
Expand All @@ -205,6 +216,8 @@ impl ArchiveReader {
}
Err(nom::Err::Error(_)) | Err(nom::Err::Failure(_)) => {
// we don't have a zip64 end of central directory locator - that's ok!
trace!("ReadEocd64Locator | no zip64 end of central directory locator");
trace!("ReadEocd64Locator | data we got: {:02x?}", buffer.data());
transition!(self.state => (S::ReadEocd64Locator { mut buffer, eocdr }) {
buffer.reset();
S::ReadCentralDirectory {
Expand All @@ -216,6 +229,10 @@ impl ArchiveReader {
Ok(R::Continue)
}
Ok((_, locator)) => {
trace!(
?locator,
"ReadEocd64Locator | found zip64 end of central directory locator"
);
transition!(self.state => (S::ReadEocd64Locator { mut buffer, eocdr }) {
buffer.reset();
S::ReadEocd64 {
Expand Down
Loading

0 comments on commit cad55f0

Please sign in to comment.