Skip to content

Commit 3259c5e

Browse files
Revert "remove read_zipfile_from_stream()"
This reverts commit 3abac52.
1 parent c83e9b6 commit 3259c5e

7 files changed

Lines changed: 197 additions & 71 deletions

File tree

benches/read_metadata.rs

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,7 @@ use bencher::Bencher;
77
use getrandom::getrandom;
88
use tempdir::TempDir;
99
use zip::write::SimpleFileOptions;
10-
use zip::{
11-
result::ZipResult,
12-
unstable::{
13-
read::streaming::{StreamingZipEntry, ZipStreamFileMetadata},
14-
stream::{ZipStreamReader, ZipStreamVisitor},
15-
},
16-
CompressionMethod, ZipArchive, ZipWriter,
17-
};
10+
use zip::{result::ZipResult, CompressionMethod, ZipArchive, ZipWriter};
1811

1912
const FILE_COUNT: usize = 15_000;
2013
const FILE_SIZE: usize = 1024;
@@ -113,24 +106,12 @@ fn parse_stream_archive(bench: &mut Bencher) {
113106
let out = dir.path().join("bench-out.zip");
114107
fs::write(&out, &bytes).unwrap();
115108

116-
struct V;
117-
impl ZipStreamVisitor for V {
118-
fn visit_file(&mut self, _file: &mut StreamingZipEntry<impl Read>) -> ZipResult<()> {
119-
Ok(())
120-
}
121-
122-
fn visit_additional_metadata(
123-
&mut self,
124-
_metadata: &ZipStreamFileMetadata,
125-
) -> ZipResult<()> {
126-
Ok(())
127-
}
128-
}
129-
130109
bench.iter(|| {
131-
let f = fs::File::open(&out).unwrap();
132-
let archive = ZipStreamReader::new(f);
133-
archive.visit(&mut V).unwrap();
110+
let mut f = fs::File::open(&out).unwrap();
111+
while zip::read::read_zipfile_from_stream(&mut f)
112+
.unwrap()
113+
.is_some()
114+
{}
134115
});
135116
bench.bytes = bytes.len() as u64;
136117
}

examples/stdin_info.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
use std::io::{self, Read};
22

3-
use zip::unstable::read::{streaming::StreamingArchive, ArchiveEntry};
4-
53
fn main() {
64
std::process::exit(real_main());
75
}
86

