Fix ZIP64 write support.
This commit is contained in:
parent
4aafe04be6
commit
e9706ae4f5
1 changed files with 18 additions and 29 deletions
47
src/write.rs
47
src/write.rs
|
@ -647,6 +647,7 @@ impl<W: Write + io::Seek> ZipWriter<W> {
|
||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
{
|
{
|
||||||
let mut options = FileOptions::default()
|
let mut options = FileOptions::default()
|
||||||
|
.large_file(file.compressed_size().max(file.size()) > 0xFFFFFFFF)
|
||||||
.last_modified_time(file.last_modified())
|
.last_modified_time(file.last_modified())
|
||||||
.compression_method(file.compression());
|
.compression_method(file.compression());
|
||||||
if let Some(perms) = file.unix_mode() {
|
if let Some(perms) = file.unix_mode() {
|
||||||
|
@ -866,7 +867,7 @@ impl<W: Write + io::Seek> GenericZipWriter<W> {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
match compression {
|
match compression {
|
||||||
CompressionMethod::Stored => {
|
CompressionMethod::Stored => {
|
||||||
if let Some(_) = compression_level {
|
if compression_level.is_some() {
|
||||||
return Err(ZipError::UnsupportedArchive(
|
return Err(ZipError::UnsupportedArchive(
|
||||||
"Unsupported compression level",
|
"Unsupported compression level",
|
||||||
));
|
));
|
||||||
|
@ -917,7 +918,7 @@ impl<W: Write + io::Seek> GenericZipWriter<W> {
|
||||||
bare,
|
bare,
|
||||||
clamp_opt(
|
clamp_opt(
|
||||||
compression_level.unwrap_or(zstd::DEFAULT_COMPRESSION_LEVEL),
|
compression_level.unwrap_or(zstd::DEFAULT_COMPRESSION_LEVEL),
|
||||||
zstd::compression_level_range().clone(),
|
zstd::compression_level_range(),
|
||||||
)
|
)
|
||||||
.ok_or(ZipError::UnsupportedArchive(
|
.ok_or(ZipError::UnsupportedArchive(
|
||||||
"Unsupported compression level",
|
"Unsupported compression level",
|
||||||
|
@ -1027,18 +1028,14 @@ fn write_local_file_header<T: Write>(writer: &mut T, file: &ZipFileData) -> ZipR
|
||||||
writer.write_u16::<LittleEndian>(file.last_modified_time.datepart())?;
|
writer.write_u16::<LittleEndian>(file.last_modified_time.datepart())?;
|
||||||
// crc-32
|
// crc-32
|
||||||
writer.write_u32::<LittleEndian>(file.crc32)?;
|
writer.write_u32::<LittleEndian>(file.crc32)?;
|
||||||
// compressed size
|
// compressed size and uncompressed size
|
||||||
writer.write_u32::<LittleEndian>(if file.compressed_size > 0xFFFFFFFF {
|
if file.large_file {
|
||||||
0xFFFFFFFF
|
writer.write_u32::<LittleEndian>(0xFFFFFFFF)?;
|
||||||
|
writer.write_u32::<LittleEndian>(0xFFFFFFFF)?;
|
||||||
} else {
|
} else {
|
||||||
file.compressed_size as u32
|
writer.write_u32::<LittleEndian>(file.compressed_size as u32)?;
|
||||||
})?;
|
writer.write_u32::<LittleEndian>(file.uncompressed_size as u32)?;
|
||||||
// uncompressed size
|
}
|
||||||
writer.write_u32::<LittleEndian>(if file.uncompressed_size > 0xFFFFFFFF {
|
|
||||||
0xFFFFFFFF
|
|
||||||
} else {
|
|
||||||
file.uncompressed_size as u32
|
|
||||||
})?;
|
|
||||||
// file name length
|
// file name length
|
||||||
writer.write_u16::<LittleEndian>(file.file_name.as_bytes().len() as u16)?;
|
writer.write_u16::<LittleEndian>(file.file_name.as_bytes().len() as u16)?;
|
||||||
// extra field length
|
// extra field length
|
||||||
|
@ -1061,27 +1058,19 @@ fn update_local_file_header<T: Write + io::Seek>(
|
||||||
const CRC32_OFFSET: u64 = 14;
|
const CRC32_OFFSET: u64 = 14;
|
||||||
writer.seek(io::SeekFrom::Start(file.header_start + CRC32_OFFSET))?;
|
writer.seek(io::SeekFrom::Start(file.header_start + CRC32_OFFSET))?;
|
||||||
writer.write_u32::<LittleEndian>(file.crc32)?;
|
writer.write_u32::<LittleEndian>(file.crc32)?;
|
||||||
writer.write_u32::<LittleEndian>(if file.compressed_size > 0xFFFFFFFF {
|
if file.large_file {
|
||||||
if file.large_file {
|
update_local_zip64_extra_field(writer, file)?;
|
||||||
0xFFFFFFFF
|
} else {
|
||||||
} else {
|
// check compressed size as well as it can also be slightly larger than uncompressed size
|
||||||
// compressed size can be slightly larger than uncompressed size
|
if file.compressed_size > 0xFFFFFFFF {
|
||||||
return Err(ZipError::Io(io::Error::new(
|
return Err(ZipError::Io(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
"Large file option has not been set",
|
"Large file option has not been set",
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
} else {
|
writer.write_u32::<LittleEndian>(file.compressed_size as u32)?;
|
||||||
file.compressed_size as u32
|
// uncompressed size is already checked on write to catch it as soon as possible
|
||||||
})?;
|
writer.write_u32::<LittleEndian>(file.uncompressed_size as u32)?;
|
||||||
writer.write_u32::<LittleEndian>(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)?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue