GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/zipstreams.c
Date: 2026-08-06 22:46:24
Exec Total Coverage
Lines: 250 311 80.4%
Functions: 23 24 95.8%
Branches: 70 144 48.6%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, 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) && !defined(GATE_ENCODE_NO_BASIC_COMPRESSION)
35 # define GATE_ENCODE_ZIPSTREAM_IMPL 1
36 #else
37 # define GATE_ECNODE_ZIPSTREAM_NO_IMPL 1
38 #endif
39
40
41 4 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 4 gate_mem_clear(entry, sizeof(gate_zipentry_t));
45
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (path)
46 {
47 gate_string_to_buffer(path, entry->path, sizeof(entry->path));
48 }
49
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (comment)
50 {
51 gate_string_to_buffer(comment, entry->comment, sizeof(entry->comment));
52 }
53 4 entry->size = size;
54 4 entry->attribs = attribs;
55 4 entry->access = accessbits;
56 4 }
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 302 times.
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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
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* const target = (gate_ziptarget_t*)opaque;
212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
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* const target = (gate_ziptarget_t*)opaque;
224 GATE_DEBUG_ASSERT(target->stream == (gate_stream_t*)stream);
225 GATE_UNUSED_ARG(stream);
226
227 if (GATE_FAILED(target->last_result))
228 {
229 return 1;
230 }
231 return 0;
232 }
233
234 12 static long ZCALLBACK gate_zipwriter_tell_file_func(voidpf opaque, voidpf stream)
235 {
236 12 gate_ziptarget_t* target = (gate_ziptarget_t*)opaque;
237 12 gate_int64_t position = 0;
238 gate_result_t res;
239
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 GATE_DEBUG_ASSERT(target->stream == (gate_stream_t*)stream);
240 GATE_UNUSED_ARG(stream);
241
242
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (target->control_stream)
243 {
244 12 res = gate_stream_get_position(target->control_stream, &position);
245
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (GATE_SUCCEEDED(res))
246 {
247 12 return (long)position;
248 }
249 }
250 else
251 {
252 return (long)(target->bytes_received + target->bytes_written);
253 }
254 return -1;
255 }
256 41 static long ZCALLBACK gate_zipwriter_seek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin)
257 {
258 41 gate_ziptarget_t* target = (gate_ziptarget_t*)opaque;
259 41 gate_result_t res = 0;
260 41 gate_int64_t stream_pos = (gate_int64_t)offset;
261 41 gate_int64_t new_pos = 0;
262 gate_uint32_t stream_origin;
263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 GATE_DEBUG_ASSERT(target->stream == (gate_stream_t*)stream);
264 GATE_UNUSED_ARG(stream);
265
266
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 if (target->control_stream)
267 {
268
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
41 switch (origin)
269 {
270 case ZLIB_FILEFUNC_SEEK_CUR: stream_origin = GATE_STREAM_SEEK_CURRENT; break;
271 6 case ZLIB_FILEFUNC_SEEK_END: stream_origin = GATE_STREAM_SEEK_END; break;
272 35 case ZLIB_FILEFUNC_SEEK_SET: stream_origin = GATE_STREAM_SEEK_BEGIN; break;
273 default: return -1;
274 }
275
276 41 res = gate_stream_seek(target->control_stream, stream_pos, stream_origin, &new_pos);
277
1/2
✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
41 if (GATE_SUCCEEDED(res))
278 {
279 41 return 0;
280 }
281 }
282 else
283 {
284 switch (origin)
285 {
286 case ZLIB_FILEFUNC_SEEK_CUR:
287 {
288 if (offset == 0)
289 {
290 return 0; /* no change is supported */
291 }
292 return -1; /* any other change is not supported */
293 }
294 case ZLIB_FILEFUNC_SEEK_END:
295 {
296 return -1; /* moving to end is not supported */
297 }
298 case ZLIB_FILEFUNC_SEEK_SET:
299 {
300 if (offset == 0)
301 {
302 return ((target->bytes_received == 0) && (target->bytes_written == 0)) ? 0 : -1;
303 }
304 return ((target->bytes_received == offset) || (target->bytes_written == offset)) ? 0 : -1;
305 }
306 default:
307 {
308 return -1;
309 }
310 }
311 }
312 return -1;
313 }
314
315
316
317 1 gate_result_t gate_zipwriter_create(gate_zipwriter_t* writer, gate_stream_t* stream)
318 {
319 1 gate_result_t ret = GATE_RESULT_FAILED;
320
321 do
322 {
323 zlib_filefunc_def* file_functions;
324
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (!writer || !stream)
325 {
326 ret = GATE_RESULT_NULLPOINTER;
327 break;
328 }
329
330 1 gate_mem_clear(writer, sizeof(gate_zipwriter_t*));
331
332 1 writer->zipstream.last_result = GATE_RESULT_OK;
333 1 writer->zipstream.bytes_written = 0;
334 1 writer->zipstream.bytes_received = 0;
335 1 writer->zipstream.stream = stream;
336 1 writer->zipstream.control_stream = NULL;
337
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))
338 {
339 1 writer->zipstream.control_stream = (gate_controlstream_t*)stream;
340 }
341 1 file_functions = (zlib_filefunc_def*)&writer->native_params;
342 1 file_functions->zopen_file = &gate_zipwriter_open_file_func;
343 1 file_functions->zread_file = &gate_zipwriter_read_file_func;
344 1 file_functions->zwrite_file = &gate_zipwriter_write_file_func;
345 1 file_functions->ztell_file = &gate_zipwriter_tell_file_func;
346 1 file_functions->zseek_file = &gate_zipwriter_seek_file_func;
347 1 file_functions->zclose_file = &gate_zipwriter_close_file_func;
348 1 file_functions->zerror_file = &gate_zipwriter_testerror_file_func;
349 1 file_functions->opaque = &writer->zipstream;
350
351 1 writer->native_handle = (void*)zipOpen2((char const*)&writer->zipstream, APPEND_STATUS_CREATE, NULL, file_functions);
352
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (NULL == writer->native_handle)
353 {
354 gate_mem_clear(writer, sizeof(gate_zipwriter_t*));
355 ret = GATE_RESULT_FAILED;
356 break;
357 }
358
359 1 gate_object_retain(writer->zipstream.stream);
360 1 ret = GATE_RESULT_OK;
361 } while (0);
362
363 1 return ret;
364 }
365
366 2 gate_result_t gate_zipwriter_add(gate_zipwriter_t* writer, gate_zipentry_t const* entry, gate_stream_t* stream)
367 {
368 2 gate_result_t ret = GATE_RESULT_FAILED;
369
370 do
371 {
372 2 gate_size_t const comment_length = gate_str_length(entry->comment);
373
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 char const* const ptr_comment = (comment_length != 0) ? &entry->comment[0] : NULL;
374 2 zip_fileinfo zip_info = GATE_INIT_EMPTY;
375 gate_datetime_t dt;
376 2 const int use_zip64 = entry->size > 0x0ffffffffUL ? 1 : 0;
377 int result;
378 #if defined(GATE_SYS_DOS)
379 int window_bits = (MAX_WBITS - 1);
380 int compression_level = (Z_BEST_COMPRESSION + Z_BEST_SPEED) / 2;
381 int memlevel = (DEF_MEM_LEVEL - 1);
382 #else
383 2 int window_bits = MAX_WBITS;
384 2 int compression_level = Z_BEST_COMPRESSION;
385 2 int memlevel = DEF_MEM_LEVEL;
386 #endif
387
388
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (entry->modified_date.timestamp)
389 {
390 2 ret = gate_time_to_datetime(&entry->modified_date, &dt);
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
392
393 2 zip_info.tmz_date.tm_year = dt.date.year;
394 2 zip_info.tmz_date.tm_mon = dt.date.month - 1;
395 2 zip_info.tmz_date.tm_mday = dt.date.day;
396 2 zip_info.tmz_date.tm_hour = dt.time.hour;
397 2 zip_info.tmz_date.tm_min = dt.time.minute;
398 2 zip_info.tmz_date.tm_sec = dt.time.second;
399 }
400 2 zip_info.external_fa = gate_accessbits_to_zip_attribs(entry->access);
401 2 zip_info.external_fa |= gate_attribs_to_zip_attribs(entry->attribs);
402
403 4 result = zipOpenNewFileInZip4_64((zipFile)writer->native_handle,
404 2 entry->path, &zip_info, 0, 0, 0, 0,
405 ptr_comment,
406 Z_DEFLATED, compression_level, 0,
407 -window_bits, memlevel, Z_DEFAULT_STRATEGY,
408 NULL, 0, 0, 0, use_zip64);
409
410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ZIP_OK != result)
411 {
412 ret = GATE_RESULT_FAILED;
413 break;
414 }
415
416 do
417 {
418 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
419 gate_size_t buffer_used;
420 4 ret = gate_stream_read_block(stream, buffer, sizeof(buffer), &buffer_used);
421
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
422 {
423
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (buffer_used == 0)
424 {
425 /* end of stream reached */
426 2 break;
427 }
428 2 result = zipWriteInFileInZip((zipFile)writer->native_handle, buffer, (unsigned int)buffer_used);
429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ZIP_OK != result)
430 {
431 ret = GATE_RESULT_INVALIDOUTPUT;
432 break;
433 }
434 }
435
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 } while (GATE_SUCCEEDED(ret));
436
437 2 zipCloseFileInZip((zipFile)writer->native_handle);
438 } while (0);
439 2 return ret;
440 }
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
450 1 gate_result_t gate_zipwriter_flush(gate_zipwriter_t* writer)
451 {
452 1 return gate_stream_flush(writer->zipstream.stream);
453 }
454
455 1 gate_result_t gate_zipwriter_destroy(gate_zipwriter_t* writer)
456 {
457 1 gate_result_t ret = GATE_RESULT_OK;
458
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (writer->native_handle)
459 {
460 1 zipClose(writer->native_handle, NULL);
461 }
462
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (writer->zipstream.stream)
463 {
464 1 gate_object_release(writer->zipstream.stream);
465 }
466 1 gate_mem_clear(writer, sizeof(gate_zipwriter_t));
467 1 return ret;
468 }
469
470
471
472
473 /* zip reader */
474
475 3 gate_result_t gate_zipreader_create(gate_zipreader_t* reader, gate_stream_t* stream)
476 {
477 3 gate_result_t ret = GATE_RESULT_FAILED;
478
479 do
480 {
481 zlib_filefunc_def* file_functions;
482
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (!reader || !stream)
483 {
484 ret = GATE_RESULT_NULLPOINTER;
485 break;
486 }
487
488 3 gate_mem_clear(reader, sizeof(gate_zipreader_t));
489 3 reader->zipstream.stream = stream;
490 3 reader->zipstream.bytes_written = 0;
491 3 reader->zipstream.bytes_received = 0;
492
493 3 reader->zipstream.last_result = GATE_RESULT_OK;
494 3 reader->zipstream.stream = stream;
495 3 reader->zipstream.control_stream = NULL;
496
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))
497 {
498 3 reader->zipstream.control_stream = (gate_controlstream_t*)stream;
499 }
500 3 file_functions = (zlib_filefunc_def*)&reader->native_params;
501 3 file_functions->zopen_file = &gate_zipwriter_open_file_func;
502 3 file_functions->zread_file = &gate_zipwriter_read_file_func;
503 3 file_functions->zwrite_file = &gate_zipwriter_write_file_func;
504 3 file_functions->ztell_file = &gate_zipwriter_tell_file_func;
505 3 file_functions->zseek_file = &gate_zipwriter_seek_file_func;
506 3 file_functions->zclose_file = &gate_zipwriter_close_file_func;
507 3 file_functions->zerror_file = &gate_zipwriter_testerror_file_func;
508 3 file_functions->opaque = &reader->zipstream;
509
510 3 reader->native_handle = (void*)unzOpen2((char const*)&reader->zipstream, file_functions);
511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (NULL == reader->native_handle)
512 {
513 gate_mem_clear(reader, sizeof(gate_zipwriter_t*));
514 ret = GATE_RESULT_FAILED;
515 break;
516 }
517
518 3 gate_object_retain(reader->zipstream.stream);
519 3 ret = GATE_RESULT_OK;
520 } while (0);
521
522 3 return ret;
523 }
524
525 4 static gate_result_t gate_zipreader_build_entry(unzFile unz_handle, gate_zipentry_t* ptr_entry)
526 {
527 4 unz_file_info64 info = GATE_INIT_EMPTY;
528 gate_datetime_t dtm;
529 4 gate_time_t now = GATE_INIT_EMPTY;
530 gate_size_t pathlen;
531 int result;
532 4 gate_mem_clear(ptr_entry, sizeof(gate_zipentry_t));
533 4 result = unzGetCurrentFileInfo64(unz_handle, &info,
534 4 ptr_entry->path, sizeof(ptr_entry->path),
535 NULL, 0,
536 4 ptr_entry->comment, sizeof(ptr_entry->comment));
537
538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (UNZ_OK != result)
539 {
540 GATE_DEBUG_TRACE("unzGetCurrentFileInfo64() failed");
541 return GATE_RESULT_FAILED;
542 }
543
544 4 gate_time_now(&now);
545
546 4 ptr_entry->crc = info.crc;
547 4 ptr_entry->version = info.version;
548 4 ptr_entry->flag = info.flag;
549 4 ptr_entry->compression_method = info.compression_method;
550 4 ptr_entry->attribs = zip_attribs_to_gate_attribs(info.external_fa);
551 4 ptr_entry->access = zip_attribs_to_gate_accessbits(info.external_fa);
552
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!GATE_FLAG_ENABLED(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_FILE)
553
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 && !GATE_FLAG_ENABLED(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_DIRECTORY)
554
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 && !GATE_FLAG_ENABLED(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_LINK))
555 {
556 4 pathlen = gate_str_length_max(ptr_entry->path, sizeof(ptr_entry->path));
557
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (pathlen > 0)
558 {
559
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ptr_entry->path[pathlen - 1] == '/')
560 {
561 GATE_FLAG_SET(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_DIRECTORY, true);
562 }
563 else
564 {
565 4 GATE_FLAG_SET(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_FILE, true);
566 }
567 }
568 }
569 4 ptr_entry->size = info.uncompressed_size;
570 4 ptr_entry->compressed_size = info.compressed_size;
571 4 ptr_entry->modified_date.bias = 0;
572
573 4 dtm.date.year = (gate_uint16_t)info.tmu_date.tm_year;
574 4 dtm.date.month = (gate_uint8_t)(info.tmu_date.tm_mon + 1);
575 4 dtm.date.day = (gate_uint8_t)info.tmu_date.tm_mday;
576 4 dtm.time.hour = (gate_uint8_t)info.tmu_date.tm_hour;
577 4 dtm.time.minute = (gate_uint8_t)info.tmu_date.tm_min;
578 4 dtm.time.second = (gate_uint8_t)info.tmu_date.tm_sec;
579 4 dtm.time.microsecond = 0;
580 4 gate_date_to_time(&dtm, &ptr_entry->modified_date);
581 //ptr_entry->modified_date.bias = now.bias;
582 4 return GATE_RESULT_OK;
583 }
584
585
586 1 gate_result_t gate_zipreader_get_first_entry(gate_zipreader_t* reader, gate_zipentry_t* ptr_entry)
587 {
588 1 unzFile unz_handle = (unzFile)reader->native_handle;
589 1 int result = unzGoToFirstFile(unz_handle);
590
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (UNZ_OK != result)
591 {
592 GATE_DEBUG_TRACE("unzGoToFirstFile() failed");
593 return GATE_RESULT_FAILED;
594 }
595 1 reader->eof_reached = false;
596 1 return gate_zipreader_build_entry(unz_handle, ptr_entry);
597 }
598
599 1 gate_result_t gate_zipreader_get_next_entry(gate_zipreader_t* reader, gate_zipentry_t* ptr_entry)
600 {
601 1 unzFile unz_handle = (unzFile)reader->native_handle;
602 1 int result = unzGoToNextFile(unz_handle);
603
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (UNZ_END_OF_LIST_OF_FILE == result)
604 {
605 GATE_DEBUG_TRACE("unzGoToNextFile() == UNZ_END_OF_LIST_OF_FILE");
606 return GATE_RESULT_ENDOFSTREAM;
607 }
608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (UNZ_OK != result)
609 {
610 GATE_DEBUG_TRACE("unzGoToNextFile() failed");
611 return GATE_RESULT_FAILED;
612 }
613 1 return gate_zipreader_build_entry(unz_handle, ptr_entry);
614 }
615
616 2 gate_result_t gate_zipreader_find_entry(gate_zipreader_t* reader, gate_string_t const* path, gate_zipentry_t* ptr_entry)
617 {
618 2 unzFile unz_handle = (unzFile)reader->native_handle;
619 int result;
620 char path_buffer[GATE_MAX_FILEPATH_LENGTH];
621 2 gate_string_to_buffer(path, path_buffer, sizeof(path_buffer));
622 2 result = unzLocateFile(unz_handle, path_buffer, 0);
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (UNZ_OK != result)
624 {
625 return GATE_RESULT_NOMATCH;
626 }
627 2 return gate_zipreader_build_entry(unz_handle, ptr_entry);
628 }
629
630 2 gate_result_t gate_zipreader_extract_content(gate_zipreader_t* reader, gate_stream_t* output_target)
631 {
632 2 gate_result_t ret = GATE_RESULT_FAILED;
633
634 do
635 {
636 2 unzFile unz_handle = (unzFile)reader->native_handle;
637 2 int result = unzOpenCurrentFile(unz_handle);
638
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (UNZ_OK != result)
639 {
640 ret = GATE_RESULT_FAILED;
641 break;
642 }
643 2 ret = GATE_RESULT_OK;
644 for (;;)
645 2 {
646 char buffer[8192];
647 gate_size_t written;
648 4 result = unzReadCurrentFile(unz_handle, buffer, sizeof(buffer));
649
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (result == 0)
650 {
651 2 break;
652 }
653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (result < 0)
654 {
655 GATE_DEBUG_TRACE("unzReadCurrentFile() failed");
656 ret = GATE_RESULT_FAILED;
657 break;
658 }
659 2 ret = gate_stream_write_block(output_target, buffer, (gate_size_t)result, &written);
660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
661 }
662 2 unzCloseCurrentFile(unz_handle);
663
664 } while (0);
665
666 2 return ret;
667 }
668
669 3 gate_result_t gate_zipreader_destroy(gate_zipreader_t* reader)
670 {
671
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (reader->native_handle)
672 {
673 3 unzClose(reader->native_handle);
674 }
675
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (reader->zipstream.stream)
676 {
677 3 gate_object_release(reader->zipstream.stream);
678 }
679 3 return GATE_RESULT_OK;
680 }
681
682 #endif /* GATE_ENCODE_ZIPSTREAM_IMPL */
683
684
685 #if defined(GATE_ECNODE_ZIPSTREAM_NO_IMPL)
686
687 gate_result_t gate_zipwriter_create(gate_zipwriter_t* writer, gate_stream_t* stream)
688 {
689 (void)writer;
690 (void)stream;
691 return GATE_RESULT_NOTIMPLEMENTED;
692 }
693 gate_result_t gate_zipwriter_add(gate_zipwriter_t* writer, gate_zipentry_t const* entry, gate_stream_t* stream)
694 {
695 (void)writer;
696 (void)entry;
697 (void)stream;
698 return GATE_RESULT_NOTIMPLEMENTED;
699 }
700 gate_result_t gate_zipwriter_add_data(gate_zipwriter_t* writer, gate_zipentry_t const* entry, void const* data)
701 {
702 (void)writer;
703 (void)entry;
704 (void)data;
705 return GATE_RESULT_NOTIMPLEMENTED;
706 }
707 gate_result_t gate_zipwriter_flush(gate_zipwriter_t* writer)
708 {
709 (void)writer;
710 return GATE_RESULT_NOTIMPLEMENTED;
711 }
712 gate_result_t gate_zipwriter_destroy(gate_zipwriter_t* writer)
713 {
714 (void)writer;
715 return GATE_RESULT_NOTIMPLEMENTED;
716 }
717
718
719 gate_result_t gate_zipreader_create(gate_zipreader_t* reader, gate_stream_t* stream)
720 {
721 (void)reader;
722 (void)stream;
723 return GATE_RESULT_NOTIMPLEMENTED;
724 }
725 gate_result_t gate_zipreader_get_first_entry(gate_zipreader_t* reader, gate_zipentry_t* ptr_entry)
726 {
727 (void)reader;
728 (void)ptr_entry;
729 return GATE_RESULT_NOTIMPLEMENTED;
730 }
731 gate_result_t gate_zipreader_get_next_entry(gate_zipreader_t* reader, gate_zipentry_t* ptr_entry)
732 {
733 (void)reader;
734 (void)ptr_entry;
735 return GATE_RESULT_NOTIMPLEMENTED;
736 }
737 gate_result_t gate_zipreader_find_entry(gate_zipreader_t* reader, gate_string_t const* path, gate_zipentry_t* ptr_entry)
738 {
739 (void)reader;
740 (void)path;
741 (void)ptr_entry;
742 return GATE_RESULT_NOTIMPLEMENTED;
743 }
744 gate_result_t gate_zipreader_extract_content(gate_zipreader_t* reader, gate_stream_t* output_target)
745 {
746 (void)reader;
747 (void)output_target;
748 return GATE_RESULT_NOTIMPLEMENTED;
749 }
750 gate_result_t gate_zipreader_destroy(gate_zipreader_t* reader)
751 {
752 (void)reader;
753 return GATE_RESULT_NOTIMPLEMENTED;
754 }
755
756
757 #endif /* GATE_ECNODE_ZIPSTREAM_NO_IMPL */
758