1use crate::{archive::*, decoders::add_decoder, error::Error, folder::*, password::Password};
2use bit_set::BitSet;
3use crc32fast::Hasher;
4use std::collections::HashMap;
5use std::{
6 fs::File,
7 io::{ErrorKind, Read, Seek, SeekFrom},
8};
9
10const MAX_MEM_LIMIT_KB: usize = usize::MAX / 1024;
11
12pub struct BoundedReader<R: Read> {
13 inner: R,
14 remain: usize,
15}
16
17impl<R: Read> BoundedReader<R> {
18 pub fn new(inner: R, max_size: usize) -> Self {
19 Self {
20 inner,
21 remain: max_size,
22 }
23 }
24}
25
26impl<R: Read> Read for BoundedReader<R> {
27 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
28 if self.remain == 0 {
29 return Ok(0);
30 }
31 let remain = self.remain;
32 let buf2 = if buf.len() < remain {
33 buf
34 } else {
35 &mut buf[..remain]
36 };
37 match self.inner.read(buf2) {
38 Ok(size) => {
39 if self.remain < size {
40 self.remain = 0;
41 } else {
42 self.remain -= size;
43 }
44 Ok(size)
45 }
46 Err(e) => Err(e),
47 }
48 }
49}
50
51#[derive(Debug, Default, Clone)]
52pub struct SeekableBoundedReader<R: Read + Seek> {
53 inner: R,
54 cur: u64,
55 bounds: (u64, u64),
56}
57
58impl<R: Read + Seek> Seek for SeekableBoundedReader<R> {
59 fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
60 let new_pos = match pos {
61 SeekFrom::Start(pos) => self.bounds.0 as i64 + pos as i64,
62 SeekFrom::End(pos) => self.bounds.1 as i64 + pos,
63 SeekFrom::Current(pos) => self.cur as i64 + pos,
64 };
65 if new_pos < 0 {
66 return Err(std::io::Error::new(ErrorKind::Other, "SeekBeforeStart"));
67 }
68 self.cur = new_pos as u64;
69 self.inner.seek(SeekFrom::Start(self.cur))
70 }
71}
72
73impl<R: Read + Seek> Read for SeekableBoundedReader<R> {
74 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
75 if self.cur >= self.bounds.1 {
76 return Ok(0);
77 }
78 if self.stream_position()? != self.cur {
79 self.inner.seek(SeekFrom::Start(self.cur))?;
80 }
81 let buf2 = if buf.len() < (self.bounds.1 - self.cur) as usize {
82 buf
83 } else {
84 &mut buf[..(self.bounds.1 - self.cur) as usize]
85 };
86 let size = self.inner.read(buf2)?;
87 self.cur += size as u64;
88 Ok(size)
89 }
90}
91
92impl<R: Read + Seek> SeekableBoundedReader<R> {
93 pub fn new(inner: R, bounds: (u64, u64)) -> Self {
94 Self {
95 inner,
96 cur: bounds.0,
97 bounds,
98 }
99 }
100}
101
102struct Crc32VerifyingReader<R> {
103 inner: R,
104 crc_digest: Hasher,
105 expected_value: u64,
106 remaining: i64,
107}
108
109impl<R: Read> Crc32VerifyingReader<R> {
110 fn new(inner: R, remaining: usize, expected_value: u64) -> Self {
111 Self {
112 inner,
113 crc_digest: Hasher::new(),
114 expected_value,
115 remaining: remaining as i64,
116 }
117 }
118}
119
120impl<R: Read> Read for Crc32VerifyingReader<R> {
121 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
122 if self.remaining <= 0 {
123 return Ok(0);
124 }
125 let size = self.inner.read(buf)?;
126 if size > 0 {
127 self.remaining -= size as i64;
128 self.crc_digest.update(&buf[..size]);
129 }
130 if self.remaining <= 0 {
131 let d = std::mem::replace(&mut self.crc_digest, Hasher::new()).finalize();
132 if d as u64 != self.expected_value {
133 return Err(std::io::Error::new(
134 ErrorKind::Other,
135 Error::ChecksumVerificationFailed,
136 ));
137 }
138 }
139 Ok(size)
140 }
141}
142
143impl Archive {
144 #[inline]
146 pub fn open(path: impl AsRef<std::path::Path>) -> Result<Archive, Error> {
147 Self::open_with_password(path, &Password::empty())
148 }
149
150 #[inline]
152 pub fn open_with_password(
153 path: impl AsRef<std::path::Path>,
154 password: &Password,
155 ) -> Result<Archive, Error> {
156 let mut file = File::open(path)?;
157 let len = file.metadata()?.len();
158 Self::read(&mut file, len, password.as_ref())
159 }
160 pub fn read<R: Read + Seek>(
181 reader: &mut R,
182 reader_len: u64,
183 password: &[u8],
184 ) -> Result<Archive, Error> {
185 let mut signature = [0; 6];
186 reader.read_exact(&mut signature).map_err(Error::io)?;
187 if signature != SEVEN_Z_SIGNATURE {
188 return Err(Error::BadSignature(signature));
189 }
190 let mut versions = [0; 2];
191 reader.read_exact(&mut versions).map_err(Error::io)?;
192 let version_major = versions[0];
193 let version_minor = versions[1];
194 if version_major != 0 {
195 return Err(Error::UnsupportedVersion {
196 major: version_major,
197 minor: version_minor,
198 });
199 }
200
201 let start_header_crc = read_u32(reader)?;
202
203 let header_valid = if start_header_crc == 0 {
204 let current_position = reader.stream_position().map_err(Error::io)?;
205 let mut buf = [0; 20];
206 reader.read_exact(&mut buf).map_err(Error::io)?;
207 reader
208 .seek(SeekFrom::Start(current_position))
209 .map_err(Error::io)?;
210 buf.iter().any(|a| *a != 0)
211 } else {
212 true
213 };
214 if header_valid {
215 let start_header = Self::read_start_header(reader, start_header_crc)?;
216 Self::init_archive(reader, start_header, password, true)
217 } else {
218 Self::try_to_locale_end_header(reader, reader_len, password)
219 }
220 }
221
222 fn read_start_header<R: Read>(
223 reader: &mut R,
224 start_header_crc: u32,
225 ) -> Result<StartHeader, Error> {
226 let mut buf = [0; 20];
227 reader.read_exact(&mut buf).map_err(Error::io)?;
228 let crc32 = crc32fast::hash(&buf);
229 if crc32 != start_header_crc {
230 return Err(Error::ChecksumVerificationFailed);
231 }
232 let mut buf_read = buf.as_slice();
233 let offset = read_u64le(&mut buf_read)?;
234
235 let size = read_u64le(&mut buf_read)?;
236 let crc = read_u32(&mut buf_read)?;
237 Ok(StartHeader {
238 next_header_offset: offset,
239 next_header_size: size,
240 next_header_crc: crc as u64,
241 })
242 }
243
244 fn read_header<R: Read + Seek>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
245 let mut nid = read_u8(header)?;
246 if nid == K_ARCHIVE_PROPERTIES {
247 Self::read_archive_properties(header)?;
248 nid = read_u8(header)?;
249 }
250
251 if nid == K_ADDITIONAL_STREAMS_INFO {
252 return Err(Error::other("Additional streams unsupported"));
253 }
254 if nid == K_MAIN_STREAMS_INFO {
255 Self::read_streams_info(header, archive)?;
256 nid = read_u8(header)?;
257 }
258 if nid == K_FILES_INFO {
259 Self::read_files_info(header, archive)?;
260 nid = read_u8(header)?;
261 }
262 if nid != K_END {
263 return Err(Error::BadTerminatedheader(nid));
264 }
265
266 Ok(())
267 }
268
269 fn read_archive_properties<R: Read + Seek>(header: &mut R) -> Result<(), Error> {
270 let mut nid = read_u8(header)?;
271 while nid != K_END {
272 let property_size = read_usize(header, "propertySize")?;
273 header
274 .seek(SeekFrom::Current(property_size as i64))
275 .map_err(Error::io)?;
276 nid = read_u8(header)?;
277 }
278 Ok(())
279 }
280
281 fn try_to_locale_end_header<R: Read + Seek>(
282 reader: &mut R,
283 reader_len: u64,
284 password: &[u8],
285 ) -> Result<Self, Error> {
286 let search_limit = 1024 * 1024;
287 let prev_data_size = reader.stream_position().map_err(Error::io)? + 20;
288 let size = reader_len;
289 let min_pos = if reader.stream_position().map_err(Error::io)? + search_limit > size {
290 reader.stream_position().map_err(Error::io)?
291 } else {
292 size - search_limit
293 };
294 let mut pos = reader_len - 1;
295 while pos > min_pos {
296 pos -= 1;
297
298 reader.seek(SeekFrom::Start(pos)).map_err(Error::io)?;
299 let nid = read_u8(reader)?;
300 if nid == K_ENCODED_HEADER || nid == K_HEADER {
301 let start_header = StartHeader {
302 next_header_offset: pos - prev_data_size,
303 next_header_size: reader_len - pos,
304 next_header_crc: 0,
305 };
306 let result = Self::init_archive(reader, start_header, password, false)?;
307
308 if !result.files.is_empty() {
309 return Ok(result);
310 }
311 }
312 }
313 Err(Error::other(
314 "Start header corrupt and unable to guess end header",
315 ))
316 }
317
318 fn init_archive<R: Read + Seek>(
319 reader: &mut R,
320 start_header: StartHeader,
321 password: &[u8],
322 verify_crc: bool,
323 ) -> Result<Self, Error> {
324 if start_header.next_header_size > usize::MAX as u64 {
325 return Err(Error::other(format!(
326 "Cannot handle next_header_size {}",
327 start_header.next_header_size
328 )));
329 }
330
331 let next_header_size_int = start_header.next_header_size as usize;
332
333 reader
334 .seek(SeekFrom::Start(
335 SIGNATURE_HEADER_SIZE + start_header.next_header_offset,
336 ))
337 .map_err(Error::io)?;
338
339 let mut buf = vec![0; next_header_size_int];
340 reader.read_exact(&mut buf).map_err(Error::io)?;
341 if verify_crc && crc32fast::hash(&buf) as u64 != start_header.next_header_crc {
342 return Err(Error::NextHeaderCrcMismatch);
343 }
344
345 let mut archive = Archive::default();
346 let mut buf_reader = buf.as_slice();
347 let mut nid = read_u8(&mut buf_reader)?;
348 let mut header = if nid == K_ENCODED_HEADER {
349 let (mut out_reader, buf_size) =
350 Self::read_encoded_header(&mut buf_reader, reader, &mut archive, password)?;
351 buf.clear();
352 buf.resize(buf_size, 0);
353 out_reader
354 .read_exact(&mut buf)
355 .map_err(|e| Error::bad_password(e, !password.is_empty()))?;
356 archive = Archive::default();
357 buf_reader = buf.as_slice();
358 nid = read_u8(&mut buf_reader)?;
359 buf_reader
360 } else {
361 buf_reader
362 };
363 let mut header = std::io::Cursor::new(&mut header);
364 if nid == K_HEADER {
365 Self::read_header(&mut header, &mut archive)?;
366 } else {
367 return Err(Error::other("Broken or unsupported archive: no Header"));
368 }
369
370 archive.is_solid = archive
371 .folders
372 .iter()
373 .any(|folder| folder.num_unpack_sub_streams > 1);
374
375 Ok(archive)
376 }
377
378 fn read_encoded_header<'r, R: Read, RI: 'r + Read + Seek>(
379 header: &mut R,
380 reader: &'r mut RI,
381 archive: &mut Archive,
382 password: &[u8],
383 ) -> Result<(Box<dyn Read + 'r>, usize), Error> {
384 Self::read_streams_info(header, archive)?;
385 let folder = archive
386 .folders
387 .first()
388 .ok_or(Error::other("no folders, can't read encoded header"))?;
389 let first_pack_stream_index = 0;
390 let folder_offset = SIGNATURE_HEADER_SIZE + archive.pack_pos;
391 if archive.pack_sizes.is_empty() {
392 return Err(Error::other("no packed streams, can't read encoded header"));
393 }
394
395 reader
396 .seek(SeekFrom::Start(folder_offset))
397 .map_err(Error::io)?;
398 let coder_len = folder.coders.len();
399 let unpack_size = folder.get_unpack_size() as usize;
400 let pack_size = archive.pack_sizes[first_pack_stream_index] as usize;
401 let input_reader =
402 SeekableBoundedReader::new(reader, (folder_offset, folder_offset + pack_size as u64));
403 let mut decoder: Box<dyn Read> = Box::new(input_reader);
404 let mut decoder = if coder_len > 0 {
405 for (index, coder) in folder.ordered_coder_iter() {
406 if coder.num_in_streams != 1 || coder.num_out_streams != 1 {
407 return Err(Error::other(
408 "Multi input/output stream coders are not yet supported",
409 ));
410 }
411 let next = add_decoder(
412 decoder,
413 folder.get_unpack_size_at_index(index) as usize,
414 coder,
415 password,
416 MAX_MEM_LIMIT_KB,
417 )?;
418 decoder = Box::new(next);
419 }
420 decoder
421 } else {
422 decoder
423 };
424 if folder.has_crc {
425 decoder = Box::new(Crc32VerifyingReader::new(decoder, unpack_size, folder.crc));
426 }
427
428 Ok((decoder, unpack_size))
429 }
430
431 fn read_streams_info<R: Read>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
432 let mut nid = read_u8(header)?;
433 if nid == K_PACK_INFO {
434 Self::read_pack_info(header, archive)?;
435 nid = read_u8(header)?;
436 }
437
438 if nid == K_UNPACK_INFO {
439 Self::read_unpack_info(header, archive)?;
440 nid = read_u8(header)?;
441 } else {
442 archive.folders.clear();
443 }
444 if nid == K_SUB_STREAMS_INFO {
445 Self::read_sub_streams_info(header, archive)?;
446 nid = read_u8(header)?;
447 }
448 if nid != K_END {
449 return Err(Error::BadTerminatedStreamsInfo(nid));
450 }
451
452 Ok(())
453 }
454
455 fn read_files_info<R: Read + Seek>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
456 let num_files = read_usize(header, "num files")?;
457 let mut files: Vec<SevenZArchiveEntry> = vec![Default::default(); num_files];
458
459 let mut is_empty_stream: Option<BitSet> = None;
460 let mut is_empty_file: Option<BitSet> = None;
461 let mut is_anti: Option<BitSet> = None;
462 loop {
463 let prop_type = read_u8(header)?;
464 if prop_type == 0 {
465 break;
466 }
467 let size = read_u64(header)?;
468 match prop_type {
469 K_EMPTY_STREAM => {
470 is_empty_stream = Some(read_bits(header, num_files)?);
471 }
472 K_EMPTY_FILE => {
473 let n = if let Some(s) = &is_empty_stream {
474 s.len()
475 } else {
476 return Err(Error::other(
477 "Header format error: kEmptyStream must appear before kEmptyFile",
478 ));
479 };
480 is_empty_file = Some(read_bits(header, n)?);
481 }
482 K_ANTI => {
483 let n = if let Some(s) = is_empty_stream.as_ref() {
484 s.len()
485 } else {
486 return Err(Error::other(
487 "Header format error: kEmptyStream must appear before kEmptyFile",
488 ));
489 };
490 is_anti = Some(read_bits(header, n)?);
491 }
492 K_NAME => {
493 let external = read_u8(header)?;
494 if external != 0 {
495 return Err(Error::other("Not implemented:external != 0"));
496 }
497 if (size - 1) & 1 != 0 {
498 return Err(Error::other("file names length invalid"));
499 }
500
501 let size = assert_usize(size, "file names length")?;
502 let names_reader = NamesReader::new(header, size - 1);
505
506 let mut next_file = 0;
507 for s in names_reader {
508 files[next_file].name = s?;
509 next_file += 1;
510 }
511
512 if next_file != files.len() {
513 return Err(Error::other("Error parsing file names"));
514 }
515 }
516 K_C_TIME => {
517 let times_defined = read_all_or_bits(header, num_files)?;
518 let external = read_u8(header)?;
519 if external != 0 {
520 return Err(Error::other(format!(
521 "kCTime Unimplemented:external={}",
522 external
523 )));
524 }
525 for (i, file) in files.iter_mut().enumerate() {
526 file.has_creation_date = times_defined.contains(i);
527 if file.has_creation_date {
528 file.creation_date = read_u64le(header)?.into();
529 }
530 }
531 }
532 K_A_TIME => {
533 let times_defined = read_all_or_bits(header, num_files)?;
534 let external = read_u8(header)?;
535 if external != 0 {
536 return Err(Error::other(format!(
537 "kATime Unimplemented:external={}",
538 external
539 )));
540 }
541 for (i, file) in files.iter_mut().enumerate() {
542 file.has_access_date = times_defined.contains(i);
543 if file.has_access_date {
544 file.access_date = read_u64le(header)?.into();
545 }
546 }
547 }
548 K_M_TIME => {
549 let times_defined = read_all_or_bits(header, num_files)?;
550 let external = read_u8(header)?;
551 if external != 0 {
552 return Err(Error::other(format!(
553 "kMTime Unimplemented:external={}",
554 external
555 )));
556 }
557 for (i, file) in files.iter_mut().enumerate() {
558 file.has_last_modified_date = times_defined.contains(i);
559 if file.has_last_modified_date {
560 file.last_modified_date = read_u64le(header)?.into();
561 }
562 }
563 }
564 K_WIN_ATTRIBUTES => {
565 let times_defined = read_all_or_bits(header, num_files)?;
566 let external = read_u8(header)?;
567 if external != 0 {
568 return Err(Error::other(format!(
569 "kWinAttributes Unimplemented:external={}",
570 external
571 )));
572 }
573 for (i, file) in files.iter_mut().enumerate() {
574 file.has_windows_attributes = times_defined.contains(i);
575 if file.has_windows_attributes {
576 file.windows_attributes = read_u32(header)?;
577 }
578 }
579 }
580 K_START_POS => return Err(Error::other("kStartPos is unsupported, please report")),
581 K_DUMMY => {
582 header
583 .seek(SeekFrom::Current(size as i64))
584 .map_err(Error::io)?;
585 }
586 _ => {
587 header
588 .seek(SeekFrom::Current(size as i64))
589 .map_err(Error::io)?;
590 }
591 };
592 }
593
594 let mut non_empty_file_counter = 0;
595 let mut empty_file_counter = 0;
596 for (i, file) in files.iter_mut().enumerate() {
597 file.has_stream = is_empty_stream
598 .as_ref()
599 .map(|s| !s.contains(i))
600 .unwrap_or(true);
601 if file.has_stream {
602 let sub_stream_info = if let Some(s) = archive.sub_streams_info.as_ref() {
603 s
604 } else {
605 return Err(Error::other(
606 "Archive contains file with streams but no subStreamsInfo",
607 ));
608 };
609 file.is_directory = false;
610 file.is_anti_item = false;
611 file.has_crc = sub_stream_info.has_crc.contains(non_empty_file_counter);
612 file.crc = sub_stream_info.crcs[non_empty_file_counter];
613 file.size = sub_stream_info.unpack_sizes[non_empty_file_counter];
614 non_empty_file_counter += 1;
615 } else {
616 file.is_directory = if let Some(s) = &is_empty_file {
617 !s.contains(empty_file_counter)
618 } else {
619 true
620 };
621 file.is_anti_item = is_anti
622 .as_ref()
623 .map(|s| s.contains(empty_file_counter))
624 .unwrap_or(false);
625 file.has_crc = false;
626 file.size = 0;
627 empty_file_counter += 1;
628 }
629 }
630 archive.files = files;
631
632 Self::calculate_stream_map(archive)?;
633 Ok(())
634 }
635
636 fn calculate_stream_map(archive: &mut Archive) -> Result<(), Error> {
637 let mut stream_map = StreamMap::default();
638
639 let mut next_folder_pack_stream_index = 0;
640 let num_folders = archive.folders.len();
641 stream_map.folder_first_pack_stream_index = vec![0; num_folders];
642 for i in 0..num_folders {
643 stream_map.folder_first_pack_stream_index[i] = next_folder_pack_stream_index;
644 next_folder_pack_stream_index += archive.folders[i].packed_streams.len();
645 }
646
647 let mut next_pack_stream_offset = 0;
648 let num_pack_sizes = archive.pack_sizes.len();
649 stream_map.pack_stream_offsets = vec![0; num_pack_sizes];
650 for i in 0..num_pack_sizes {
651 stream_map.pack_stream_offsets[i] = next_pack_stream_offset;
652 next_pack_stream_offset += archive.pack_sizes[i];
653 }
654
655 stream_map.folder_first_file_index = vec![0; num_folders];
656 stream_map.file_folder_index = vec![None; archive.files.len()];
657 let mut next_folder_index = 0;
658 let mut next_folder_unpack_stream_index = 0;
659 for i in 0..archive.files.len() {
660 if !archive.files[i].has_stream && next_folder_unpack_stream_index == 0 {
661 stream_map.file_folder_index[i] = None;
662 continue;
663 }
664 if next_folder_unpack_stream_index == 0 {
665 while next_folder_index < archive.folders.len() {
666 stream_map.folder_first_file_index[next_folder_index] = i;
667 if archive.folders[next_folder_index].num_unpack_sub_streams > 0 {
668 break;
669 }
670 next_folder_index += 1;
671 }
672 if next_folder_index >= archive.folders.len() {
673 return Err(Error::other("Too few folders in archive"));
674 }
675 }
676 stream_map.file_folder_index[i] = Some(next_folder_index);
677 if !archive.files[i].has_stream {
678 continue;
679 }
680
681 if stream_map.folder_first_file_index[next_folder_index] == i {
683 let first_pack_stream_index =
684 stream_map.folder_first_pack_stream_index[next_folder_index];
685 let pack_size = archive.pack_sizes[first_pack_stream_index];
686
687 archive.files[i].compressed_size = pack_size;
688 }
689
690 next_folder_unpack_stream_index += 1;
691 if next_folder_unpack_stream_index
692 >= archive.folders[next_folder_index].num_unpack_sub_streams
693 {
694 next_folder_index += 1;
695 next_folder_unpack_stream_index = 0;
696 }
697 }
698
699 archive.stream_map = stream_map;
700 Ok(())
701 }
702
703 fn read_pack_info<R: Read>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
704 archive.pack_pos = read_u64(header)?;
705 let num_pack_streams = read_usize(header, "num pack streams")?;
706 let mut nid = read_u8(header)?;
707 if nid == K_SIZE {
708 archive.pack_sizes = vec![0u64; num_pack_streams];
709 for i in 0..archive.pack_sizes.len() {
710 archive.pack_sizes[i] = read_u64(header)?;
711 }
712 nid = read_u8(header)?;
713 }
714
715 if nid == K_CRC {
716 archive.pack_crcs_defined = read_all_or_bits(header, num_pack_streams)?;
717 archive.pack_crcs = vec![0; num_pack_streams];
718 for i in 0..num_pack_streams {
719 if archive.pack_crcs_defined.contains(i) {
720 archive.pack_crcs[i] = read_u32(header)? as u64;
721 }
722 }
723 nid = read_u8(header)?;
724 }
725
726 if nid != K_END {
727 return Err(Error::BadTerminatedPackInfo(nid));
728 }
729
730 Ok(())
731 }
732 fn read_unpack_info<R: Read>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
733 let nid = read_u8(header)?;
734 if nid != K_FOLDER {
735 return Err(Error::other(format!("Expected kFolder, got {}", nid)));
736 }
737 let num_folders = read_usize(header, "num folders")?;
738
739 archive.folders.reserve_exact(num_folders);
740 let external = read_u8(header)?;
741 if external != 0 {
742 return Err(Error::ExternalUnsupported);
743 }
744
745 for _ in 0..num_folders {
746 archive.folders.push(Self::read_folder(header)?);
747 }
748
749 let nid = read_u8(header)?;
750 if nid != K_CODERS_UNPACK_SIZE {
751 return Err(Error::other(format!(
752 "Expected kCodersUnpackSize, got {}",
753 nid
754 )));
755 }
756
757 for folder in archive.folders.iter_mut() {
758 let tos = folder.total_output_streams;
759 folder.unpack_sizes.reserve_exact(tos);
760 for _ in 0..tos {
761 folder.unpack_sizes.push(read_u64(header)?);
762 }
763 }
764
765 let mut nid = read_u8(header)?;
766 if nid == K_CRC {
767 let crcs_defined = read_all_or_bits(header, num_folders)?;
768 for i in 0..num_folders {
769 if crcs_defined.contains(i) {
770 archive.folders[i].has_crc = true;
771 archive.folders[i].crc = read_u32(header)? as u64;
772 } else {
773 archive.folders[i].has_crc = false;
774 }
775 }
776 nid = read_u8(header)?;
777 }
778 if nid != K_END {
779 return Err(Error::BadTerminatedUnpackInfo);
780 }
781
782 Ok(())
783 }
784
785 fn read_sub_streams_info<R: Read>(header: &mut R, archive: &mut Archive) -> Result<(), Error> {
786 for folder in archive.folders.iter_mut() {
787 folder.num_unpack_sub_streams = 1;
788 }
789 let mut total_unpack_streams = archive.folders.len();
790
791 let mut nid = read_u8(header)?;
792 if nid == K_NUM_UNPACK_STREAM {
793 total_unpack_streams = 0;
794 for folder in archive.folders.iter_mut() {
795 let num_streams = read_usize(header, "numStreams")?;
796 folder.num_unpack_sub_streams = num_streams;
797 total_unpack_streams += num_streams;
798 }
799 nid = read_u8(header)?;
800 }
801
802 let mut sub_streams_info = SubStreamsInfo::default();
803 sub_streams_info
804 .unpack_sizes
805 .resize(total_unpack_streams, Default::default());
806 sub_streams_info
807 .has_crc
808 .reserve_len_exact(total_unpack_streams);
809 sub_streams_info.crcs = vec![0; total_unpack_streams];
810
811 let mut next_unpack_stream = 0;
812 for folder in archive.folders.iter() {
813 if folder.num_unpack_sub_streams == 0 {
814 continue;
815 }
816 let mut sum = 0;
817 if nid == K_SIZE {
818 for _i in 0..folder.num_unpack_sub_streams - 1 {
819 let size = read_u64(header)?;
820 sub_streams_info.unpack_sizes[next_unpack_stream] = size;
821 next_unpack_stream += 1;
822 sum += size;
823 }
824 }
825 if sum > folder.get_unpack_size() {
826 return Err(Error::other(
827 "sum of unpack sizes of folder exceeds total unpack size",
828 ));
829 }
830 sub_streams_info.unpack_sizes[next_unpack_stream] = folder.get_unpack_size() - sum;
831 next_unpack_stream += 1;
832 }
833 if nid == K_SIZE {
834 nid = read_u8(header)?;
835 }
836
837 let mut num_digests = 0;
838 for folder in archive.folders.iter() {
839 if folder.num_unpack_sub_streams != 1 || !folder.has_crc {
840 num_digests += folder.num_unpack_sub_streams;
841 }
842 }
843
844 if nid == K_CRC {
845 let has_missing_crc = read_all_or_bits(header, num_digests)?;
846 let mut missing_crcs = vec![0; num_digests];
847 for (i, missing_crc) in missing_crcs.iter_mut().enumerate() {
848 if has_missing_crc.contains(i) {
849 *missing_crc = read_u32(header)? as u64;
850 }
851 }
852 let mut next_crc = 0;
853 let mut next_missing_crc = 0;
854 for folder in archive.folders.iter() {
855 if folder.num_unpack_sub_streams == 1 && folder.has_crc {
856 sub_streams_info.has_crc.insert(next_crc);
857 sub_streams_info.crcs[next_crc] = folder.crc;
858 next_crc += 1;
859 } else {
860 for _i in 0..folder.num_unpack_sub_streams {
861 if has_missing_crc.contains(next_missing_crc) {
862 sub_streams_info.has_crc.insert(next_crc);
863 } else {
864 sub_streams_info.has_crc.remove(next_crc);
865 }
866 sub_streams_info.crcs[next_crc] = missing_crcs[next_missing_crc];
867 next_crc += 1;
868 next_missing_crc += 1;
869 }
870 }
871 }
872
873 nid = read_u8(header)?;
874 }
875
876 if nid != K_END {
877 return Err(Error::BadTerminatedSubStreamsInfo);
878 }
879
880 archive.sub_streams_info = Some(sub_streams_info);
881 Ok(())
882 }
883
884 fn read_folder<R: Read>(header: &mut R) -> Result<Folder, Error> {
885 let mut folder = Folder::default();
886
887 let num_coders = read_usize(header, "num coders")?;
888 let mut coders = Vec::with_capacity(num_coders);
889 let mut total_in_streams = 0;
890 let mut total_out_streams = 0;
891 for _i in 0..num_coders {
892 let mut coder = Coder::default();
893 let bits = read_u8(header)?;
894 let id_size = bits & 0xf;
895 let is_simple = (bits & 0x10) == 0;
896 let has_attributes = (bits & 0x20) != 0;
897 let more_alternative_methods = (bits & 0x80) != 0;
898
899 coder.id_size = id_size as usize;
900
901 header
902 .read(coder.decompression_method_id_mut())
903 .map_err(Error::io)?;
904 if is_simple {
905 coder.num_in_streams = 1;
906 coder.num_out_streams = 1;
907 } else {
908 coder.num_in_streams = read_u64(header)?;
909 coder.num_out_streams = read_u64(header)?;
910 }
911 total_in_streams += coder.num_in_streams;
912 total_out_streams += coder.num_out_streams;
913 if has_attributes {
914 let properties_size = read_usize(header, "properties size")?;
915 let mut props = vec![0u8; properties_size];
916 header.read(&mut props).map_err(Error::io)?;
917 coder.properties = props;
918 }
919 coders.push(coder);
920 if more_alternative_methods {
922 return Err(Error::other("Alternative methods are unsupported, please report. The reference implementation doesn't support them either."));
923 }
924 }
925 folder.coders = coders;
926 let total_in_streams = assert_usize(total_in_streams, "totalInStreams")?;
927 let total_out_streams = assert_usize(total_out_streams, "totalOutStreams")?;
928 folder.total_input_streams = total_in_streams;
929 folder.total_output_streams = total_out_streams;
930
931 if total_out_streams == 0 {
932 return Err(Error::other("Total output streams can't be 0"));
933 }
934 let num_bind_pairs = total_out_streams - 1;
935 let mut bind_pairs = Vec::with_capacity(num_bind_pairs);
936 for _ in 0..num_bind_pairs {
937 let bp = BindPair {
938 in_index: read_u64(header)?,
939 out_index: read_u64(header)?,
940 };
941 bind_pairs.push(bp);
942 }
943 folder.bind_pairs = bind_pairs;
944
945 if total_in_streams < num_bind_pairs {
946 return Err(Error::other(
947 "Total input streams can't be less than the number of bind pairs",
948 ));
949 }
950 let num_packed_streams = total_in_streams - num_bind_pairs;
951 let mut packed_streams = vec![0; num_packed_streams];
952 if num_packed_streams == 1 {
953 let mut index = u64::MAX;
954 for i in 0..total_in_streams {
955 if folder.find_bind_pair_for_in_stream(i).is_none() {
956 index = i as u64;
957 break;
958 }
959 }
960 if index == u64::MAX {
961 return Err(Error::other("Couldn't find stream's bind pair index"));
962 }
963 packed_streams[0] = index;
964 } else {
965 for packed_stream in packed_streams.iter_mut() {
966 *packed_stream = read_u64(header)?;
967 }
968 }
969 folder.packed_streams = packed_streams;
970
971 Ok(folder)
972 }
973}
974
975#[inline]
976fn read_usize<R: Read>(reader: &mut R, field: &str) -> Result<usize, Error> {
977 let size = read_u64(reader)?;
978 assert_usize(size, field)
979}
980
981#[inline]
982fn assert_usize(size: u64, field: &str) -> Result<usize, Error> {
983 if size > usize::MAX as u64 {
984 return Err(Error::other(format!("Cannot handle {} {}", field, size)));
985 }
986 Ok(size as usize)
987}
988
989#[inline]
990fn read_u64le<R: Read>(reader: &mut R) -> Result<u64, Error> {
991 let mut buf = [0; 8];
992 reader.read_exact(&mut buf).map_err(Error::io)?;
993 Ok(u64::from_le_bytes(buf))
994}
995
996fn read_u64<R: Read>(reader: &mut R) -> Result<u64, Error> {
997 let first = read_u8(reader)? as u64;
998 let mut mask = 0x80_u64;
999 let mut value = 0;
1000 for i in 0..8 {
1001 if (first & mask) == 0 {
1002 return Ok(value | ((first & (mask - 1)) << (8 * i)));
1003 }
1004 let b = read_u8(reader)? as u64;
1005 value |= b << (8 * i);
1006 mask >>= 1;
1007 }
1008 Ok(value)
1009}
1010
1011#[inline(always)]
1012fn read_u32<R: Read>(reader: &mut R) -> Result<u32, Error> {
1013 let mut buf = [0; 4];
1014 reader.read_exact(&mut buf).map_err(Error::io)?;
1015 Ok(u32::from_le_bytes(buf))
1016}
1017
1018#[inline(always)]
1019fn read_u8<R: Read>(reader: &mut R) -> Result<u8, Error> {
1020 let mut buf = [0];
1021 reader.read_exact(&mut buf).map_err(Error::io)?;
1022 Ok(buf[0])
1023}
1024
1025fn read_all_or_bits<R: Read>(header: &mut R, size: usize) -> Result<BitSet, Error> {
1026 let all = read_u8(header)?;
1027 if all != 0 {
1028 let mut bits = BitSet::with_capacity(size);
1029 for i in 0..size {
1030 bits.insert(i);
1031 }
1032 Ok(bits)
1033 } else {
1034 read_bits(header, size)
1035 }
1036}
1037
1038fn read_bits<R: Read>(header: &mut R, size: usize) -> Result<BitSet, Error> {
1039 let mut bits = BitSet::with_capacity(size);
1040 let mut mask = 0u32;
1041 let mut cache = 0u32;
1042 for i in 0..size {
1043 if mask == 0 {
1044 mask = 0x80;
1045 cache = read_u8(header)? as u32;
1046 }
1047 if (cache & mask) != 0 {
1048 bits.insert(i);
1049 }
1050 mask >>= 1;
1051 }
1052 Ok(bits)
1053}
1054
1055struct NamesReader<'a, R: Read> {
1056 max_bytes: usize,
1057 read_bytes: usize,
1058 cache: Vec<u16>,
1059 reader: &'a mut R,
1060}
1061
1062impl<'a, R: Read> NamesReader<'a, R> {
1063 fn new(reader: &'a mut R, max_bytes: usize) -> Self {
1064 Self {
1065 max_bytes,
1066 reader,
1067 read_bytes: 0,
1068 cache: Vec::with_capacity(16),
1069 }
1070 }
1071}
1072
1073impl<R: Read> Iterator for NamesReader<'_, R> {
1074 type Item = Result<String, Error>;
1075
1076 fn next(&mut self) -> Option<Self::Item> {
1077 if self.max_bytes <= self.read_bytes {
1078 return None;
1079 }
1080 self.cache.clear();
1081 let mut buf = [0; 2];
1082 while self.read_bytes < self.max_bytes {
1083 let r = self.reader.read_exact(&mut buf).map_err(Error::io);
1084 self.read_bytes += 2;
1085 if let Err(e) = r {
1086 return Some(Err(e));
1087 }
1088 let u = u16::from_le_bytes(buf);
1089 if u == 0 {
1090 break;
1091 }
1092 self.cache.push(u);
1093 }
1094
1095 Some(String::from_utf16(&self.cache).map_err(|e| Error::other(e.to_string())))
1096 }
1097}
1098
1099#[derive(Copy, Clone)]
1100struct IndexEntry {
1101 folder_index: Option<usize>,
1102 file_index: usize,
1103}
1104
1105pub struct SevenZReader<R: Read + Seek> {
1106 source: R,
1107 archive: Archive,
1108 password: Vec<u8>,
1109 index: HashMap<String, IndexEntry>,
1110}
1111
1112#[cfg(not(target_arch = "wasm32"))]
1113impl SevenZReader<File> {
1114 #[inline]
1115 pub fn open(path: impl AsRef<std::path::Path>, password: Password) -> Result<Self, Error> {
1116 let file = File::open(path.as_ref())
1117 .map_err(|e| Error::file_open(e, path.as_ref().to_string_lossy().to_string()))?;
1118 let len = file.metadata().map(|m| m.len()).map_err(Error::io)?;
1119 Self::new(file, len, password)
1120 }
1121}
1122
1123impl<R: Read + Seek> SevenZReader<R> {
1124 #[inline]
1125 pub fn new(mut source: R, reader_len: u64, password: Password) -> Result<Self, Error> {
1126 let password = password.to_vec();
1127 let archive = Archive::read(&mut source, reader_len, &password)?;
1128
1129 let mut reader = Self {
1130 source,
1131 archive,
1132 password,
1133 index: HashMap::default(),
1134 };
1135
1136 reader.fill_index();
1137
1138 Ok(reader)
1139 }
1140
1141 #[inline]
1142 pub fn from_archive(archive: Archive, source: R, password: Password) -> Self {
1143 let mut reader = Self {
1144 source,
1145 archive,
1146 password: password.to_vec(),
1147 index: HashMap::default(),
1148 };
1149
1150 reader.fill_index();
1151
1152 reader
1153 }
1154
1155 fn fill_index(&mut self) {
1156 for (file_index, file) in self.archive.files.iter().enumerate() {
1157 let folder_index = self.archive.stream_map.file_folder_index[file_index];
1158
1159 self.index.insert(
1160 file.name.clone(),
1161 IndexEntry {
1162 folder_index,
1163 file_index,
1164 },
1165 );
1166 }
1167 }
1168
1169 #[inline]
1170 pub fn archive(&self) -> &Archive {
1171 &self.archive
1172 }
1173
1174 fn build_decode_stack<'r>(
1175 source: &'r mut R,
1176 archive: &Archive,
1177 folder_index: usize,
1178 password: &[u8],
1179 ) -> Result<(Box<dyn Read + 'r>, usize), Error> {
1180 let folder = &archive.folders[folder_index];
1181 if folder.total_input_streams > folder.total_output_streams {
1182 return Self::build_decode_stack2(source, archive, folder_index, password);
1183 }
1184 let first_pack_stream_index =
1185 archive.stream_map.folder_first_pack_stream_index[folder_index];
1186 let folder_offset = SIGNATURE_HEADER_SIZE
1187 + archive.pack_pos
1188 + archive.stream_map.pack_stream_offsets[first_pack_stream_index];
1189
1190 source
1191 .seek(SeekFrom::Start(folder_offset))
1192 .map_err(Error::io)?;
1193 let pack_size = archive.pack_sizes[first_pack_stream_index] as usize;
1194
1195 let mut decoder: Box<dyn Read> = Box::new(BoundedReader::new(source, pack_size));
1196 let folder = &archive.folders[folder_index];
1197 for (index, coder) in folder.ordered_coder_iter() {
1198 if coder.num_in_streams != 1 || coder.num_out_streams != 1 {
1199 return Err(Error::unsupported(
1200 "Multi input/output stream coders are not yet supported",
1201 ));
1202 }
1203 let next = add_decoder(
1204 decoder,
1205 folder.get_unpack_size_at_index(index) as usize,
1206 coder,
1207 password,
1208 MAX_MEM_LIMIT_KB,
1209 )?;
1210 decoder = Box::new(next);
1211 }
1212 if folder.has_crc {
1213 decoder = Box::new(Crc32VerifyingReader::new(
1214 decoder,
1215 folder.get_unpack_size() as usize,
1216 folder.crc,
1217 ));
1218 }
1219
1220 Ok((decoder, pack_size))
1221 }
1222
1223 fn build_decode_stack2<'r>(
1224 source: &'r mut R,
1225 archive: &Archive,
1226 folder_index: usize,
1227 password: &[u8],
1228 ) -> Result<(Box<dyn Read + 'r>, usize), Error> {
1229 const MAX_CODER_COUNT: usize = 32;
1230 let folder = &archive.folders[folder_index];
1231 if folder.coders.len() > MAX_CODER_COUNT {
1232 return Err(Error::unsupported(format!(
1233 "Too many coders: {}",
1234 folder.coders.len()
1235 )));
1236 }
1237
1238 assert!(folder.total_input_streams > folder.total_output_streams);
1239 let source = ReaderPtr::new(source);
1240 let first_pack_stream_index =
1241 archive.stream_map.folder_first_pack_stream_index[folder_index];
1242 let start_pos = SIGNATURE_HEADER_SIZE + archive.pack_pos;
1243 let offsets = &archive.stream_map.pack_stream_offsets[first_pack_stream_index..];
1244
1245 let mut sources = Vec::with_capacity(folder.packed_streams.len());
1246
1247 for (i, offset) in offsets[..folder.packed_streams.len()].iter().enumerate() {
1248 let pack_pos = start_pos + offset;
1249 let pack_size = archive.pack_sizes[first_pack_stream_index + i];
1250 let pack_reader =
1251 SeekableBoundedReader::new(source.clone(), (pack_pos, pack_pos + pack_size));
1252 sources.push(pack_reader);
1253 }
1254
1255 let mut coder_to_stream_map = [usize::MAX; MAX_CODER_COUNT];
1256
1257 let mut si = 0;
1258 for (i, coder) in folder.coders.iter().enumerate() {
1259 coder_to_stream_map[i] = si;
1260 si += coder.num_in_streams as usize;
1261 }
1262
1263 let main_coder_index = {
1264 let mut coder_used = [false; MAX_CODER_COUNT];
1265 for bp in folder.bind_pairs.iter() {
1266 coder_used[bp.out_index as usize] = true;
1267 }
1268 let mut mci = 0;
1269 for (i, used) in coder_used[..folder.coders.len()].iter().enumerate() {
1270 if !used {
1271 mci = i;
1272 break;
1273 }
1274 }
1275 mci
1276 };
1277
1278 let id = folder.coders[main_coder_index].decompression_method_id();
1279 if id != SevenZMethod::ID_BCJ2 {
1280 return Err(Error::unsupported(format!("Unsupported method: {:?}", id)));
1281 }
1282
1283 let num_in_streams = folder.coders[main_coder_index].num_in_streams as usize;
1284 let mut inputs: Vec<Box<dyn Read>> = Vec::with_capacity(num_in_streams);
1285 let start_i = coder_to_stream_map[main_coder_index];
1286 for i in start_i..num_in_streams + start_i {
1287 inputs.push(Self::get_in_stream(
1288 folder,
1289 &sources,
1290 &coder_to_stream_map,
1291 password,
1292 i,
1293 )?);
1294 }
1295 let mut decoder: Box<dyn Read> = Box::new(crate::bcj2::BCJ2Reader::new(
1296 inputs,
1297 folder.get_unpack_size(),
1298 ));
1299 if folder.has_crc {
1300 decoder = Box::new(Crc32VerifyingReader::new(
1301 decoder,
1302 folder.get_unpack_size() as usize,
1303 folder.crc,
1304 ));
1305 }
1306 Ok((
1307 decoder,
1308 archive.pack_sizes[first_pack_stream_index] as usize,
1309 ))
1310 }
1311
1312 fn get_in_stream<'r>(
1313 folder: &Folder,
1314 sources: &[SeekableBoundedReader<ReaderPtr<R>>],
1315 coder_to_stream_map: &[usize],
1316 password: &[u8],
1317
1318 in_stream_index: usize,
1319 ) -> Result<Box<dyn Read + 'r>, Error>
1320 where
1321 R: 'r,
1322 {
1323 let index = folder
1324 .packed_streams
1325 .iter()
1326 .position(|&i| i == in_stream_index as u64);
1327 if let Some(index) = index {
1328 return Ok(Box::new(sources[index].clone()));
1329 }
1330
1331 let bp = folder
1332 .find_bind_pair_for_in_stream(in_stream_index)
1333 .ok_or_else(|| {
1334 Error::other(format!(
1335 "Couldn't find bind pair for stream {}",
1336 in_stream_index
1337 ))
1338 })?;
1339 let index = folder.bind_pairs[bp].out_index as usize;
1340
1341 Self::get_in_stream2(folder, sources, coder_to_stream_map, password, index)
1342 }
1343
1344 fn get_in_stream2<'r>(
1345 folder: &Folder,
1346 sources: &[SeekableBoundedReader<ReaderPtr<R>>],
1347 coder_to_stream_map: &[usize],
1348 password: &[u8],
1349 in_stream_index: usize,
1350 ) -> Result<Box<dyn Read + 'r>, Error>
1351 where
1352 R: 'r,
1353 {
1354 let coder = &folder.coders[in_stream_index];
1355 let start_index = coder_to_stream_map[in_stream_index];
1356 if start_index == usize::MAX {
1357 return Err(Error::other("in_stream_index out of range"));
1358 }
1359 let uncompressed_len = folder.unpack_sizes[in_stream_index] as usize;
1360 if coder.num_in_streams == 1 {
1361 let input =
1362 Self::get_in_stream(folder, sources, coder_to_stream_map, password, start_index)?;
1363
1364 let decoder = add_decoder(input, uncompressed_len, coder, password, MAX_MEM_LIMIT_KB)?;
1365 return Ok(Box::new(decoder));
1366 }
1367 Err(Error::unsupported(
1368 "Multi input stream coders are not yet supported",
1369 ))
1370 }
1371
1372 pub fn for_each_entries<F: FnMut(&SevenZArchiveEntry, &mut dyn Read) -> Result<bool, Error>>(
1381 &mut self,
1382 mut each: F,
1383 ) -> Result<(), Error> {
1384 let folder_count = self.archive.folders.len();
1385 for folder_index in 0..folder_count {
1386 let forder_dec = BlockDecoder::new(
1387 folder_index,
1388 &self.archive,
1389 &self.password,
1390 &mut self.source,
1391 );
1392 forder_dec.for_each_entries(&mut each)?;
1393 }
1394 for file_index in 0..self.archive.files.len() {
1396 let folder_index = self.archive.stream_map.file_folder_index[file_index];
1397 if folder_index.is_none() {
1398 let file = &self.archive.files[file_index];
1399 let empty_reader: &mut dyn Read = &mut ([0u8; 0].as_slice());
1400 if !each(file, empty_reader)? {
1401 return Ok(());
1402 }
1403 }
1404 }
1405 Ok(())
1406 }
1407
1408 pub fn read_file(&mut self, name: &str) -> Result<Vec<u8>, Error> {
1414 let index_entry = *self.index.get(name).ok_or(Error::FileNotFound)?;
1415 let file = &self.archive.files[index_entry.file_index];
1416
1417 if !file.has_stream {
1418 return Ok(Vec::new());
1419 }
1420
1421 let folder_index = index_entry
1422 .folder_index
1423 .ok_or_else(|| Error::other("File has no associated folder"))?;
1424
1425 match self.archive.is_solid {
1426 true => {
1427 let mut result = None;
1428 let target_file_ptr = file as *const _;
1429
1430 BlockDecoder::new(
1431 folder_index,
1432 &self.archive,
1433 &self.password,
1434 &mut self.source,
1435 )
1436 .for_each_entries(&mut |archive_entry, reader| {
1437 let mut data = Vec::with_capacity(archive_entry.size as usize);
1438 reader.read_to_end(&mut data)?;
1439
1440 if archive_entry as *const _ == target_file_ptr {
1441 result = Some(data);
1442 Ok(false)
1443 } else {
1444 Ok(true)
1445 }
1446 })?;
1447
1448 result.ok_or(Error::FileNotFound)
1449 }
1450 false => {
1451 let pack_index =
1452 self.archive.stream_map.folder_first_pack_stream_index[folder_index];
1453 let pack_offset = self.archive.stream_map.pack_stream_offsets[pack_index];
1454 let folder_offset = SIGNATURE_HEADER_SIZE + self.archive.pack_pos + pack_offset;
1455
1456 self.source.seek(SeekFrom::Start(folder_offset))?;
1457
1458 let (mut folder_reader, _size) = Self::build_decode_stack(
1459 &mut self.source,
1460 &self.archive,
1461 folder_index,
1462 &self.password,
1463 )?;
1464
1465 let mut data = Vec::with_capacity(file.size as usize);
1466 let mut decoder: Box<dyn Read> =
1467 Box::new(BoundedReader::new(&mut folder_reader, file.size as usize));
1468
1469 if file.has_crc {
1470 decoder = Box::new(Crc32VerifyingReader::new(
1471 decoder,
1472 file.size as usize,
1473 file.crc,
1474 ));
1475 }
1476
1477 decoder.read_to_end(&mut data)?;
1478
1479 Ok(data)
1480 }
1481 }
1482 }
1483}
1484
1485pub struct BlockDecoder<'a, R: Read + Seek> {
1486 folder_index: usize,
1487 archive: &'a Archive,
1488 password: &'a [u8],
1489 source: &'a mut R,
1490}
1491
1492impl<'a, R: Read + Seek> BlockDecoder<'a, R> {
1493 pub fn new(
1494 folder_index: usize,
1495 archive: &'a Archive,
1496 password: &'a [u8],
1497 source: &'a mut R,
1498 ) -> Self {
1499 Self {
1500 folder_index,
1501 archive,
1502 password,
1503 source,
1504 }
1505 }
1506
1507 pub fn entries(&self) -> &[SevenZArchiveEntry] {
1508 let start = self.archive.stream_map.folder_first_file_index[self.folder_index];
1509 let file_count = self.archive.folders[self.folder_index].num_unpack_sub_streams;
1510 &self.archive.files[start..(file_count + start)]
1511 }
1512
1513 pub fn entry_count(&self) -> usize {
1514 self.archive.folders[self.folder_index].num_unpack_sub_streams
1515 }
1516
1517 pub fn for_each_entries<F: FnMut(&SevenZArchiveEntry, &mut dyn Read) -> Result<bool, Error>>(
1525 self,
1526 each: &mut F,
1527 ) -> Result<bool, Error> {
1528 let Self {
1529 folder_index,
1530 archive,
1531 password,
1532 source,
1533 } = self;
1534 let (mut folder_reader, _size) =
1535 SevenZReader::build_decode_stack(source, archive, folder_index, password)?;
1536 let start = archive.stream_map.folder_first_file_index[folder_index];
1537 let file_count = archive.folders[folder_index].num_unpack_sub_streams;
1538
1539 for file_index in start..(file_count + start) {
1540 let file = &archive.files[file_index];
1541 if file.has_stream && file.size > 0 {
1542 let mut decoder: Box<dyn Read> =
1543 Box::new(BoundedReader::new(&mut folder_reader, file.size as usize));
1544 if file.has_crc {
1545 decoder = Box::new(Crc32VerifyingReader::new(
1546 decoder,
1547 file.size as usize,
1548 file.crc,
1549 ));
1550 }
1551 if !each(file, &mut decoder)
1552 .map_err(|e| e.maybe_bad_password(!self.password.is_empty()))?
1553 {
1554 return Ok(false);
1555 }
1556 } else {
1557 let empty_reader: &mut dyn Read = &mut ([0u8; 0].as_slice());
1558 if !each(file, empty_reader)? {
1559 return Ok(false);
1560 }
1561 }
1562 }
1563 Ok(true)
1564 }
1565}
1566
1567#[derive(Debug, Copy)]
1568struct ReaderPtr<R> {
1569 reader: *mut R,
1570}
1571
1572impl<R> Clone for ReaderPtr<R> {
1573 fn clone(&self) -> Self {
1574 Self {
1575 reader: self.reader,
1576 }
1577 }
1578}
1579
1580impl<R> ReaderPtr<R> {
1581 fn new(reader: &mut R) -> Self {
1582 Self {
1583 reader: reader as *mut R,
1584 }
1585 }
1586}
1587
1588impl<R: Read> Read for ReaderPtr<R> {
1589 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
1590 unsafe { (*self.reader).read(buf) }
1591 }
1592}
1593
1594impl<R: Seek> Seek for ReaderPtr<R> {
1595 fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
1596 unsafe { (*self.reader).seek(pos) }
1597 }
1598}