aboutsummaryrefslogtreecommitdiff
path: root/src/zip
diff options
context:
space:
mode:
authorIgor Tolmachov <me@igorek.dev>2023-08-30 23:33:11 +0900
committerIgor Tolmachev <me@igorek.dev>2024-06-23 15:34:33 +0900
commitb8c83ab5c133dc1330aa425a012d45f3c62e7ef1 (patch)
treee25f07a28b09ba5ae3d6c435a9be63fc59105800 /src/zip
parentf02a44964a2fdb91d62dee9c55f6d03648f985cb (diff)
downloadarchivator-b8c83ab5c133dc1330aa425a012d45f3c62e7ef1.tar.gz
archivator-b8c83ab5c133dc1330aa425a012d45f3c62e7ef1.zip
Add zip archive datatypes
Diffstat (limited to 'src/zip')
-rw-r--r--src/zip/datatypes.rs270
-rw-r--r--src/zip/mod.rs1
2 files changed, 271 insertions, 0 deletions
diff --git a/src/zip/datatypes.rs b/src/zip/datatypes.rs
new file mode 100644
index 0000000..b280e5d
--- /dev/null
+++ b/src/zip/datatypes.rs
@@ -0,0 +1,270 @@
1use crate::datatypes::{utils, ArchiveDatatype};
2use crate::result::{ArchiveError, ArchiveResult};
3use std::io::{Read, Write};
4
5utils::create_archive_datatype! {
6 pub struct LocalFileHeader {
7 signature: u32,
8 version_needed: u16,
9 general_purpose_bit_flag: u16,
10 compression_method: u16,
11 last_mod_file_time: u16,
12 last_mod_file_date: u16,
13 crc32: u32,
14 compressed_size: u32,
15 uncompressed_size: u32,
16 file_name_length: u16,
17 extra_field_length: u16,
18 }
19
20 let file_name: String {
21 size: file_name_length,
22 read: utils::read_string,
23 write: utils::write_string,
24 }
25
26 let extra_field: Vec<u8> {
27 size: file_name_length,
28 read: utils::vec,
29 write: utils::vec,
30 }
31
32 const {
33 SIGNATURE: u32 = 0x04034b50;
34 }
35
36 read {
37 if signature != Self::SIGNATURE {
38 return Err(ArchiveError::WrongSignature { expected: Self::SIGNATURE, received: signature })
39 }
40 }
41}
42
43pub struct DataDescriptor {
44 pub signature: Option<u32>,
45 pub crc32: u32,
46 pub compressed_size: u32,
47 pub uncompressed_size: u32,
48}
49
50impl DataDescriptor {
51 const SIGNATURE: u32 = 0x04034b50;
52}
53
54impl ArchiveDatatype for DataDescriptor {
55 const SIZE: usize = 12;
56
57 fn read(mut reader: impl Read) -> ArchiveResult<Self> {
58 let mut buf = [0; Self::SIZE];
59 reader.read(&mut buf)?;
60
61 let signature = u32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]]);
62 if signature == Self::SIGNATURE {
63 return Ok(Self {
64 signature: Some(signature),
65 crc32: u32::from_le_bytes([buf[4], buf[5], buf[6], buf[7]]),
66 compressed_size: u32::from_le_bytes([buf[8], buf[9], buf[10], buf[11]]),
67 uncompressed_size: {
68 let mut buf = [0; 4];
69 reader.read(&mut buf)?;
70 u32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]])
71 },
72 });
73 } else {
74 return Ok(Self {
75 signature: None,
76 crc32: signature,
77 compressed_size: u32::from_le_bytes([buf[4], buf[5], buf[6], buf[7]]),
78 uncompressed_size: u32::from_le_bytes([buf[8], buf[9], buf[10], buf[11]]),
79 });
80 }
81 }
82
83 fn write(&self, mut writer: impl Write) -> ArchiveResult<()> {
84 writer.write(
85 &[
86 Self::SIGNATURE.to_le_bytes(),
87 self.crc32.to_le_bytes(),
88 self.compressed_size.to_le_bytes(),
89 self.uncompressed_size.to_le_bytes(),
90 ]
91 .concat(),
92 )?;
93 Ok(())
94 }
95}
96
97utils::create_archive_datatype! {
98 pub struct ArchiveExtraDataRecord {
99 signature: u32,
100 extra_field_length: u32,
101 }
102
103 let extra_field: Vec<u8> {
104 size: extra_field_length,
105 read: utils::vec,
106 write: utils::vec,
107 }
108
109 const {
110 SIGNATURE: u32 = 0x08064b50;
111 }
112
113 read {
114 if signature != Self::SIGNATURE {
115 return Err(ArchiveError::WrongSignature { expected: Self::SIGNATURE, received: signature })
116 }
117 }
118}
119
120utils::create_archive_datatype! {
121 pub struct CentralDirectoryRecord {
122 signature: u32,
123 version_made_by: u16,
124 version_needed: u16,
125 general_purpose_bit_flag: u16,
126 compression_method: u16,
127 last_mod_file_time: u16,
128 last_mod_file_date: u16,
129 crc32: u32,
130 compressed_size: u32,
131 uncompressed_size: u32,
132 file_name_length: u16,
133 extra_field_length: u16,
134 file_comment_length: u16,
135 disk_number: u16,
136 internal_file_attributes: u16,
137 external_file_attributes: u32,
138 relative_header_offset: u32,
139 }
140
141 let file_name: String {
142 size: file_name_length,
143 read: utils::read_string,
144 write: utils::write_string,
145 }
146
147 let extra_field: Vec<u8> {
148 size: external_file_attributes,
149 read: utils::vec,
150 write: utils::vec,
151 }
152
153 let file_comment: String {
154 size: file_comment_length,
155 read: utils::read_string,
156 write: utils::write_string,
157 }
158
159 const {
160 SIGNATURE: u32 = 0x02014b50;
161 }
162
163 read {
164 if signature != Self::SIGNATURE {
165 return Err(ArchiveError::WrongSignature { expected: Self::SIGNATURE, received: signature })
166 }
167 }
168}
169
170utils::create_archive_datatype! {
171 pub struct DigitalSignature{
172 signature: u32,
173 data_size: u16,
174 }
175
176 let data: Vec<u8> {
177 size: data_size,
178 read: utils::vec,
179 write: utils::vec,
180 }
181
182 const {
183 SIGNATURE: u32 = 0x05054b50;
184 }
185
186 read {
187 if signature != Self::SIGNATURE {
188 return Err(ArchiveError::WrongSignature { expected: Self::SIGNATURE, received: signature })
189 }
190 }
191}
192
193utils::create_archive_datatype! {
194 pub struct Zip64EndOfCentralDirectoryRecord {
195 signature: u32,
196 size_of_struct: u64,
197 version_made_by: u16,
198 version_needed: u16,
199 disk_number: u32,
200 disk_number_where_starts_central_directory: u32,
201 entries_in_central_directory_on_disk: u64,
202 entries_in_central_directory: u64,
203 size_of_central_directory_records: u64,
204 offset_of_central_directory_entries: u64,
205 }
206
207 let extensible_data: Vec<u8> {
208 size: size_of_struct - Self::SIZE as u64 + 12,
209 read: utils::vec,
210 write: utils::vec,
211 }
212
213 const {
214 SIGNATURE: u32 = 0x08064b50;
215 }
216
217 read {
218 if signature != Self::SIGNATURE {
219 return Err(ArchiveError::WrongSignature { expected: Self::SIGNATURE, received: signature })
220 }
221 }
222}
223
224utils::create_archive_datatype! {
225 pub struct Zip64EndOfCentralDirectoryLocator {
226 signature: u32,
227 disk_number_where_starts_zip64_eocd: u32,
228 relative_offset_of_zip64_eocd: u64,
229 total_disks_number: u32,
230 }
231
232 const {
233 SIGNATURE: u32 = 0x07064b50;
234 }
235
236 read {
237 if signature != Self::SIGNATURE {
238 return Err(ArchiveError::WrongSignature { expected: Self::SIGNATURE, received: signature })
239 }
240 }
241}
242
243utils::create_archive_datatype! {
244 pub struct EndOfCentralDirectoryRecord {
245 signature: u32,
246 disk_number: u16,
247 disk_number_where_starts_central_directory: u16,
248 entries_in_central_directory_on_disk: u16,
249 entries_in_central_directory: u16,
250 size_of_central_directory_records: u32,
251 offset_of_central_directory_entries: u32,
252 comment_length: u16,
253 }
254
255 let comment: String {
256 size: comment_length,
257 read: utils::read_string,
258 write: utils::write_string,
259 }
260
261 const {
262 SIGNATURE: u32 = 0x06054b50;
263 }
264
265 read {
266 if signature != Self::SIGNATURE {
267 return Err(ArchiveError::WrongSignature { expected: Self::SIGNATURE, received: signature })
268 }
269 }
270}
diff --git a/src/zip/mod.rs b/src/zip/mod.rs
index 5241c87..b668b6b 100644
--- a/src/zip/mod.rs
+++ b/src/zip/mod.rs
@@ -1,4 +1,5 @@
1mod archive; 1mod archive;
2mod datatypes;
2mod file; 3mod file;
3mod io; 4mod io;
4 5