Skip to content

Commit 5fe2ea4

Browse files
committed
Fix merge
1 parent 0ab2c55 commit 5fe2ea4

File tree

2 files changed

+57
-50
lines changed

2 files changed

+57
-50
lines changed

src/read.rs

Lines changed: 42 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ use crate::extra_fields::{ExtendedTimestamp, ExtraField, Ntfs};
99
use crate::read::zip_archive::{Shared, SharedBuilder};
1010
use crate::result::invalid;
1111
use crate::result::{ZipError, ZipResult};
12-
use crate::spec::{self, DataAndPosition,
13-
FixedSizeBlock, Magic, Zip32CentralDirectoryEnd};
12+
use crate::spec::{self, CentralDirectoryEndInfo, DataAndPosition, FixedSizeBlock, Magic, Pod};
1413
use crate::types::{
1514
AesMode, AesVendorVersion, DateTime, System, ZipCentralEntryBlock, ZipDataDescriptor,
1615
ZipFileData, ZipLocalEntryBlock, ZipLocalEntryBlockAndFields,
@@ -1909,6 +1908,34 @@ impl<R: Read> Drop for ZipFile<'_, R> {
19091908
}
19101909
}
19111910

1911+
/// Read ZipFile structures from a non-seekable reader.
1912+
///
1913+
/// This is an alternative method to read a zip file. If possible, use the ZipArchive functions
1914+
/// as some information will be missing when reading this manner.
1915+
///
1916+
/// Reads a file header from the start of the stream. Will return `Ok(Some(..))` if a file is
1917+
/// present at the start of the stream. Returns `Ok(None)` if the start of the central directory
1918+
/// is encountered. No more files should be read after this.
1919+
///
1920+
/// The Drop implementation of ZipFile ensures that the reader will be correctly positioned after
1921+
/// the structure is done.
1922+
///
1923+
/// Missing fields are:
1924+
/// * `comment`: set to an empty string
1925+
/// * `data_start`: set to 0
1926+
/// * `external_attributes`: `unix_mode()`: will return None
1927+
pub fn read_zipfile_from_stream<R: Read>(reader: &mut R) -> ZipResult<Option<ZipFile<'_, R>>> {
1928+
let block = read_local_fileblock(reader)?;
1929+
let block = match block {
1930+
Some(block) => block,
1931+
None => return Ok(None),
1932+
};
1933+
1934+
// we can't look for a data descriptor since we can't seek back
1935+
// TODO: provide a method that buffers the read data and allows seeking back
1936+
read_zipfile_from_fileblock(block, reader, None)
1937+
}
1938+
19121939
/// A filter that determines whether an entry should be ignored when searching
19131940
/// for the root directory of a Zip archive.
19141941
///
@@ -1950,11 +1977,11 @@ pub fn root_dir_common_filter(path: &Path) -> bool {
19501977

19511978
if path.components().count() == 1
19521979
&& path.file_name().is_some_and(|file_name| {
1953-
COMMON_FILTER_ROOT_FILES
1954-
.iter()
1955-
.map(OsStr::new)
1956-
.any(|cmp| cmp == file_name)
1957-
})
1980+
COMMON_FILTER_ROOT_FILES
1981+
.iter()
1982+
.map(OsStr::new)
1983+
.any(|cmp| cmp == file_name)
1984+
})
19581985
{
19591986
return false;
19601987
}
@@ -1994,12 +2021,12 @@ fn read_local_fileblock<R: Read>(reader: &mut R) -> ZipResult<Option<ZipLocalEnt
19942021
}))
19952022
}
19962023

1997-
fn read_zipfile_from_fileblock<'a, R: Read>(
2024+
fn read_zipfile_from_fileblock<R: Read>(
19982025
block: ZipLocalEntryBlockAndFields,
1999-
reader: &'a mut R,
2026+
reader: &mut R,
20002027
data_descriptor: Option<ZipDataDescriptor>,
2001-
) -> ZipResult<Option<ZipFile<'_>>> {
2002-
let mut result = ZipFileData::from_local_block(block, data_descriptor)?;
2028+
) -> ZipResult<Option<ZipFile<R>>> {
2029+
let mut result = ZipFileData::from_local_block(block, data_descriptor, reader)?;
20032030

20042031
match crate::read::parse_extra_field(&mut result) {
20052032
Ok(..) | Err(ZipError::Io(..)) => {}
@@ -2029,37 +2056,6 @@ fn read_zipfile_from_fileblock<'a, R: Read>(
20292056
}))
20302057
}
20312058

