Line | Branch | Exec | Source |
---|---|---|---|
1 | /* GATE PROJECT LICENSE: | ||
2 | +----------------------------------------------------------------------------+ | ||
3 | | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> | | ||
4 | | All rights reserved. | | ||
5 | | | | ||
6 | | Redistribution and use in source and binary forms, with or without | | ||
7 | | modification, are permitted provided that the following conditions are met:| | ||
8 | | | | ||
9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
10 | | this list of conditions and the following disclaimer. | | ||
11 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
12 | | notice, this list of conditions and the following disclaimer in the | | ||
13 | | documentation and/or other materials provided with the distribution. | | ||
14 | | | | ||
15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
26 | +----------------------------------------------------------------------------+ | ||
27 | */ | ||
28 | |||
29 | #include "gate/encode/zipstreams.h" | ||
30 | #include "gate/results.h" | ||
31 | #include "gate/debugging.h" | ||
32 | #include "gate/files.h" | ||
33 | |||
34 | #if defined(GATE_EXTLIB_MINIZIP) | ||
35 | # define GATE_ENCODE_ZIPSTREAM_IMPL 1 | ||
36 | #else | ||
37 | # define GATE_ECNODE_ZIPSTREAM_NO_IMPL 1 | ||
38 | #endif | ||
39 | |||
40 | |||
41 | ✗ | void gate_zipentry_init(gate_zipentry_t* entry, gate_string_t const* path, gate_uint64_t size, | |
42 | gate_enumint_t attribs, gate_enumint_t accessbits, gate_string_t const* comment) | ||
43 | { | ||
44 | ✗ | gate_mem_clear(entry, sizeof(gate_zipentry_t)); | |
45 | ✗ | if (path) | |
46 | { | ||
47 | ✗ | gate_string_to_buffer(path, entry->path, sizeof(entry->path)); | |
48 | } | ||
49 | ✗ | if (comment) | |
50 | { | ||
51 | ✗ | gate_string_to_buffer(comment, entry->comment, sizeof(entry->comment)); | |
52 | } | ||
53 | ✗ | entry->size = size; | |
54 | ✗ | entry->attribs = attribs; | |
55 | ✗ | entry->access = accessbits; | |
56 | ✗ | } | |
57 | |||
58 | struct gate_zip_attrib_mapping | ||
59 | { | ||
60 | gate_enumint_t gate_attr; | ||
61 | gate_uint32_t zip_attr; | ||
62 | }; | ||
63 | |||
64 | static struct gate_zip_attrib_mapping const zip_attribs[] = | ||
65 | { | ||
66 | { GATE_FILEENTRY_ATTRIB_READONLY, 0x00000001 }, | ||
67 | { GATE_FILEENTRY_ATTRIB_HIDDEN, 0x00000002 }, | ||
68 | { GATE_FILEENTRY_ATTRIB_SYSTEM, 0x00000004 }, | ||
69 | { GATE_FILEENTRY_ATTRIB_DIRECTORY, 0x40000010 }, | ||
70 | { GATE_FILEENTRY_ATTRIB_ARCHIVE, 0x00000020 } | ||
71 | }; | ||
72 | static gate_size_t const zip_attribs_count = sizeof(zip_attribs) / sizeof(zip_attribs[0]); | ||
73 | |||
74 | static struct gate_zip_attrib_mapping const zip_accessbits[] = | ||
75 | { | ||
76 | { GATE_FILEENTRY_ACCESS_OWNERREAD, 0x01000000 }, | ||
77 | { GATE_FILEENTRY_ACCESS_OWNERWRITE, 0x00800000 }, | ||
78 | { GATE_FILEENTRY_ACCESS_OWNEREXECUTE, 0x00400000 }, | ||
79 | { GATE_FILEENTRY_ACCESS_OWNERSETID, 0x08000000 }, | ||
80 | { GATE_FILEENTRY_ACCESS_GROUPREAD, 0x00200000 }, | ||
81 | { GATE_FILEENTRY_ACCESS_GROUPWRITE, 0x00100000 }, | ||
82 | { GATE_FILEENTRY_ACCESS_GROUPEXECUTE, 0x00080000 }, | ||
83 | { GATE_FILEENTRY_ACCESS_GROUPSETID, 0x04000000 }, | ||
84 | { GATE_FILEENTRY_ACCESS_ALLREAD, 0x00040000 }, | ||
85 | { GATE_FILEENTRY_ACCESS_ALLWRITE, 0x00020000 }, | ||
86 | { GATE_FILEENTRY_ACCESS_ALLEXECUTE, 0x00010000 }, | ||
87 | { GATE_FILEENTRY_ACCESS_NODELETE, 0x02000000 }, | ||
88 | }; | ||
89 | static gate_size_t const zip_accessbits_count = sizeof(zip_accessbits) / sizeof(zip_accessbits[0]); | ||
90 | |||
91 | #define GATE_ZIP_FILETYPE_FILE 0x08 | ||
92 | #define GATE_ZIP_FILETYPE_DIR 0x04 | ||
93 | #define GATE_ZIP_FILETYPE_LINK 0x0a | ||
94 | |||
95 | |||
96 | 2 | static gate_uint32_t gate_attribs_to_zip_attribs(gate_enumint_t gateattrs) | |
97 | { | ||
98 | 2 | gate_uint32_t zip_attrs = 0; | |
99 | gate_size_t n; | ||
100 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
|
12 | for (n = 0; n != zip_attribs_count; ++n) |
101 | { | ||
102 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | GATE_FLAG_SET(zip_attrs, zip_attribs[n].zip_attr, GATE_FLAG_ENABLED(gateattrs, zip_attribs[n].gate_attr)); |
103 | } | ||
104 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (GATE_FLAG_ENABLED(gateattrs, GATE_FILEENTRY_ATTRIB_DIRECTORY)) |
105 | { | ||
106 | ✗ | zip_attrs |= (((gate_uint32_t)GATE_ZIP_FILETYPE_DIR) << 28); | |
107 | } | ||
108 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (GATE_FLAG_ENABLED(gateattrs, GATE_FILEENTRY_ATTRIB_LINK)) |
109 | { | ||
110 | ✗ | zip_attrs |= (((gate_uint32_t)GATE_ZIP_FILETYPE_DIR) << 28); | |
111 | } | ||
112 | 2 | return zip_attrs; | |
113 | } | ||
114 | 2 | static gate_uint32_t gate_accessbits_to_zip_attribs(gate_enumint_t gateaccessbits) | |
115 | { | ||
116 | 2 | gate_uint32_t zip_attrs = 0; | |
117 | gate_size_t n; | ||
118 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 2 times.
|
26 | for (n = 0; n != zip_accessbits_count; ++n) |
119 | { | ||
120 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20 times.
|
24 | GATE_FLAG_SET(zip_attrs, zip_accessbits[n].zip_attr, GATE_FLAG_ENABLED(gateaccessbits, zip_accessbits[n].gate_attr)); |
121 | } | ||
122 | 2 | return zip_attrs; | |
123 | } | ||
124 | |||
125 | 4 | static gate_enumint_t zip_attribs_to_gate_attribs(gate_uint32_t attrs) | |
126 | { | ||
127 | 4 | gate_enumint_t gate_attrs = 0; | |
128 | gate_size_t n; | ||
129 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 4 times.
|
24 | for (n = 0; n != zip_attribs_count; ++n) |
130 | { | ||
131 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | GATE_FLAG_SET(gate_attrs, zip_attribs[n].gate_attr, GATE_FLAG_ENABLED(attrs, zip_attribs[n].zip_attr)); |
132 | } | ||
133 | 4 | attrs >>= 28; | |
134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (attrs == GATE_ZIP_FILETYPE_DIR) |
135 | { | ||
136 | ✗ | gate_attrs |= GATE_FILEENTRY_ATTRIB_DIRECTORY; | |
137 | } | ||
138 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (attrs == GATE_ZIP_FILETYPE_LINK) |
139 | { | ||
140 | ✗ | gate_attrs |= GATE_FILEENTRY_ATTRIB_LINK; | |
141 | } | ||
142 | 4 | return gate_attrs; | |
143 | } | ||
144 | 4 | static gate_enumint_t zip_attribs_to_gate_accessbits(gate_uint32_t attrs) | |
145 | { | ||
146 | 4 | gate_enumint_t gate_access = 0; | |
147 | gate_size_t n; | ||
148 |
2/2✓ Branch 0 taken 48 times.
✓ Branch 1 taken 4 times.
|
52 | for (n = 0; n != zip_accessbits_count; ++n) |
149 | { | ||
150 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 40 times.
|
48 | GATE_FLAG_SET(gate_access, zip_accessbits[n].gate_attr, GATE_FLAG_ENABLED(attrs, zip_accessbits[n].zip_attr)); |
151 | } | ||
152 | 4 | return gate_access; | |
153 | } | ||
154 | |||
155 | |||
156 | |||
157 | #if defined(GATE_ENCODE_ZIPSTREAM_IMPL) | ||
158 | |||
159 | #if defined(GATE_EXTLIB_BZIP2) && !defined(HAVE_BZIP2) | ||
160 | # define HAVE_BZIP2 | ||
161 | #endif | ||
162 | #include "zlib.h" | ||
163 | #include "zip.h" | ||
164 | #include "unzip.h" | ||
165 | |||
166 | 4 | static voidpf ZCALLBACK gate_zipwriter_open_file_func(voidpf opaque, const char* filename, int mode) | |
167 | { | ||
168 | 4 | gate_ziptarget_t* target = (gate_ziptarget_t*)opaque; | |
169 | GATE_UNUSED_ARG(filename); | ||
170 | GATE_UNUSED_ARG(mode); | ||
171 | 4 | return target->stream; | |
172 | } | ||
173 | 302 | static uLong ZCALLBACK gate_zipwriter_read_file_func(voidpf opaque, voidpf stream, void* buf, uLong size) | |
174 | { | ||
175 | 302 | gate_ziptarget_t* target = (gate_ziptarget_t*)opaque; | |
176 | 302 | gate_size_t returned = 0; | |
177 | 302 | GATE_DEBUG_ASSERT(target->stream == (gate_stream_t*)stream); | |
178 | GATE_UNUSED_ARG(stream); | ||
179 | |||
180 | 302 | target->last_result = gate_stream_read_block(target->stream, (char*)buf, (gate_size_t)size, &returned); | |
181 |
1/2✓ Branch 0 taken 302 times.
✗ Branch 1 not taken.
|
302 | if (GATE_SUCCEEDED(target->last_result)) |
182 | { | ||
183 | 302 | target->bytes_received += returned; | |
184 | 302 | return (uLong)returned; | |
185 | } | ||
186 | else | ||
187 | { | ||
188 | ✗ | return 0; | |
189 | } | ||
190 | } | ||
191 | 39 | static uLong ZCALLBACK gate_zipwriter_write_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) | |
192 | { | ||
193 | 39 | gate_ziptarget_t* target = (gate_ziptarget_t*)opaque; | |
194 | 39 | gate_size_t written = 0; | |
195 | 39 | GATE_DEBUG_ASSERT(target->stream == (gate_stream_t*)stream); | |
196 | GATE_UNUSED_ARG(stream); | ||
197 | |||
198 | 39 | target->last_result = gate_stream_write_block(target->stream, (char const*)buf, (gate_size_t)size, &written); | |
199 |
1/2✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
|
39 | if (GATE_SUCCEEDED(target->last_result)) |
200 | { | ||
201 | 39 | target->bytes_written += written; | |
202 | 39 | return (uLong)written; | |
203 | } | ||
204 | else | ||
205 | { | ||
206 | ✗ | return 0; | |
207 | } | ||
208 | } | ||
209 | 4 | static int ZCALLBACK gate_zipwriter_close_file_func(voidpf opaque, voidpf stream) | |
210 | { | ||
211 | 4 | gate_ziptarget_t* target = (gate_ziptarget_t*)opaque; | |
212 | 4 | GATE_DEBUG_ASSERT(target->stream == (gate_stream_t*)stream); | |
213 | GATE_UNUSED_ARG(stream); | ||
214 | |||
215 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (target->control_stream) |
216 | { | ||
217 | 4 | target->last_result = gate_stream_close(target->control_stream, GATE_STREAM_CLOSE_DEFAULT); | |
218 | } | ||
219 | 4 | return 0; | |
220 | } | ||
221 | ✗ | static int ZCALLBACK gate_zipwriter_testerror_file_func(voidpf opaque, voidpf stream) | |
222 | { | ||
223 | ✗ | gate_ziptarget_t* target = (gate_ziptarget_t*)opaque; | |
224 | ✗ | GATE_DEBUG_ASSERT(target->stream == (gate_stream_t*)stream); | |
225 | ✗ | if (GATE_FAILED(target->last_result)) | |
226 | { | ||
227 | ✗ | return 1; | |
228 | } | ||
229 | ✗ | return 0; | |
230 | } | ||
231 | |||
232 | 12 | static long ZCALLBACK gate_zipwriter_tell_file_func(voidpf opaque, voidpf stream) | |
233 | { | ||
234 | 12 | gate_ziptarget_t* target = (gate_ziptarget_t*)opaque; | |
235 | 12 | gate_int64_t position = 0; | |
236 | gate_result_t res; | ||
237 | 12 | GATE_DEBUG_ASSERT(target->stream == (gate_stream_t*)stream); | |
238 | GATE_UNUSED_ARG(stream); | ||
239 | |||
240 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (target->control_stream) |
241 | { | ||
242 | 12 | res = gate_stream_get_position(target->control_stream, &position); | |
243 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | if (GATE_SUCCEEDED(res)) |
244 | { | ||
245 | 12 | return (long)position; | |
246 | } | ||
247 | } | ||
248 | else | ||
249 | { | ||
250 | ✗ | return (long)(target->bytes_received + target->bytes_written); | |
251 | } | ||
252 | ✗ | return -1; | |
253 | } | ||
254 | 41 | static long ZCALLBACK gate_zipwriter_seek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) | |
255 | { | ||
256 | 41 | gate_ziptarget_t* target = (gate_ziptarget_t*)opaque; | |
257 | 41 | gate_result_t res = 0; | |
258 | 41 | gate_int64_t stream_pos = (gate_int64_t)offset; | |
259 | 41 | gate_int64_t new_pos = 0; | |
260 | gate_uint32_t stream_origin; | ||
261 | 41 | GATE_DEBUG_ASSERT(target->stream == (gate_stream_t*)stream); | |
262 | GATE_UNUSED_ARG(stream); | ||
263 | |||
264 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | if (target->control_stream) |
265 | { | ||
266 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
|
41 | switch (origin) |
267 | { | ||
268 | ✗ | case ZLIB_FILEFUNC_SEEK_CUR: stream_origin = GATE_STREAM_SEEK_CURRENT; break; | |
269 | 6 | case ZLIB_FILEFUNC_SEEK_END: stream_origin = GATE_STREAM_SEEK_END; break; | |
270 | 35 | case ZLIB_FILEFUNC_SEEK_SET: stream_origin = GATE_STREAM_SEEK_BEGIN; break; | |
271 | ✗ | default: return -1; | |
272 | } | ||
273 | |||
274 | 41 | res = gate_stream_seek(target->control_stream, stream_pos, stream_origin, &new_pos); | |
275 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | if (GATE_SUCCEEDED(res)) |
276 | { | ||
277 | 41 | return 0; | |
278 | } | ||
279 | } | ||
280 | else | ||
281 | { | ||
282 | ✗ | switch (origin) | |
283 | { | ||
284 | ✗ | case ZLIB_FILEFUNC_SEEK_CUR: | |
285 | { | ||
286 | ✗ | if (offset == 0) | |
287 | { | ||
288 | ✗ | return 0; /* no change is supported */ | |
289 | } | ||
290 | ✗ | return -1; /* any other change is not supported */ | |
291 | } | ||
292 | ✗ | case ZLIB_FILEFUNC_SEEK_END: | |
293 | { | ||
294 | ✗ | return -1; /* moving to end is not supported */ | |
295 | } | ||
296 | ✗ | case ZLIB_FILEFUNC_SEEK_SET: | |
297 | { | ||
298 | ✗ | if (offset == 0) | |
299 | { | ||
300 | ✗ | return ((target->bytes_received == 0) && (target->bytes_written == 0)) ? 0 : -1; | |
301 | } | ||
302 | ✗ | return ((target->bytes_received == offset) || (target->bytes_written == offset)) ? 0 : -1; | |
303 | } | ||
304 | ✗ | default: | |
305 | { | ||
306 | ✗ | return -1; | |
307 | } | ||
308 | } | ||
309 | } | ||
310 | ✗ | return -1; | |
311 | } | ||
312 | |||
313 | |||
314 | |||
315 | 1 | gate_result_t gate_zipwriter_create(gate_zipwriter_t* writer, gate_stream_t* stream) | |
316 | { | ||
317 | 1 | gate_result_t ret = GATE_RESULT_FAILED; | |
318 | zlib_filefunc_def* file_functions; | ||
319 | |||
320 | do | ||
321 | { | ||
322 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (!writer || !stream) |
323 | { | ||
324 | ✗ | ret = GATE_RESULT_NULLPOINTER; | |
325 | ✗ | break; | |
326 | } | ||
327 | |||
328 | 1 | gate_mem_clear(writer, sizeof(gate_zipwriter_t*)); | |
329 | |||
330 | 1 | writer->zipstream.last_result = GATE_RESULT_OK; | |
331 | 1 | writer->zipstream.bytes_written = 0; | |
332 | 1 | writer->zipstream.bytes_received = 0; | |
333 | 1 | writer->zipstream.stream = stream; | |
334 | 1 | writer->zipstream.control_stream = NULL; | |
335 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (gate_object_implements_interface((gate_object_t*)stream, GATE_INTERFACE_NAME_CONTROLSTREAM)) |
336 | { | ||
337 | 1 | writer->zipstream.control_stream = (gate_controlstream_t*)stream; | |
338 | } | ||
339 | 1 | file_functions = (zlib_filefunc_def*)&writer->native_params; | |
340 | 1 | file_functions->zopen_file = &gate_zipwriter_open_file_func; | |
341 | 1 | file_functions->zread_file = &gate_zipwriter_read_file_func; | |
342 | 1 | file_functions->zwrite_file = &gate_zipwriter_write_file_func; | |
343 | 1 | file_functions->ztell_file = &gate_zipwriter_tell_file_func; | |
344 | 1 | file_functions->zseek_file = &gate_zipwriter_seek_file_func; | |
345 | 1 | file_functions->zclose_file = &gate_zipwriter_close_file_func; | |
346 | 1 | file_functions->zerror_file = &gate_zipwriter_testerror_file_func; | |
347 | 1 | file_functions->opaque = &writer->zipstream; | |
348 | |||
349 | 1 | writer->native_handle = (void*)zipOpen2((char const*)&writer->zipstream, APPEND_STATUS_CREATE, NULL, file_functions); | |
350 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (NULL == writer->native_handle) |
351 | { | ||
352 | ✗ | gate_mem_clear(writer, sizeof(gate_zipwriter_t*)); | |
353 | ✗ | ret = GATE_RESULT_FAILED; | |
354 | ✗ | break; | |
355 | } | ||
356 | |||
357 | 1 | gate_object_retain(writer->zipstream.stream); | |
358 | 1 | ret = GATE_RESULT_OK; | |
359 | } while (0); | ||
360 | |||
361 | 1 | return ret; | |
362 | } | ||
363 | 2 | gate_result_t gate_zipwriter_add(gate_zipwriter_t* writer, gate_zipentry_t const* entry, gate_stream_t* stream) | |
364 | { | ||
365 | 2 | gate_result_t ret = GATE_RESULT_FAILED; | |
366 | char buffer[GATE_MAX_COPYBUFFER_LENGTH]; | ||
367 | gate_size_t buffer_used; | ||
368 | 2 | gate_size_t comment_length = 0; | |
369 | 2 | zip_fileinfo zip_info = GATE_INIT_EMPTY; | |
370 | gate_datetime_t dt; | ||
371 | int result; | ||
372 | #if defined(GATE_SYS_DOS) | ||
373 | int window_bits = (MAX_WBITS - 1); | ||
374 | int compression_level = (Z_BEST_COMPRESSION + Z_BEST_SPEED) / 2; | ||
375 | int memlevel = (DEF_MEM_LEVEL - 1); | ||
376 | #else | ||
377 | 2 | int window_bits = MAX_WBITS; | |
378 | 2 | int compression_level = Z_BEST_COMPRESSION; | |
379 | 2 | int memlevel = DEF_MEM_LEVEL; | |
380 | #endif | ||
381 | |||
382 | do | ||
383 | { | ||
384 | 2 | comment_length = gate_str_length(entry->comment); | |
385 | |||
386 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (entry->modified_date.timestamp) |
387 | { | ||
388 | 2 | ret = gate_time_to_datetime(&entry->modified_date, &dt); | |
389 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | GATE_BREAK_IF_FAILED(ret); |
390 | |||
391 | 2 | zip_info.tmz_date.tm_year = dt.date.year; | |
392 | 2 | zip_info.tmz_date.tm_mon = dt.date.month - 1; | |
393 | 2 | zip_info.tmz_date.tm_mday = dt.date.day; | |
394 | 2 | zip_info.tmz_date.tm_hour = dt.time.hour; | |
395 | 2 | zip_info.tmz_date.tm_min = dt.time.minute; | |
396 | 2 | zip_info.tmz_date.tm_sec = dt.time.second; | |
397 | } | ||
398 | 2 | zip_info.external_fa = gate_accessbits_to_zip_attribs(entry->access); | |
399 | 2 | zip_info.external_fa |= gate_attribs_to_zip_attribs(entry->attribs); | |
400 | |||
401 | /* | ||
402 | result = zipOpenNewFileInZip64((zipFile)writer->native_handle, entry->path, &zip_info, 0, 0, 0, 0, | ||
403 | ((comment_length == 0) ? NULL : entry->comment), | ||
404 | Z_DEFLATED, Z_BEST_COMPRESSION, | ||
405 | (entry->size >= 0xffffffff) ? 1 : 0); | ||
406 | */ | ||
407 | 2 | result = zipOpenNewFileInZip4_64((zipFile)writer->native_handle, entry->path, &zip_info, 0, 0, 0, 0, | |
408 | ((comment_length == 0) ? NULL : entry->comment), | ||
409 | Z_DEFLATED, compression_level, 0, | ||
410 | -window_bits, memlevel, Z_DEFAULT_STRATEGY, | ||
411 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | NULL, 0, 0, 0, (entry->size >= 0xffffffff) ? 1 : 0); |
412 | |||
413 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ZIP_OK != result) |
414 | { | ||
415 | ✗ | ret = GATE_RESULT_FAILED; | |
416 | ✗ | break; | |
417 | } | ||
418 | |||
419 | do | ||
420 | { | ||
421 | 4 | ret = gate_stream_read_block(stream, buffer, sizeof(buffer), &buffer_used); | |
422 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (GATE_SUCCEEDED(ret)) |
423 | { | ||
424 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | if (buffer_used == 0) |
425 | { | ||
426 | /* end of stream reached */ | ||
427 | 2 | break; | |
428 | } | ||
429 | 2 | result = zipWriteInFileInZip((zipFile)writer->native_handle, buffer, (unsigned int)buffer_used); | |
430 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ZIP_OK != result) |
431 | { | ||
432 | ✗ | ret = GATE_RESULT_INVALIDOUTPUT; | |
433 | ✗ | break; | |
434 | } | ||
435 | } | ||
436 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | } while (GATE_SUCCEEDED(ret)); |
437 | |||
438 | 2 | zipCloseFileInZip((zipFile)writer->native_handle); | |
439 | } while (0); | ||
440 | 2 | return ret; | |
441 | } | ||
442 | 2 | gate_result_t gate_zipwriter_add_data(gate_zipwriter_t* writer, gate_zipentry_t const* entry, void const* data) | |
443 | { | ||
444 | 2 | gate_memstream_impl_t impl = GATE_INIT_EMPTY; | |
445 | 2 | gate_size_t datalen = (gate_size_t)entry->size; | |
446 | 2 | gate_memstream_t* stream = gate_memstream_create_static_unmanaged_readonly(&impl, data, datalen, datalen); | |
447 | 2 | return gate_zipwriter_add(writer, entry, (gate_stream_t*)stream); | |
448 | } | ||
449 | 1 | gate_result_t gate_zipwriter_flush(gate_zipwriter_t* writer) | |
450 | { | ||
451 | 1 | return gate_stream_flush(writer->zipstream.stream); | |
452 | } | ||
453 | 1 | gate_result_t gate_zipwriter_destroy(gate_zipwriter_t* writer) | |
454 | { | ||
455 | 1 | gate_result_t ret = GATE_RESULT_OK; | |
456 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (writer->native_handle) |
457 | { | ||
458 | 1 | zipClose(writer->native_handle, NULL); | |
459 | } | ||
460 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (writer->zipstream.stream) |
461 | { | ||
462 | 1 | gate_object_release(writer->zipstream.stream); | |
463 | } | ||
464 | 1 | gate_mem_clear(writer, sizeof(gate_zipwriter_t)); | |
465 | 1 | return ret; | |
466 | } | ||
467 | |||
468 | |||
469 | |||
470 | |||
471 | /* zip reader */ | ||
472 | |||
473 | 3 | gate_result_t gate_zipreader_create(gate_zipreader_t* reader, gate_stream_t* stream) | |
474 | { | ||
475 | 3 | gate_result_t ret = GATE_RESULT_FAILED; | |
476 | zlib_filefunc_def* file_functions; | ||
477 | |||
478 | do | ||
479 | { | ||
480 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (!reader || !stream) |
481 | { | ||
482 | ✗ | ret = GATE_RESULT_NULLPOINTER; | |
483 | ✗ | break; | |
484 | } | ||
485 | |||
486 | 3 | gate_mem_clear(reader, sizeof(gate_zipreader_t)); | |
487 | 3 | reader->zipstream.stream = stream; | |
488 | 3 | reader->zipstream.bytes_written = 0; | |
489 | 3 | reader->zipstream.bytes_received = 0; | |
490 | |||
491 | 3 | reader->zipstream.last_result = GATE_RESULT_OK; | |
492 | 3 | reader->zipstream.stream = stream; | |
493 | 3 | reader->zipstream.control_stream = NULL; | |
494 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if (gate_object_implements_interface((gate_object_t*)stream, GATE_INTERFACE_NAME_CONTROLSTREAM)) |
495 | { | ||
496 | 3 | reader->zipstream.control_stream = (gate_controlstream_t*)stream; | |
497 | } | ||
498 | 3 | file_functions = (zlib_filefunc_def*)&reader->native_params; | |
499 | 3 | file_functions->zopen_file = &gate_zipwriter_open_file_func; | |
500 | 3 | file_functions->zread_file = &gate_zipwriter_read_file_func; | |
501 | 3 | file_functions->zwrite_file = &gate_zipwriter_write_file_func; | |
502 | 3 | file_functions->ztell_file = &gate_zipwriter_tell_file_func; | |
503 | 3 | file_functions->zseek_file = &gate_zipwriter_seek_file_func; | |
504 | 3 | file_functions->zclose_file = &gate_zipwriter_close_file_func; | |
505 | 3 | file_functions->zerror_file = &gate_zipwriter_testerror_file_func; | |
506 | 3 | file_functions->opaque = &reader->zipstream; | |
507 | |||
508 | 3 | reader->native_handle = (void*)unzOpen2((char const*)&reader->zipstream, file_functions); | |
509 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (NULL == reader->native_handle) |
510 | { | ||
511 | ✗ | gate_mem_clear(reader, sizeof(gate_zipwriter_t*)); | |
512 | ✗ | ret = GATE_RESULT_FAILED; | |
513 | ✗ | break; | |
514 | } | ||
515 | |||
516 | 3 | gate_object_retain(reader->zipstream.stream); | |
517 | 3 | ret = GATE_RESULT_OK; | |
518 | } while (0); | ||
519 | |||
520 | 3 | return ret; | |
521 | } | ||
522 | |||
523 | 4 | static gate_result_t gate_zipreader_build_entry(unzFile unz_handle, gate_zipentry_t* ptr_entry) | |
524 | { | ||
525 | 4 | unz_file_info64 info = GATE_INIT_EMPTY; | |
526 | gate_datetime_t dtm; | ||
527 | 4 | gate_time_t now = GATE_INIT_EMPTY; | |
528 | gate_size_t pathlen; | ||
529 | int result; | ||
530 | 4 | gate_mem_clear(ptr_entry, sizeof(gate_zipentry_t)); | |
531 | 4 | result = unzGetCurrentFileInfo64(unz_handle, &info, | |
532 | 4 | ptr_entry->path, sizeof(ptr_entry->path), | |
533 | NULL, 0, | ||
534 | 4 | ptr_entry->comment, sizeof(ptr_entry->comment)); | |
535 | |||
536 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (UNZ_OK != result) |
537 | { | ||
538 | ✗ | GATE_DEBUG_TRACE("unzGetCurrentFileInfo64() failed"); | |
539 | ✗ | return GATE_RESULT_FAILED; | |
540 | } | ||
541 | |||
542 | 4 | gate_time_now(&now); | |
543 | |||
544 | 4 | ptr_entry->crc = info.crc; | |
545 | 4 | ptr_entry->version = info.version; | |
546 | 4 | ptr_entry->flag = info.flag; | |
547 | 4 | ptr_entry->compression_method = info.compression_method; | |
548 | 4 | ptr_entry->attribs = zip_attribs_to_gate_attribs(info.external_fa); | |
549 | 4 | ptr_entry->access = zip_attribs_to_gate_accessbits(info.external_fa); | |
550 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (!GATE_FLAG_ENABLED(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_FILE) |
551 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | && !GATE_FLAG_ENABLED(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_DIRECTORY) |
552 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | && !GATE_FLAG_ENABLED(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_LINK)) |
553 | { | ||
554 | 4 | pathlen = gate_str_length_max(ptr_entry->path, sizeof(ptr_entry->path)); | |
555 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (pathlen > 0) |
556 | { | ||
557 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (ptr_entry->path[pathlen - 1] == '/') |
558 | { | ||
559 | ✗ | GATE_FLAG_SET(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_DIRECTORY, true); | |
560 | } | ||
561 | else | ||
562 | { | ||
563 | 4 | GATE_FLAG_SET(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_FILE, true); | |
564 | } | ||
565 | } | ||
566 | } | ||
567 | 4 | ptr_entry->size = info.uncompressed_size; | |
568 | 4 | ptr_entry->compressed_size = info.compressed_size; | |
569 | 4 | ptr_entry->modified_date.bias = 0; | |
570 | |||
571 | 4 | dtm.date.year = (gate_uint16_t)info.tmu_date.tm_year; | |
572 | 4 | dtm.date.month = (gate_uint8_t)(info.tmu_date.tm_mon + 1); | |
573 | 4 | dtm.date.day = (gate_uint8_t)info.tmu_date.tm_mday; | |
574 | 4 | dtm.time.hour = (gate_uint8_t)info.tmu_date.tm_hour; | |
575 | 4 | dtm.time.minute = (gate_uint8_t)info.tmu_date.tm_min; | |
576 | 4 | dtm.time.second = (gate_uint8_t)info.tmu_date.tm_sec; | |
577 | 4 | dtm.time.microsecond = 0; | |
578 | 4 | gate_date_to_time(&dtm, &ptr_entry->modified_date); | |
579 | //ptr_entry->modified_date.bias = now.bias; | ||
580 | 4 | return GATE_RESULT_OK; | |
581 | } | ||
582 | |||
583 | |||
584 | 1 | gate_result_t gate_zipreader_get_first_entry(gate_zipreader_t* reader, gate_zipentry_t* ptr_entry) | |
585 | { | ||
586 | 1 | unzFile unz_handle = (unzFile)reader->native_handle; | |
587 | 1 | int result = unzGoToFirstFile(unz_handle); | |
588 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (UNZ_OK != result) |
589 | { | ||
590 | ✗ | GATE_DEBUG_TRACE("unzGoToFirstFile() failed"); | |
591 | ✗ | return GATE_RESULT_FAILED; | |
592 | } | ||
593 | 1 | reader->eof_reached = false; | |
594 | 1 | return gate_zipreader_build_entry(unz_handle, ptr_entry); | |
595 | } | ||
596 | |||
597 | 1 | gate_result_t gate_zipreader_get_next_entry(gate_zipreader_t* reader, gate_zipentry_t* ptr_entry) | |
598 | { | ||
599 | 1 | unzFile unz_handle = (unzFile)reader->native_handle; | |
600 | 1 | int result = unzGoToNextFile(unz_handle); | |
601 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (UNZ_END_OF_LIST_OF_FILE == result) |
602 | { | ||
603 | ✗ | GATE_DEBUG_TRACE("unzGoToNextFile() == UNZ_END_OF_LIST_OF_FILE"); | |
604 | ✗ | return GATE_RESULT_ENDOFSTREAM; | |
605 | } | ||
606 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (UNZ_OK != result) |
607 | { | ||
608 | ✗ | GATE_DEBUG_TRACE("unzGoToNextFile() failed"); | |
609 | ✗ | return GATE_RESULT_FAILED; | |
610 | } | ||
611 | 1 | return gate_zipreader_build_entry(unz_handle, ptr_entry); | |
612 | } | ||
613 | 2 | gate_result_t gate_zipreader_find_entry(gate_zipreader_t* reader, gate_string_t const* path, gate_zipentry_t* ptr_entry) | |
614 | { | ||
615 | 2 | unzFile unz_handle = (unzFile)reader->native_handle; | |
616 | int result; | ||
617 | char path_buffer[GATE_MAX_FILEPATH_LENGTH]; | ||
618 | 2 | gate_string_to_buffer(path, path_buffer, sizeof(path_buffer)); | |
619 | 2 | result = unzLocateFile(unz_handle, path_buffer, 0); | |
620 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (UNZ_OK != result) |
621 | { | ||
622 | ✗ | return GATE_RESULT_NOMATCH; | |
623 | } | ||
624 | 2 | return gate_zipreader_build_entry(unz_handle, ptr_entry); | |
625 | } | ||
626 | 2 | gate_result_t gate_zipreader_extract_content(gate_zipreader_t* reader, gate_stream_t* output_target) | |
627 | { | ||
628 | 2 | gate_result_t ret = GATE_RESULT_FAILED; | |
629 | char buffer[8192]; | ||
630 | 2 | unzFile unz_handle = (unzFile)reader->native_handle; | |
631 | gate_size_t written; | ||
632 | |||
633 | int result; | ||
634 | do | ||
635 | { | ||
636 | 2 | result = unzOpenCurrentFile(unz_handle); | |
637 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (UNZ_OK != result) |
638 | { | ||
639 | ✗ | ret = GATE_RESULT_FAILED; | |
640 | ✗ | break; | |
641 | } | ||
642 | 2 | ret = GATE_RESULT_OK; | |
643 | for (;;) | ||
644 | { | ||
645 | 4 | result = unzReadCurrentFile(unz_handle, buffer, sizeof(buffer)); | |
646 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | if (result == 0) |
647 | { | ||
648 | 2 | break; | |
649 | } | ||
650 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (result < 0) |
651 | { | ||
652 | ✗ | GATE_DEBUG_TRACE("unzReadCurrentFile() failed"); | |
653 | ✗ | ret = GATE_RESULT_FAILED; | |
654 | ✗ | break; | |
655 | } | ||
656 | 2 | ret = gate_stream_write_block(output_target, buffer, (gate_size_t)result, &written); | |
657 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | GATE_BREAK_IF_FAILED(ret); |
658 | } | ||
659 | 2 | unzCloseCurrentFile(unz_handle); | |
660 | |||
661 | } while (0); | ||
662 | |||
663 | 2 | return ret; | |
664 | } | ||
665 | |||
666 | 3 | gate_result_t gate_zipreader_destroy(gate_zipreader_t* reader) | |
667 | { | ||
668 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (reader->native_handle) |
669 | { | ||
670 | 3 | unzClose(reader->native_handle); | |
671 | } | ||
672 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (reader->zipstream.stream) |
673 | { | ||
674 | 3 | gate_object_release(reader->zipstream.stream); | |
675 | } | ||
676 | 3 | return GATE_RESULT_OK; | |
677 | } | ||
678 | |||
679 | #endif /* GATE_ENCODE_ZIPSTREAM_IMPL */ | ||
680 | |||
681 | |||
682 | #if defined(GATE_ECNODE_ZIPSTREAM_NO_IMPL) | ||
683 | |||
684 | gate_result_t gate_zipwriter_create(gate_zipwriter_t* writer, gate_stream_t* stream) | ||
685 | { | ||
686 | (void)writer; | ||
687 | (void)stream; | ||
688 | return GATE_RESULT_NOTIMPLEMENTED; | ||
689 | } | ||
690 | gate_result_t gate_zipwriter_add(gate_zipwriter_t* writer, gate_zipentry_t const* entry, gate_stream_t* stream) | ||
691 | { | ||
692 | (void)writer; | ||
693 | (void)entry; | ||
694 | (void)stream; | ||
695 | return GATE_RESULT_NOTIMPLEMENTED; | ||
696 | } | ||
697 | gate_result_t gate_zipwriter_add_data(gate_zipwriter_t* writer, gate_zipentry_t const* entry, void const* data) | ||
698 | { | ||
699 | (void)writer; | ||
700 | (void)entry; | ||
701 | (void)data; | ||
702 | return GATE_RESULT_NOTIMPLEMENTED; | ||
703 | } | ||
704 | gate_result_t gate_zipwriter_flush(gate_zipwriter_t* writer) | ||
705 | { | ||
706 | (void)writer; | ||
707 | return GATE_RESULT_NOTIMPLEMENTED; | ||
708 | } | ||
709 | gate_result_t gate_zipwriter_destroy(gate_zipwriter_t* writer) | ||
710 | { | ||
711 | (void)writer; | ||
712 | return GATE_RESULT_NOTIMPLEMENTED; | ||
713 | } | ||
714 | |||
715 | |||
716 | gate_result_t gate_zipreader_create(gate_zipreader_t* reader, gate_stream_t* stream) | ||
717 | { | ||
718 | (void)reader; | ||
719 | (void)stream; | ||
720 | return GATE_RESULT_NOTIMPLEMENTED; | ||
721 | } | ||
722 | gate_result_t gate_zipreader_get_first_entry(gate_zipreader_t* reader, gate_zipentry_t* ptr_entry) | ||
723 | { | ||
724 | (void)reader; | ||
725 | (void)ptr_entry; | ||
726 | return GATE_RESULT_NOTIMPLEMENTED; | ||
727 | } | ||
728 | gate_result_t gate_zipreader_get_next_entry(gate_zipreader_t* reader, gate_zipentry_t* ptr_entry) | ||
729 | { | ||
730 | (void)reader; | ||
731 | (void)ptr_entry; | ||
732 | return GATE_RESULT_NOTIMPLEMENTED; | ||
733 | } | ||
734 | gate_result_t gate_zipreader_find_entry(gate_zipreader_t* reader, gate_string_t const* path, gate_zipentry_t* ptr_entry) | ||
735 | { | ||
736 | (void)reader; | ||
737 | (void)path; | ||
738 | (void)ptr_entry; | ||
739 | return GATE_RESULT_NOTIMPLEMENTED; | ||
740 | } | ||
741 | gate_result_t gate_zipreader_extract_content(gate_zipreader_t* reader, gate_stream_t* output_target) | ||
742 | { | ||
743 | (void)reader; | ||
744 | (void)output_target; | ||
745 | return GATE_RESULT_NOTIMPLEMENTED; | ||
746 | } | ||
747 | gate_result_t gate_zipreader_destroy(gate_zipreader_t* reader) | ||
748 | { | ||
749 | (void)reader; | ||
750 | return GATE_RESULT_NOTIMPLEMENTED; | ||
751 | } | ||
752 | |||
753 | |||
754 | #endif /* GATE_ECNODE_ZIPSTREAM_NO_IMPL */ | ||
755 |