From 2f0f96ce4625d2ef1273c7bea98a1e9415419fdf Mon Sep 17 00:00:00 2001 From: Igor Tolmachev Date: Tue, 16 Jul 2024 21:15:38 +0900 Subject: Add BufReader for CD records parser --- src/zip/driver.rs | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'src/zip') diff --git a/src/zip/driver.rs b/src/zip/driver.rs index 631c4ed..e7878cf 100644 --- a/src/zip/driver.rs +++ b/src/zip/driver.rs @@ -9,7 +9,7 @@ use crate::zip::{ use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime}; use std::collections::HashMap as Map; use std::fs::File; -use std::io::{Read, Seek, SeekFrom, Write}; +use std::io::{BufReader, Read, Seek, SeekFrom, Write}; fn dos_to_local(date: u16, time: u16) -> ZipResult> { Ok(NaiveDateTime::new( @@ -111,33 +111,32 @@ impl ArchiveRead for Zip { let mut indexes = Map::with_capacity(cd_records as usize); let mut files = Vec::with_capacity(cd_records as usize); io.seek(SeekFrom::Start(cd_pointer))?; - let buf = io.read_vec(cd_size as usize)?; + let mut buf_reader = BufReader::with_capacity(cd_size.min(131072) as usize, &mut io); - let mut p: usize = 0; for i in 0..cd_records as usize { - if u32::from_le_bytes(buf[p..p + 4].try_into().unwrap()) != 0x02014b50 { + let buf = buf_reader.read_arr::<46>()?; + + if u32::from_le_bytes(buf[..4].try_into().unwrap()) != 0x02014b50 { return Err(ZipError::InvalidCDRSignature.into()); } - p += 4; - let cdr: Cdr = deserialize(&buf[p..p + 42]).unwrap(); + let cdr: Cdr = deserialize(&buf[4..46]).unwrap(); let bit_flag = BitFlag::new(cdr.bit_flag); - p += 42; + + let name = buf_reader.read_vec(cdr.name_len as usize)?; let name = if bit_flag.is_utf8() { - String::from_utf8(buf[p..p + cdr.name_len as usize].to_vec()) - .map_err(|_| ZipError::InvalidFileName)? + String::from_utf8(name).map_err(|_| ZipError::InvalidFileName)? } else { - String::from_cp437(&buf[p..p + cdr.name_len as usize]) + String::from_cp437(name) }; - p += cdr.name_len as usize; - let extra_fields: Vec = buf[p..p + cdr.extra_field_len as usize].into(); - p += cdr.extra_field_len as usize; + + let extra_fields = buf_reader.read_vec(cdr.extra_field_len as usize)?; + + let comment = buf_reader.read_vec(cdr.comment_len as usize)?; let comment = if bit_flag.is_utf8() { - String::from_utf8(buf[p..p + cdr.comment_len as usize].to_vec()) - .map_err(|_| ZipError::InvalidFileComment)? + String::from_utf8(comment).map_err(|_| ZipError::InvalidFileComment)? } else { - String::from_cp437(&buf[p..p + cdr.comment_len as usize]) + String::from_cp437(comment) }; - p += cdr.comment_len as usize; let mut compressed_size = cdr.compressed_size as u64; let mut size = cdr.size as u64; @@ -152,6 +151,7 @@ impl ArchiveRead for Zip { while ep < cdr.extra_field_len as usize { let header: ExtraHeader = deserialize(&extra_fields[ep..ep + 4]).unwrap(); ep += 4; + match header.id { // Zip64 0x0001 => { @@ -182,6 +182,7 @@ impl ArchiveRead for Zip { let header: ExtraHeader = deserialize(&extra_fields[tp..tp + 4]).unwrap(); tp += 4; + match header.id { 0x0001 => { mtime = ntfs_to_local(u64::from_le_bytes( -- cgit v1.2.3