GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/zipstreams.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 240 309 77.7%
Functions: 22 24 91.7%
Branches: 63 132 47.7%

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