diff --git a/src/lib.rs b/src/lib.rs index a5f6b2bf5..130333084 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,6 +32,7 @@ pub use crate::compression::{CompressionMethod, SUPPORTED_COMPRESSION_METHODS}; pub use crate::read::HasZipMetadata; pub use crate::read::ZipArchive; +pub use crate::spec::{ZIP64_BYTES_THR, ZIP64_ENTRY_THR}; pub use crate::types::{AesMode, DateTime}; pub use crate::write::ZipWriter; diff --git a/src/spec.rs b/src/spec.rs old mode 100644 new mode 100755 index 80cbdee0e..a75c4481e --- a/src/spec.rs +++ b/src/spec.rs @@ -87,8 +87,56 @@ impl ExtraFieldMagic { pub const ZIP64_EXTRA_FIELD_TAG: Self = Self::literal(0x0001); } -/// This should be equal to `0xFFFFFFFF`. +/// The file size at which a ZIP64 record becomes necessary. +/// +/// If a file larger than this threshold attempts to be written, compressed or uncompressed, and +/// [`FileOptions::large_file()`](crate::write::FileOptions) was not true, then [`ZipWriter`] will +/// raise an [`io::Error`] with [`io::ErrorKind::Other`]. +/// +/// If the zip file itself is larger than this value, then a zip64 central directory record will be +/// written to the end of the file. +/// +///``` +/// # fn main() -> Result<(), zip::result::ZipError> { +/// use std::io::{self, Cursor, prelude::*}; +/// use std::error::Error; +/// use zip::{ZipWriter, write::SimpleFileOptions}; +/// +/// let mut zip = ZipWriter::new(Cursor::new(Vec::new())); +/// // Writing an extremely large file for this test is faster without compression. +/// let options = SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored); +/// +/// let big_len: usize = (zip::ZIP64_BYTES_THR as usize) + 1; +/// let big_buf = vec![0u8; big_len]; +/// zip.start_file("zero.dat", options)?; +/// // This is too big! +/// let res = zip.write_all(&big_buf[..]).err().unwrap(); +/// assert_eq!(res.kind(), io::ErrorKind::Other); +/// let description = format!("{}", &res); +/// assert_eq!(description, "Large file option has not been set"); +/// // Attempting to write anything further to the same zip will still succeed, but the previous +/// // failing entry has been removed. +/// zip.start_file("one.dat", options)?; +/// let zip = zip.finish_into_readable()?; +/// let names: Vec<_> = zip.file_names().collect(); +/// assert_eq!(&names, &["one.dat"]); +/// +/// // Create a new zip output. +/// let mut zip = ZipWriter::new(Cursor::new(Vec::new())); +/// // This time, create a zip64 record for the file. +/// let options = options.large_file(true); +/// zip.start_file("zero.dat", options)?; +/// // This succeeds because we specified that it could be a large file. +/// assert!(zip.write_all(&big_buf[..]).is_ok()); +/// # Ok(()) +/// # } +///``` pub const ZIP64_BYTES_THR: u64 = u32::MAX as u64; +/// The number of entries within a single zip necessary to allocate a zip64 central +/// directory record. +/// +/// If more than this number of entries is written to a [`ZipWriter`], then [`ZipWriter::finish()`] +/// will write out extra zip64 data to the end of the zip file. pub const ZIP64_ENTRY_THR: usize = u16::MAX as usize; /// # Safety