Line | Count | Source |
1 | | use crate::result::{ZipError, ZipResult}; |
2 | | use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; |
3 | | use std::io; |
4 | | use std::io::prelude::*; |
5 | | |
6 | | pub const LOCAL_FILE_HEADER_SIGNATURE: u32 = 0x04034b50; |
7 | | pub const CENTRAL_DIRECTORY_HEADER_SIGNATURE: u32 = 0x02014b50; |
8 | | const CENTRAL_DIRECTORY_END_SIGNATURE: u32 = 0x06054b50; |
9 | | pub const ZIP64_CENTRAL_DIRECTORY_END_SIGNATURE: u32 = 0x06064b50; |
10 | | const ZIP64_CENTRAL_DIRECTORY_END_LOCATOR_SIGNATURE: u32 = 0x07064b50; |
11 | | |
12 | | pub const ZIP64_BYTES_THR: u64 = u32::MAX as u64; |
13 | | pub const ZIP64_ENTRY_THR: usize = u16::MAX as usize; |
14 | | |
15 | | pub struct CentralDirectoryEnd { |
16 | | pub disk_number: u16, |
17 | | pub disk_with_central_directory: u16, |
18 | | pub number_of_files_on_this_disk: u16, |
19 | | pub number_of_files: u16, |
20 | | pub central_directory_size: u32, |
21 | | pub central_directory_offset: u32, |
22 | | pub zip_file_comment: Vec<u8>, |
23 | | } |
24 | | |
25 | | impl CentralDirectoryEnd { |
26 | | // Per spec 4.4.1.4 - a CentralDirectoryEnd field might be insufficient to hold the |
27 | | // required data. In this case the file SHOULD contain a ZIP64 format record |
28 | | // and the field of this record will be set to -1 |
29 | 4.21k | pub(crate) fn record_too_small(&self) -> bool { |
30 | 4.21k | self.disk_number == 0xFFFF |
31 | 3.64k | || self.disk_with_central_directory == 0xFFFF |
32 | 3.24k | || self.number_of_files_on_this_disk == 0xFFFF |
33 | 3.09k | || self.number_of_files == 0xFFFF |
34 | 2.74k | || self.central_directory_size == 0xFFFFFFFF |
35 | 2.72k | || self.central_directory_offset == 0xFFFFFFFF |
36 | 4.21k | } |
37 | | |
38 | 3.54k | pub fn parse<T: Read>(reader: &mut T) -> ZipResult<CentralDirectoryEnd> { |
39 | 3.54k | let magic = reader.read_u32::<LittleEndian>()?; |
40 | 3.54k | if magic != CENTRAL_DIRECTORY_END_SIGNATURE { |
41 | 0 | return Err(ZipError::InvalidArchive("Invalid digital signature header")); |
42 | 3.54k | } |
43 | 3.54k | let disk_number = reader.read_u16::<LittleEndian>()?; |
44 | 3.54k | let disk_with_central_directory = reader.read_u16::<LittleEndian>()?; |
45 | 3.54k | let number_of_files_on_this_disk = reader.read_u16::<LittleEndian>()?; |
46 | 3.54k | let number_of_files = reader.read_u16::<LittleEndian>()?; |
47 | 3.54k | let central_directory_size = reader.read_u32::<LittleEndian>()?; |
48 | 3.54k | let central_directory_offset = reader.read_u32::<LittleEndian>()?; |
49 | 3.54k | let zip_file_comment_length = reader.read_u16::<LittleEndian>()? as usize; |
50 | 3.54k | let mut zip_file_comment = vec![0; zip_file_comment_length]; |
51 | 3.54k | reader.read_exact(&mut zip_file_comment)?; |
52 | | |
53 | 3.51k | Ok(CentralDirectoryEnd { |
54 | 3.51k | disk_number, |
55 | 3.51k | disk_with_central_directory, |
56 | 3.51k | number_of_files_on_this_disk, |
57 | 3.51k | number_of_files, |
58 | 3.51k | central_directory_size, |
59 | 3.51k | central_directory_offset, |
60 | 3.51k | zip_file_comment, |
61 | 3.51k | }) |
62 | 3.54k | } <zip::spec::CentralDirectoryEnd>::parse::<std::io::cursor::Cursor<&[u8]>> Line | Count | Source | 38 | 2.37k | pub fn parse<T: Read>(reader: &mut T) -> ZipResult<CentralDirectoryEnd> { | 39 | 2.37k | let magic = reader.read_u32::<LittleEndian>()?; | 40 | 2.37k | if magic != CENTRAL_DIRECTORY_END_SIGNATURE { | 41 | 0 | return Err(ZipError::InvalidArchive("Invalid digital signature header")); | 42 | 2.37k | } | 43 | 2.37k | let disk_number = reader.read_u16::<LittleEndian>()?; | 44 | 2.37k | let disk_with_central_directory = reader.read_u16::<LittleEndian>()?; | 45 | 2.37k | let number_of_files_on_this_disk = reader.read_u16::<LittleEndian>()?; | 46 | 2.37k | let number_of_files = reader.read_u16::<LittleEndian>()?; | 47 | 2.37k | let central_directory_size = reader.read_u32::<LittleEndian>()?; | 48 | 2.37k | let central_directory_offset = reader.read_u32::<LittleEndian>()?; | 49 | 2.37k | let zip_file_comment_length = reader.read_u16::<LittleEndian>()? as usize; | 50 | 2.37k | let mut zip_file_comment = vec![0; zip_file_comment_length]; | 51 | 2.37k | reader.read_exact(&mut zip_file_comment)?; | 52 | | | 53 | 2.34k | Ok(CentralDirectoryEnd { | 54 | 2.34k | disk_number, | 55 | 2.34k | disk_with_central_directory, | 56 | 2.34k | number_of_files_on_this_disk, | 57 | 2.34k | number_of_files, | 58 | 2.34k | central_directory_size, | 59 | 2.34k | central_directory_offset, | 60 | 2.34k | zip_file_comment, | 61 | 2.34k | }) | 62 | 2.37k | } |
<zip::spec::CentralDirectoryEnd>::parse::<std::io::cursor::Cursor<&[u8]>> Line | Count | Source | 38 | 423 | pub fn parse<T: Read>(reader: &mut T) -> ZipResult<CentralDirectoryEnd> { | 39 | 423 | let magic = reader.read_u32::<LittleEndian>()?; | 40 | 423 | if magic != CENTRAL_DIRECTORY_END_SIGNATURE { | 41 | 0 | return Err(ZipError::InvalidArchive("Invalid digital signature header")); | 42 | 423 | } | 43 | 423 | let disk_number = reader.read_u16::<LittleEndian>()?; | 44 | 423 | let disk_with_central_directory = reader.read_u16::<LittleEndian>()?; | 45 | 423 | let number_of_files_on_this_disk = reader.read_u16::<LittleEndian>()?; | 46 | 423 | let number_of_files = reader.read_u16::<LittleEndian>()?; | 47 | 423 | let central_directory_size = reader.read_u32::<LittleEndian>()?; | 48 | 423 | let central_directory_offset = reader.read_u32::<LittleEndian>()?; | 49 | 423 | let zip_file_comment_length = reader.read_u16::<LittleEndian>()? as usize; | 50 | 423 | let mut zip_file_comment = vec![0; zip_file_comment_length]; | 51 | 423 | reader.read_exact(&mut zip_file_comment)?; | 52 | | | 53 | 420 | Ok(CentralDirectoryEnd { | 54 | 420 | disk_number, | 55 | 420 | disk_with_central_directory, | 56 | 420 | number_of_files_on_this_disk, | 57 | 420 | number_of_files, | 58 | 420 | central_directory_size, | 59 | 420 | central_directory_offset, | 60 | 420 | zip_file_comment, | 61 | 420 | }) | 62 | 423 | } |
<zip::spec::CentralDirectoryEnd>::parse::<std::io::cursor::Cursor<alloc::vec::Vec<u8>>> Line | Count | Source | 38 | 748 | pub fn parse<T: Read>(reader: &mut T) -> ZipResult<CentralDirectoryEnd> { | 39 | 748 | let magic = reader.read_u32::<LittleEndian>()?; | 40 | 748 | if magic != CENTRAL_DIRECTORY_END_SIGNATURE { | 41 | 0 | return Err(ZipError::InvalidArchive("Invalid digital signature header")); | 42 | 748 | } | 43 | 748 | let disk_number = reader.read_u16::<LittleEndian>()?; | 44 | 748 | let disk_with_central_directory = reader.read_u16::<LittleEndian>()?; | 45 | 748 | let number_of_files_on_this_disk = reader.read_u16::<LittleEndian>()?; | 46 | 748 | let number_of_files = reader.read_u16::<LittleEndian>()?; | 47 | 748 | let central_directory_size = reader.read_u32::<LittleEndian>()?; | 48 | 748 | let central_directory_offset = reader.read_u32::<LittleEndian>()?; | 49 | 748 | let zip_file_comment_length = reader.read_u16::<LittleEndian>()? as usize; | 50 | 748 | let mut zip_file_comment = vec![0; zip_file_comment_length]; | 51 | 748 | reader.read_exact(&mut zip_file_comment)?; | 52 | | | 53 | 748 | Ok(CentralDirectoryEnd { | 54 | 748 | disk_number, | 55 | 748 | disk_with_central_directory, | 56 | 748 | number_of_files_on_this_disk, | 57 | 748 | number_of_files, | 58 | 748 | central_directory_size, | 59 | 748 | central_directory_offset, | 60 | 748 | zip_file_comment, | 61 | 748 | }) | 62 | 748 | } |
|
63 | | |
64 | 14.6k | pub fn find_and_parse<T: Read + io::Seek>( |
65 | 14.6k | reader: &mut T, |
66 | 14.6k | ) -> ZipResult<(CentralDirectoryEnd, u64)> { |
67 | | const HEADER_SIZE: u64 = 22; |
68 | | const BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE: u64 = HEADER_SIZE - 6; |
69 | 14.6k | let file_length = reader.seek(io::SeekFrom::End(0))?; |
70 | | |
71 | 14.6k | let search_upper_bound = file_length.saturating_sub(HEADER_SIZE + ::std::u16::MAX as u64); |
72 | | |
73 | 14.6k | if file_length < HEADER_SIZE { |
74 | 93 | return Err(ZipError::InvalidArchive("Invalid zip header")); |
75 | 14.5k | } |
76 | | |
77 | 14.5k | let mut pos = file_length - HEADER_SIZE; |
78 | 759M | while pos >= search_upper_bound { |
79 | 759M | reader.seek(io::SeekFrom::Start(pos))?; |
80 | 759M | if reader.read_u32::<LittleEndian>()? == CENTRAL_DIRECTORY_END_SIGNATURE { |
81 | 3.54k | reader.seek(io::SeekFrom::Current( |
82 | 3.54k | BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE as i64, |
83 | 3.54k | ))?; |
84 | 3.54k | let cde_start_pos = reader.seek(io::SeekFrom::Start(pos))?; |
85 | 3.54k | return CentralDirectoryEnd::parse(reader).map(|cde| (cde, cde_start_pos)); <zip::spec::CentralDirectoryEnd>::find_and_parse::<std::io::cursor::Cursor<&[u8]>>::{closure#0}Line | Count | Source | 85 | 2.34k | return CentralDirectoryEnd::parse(reader).map(|cde| (cde, cde_start_pos)); |
<zip::spec::CentralDirectoryEnd>::find_and_parse::<std::io::cursor::Cursor<&[u8]>>::{closure#0}Line | Count | Source | 85 | 420 | return CentralDirectoryEnd::parse(reader).map(|cde| (cde, cde_start_pos)); |
<zip::spec::CentralDirectoryEnd>::find_and_parse::<std::io::cursor::Cursor<alloc::vec::Vec<u8>>>::{closure#0}Line | Count | Source | 85 | 748 | return CentralDirectoryEnd::parse(reader).map(|cde| (cde, cde_start_pos)); |
|
86 | 759M | } |
87 | 759M | pos = match pos.checked_sub(1) { |
88 | 759M | Some(p) => p, |
89 | 63 | None => break, |
90 | | }; |
91 | | } |
92 | 11.0k | Err(ZipError::InvalidArchive( |
93 | 11.0k | "Could not find central directory end", |
94 | 11.0k | )) |
95 | 14.6k | } <zip::spec::CentralDirectoryEnd>::find_and_parse::<std::io::cursor::Cursor<&[u8]>> Line | Count | Source | 64 | 2.46k | pub fn find_and_parse<T: Read + io::Seek>( | 65 | 2.46k | reader: &mut T, | 66 | 2.46k | ) -> ZipResult<(CentralDirectoryEnd, u64)> { | 67 | | const HEADER_SIZE: u64 = 22; | 68 | | const BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE: u64 = HEADER_SIZE - 6; | 69 | 2.46k | let file_length = reader.seek(io::SeekFrom::End(0))?; | 70 | | | 71 | 2.46k | let search_upper_bound = file_length.saturating_sub(HEADER_SIZE + ::std::u16::MAX as u64); | 72 | | | 73 | 2.46k | if file_length < HEADER_SIZE { | 74 | 32 | return Err(ZipError::InvalidArchive("Invalid zip header")); | 75 | 2.43k | } | 76 | | | 77 | 2.43k | let mut pos = file_length - HEADER_SIZE; | 78 | 2.35M | while pos >= search_upper_bound { | 79 | 2.35M | reader.seek(io::SeekFrom::Start(pos))?; | 80 | 2.35M | if reader.read_u32::<LittleEndian>()? == CENTRAL_DIRECTORY_END_SIGNATURE { | 81 | 2.37k | reader.seek(io::SeekFrom::Current( | 82 | 2.37k | BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE as i64, | 83 | 2.37k | ))?; | 84 | 2.37k | let cde_start_pos = reader.seek(io::SeekFrom::Start(pos))?; | 85 | 2.37k | return CentralDirectoryEnd::parse(reader).map(|cde| (cde, cde_start_pos)); | 86 | 2.35M | } | 87 | 2.35M | pos = match pos.checked_sub(1) { | 88 | 2.35M | Some(p) => p, | 89 | 55 | None => break, | 90 | | }; | 91 | | } | 92 | 64 | Err(ZipError::InvalidArchive( | 93 | 64 | "Could not find central directory end", | 94 | 64 | )) | 95 | 2.46k | } |
<zip::spec::CentralDirectoryEnd>::find_and_parse::<std::io::cursor::Cursor<&[u8]>> Line | Count | Source | 64 | 506 | pub fn find_and_parse<T: Read + io::Seek>( | 65 | 506 | reader: &mut T, | 66 | 506 | ) -> ZipResult<(CentralDirectoryEnd, u64)> { | 67 | | const HEADER_SIZE: u64 = 22; | 68 | | const BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE: u64 = HEADER_SIZE - 6; | 69 | 506 | let file_length = reader.seek(io::SeekFrom::End(0))?; | 70 | | | 71 | 506 | let search_upper_bound = file_length.saturating_sub(HEADER_SIZE + ::std::u16::MAX as u64); | 72 | | | 73 | 506 | if file_length < HEADER_SIZE { | 74 | 61 | return Err(ZipError::InvalidArchive("Invalid zip header")); | 75 | 445 | } | 76 | | | 77 | 445 | let mut pos = file_length - HEADER_SIZE; | 78 | 7.93M | while pos >= search_upper_bound { | 79 | 7.93M | reader.seek(io::SeekFrom::Start(pos))?; | 80 | 7.93M | if reader.read_u32::<LittleEndian>()? == CENTRAL_DIRECTORY_END_SIGNATURE { | 81 | 423 | reader.seek(io::SeekFrom::Current( | 82 | 423 | BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE as i64, | 83 | 423 | ))?; | 84 | 423 | let cde_start_pos = reader.seek(io::SeekFrom::Start(pos))?; | 85 | 423 | return CentralDirectoryEnd::parse(reader).map(|cde| (cde, cde_start_pos)); | 86 | 7.93M | } | 87 | 7.93M | pos = match pos.checked_sub(1) { | 88 | 7.93M | Some(p) => p, | 89 | 8 | None => break, | 90 | | }; | 91 | | } | 92 | 22 | Err(ZipError::InvalidArchive( | 93 | 22 | "Could not find central directory end", | 94 | 22 | )) | 95 | 506 | } |
<zip::spec::CentralDirectoryEnd>::find_and_parse::<std::io::cursor::Cursor<alloc::vec::Vec<u8>>> Line | Count | Source | 64 | 11.6k | pub fn find_and_parse<T: Read + io::Seek>( | 65 | 11.6k | reader: &mut T, | 66 | 11.6k | ) -> ZipResult<(CentralDirectoryEnd, u64)> { | 67 | | const HEADER_SIZE: u64 = 22; | 68 | | const BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE: u64 = HEADER_SIZE - 6; | 69 | 11.6k | let file_length = reader.seek(io::SeekFrom::End(0))?; | 70 | | | 71 | 11.6k | let search_upper_bound = file_length.saturating_sub(HEADER_SIZE + ::std::u16::MAX as u64); | 72 | | | 73 | 11.6k | if file_length < HEADER_SIZE { | 74 | 0 | return Err(ZipError::InvalidArchive("Invalid zip header")); | 75 | 11.6k | } | 76 | | | 77 | 11.6k | let mut pos = file_length - HEADER_SIZE; | 78 | 749M | while pos >= search_upper_bound { | 79 | 749M | reader.seek(io::SeekFrom::Start(pos))?; | 80 | 749M | if reader.read_u32::<LittleEndian>()? == CENTRAL_DIRECTORY_END_SIGNATURE { | 81 | 748 | reader.seek(io::SeekFrom::Current( | 82 | 748 | BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE as i64, | 83 | 748 | ))?; | 84 | 748 | let cde_start_pos = reader.seek(io::SeekFrom::Start(pos))?; | 85 | 748 | return CentralDirectoryEnd::parse(reader).map(|cde| (cde, cde_start_pos)); | 86 | 749M | } | 87 | 749M | pos = match pos.checked_sub(1) { | 88 | 749M | Some(p) => p, | 89 | 0 | None => break, | 90 | | }; | 91 | | } | 92 | 10.9k | Err(ZipError::InvalidArchive( | 93 | 10.9k | "Could not find central directory end", | 94 | 10.9k | )) | 95 | 11.6k | } |
|
96 | | |
97 | 11.7k | pub fn write<T: Write>(&self, writer: &mut T) -> ZipResult<()> { |
98 | 11.7k | writer.write_u32::<LittleEndian>(CENTRAL_DIRECTORY_END_SIGNATURE)?; |
99 | 11.6k | writer.write_u16::<LittleEndian>(self.disk_number)?; |
100 | 11.6k | writer.write_u16::<LittleEndian>(self.disk_with_central_directory)?; |
101 | 11.6k | writer.write_u16::<LittleEndian>(self.number_of_files_on_this_disk)?; |
102 | 11.6k | writer.write_u16::<LittleEndian>(self.number_of_files)?; |
103 | 11.6k | writer.write_u32::<LittleEndian>(self.central_directory_size)?; |
104 | 11.6k | writer.write_u32::<LittleEndian>(self.central_directory_offset)?; |
105 | 11.6k | writer.write_u16::<LittleEndian>(self.zip_file_comment.len() as u16)?; |
106 | 11.6k | writer.write_all(&self.zip_file_comment)?; |
107 | 11.6k | Ok(()) |
108 | 11.7k | } |
109 | | } |
110 | | |
111 | | pub struct Zip64CentralDirectoryEndLocator { |
112 | | pub disk_with_central_directory: u32, |
113 | | pub end_of_central_directory_offset: u64, |
114 | | pub number_of_disks: u32, |
115 | | } |
116 | | |
117 | | impl Zip64CentralDirectoryEndLocator { |
118 | 3.07k | pub fn parse<T: Read>(reader: &mut T) -> ZipResult<Zip64CentralDirectoryEndLocator> { |
119 | 3.07k | let magic = reader.read_u32::<LittleEndian>()?; |
120 | 3.07k | if magic != ZIP64_CENTRAL_DIRECTORY_END_LOCATOR_SIGNATURE { |
121 | 2.37k | return Err(ZipError::InvalidArchive( |
122 | 2.37k | "Invalid zip64 locator digital signature header", |
123 | 2.37k | )); |
124 | 697 | } |
125 | 697 | let disk_with_central_directory = reader.read_u32::<LittleEndian>()?; |
126 | 697 | let end_of_central_directory_offset = reader.read_u64::<LittleEndian>()?; |
127 | 697 | let number_of_disks = reader.read_u32::<LittleEndian>()?; |
128 | | |
129 | 697 | Ok(Zip64CentralDirectoryEndLocator { |
130 | 697 | disk_with_central_directory, |
131 | 697 | end_of_central_directory_offset, |
132 | 697 | number_of_disks, |
133 | 697 | }) |
134 | 3.07k | } <zip::spec::Zip64CentralDirectoryEndLocator>::parse::<std::io::cursor::Cursor<&[u8]>> Line | Count | Source | 118 | 1.90k | pub fn parse<T: Read>(reader: &mut T) -> ZipResult<Zip64CentralDirectoryEndLocator> { | 119 | 1.90k | let magic = reader.read_u32::<LittleEndian>()?; | 120 | 1.90k | if magic != ZIP64_CENTRAL_DIRECTORY_END_LOCATOR_SIGNATURE { | 121 | 1.21k | return Err(ZipError::InvalidArchive( | 122 | 1.21k | "Invalid zip64 locator digital signature header", | 123 | 1.21k | )); | 124 | 686 | } | 125 | 686 | let disk_with_central_directory = reader.read_u32::<LittleEndian>()?; | 126 | 686 | let end_of_central_directory_offset = reader.read_u64::<LittleEndian>()?; | 127 | 686 | let number_of_disks = reader.read_u32::<LittleEndian>()?; | 128 | | | 129 | 686 | Ok(Zip64CentralDirectoryEndLocator { | 130 | 686 | disk_with_central_directory, | 131 | 686 | end_of_central_directory_offset, | 132 | 686 | number_of_disks, | 133 | 686 | }) | 134 | 1.90k | } |
<zip::spec::Zip64CentralDirectoryEndLocator>::parse::<std::io::cursor::Cursor<&[u8]>> Line | Count | Source | 118 | 418 | pub fn parse<T: Read>(reader: &mut T) -> ZipResult<Zip64CentralDirectoryEndLocator> { | 119 | 418 | let magic = reader.read_u32::<LittleEndian>()?; | 120 | 418 | if magic != ZIP64_CENTRAL_DIRECTORY_END_LOCATOR_SIGNATURE { | 121 | 407 | return Err(ZipError::InvalidArchive( | 122 | 407 | "Invalid zip64 locator digital signature header", | 123 | 407 | )); | 124 | 11 | } | 125 | 11 | let disk_with_central_directory = reader.read_u32::<LittleEndian>()?; | 126 | 11 | let end_of_central_directory_offset = reader.read_u64::<LittleEndian>()?; | 127 | 11 | let number_of_disks = reader.read_u32::<LittleEndian>()?; | 128 | | | 129 | 11 | Ok(Zip64CentralDirectoryEndLocator { | 130 | 11 | disk_with_central_directory, | 131 | 11 | end_of_central_directory_offset, | 132 | 11 | number_of_disks, | 133 | 11 | }) | 134 | 418 | } |
<zip::spec::Zip64CentralDirectoryEndLocator>::parse::<std::io::cursor::Cursor<alloc::vec::Vec<u8>>> Line | Count | Source | 118 | 748 | pub fn parse<T: Read>(reader: &mut T) -> ZipResult<Zip64CentralDirectoryEndLocator> { | 119 | 748 | let magic = reader.read_u32::<LittleEndian>()?; | 120 | 748 | if magic != ZIP64_CENTRAL_DIRECTORY_END_LOCATOR_SIGNATURE { | 121 | 748 | return Err(ZipError::InvalidArchive( | 122 | 748 | "Invalid zip64 locator digital signature header", | 123 | 748 | )); | 124 | 0 | } | 125 | 0 | let disk_with_central_directory = reader.read_u32::<LittleEndian>()?; | 126 | 0 | let end_of_central_directory_offset = reader.read_u64::<LittleEndian>()?; | 127 | 0 | let number_of_disks = reader.read_u32::<LittleEndian>()?; | 128 | | | 129 | 0 | Ok(Zip64CentralDirectoryEndLocator { | 130 | 0 | disk_with_central_directory, | 131 | 0 | end_of_central_directory_offset, | 132 | 0 | number_of_disks, | 133 | 0 | }) | 134 | 748 | } |
|
135 | | |
136 | 0 | pub fn write<T: Write>(&self, writer: &mut T) -> ZipResult<()> { |
137 | 0 | writer.write_u32::<LittleEndian>(ZIP64_CENTRAL_DIRECTORY_END_LOCATOR_SIGNATURE)?; |
138 | 0 | writer.write_u32::<LittleEndian>(self.disk_with_central_directory)?; |
139 | 0 | writer.write_u64::<LittleEndian>(self.end_of_central_directory_offset)?; |
140 | 0 | writer.write_u32::<LittleEndian>(self.number_of_disks)?; |
141 | 0 | Ok(()) |
142 | 0 | } |
143 | | } |
144 | | |
145 | | pub struct Zip64CentralDirectoryEnd { |
146 | | pub version_made_by: u16, |
147 | | pub version_needed_to_extract: u16, |
148 | | pub disk_number: u32, |
149 | | pub disk_with_central_directory: u32, |
150 | | pub number_of_files_on_this_disk: u64, |
151 | | pub number_of_files: u64, |
152 | | pub central_directory_size: u64, |
153 | | pub central_directory_offset: u64, |
154 | | //pub extensible_data_sector: Vec<u8>, <-- We don't do anything with this at the moment. |
155 | | } |
156 | | |
157 | | impl Zip64CentralDirectoryEnd { |
158 | 580 | pub fn find_and_parse<T: Read + io::Seek>( |
159 | 580 | reader: &mut T, |
160 | 580 | nominal_offset: u64, |
161 | 580 | search_upper_bound: u64, |
162 | 580 | ) -> ZipResult<(Zip64CentralDirectoryEnd, u64)> { |
163 | 580 | let mut pos = nominal_offset; |
164 | | |
165 | 3.50M | while pos <= search_upper_bound { |
166 | 3.50M | reader.seek(io::SeekFrom::Start(pos))?; |
167 | | |
168 | 3.50M | if reader.read_u32::<LittleEndian>()? == ZIP64_CENTRAL_DIRECTORY_END_SIGNATURE { |
169 | 433 | let archive_offset = pos - nominal_offset; |
170 | | |
171 | 433 | let _record_size = reader.read_u64::<LittleEndian>()?; |
172 | | // We would use this value if we did anything with the "zip64 extensible data sector". |
173 | | |
174 | 433 | let version_made_by = reader.read_u16::<LittleEndian>()?; |
175 | 433 | let version_needed_to_extract = reader.read_u16::<LittleEndian>()?; |
176 | 433 | let disk_number = reader.read_u32::<LittleEndian>()?; |
177 | 433 | let disk_with_central_directory = reader.read_u32::<LittleEndian>()?; |
178 | 433 | let number_of_files_on_this_disk = reader.read_u64::<LittleEndian>()?; |
179 | 433 | let number_of_files = reader.read_u64::<LittleEndian>()?; |
180 | 433 | let central_directory_size = reader.read_u64::<LittleEndian>()?; |
181 | 433 | let central_directory_offset = reader.read_u64::<LittleEndian>()?; |
182 | | |
183 | 433 | return Ok(( |
184 | 433 | Zip64CentralDirectoryEnd { |
185 | 433 | version_made_by, |
186 | 433 | version_needed_to_extract, |
187 | 433 | disk_number, |
188 | 433 | disk_with_central_directory, |
189 | 433 | number_of_files_on_this_disk, |
190 | 433 | number_of_files, |
191 | 433 | central_directory_size, |
192 | 433 | central_directory_offset, |
193 | 433 | }, |
194 | 433 | archive_offset, |
195 | 433 | )); |
196 | 3.50M | } |
197 | | |
198 | 3.50M | pos += 1; |
199 | | } |
200 | | |
201 | 147 | Err(ZipError::InvalidArchive( |
202 | 147 | "Could not find ZIP64 central directory end", |
203 | 147 | )) |
204 | 580 | } <zip::spec::Zip64CentralDirectoryEnd>::find_and_parse::<std::io::cursor::Cursor<&[u8]>> Line | Count | Source | 158 | 569 | pub fn find_and_parse<T: Read + io::Seek>( | 159 | 569 | reader: &mut T, | 160 | 569 | nominal_offset: u64, | 161 | 569 | search_upper_bound: u64, | 162 | 569 | ) -> ZipResult<(Zip64CentralDirectoryEnd, u64)> { | 163 | 569 | let mut pos = nominal_offset; | 164 | | | 165 | 2.18M | while pos <= search_upper_bound { | 166 | 2.18M | reader.seek(io::SeekFrom::Start(pos))?; | 167 | | | 168 | 2.18M | if reader.read_u32::<LittleEndian>()? == ZIP64_CENTRAL_DIRECTORY_END_SIGNATURE { | 169 | 423 | let archive_offset = pos - nominal_offset; | 170 | | | 171 | 423 | let _record_size = reader.read_u64::<LittleEndian>()?; | 172 | | // We would use this value if we did anything with the "zip64 extensible data sector". | 173 | | | 174 | 423 | let version_made_by = reader.read_u16::<LittleEndian>()?; | 175 | 423 | let version_needed_to_extract = reader.read_u16::<LittleEndian>()?; | 176 | 423 | let disk_number = reader.read_u32::<LittleEndian>()?; | 177 | 423 | let disk_with_central_directory = reader.read_u32::<LittleEndian>()?; | 178 | 423 | let number_of_files_on_this_disk = reader.read_u64::<LittleEndian>()?; | 179 | 423 | let number_of_files = reader.read_u64::<LittleEndian>()?; | 180 | 423 | let central_directory_size = reader.read_u64::<LittleEndian>()?; | 181 | 423 | let central_directory_offset = reader.read_u64::<LittleEndian>()?; | 182 | | | 183 | 423 | return Ok(( | 184 | 423 | Zip64CentralDirectoryEnd { | 185 | 423 | version_made_by, | 186 | 423 | version_needed_to_extract, | 187 | 423 | disk_number, | 188 | 423 | disk_with_central_directory, | 189 | 423 | number_of_files_on_this_disk, | 190 | 423 | number_of_files, | 191 | 423 | central_directory_size, | 192 | 423 | central_directory_offset, | 193 | 423 | }, | 194 | 423 | archive_offset, | 195 | 423 | )); | 196 | 2.18M | } | 197 | | | 198 | 2.18M | pos += 1; | 199 | | } | 200 | | | 201 | 146 | Err(ZipError::InvalidArchive( | 202 | 146 | "Could not find ZIP64 central directory end", | 203 | 146 | )) | 204 | 569 | } |
<zip::spec::Zip64CentralDirectoryEnd>::find_and_parse::<std::io::cursor::Cursor<&[u8]>> Line | Count | Source | 158 | 11 | pub fn find_and_parse<T: Read + io::Seek>( | 159 | 11 | reader: &mut T, | 160 | 11 | nominal_offset: u64, | 161 | 11 | search_upper_bound: u64, | 162 | 11 | ) -> ZipResult<(Zip64CentralDirectoryEnd, u64)> { | 163 | 11 | let mut pos = nominal_offset; | 164 | | | 165 | 1.32M | while pos <= search_upper_bound { | 166 | 1.32M | reader.seek(io::SeekFrom::Start(pos))?; | 167 | | | 168 | 1.32M | if reader.read_u32::<LittleEndian>()? == ZIP64_CENTRAL_DIRECTORY_END_SIGNATURE { | 169 | 10 | let archive_offset = pos - nominal_offset; | 170 | | | 171 | 10 | let _record_size = reader.read_u64::<LittleEndian>()?; | 172 | | // We would use this value if we did anything with the "zip64 extensible data sector". | 173 | | | 174 | 10 | let version_made_by = reader.read_u16::<LittleEndian>()?; | 175 | 10 | let version_needed_to_extract = reader.read_u16::<LittleEndian>()?; | 176 | 10 | let disk_number = reader.read_u32::<LittleEndian>()?; | 177 | 10 | let disk_with_central_directory = reader.read_u32::<LittleEndian>()?; | 178 | 10 | let number_of_files_on_this_disk = reader.read_u64::<LittleEndian>()?; | 179 | 10 | let number_of_files = reader.read_u64::<LittleEndian>()?; | 180 | 10 | let central_directory_size = reader.read_u64::<LittleEndian>()?; | 181 | 10 | let central_directory_offset = reader.read_u64::<LittleEndian>()?; | 182 | | | 183 | 10 | return Ok(( | 184 | 10 | Zip64CentralDirectoryEnd { | 185 | 10 | version_made_by, | 186 | 10 | version_needed_to_extract, | 187 | 10 | disk_number, | 188 | 10 | disk_with_central_directory, | 189 | 10 | number_of_files_on_this_disk, | 190 | 10 | number_of_files, | 191 | 10 | central_directory_size, | 192 | 10 | central_directory_offset, | 193 | 10 | }, | 194 | 10 | archive_offset, | 195 | 10 | )); | 196 | 1.32M | } | 197 | | | 198 | 1.32M | pos += 1; | 199 | | } | 200 | | | 201 | 1 | Err(ZipError::InvalidArchive( | 202 | 1 | "Could not find ZIP64 central directory end", | 203 | 1 | )) | 204 | 11 | } |
Unexecuted instantiation: <zip::spec::Zip64CentralDirectoryEnd>::find_and_parse::<std::io::cursor::Cursor<alloc::vec::Vec<u8>>> |
205 | | |
206 | 0 | pub fn write<T: Write>(&self, writer: &mut T) -> ZipResult<()> { |
207 | 0 | writer.write_u32::<LittleEndian>(ZIP64_CENTRAL_DIRECTORY_END_SIGNATURE)?; |
208 | 0 | writer.write_u64::<LittleEndian>(44)?; // record size |
209 | 0 | writer.write_u16::<LittleEndian>(self.version_made_by)?; |
210 | 0 | writer.write_u16::<LittleEndian>(self.version_needed_to_extract)?; |
211 | 0 | writer.write_u32::<LittleEndian>(self.disk_number)?; |
212 | 0 | writer.write_u32::<LittleEndian>(self.disk_with_central_directory)?; |
213 | 0 | writer.write_u64::<LittleEndian>(self.number_of_files_on_this_disk)?; |
214 | 0 | writer.write_u64::<LittleEndian>(self.number_of_files)?; |
215 | 0 | writer.write_u64::<LittleEndian>(self.central_directory_size)?; |
216 | 0 | writer.write_u64::<LittleEndian>(self.central_directory_offset)?; |
217 | 0 | Ok(()) |
218 | 0 | } |
219 | | } |