pub struct ZipLocator { /* private fields */ }Expand description
Locates the End of Central Directory (EOCD) record in a ZIP archive.
The ZipLocator is responsible for finding the EOCD record, which is
crucial for reading the contents of a ZIP file.
In the event, that the comment or tailing data contains the EOCD signature,
causing the zip locator to fail to parse. One can reparse the data starting
from the false EOCD offset using the reported offset
Error::eocd_offset()
Implementations§
Source§impl ZipLocator
impl ZipLocator
Sourcepub fn max_search_space(self, max_search_space: u64) -> Self
pub fn max_search_space(self, max_search_space: u64) -> Self
Sets the maximum number of bytes to search for the EOCD signature.
The search is performed backwards from the end of the data source.
use rawzip::ZipLocator;
let locator = ZipLocator::new().max_search_space(1024 * 64); // 64 KiBSourcepub fn locate_in_slice<T: AsRef<[u8]>>(
&self,
data: T,
) -> Result<ZipSliceArchive<T>, (T, Error)>
pub fn locate_in_slice<T: AsRef<[u8]>>( &self, data: T, ) -> Result<ZipSliceArchive<T>, (T, Error)>
Locates the EOCD record within a byte slice.
On success, returns a ZipSliceArchive which allows reading the archive
directly from the slice. On failure, returns the original slice and an Error.
§Examples
use rawzip::ZipLocator;
use std::fs;
use std::io::Read;
let mut file = fs::File::open("assets/readme.zip")?;
let mut data = Vec::new();
file.read_to_end(&mut data)?;
let locator = ZipLocator::new();
match locator.locate_in_slice(&data) {
Ok(archive) => {
println!("Found EOCD in slice, archive has {} files.", archive.entries_hint());
}
Err((_data, e)) => {
eprintln!("Failed to locate EOCD in slice: {:?}", e);
}
}Sourcepub fn locate_in_file(
&self,
file: File,
buffer: &mut [u8],
) -> Result<ZipArchive<FileReader>, (File, Error)>
pub fn locate_in_file( &self, file: File, buffer: &mut [u8], ) -> Result<ZipArchive<FileReader>, (File, Error)>
Locates the EOCD record within a file.
A mutable byte slice to use for reading data from the file. The buffer should be large enough to hold the EOCD record and potentially parts of the ZIP64 EOCD locator if present. A common size might be a few kilobytes.
On failure, returns the original file and an Error.
§Examples
use rawzip::ZipLocator;
use std::fs::File;
let file = File::open("assets/readme.zip")?;
let mut buffer = vec![0; rawzip::RECOMMENDED_BUFFER_SIZE];
let locator = ZipLocator::new();
match locator.locate_in_file(file, &mut buffer) {
Ok(archive) => {
println!("Found EOCD in file, archive has {} files.", archive.entries_hint());
}
Err((_file, e)) => {
eprintln!("Failed to locate EOCD in file: {:?}", e);
}
}Sourcepub fn locate_in_reader<R>(
&self,
reader: R,
buffer: &mut [u8],
end_offset: u64,
) -> Result<ZipArchive<R>, (R, Error)>where
R: ReaderAt,
pub fn locate_in_reader<R>(
&self,
reader: R,
buffer: &mut [u8],
end_offset: u64,
) -> Result<ZipArchive<R>, (R, Error)>where
R: ReaderAt,
Locates the EOCD record in a reader, treating the specified end offset as the starting point when searching backwards.
This method is useful for several scenarios:
- Zip archive is nowhere near the end of the reader
- Zip archives are concatenated
For seekable readers, you can determine the end_offset by seeking to the end of the stream.
Note that the zip locator may request data passed the end offset in order to read the entire end of the central directory record + comment.
§Examples
use rawzip::{ZipLocator, FileReader};
use std::fs::File;
use std::io::Seek;
let file = File::open("assets/test.zip").unwrap();
let mut reader = FileReader::from(file);
let mut buffer = vec![0; rawzip::RECOMMENDED_BUFFER_SIZE];
let locator = ZipLocator::new();
// An example of determining the end offset when you don't
// the length but have a seekable reader.
let end_offset = reader.seek(std::io::SeekFrom::End(0)).unwrap();
let archive = locator.locate_in_reader(reader, &mut buffer, end_offset)
.map_err(|(_, e)| e)?;
// Maybe there is another zip archive to be found.
// To find where the current archive starts, we need the minimum local header
// offset. Below we are being conservative and iterating through the entire central
// directory for the start offset, but in reality out of order central directories
// are an edge case.
let zip_start = {
let mut min_offset = u64::MAX;
let mut entries = archive.entries(&mut buffer);
while let Ok(Some(entry)) = entries.next_entry() {
min_offset = min_offset.min(entry.local_header_offset());
}
if min_offset == u64::MAX { 0 } else { min_offset }
};
match locator.locate_in_reader(archive.get_ref(), &mut buffer, zip_start) {
Ok(previous_archive) => {
println!("Found previous ZIP archive!");
}
Err((_, _)) => println!("No previous ZIP archive found"),
}