2032-
/// Read ZipFile structures from a non-seekable reader.
2033-
///
2034-
/// This is an alternative method to read a zip file. If possible, use the ZipArchive functions
2035-
/// as some information will be missing when reading this manner.
2036-
///
2037-
/// Reads a file header from the start of the stream. Will return `Ok(Some(..))` if a file is
2038-
/// present at the start of the stream. Returns `Ok(None)` if the start of the central directory
2039-
/// is encountered. No more files should be read after this.
2040-
///
2041-
/// The Drop implementation of ZipFile ensures that the reader will be correctly positioned after
2042-
/// the structure is done.
2043-
///
2044-
/// This method will not find a ZipFile entry if the zip file uses data descriptors.
2045-
/// In that case you could use [read_zipfile_from_seekable_stream]
2046-
///
2047-
/// Missing fields are:
2048-
/// * `comment`: set to an empty string
2049-
/// * `data_start`: set to 0
2050-
/// * `external_attributes`: `unix_mode()`: will return None
2051-
pub fn read_zipfile_from_stream<'a, R: Read>(reader: &'a mut R) -> ZipResult<Option<ZipFile<'_>>> {
2052-
let block = read_local_fileblock(reader)?;
2053-
let block = match block {
2054-
Some(block) => block,
2055-
None => return Ok(None),
2056-
};
2057-
2058-
// we can't look for a data descriptor since we can't seek back
2059-
// TODO: provide a method that buffers the read data and allows seeking back
2060-
read_zipfile_from_fileblock(block, reader, None)
2061-
}
2062-
20632059
/// Read ZipFile structures from a seekable reader.
20642060
///
20652061
/// This is an alternative method to read a zip file. If possible, use the ZipArchive functions
@@ -2095,7 +2091,7 @@ pub fn read_zipfile_from_stream<'a, R: Read>(reader: &'a mut R) -> ZipResult<Opt
20952091
/// * `external_attributes`: `unix_mode()`: will return None
20962092
pub fn read_zipfile_from_seekablestream<S: Read + Seek>(
20972093
reader: &mut S,
2098-
) -> ZipResult<Option<ZipFile>> {
2094+
) -> ZipResult<Option<ZipFile<S>>> {
20992095
let local_entry_block = read_local_fileblock(reader)?;
21002096
let local_entry_block = match local_entry_block {
21012097
Some(local_entry_block) => local_entry_block,
@@ -2134,15 +2130,14 @@ pub fn read_zipfile_from_seekablestream<S: Read + Seek>(
21342130
reader.seek(SeekFrom::Current(-4))?; // go back to the start of the data descriptor
21352131
read_count_total -= 4;
21362132

2137-
let mut data_descriptor_block = [0u8; mem::size_of::<ZipDataDescriptor>()];
2138-
reader.read_exact(&mut data_descriptor_block)?;
2139-
let data_descriptor_block: Box<[u8]> = data_descriptor_block.into();
2133+
let mut data_descriptor = ZipDataDescriptor::zeroed();
2134+
reader.read_exact(data_descriptor.as_bytes_mut())?;
21402135
// seek back to data end
21412136
reader.seek(SeekFrom::Current(
21422137
-(mem::size_of::<ZipDataDescriptor>() as i64),
21432138
))?;
21442139

2145-
let data_descriptor = ZipDataDescriptor::interpret(&data_descriptor_block)?;
2140+
let data_descriptor = ZipDataDescriptor::from_le(data_descriptor);
21462141

21472142
// check if the data descriptor is indeed valid for the read data
21482143
if data_descriptor.compressed_size == read_count_total as u32 {

src/types.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use crate::cp437::FromCp437;
33
use crate::write::{FileOptionExtension, FileOptions};
44
use path::{Component, Path, PathBuf};
5+
use std::borrow::Cow;
56
use std::cmp::Ordering;
67
use std::ffi::OsStr;
78
use std::fmt;
@@ -757,9 +758,10 @@ impl ZipFileData {
757758
local_block
758759
}
759760

760-
pub(crate) fn from_local_block(
761+
pub(crate) fn from_local_block<R: std::io::Read>(
761762
block: ZipLocalEntryBlockAndFields,
762763
data_descriptor: Option<ZipDataDescriptor>,
764+
reader: &mut R,
763765
) -> ZipResult<Self> {
764766
let ZipLocalEntryBlock {
765767
// magic,
@@ -771,6 +773,8 @@ impl ZipFileData {
771773
mut crc32,
772774
mut compressed_size,
773775
mut uncompressed_size,
776+
file_name_length,
777+
extra_field_length,
774778
..
775779
} = block.block;
776780

@@ -802,6 +806,13 @@ impl ZipFileData {
802806
/* flags & (1 << 1) != 0 */
803807
let is_utf8: bool = flags & (1 << 11) != 0;
804808
let compression_method = crate::CompressionMethod::parse_from_u16(compression_method);
809+
let file_name_length: usize = file_name_length.into();
810+
let extra_field_length: usize = extra_field_length.into();
811+
812+
let mut file_name_raw = vec![0u8; file_name_length];
813+
reader.read_exact(&mut file_name_raw)?;
814+
let mut extra_field = vec![0u8; extra_field_length];
815+
reader.read_exact(&mut extra_field)?;
805816

806817
let file_name: Box<str> = match is_utf8 {
807818
true => String::from_utf8_lossy(&block.file_name_raw).into(),
@@ -1085,13 +1096,14 @@ impl FixedSizeBlock for ZipLocalEntryBlock {
10851096
}
10861097

10871098
#[derive(Copy, Clone, Debug)]
1088-
#[repr(packed)]
1099+
#[repr(packed, C)]
10891100
pub(crate) struct ZipDataDescriptor {
10901101
magic: spec::Magic,
10911102
pub crc32: u32,
10921103
pub compressed_size: u32,
10931104
pub uncompressed_size: u32,
10941105
}
1106+
unsafe impl Pod for ZipDataDescriptor {}
10951107

10961108
impl FixedSizeBlock for crate::types::ZipDataDescriptor {
10971109
const MAGIC: spec::Magic = spec::Magic::DATA_DESCRIPTOR_SIGNATURE;
@@ -1101,7 +1113,7 @@ impl FixedSizeBlock for crate::types::ZipDataDescriptor {
11011113
self.magic
11021114
}
11031115

1104-
const WRONG_MAGIC_ERROR: ZipError = ZipError::InvalidArchive("Invalid data descriptor");
1116+
const WRONG_MAGIC_ERROR: ZipError = ZipError::InvalidArchive(Cow::Borrowed("Invalid data descriptor"));
11051117

11061118
to_and_from_le![
11071119
(magic, spec::Magic),

0 commit comments

Comments
 (0)