From e9706ae4f5e5a62949f296524985b9fa65cf6ca1 Mon Sep 17 00:00:00 2001 From: Rouven Spreckels Date: Fri, 25 Mar 2022 12:40:06 +0100 Subject: [PATCH] Fix ZIP64 write support. --- src/write.rs | 47 ++++++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/src/write.rs b/src/write.rs index 457839bc..a9616b04 100644 --- a/src/write.rs +++ b/src/write.rs @@ -647,6 +647,7 @@ impl ZipWriter { S: Into, { let mut options = FileOptions::default() + .large_file(file.compressed_size().max(file.size()) > 0xFFFFFFFF) .last_modified_time(file.last_modified()) .compression_method(file.compression()); if let Some(perms) = file.unix_mode() { @@ -866,7 +867,7 @@ impl GenericZipWriter { #[allow(deprecated)] match compression { CompressionMethod::Stored => { - if let Some(_) = compression_level { + if compression_level.is_some() { return Err(ZipError::UnsupportedArchive( "Unsupported compression level", )); @@ -917,7 +918,7 @@ impl GenericZipWriter { bare, clamp_opt( compression_level.unwrap_or(zstd::DEFAULT_COMPRESSION_LEVEL), - zstd::compression_level_range().clone(), + zstd::compression_level_range(), ) .ok_or(ZipError::UnsupportedArchive( "Unsupported compression level", @@ -1027,18 +1028,14 @@ fn write_local_file_header(writer: &mut T, file: &ZipFileData) -> ZipR writer.write_u16::(file.last_modified_time.datepart())?; // crc-32 writer.write_u32::(file.crc32)?; - // compressed size - writer.write_u32::(if file.compressed_size > 0xFFFFFFFF { - 0xFFFFFFFF + // compressed size and uncompressed size + if file.large_file { + writer.write_u32::(0xFFFFFFFF)?; + writer.write_u32::(0xFFFFFFFF)?; } else { - file.compressed_size as u32 - })?; - // uncompressed size - writer.write_u32::(if file.uncompressed_size > 0xFFFFFFFF { - 0xFFFFFFFF - } else { - file.uncompressed_size as u32 - })?; + writer.write_u32::(file.compressed_size as u32)?; + writer.write_u32::(file.uncompressed_size as u32)?; + } // file name length writer.write_u16::(file.file_name.as_bytes().len() as u16)?; // extra field length @@ -1061,27 +1058,19 @@ fn update_local_file_header( const CRC32_OFFSET: u64 = 14; writer.seek(io::SeekFrom::Start(file.header_start + CRC32_OFFSET))?; writer.write_u32::(file.crc32)?; - writer.write_u32::(if file.compressed_size > 0xFFFFFFFF { - if file.large_file { - 0xFFFFFFFF - } else { - // compressed size can be slightly larger than uncompressed size + if file.large_file { + update_local_zip64_extra_field(writer, file)?; + } else { + // check compressed size as well as it can also be slightly larger than uncompressed size + if file.compressed_size > 0xFFFFFFFF { return Err(ZipError::Io(io::Error::new( io::ErrorKind::Other, "Large file option has not been set", ))); } - } else { - file.compressed_size as u32 - })?; - writer.write_u32::(if file.uncompressed_size > 0xFFFFFFFF { - // uncompressed size is checked on write to catch it as soon as possible - 0xFFFFFFFF - } else { - file.uncompressed_size as u32 - })?; - if file.large_file { - update_local_zip64_extra_field(writer, file)?; + writer.write_u32::(file.compressed_size as u32)?; + // uncompressed size is already checked on write to catch it as soon as possible + writer.write_u32::(file.uncompressed_size as u32)?; } Ok(()) }