97
fn real_main() -> i32 {
108
let stdin = io::stdin();
11-
let stdin_handle = stdin.lock();
9+
let mut stdin_handle = stdin.lock();
1210
let mut buf = [0u8; 16];
1311

14-
let mut archive = StreamingArchive::new(stdin_handle);
1512
loop {
16-
match archive.next_entry() {
13+
match zip::read::read_zipfile_from_stream(&mut stdin_handle) {
1714
Ok(Some(mut file)) => {
1815
println!(
1916
"{}: {} bytes ({} bytes packed)",

fuzz/fuzz_targets/fuzz_read.rs

100755100644
Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@
33
use libfuzzer_sys::fuzz_target;
44
use std::io::{Read, Seek, SeekFrom};
55
use tikv_jemallocator::Jemalloc;
6-
use zip::unstable::{
7-
read::streaming::{StreamingArchive, StreamingZipEntry, ZipStreamFileMetadata},
8-
stream::ZipStreamVisitor,
9-
};
6+
use zip::read::read_zipfile_from_stream;
107

118
const MAX_BYTES_TO_READ: u64 = 1 << 24;
129

@@ -21,24 +18,11 @@ fn decompress_all(data: &[u8]) -> Result<(), Box<dyn std::error::Error>> {
2118
let mut file = zip.by_index(i)?.take(MAX_BYTES_TO_READ);
2219
std::io::copy(&mut file, &mut std::io::sink())?;
2320
}
24-
2521
let mut reader = zip.into_inner();
26-
reader.rewind()?;
27-
28-
struct V;
29-
impl ZipStreamVisitor for V {
30-
fn visit_file(&mut self, file: &mut StreamingZipEntry<impl Read>) -> ZipResult<()> {
31-
std::io::copy(&mut file, &mut std::io::sink())?
32-
}
33-
34-
fn visit_additional_metadata(&mut self, metadata: &ZipStreamFileMetadata) -> ZipResult<()> {
35-
Ok(())
36-
}
22+
reader.seek(SeekFrom::Start(0))?;
23+
while let Ok(Some(mut file)) = read_zipfile_from_stream(&mut reader) {
24+
std::io::copy(&mut file, &mut std::io::sink())?;
3725
}
38-
39-
let archive = StreamingArchive::new(reader)?;
40-
archive.visit(&mut V)?;
41-
4226
Ok(())
4327
}
4428

src/read.rs

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1900,6 +1900,71 @@ impl<'a> Drop for ZipFile<'a> {
19001900
}
19011901
}
19021902

1903+
/// Read ZipFile structures from a non-seekable reader.
1904+
///
1905+
/// This is an alternative method to read a zip file. If possible, use the ZipArchive functions
1906+
/// as some information will be missing when reading this manner.
1907+
///
1908+
/// Reads a file header from the start of the stream. Will return `Ok(Some(..))` if a file is
1909+
/// present at the start of the stream. Returns `Ok(None)` if the start of the central directory
1910+
/// is encountered. No more files should be read after this.
1911+
///
1912+
/// The Drop implementation of ZipFile ensures that the reader will be correctly positioned after
1913+
/// the structure is done.
1914+
///
1915+
/// Missing fields are:
1916+
/// * `comment`: set to an empty string
1917+
/// * `data_start`: set to 0
1918+
/// * `external_attributes`: `unix_mode()`: will return None
1919+
pub fn read_zipfile_from_stream<'a, R: Read>(reader: &'a mut R) -> ZipResult<Option<ZipFile<'_>>> {
1920+
// We can't use the typical ::parse() method, as we follow separate code paths depending on the
1921+
// "magic" value (since the magic value will be from the central directory header if we've
1922+
// finished iterating over all the actual files).
1923+
/* TODO: smallvec? */
1924+
let mut block = [0u8; mem::size_of::<ZipLocalEntryBlock>()];
1925+
reader.read_exact(&mut block)?;
1926+
let block: Box<[u8]> = block.into();
1927+
1928+
let signature = spec::Magic::from_first_le_bytes(&block);
1929+
1930+
match signature {
1931+
spec::Magic::LOCAL_FILE_HEADER_SIGNATURE => (),
1932+
spec::Magic::CENTRAL_DIRECTORY_HEADER_SIGNATURE => return Ok(None),
1933+
_ => return Err(ZipLocalEntryBlock::WRONG_MAGIC_ERROR),
1934+
}
1935+
1936+
let block = ZipLocalEntryBlock::interpret(&block)?;
1937+
1938+
let mut result = ZipFileData::from_local_block(block, reader)?;
1939+
1940+
match parse_extra_field(&mut result) {
1941+
Ok(..) | Err(ZipError::Io(..)) => {}
1942+
Err(e) => return Err(e),
1943+
}
1944+
1945+
let limit_reader = (reader as &'a mut dyn Read).take(result.compressed_size);
1946+
1947+
let result_crc32 = result.crc32;
1948+
let result_compression_method = result.compression_method;
1949+
let crypto_reader = make_crypto_reader(
1950+
result_compression_method,
1951+
result_crc32,
1952+
result.last_modified_time,
1953+
result.using_data_descriptor,
1954+
limit_reader,
1955+
None,
1956+
None,
1957+
#[cfg(feature = "aes-crypto")]
1958+
result.compressed_size,
1959+
)?;
1960+
1961+
Ok(Some(ZipFile {
1962+
data: Cow::Owned(result),
1963+
crypto_reader: None,
1964+
reader: make_reader(result_compression_method, result_crc32, crypto_reader)?,
1965+
}))
1966+
}
1967+
19031968
#[cfg(test)]
19041969
mod test {
19051970
use crate::result::ZipResult;
@@ -1952,13 +2017,16 @@ mod test {
19522017

19532018
#[test]
19542019
fn zip_read_streaming() {
1955-
use crate::unstable::read::streaming::StreamingArchive;
2020+
use super::read_zipfile_from_stream;
19562021

19572022
let mut v = Vec::new();
19582023
v.extend_from_slice(include_bytes!("../tests/data/mimetype.zip"));
1959-
let reader = Cursor::new(v);
1960-
let mut archive = StreamingArchive::new(reader);
1961-
while archive.next_entry().unwrap().is_some() {}
2024+
let mut reader = Cursor::new(v);
2025+
loop {
2026+
if read_zipfile_from_stream(&mut reader).unwrap().is_none() {
2027+
break;
2028+
}
2029+
}
19622030
}
19632031

19642032
#[test]

0 commit comments

Comments
 (0)