GCC Code Coverage Report


Directory: src/gate/
File: src/gate/encode/zipstreams.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 248 309 80.3%
Functions: 23 24 95.8%
Branches: 70 144 48.6%

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 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 2 gate_result_t gate_zipwriter_add(gate_zipwriter_t* writer, gate_zipentry_t const* entry, gate_stream_t* stream)
366 {
367 2 gate_result_t ret = GATE_RESULT_FAILED;
368
369 do
370 {
371 2 gate_size_t comment_length = gate_str_length(entry->comment);
372 2 zip_fileinfo zip_info = GATE_INIT_EMPTY;
373 gate_datetime_t dt;
374 int result;
375 #if defined(GATE_SYS_DOS)
376 int window_bits = (MAX_WBITS - 1);
377 int compression_level = (Z_BEST_COMPRESSION + Z_BEST_SPEED) / 2;
378 int memlevel = (DEF_MEM_LEVEL - 1);
379 #else
380 2 int window_bits = MAX_WBITS;
381 2 int compression_level = Z_BEST_COMPRESSION;
382 2 int memlevel = DEF_MEM_LEVEL;
383 #endif
384
385
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (entry->modified_date.timestamp)
386 {
387 2 ret = gate_time_to_datetime(&entry->modified_date, &dt);
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 GATE_BREAK_IF_FAILED(ret);
389
390 2 zip_info.tmz_date.tm_year = dt.date.year;
391 2 zip_info.tmz_date.tm_mon = dt.date.month - 1;
392 2 zip_info.tmz_date.tm_mday = dt.date.day;
393 2 zip_info.tmz_date.tm_hour = dt.time.hour;
394 2 zip_info.tmz_date.tm_min = dt.time.minute;
395 2 zip_info.tmz_date.tm_sec = dt.time.second;
396 }
397 2 zip_info.external_fa = gate_accessbits_to_zip_attribs(entry->access);
398 2 zip_info.external_fa |= gate_attribs_to_zip_attribs(entry->attribs);
399
400 /*
401 result = zipOpenNewFileInZip64((zipFile)writer->native_handle, entry->path, &zip_info, 0, 0, 0, 0,
402 ((comment_length == 0) ? NULL : entry->comment),
403 Z_DEFLATED, Z_BEST_COMPRESSION,
404 (entry->size >= 0xffffffff) ? 1 : 0);
405 */
406 2 result = zipOpenNewFileInZip4_64((zipFile)writer->native_handle, entry->path, &zip_info, 0, 0, 0, 0,
407 ((comment_length == 0) ? NULL : entry->comment),
408 Z_DEFLATED, compression_level, 0,
409 -window_bits, memlevel, Z_DEFAULT_STRATEGY,
410
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 NULL, 0, 0, 0, (entry->size >= 0xffffffff) ? 1 : 0);
411
412
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ZIP_OK != result)
413 {
414 ret = GATE_RESULT_FAILED;
415 break;
416 }
417
418 do
419 {
420 char buffer[GATE_MAX_COPYBUFFER_LENGTH];
421 gate_size_t buffer_used;
422 4 ret = gate_stream_read_block(stream, buffer, sizeof(buffer), &buffer_used);
423
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (GATE_SUCCEEDED(ret))
424 {
425
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (buffer_used == 0)
426 {
427 /* end of stream reached */
428 2 break;
429 }
430 2 result = zipWriteInFileInZip((zipFile)writer->native_handle, buffer, (unsigned int)buffer_used);
431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ZIP_OK != result)
432 {
433 ret = GATE_RESULT_INVALIDOUTPUT;
434 break;
435 }
436 }
437
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 } while (GATE_SUCCEEDED(ret));
438
439 2 zipCloseFileInZip((zipFile)writer->native_handle);
440 } while (0);
441 2 return ret;
442 }
443 2 gate_result_t gate_zipwriter_add_data(gate_zipwriter_t* writer, gate_zipentry_t const* entry, void const* data)
444 {
445 2 gate_memstream_impl_t impl = GATE_INIT_EMPTY;
446 2 gate_size_t datalen = (gate_size_t)entry->size;
447 2 gate_memstream_t* stream = gate_memstream_create_static_unmanaged_readonly(&impl, data, datalen, datalen);
448 2 return gate_zipwriter_add(writer, entry, (gate_stream_t*)stream);
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 1 gate_result_t gate_zipwriter_destroy(gate_zipwriter_t* writer)
455 {
456 1 gate_result_t ret = GATE_RESULT_OK;
457
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (writer->native_handle)
458 {
459 1 zipClose(writer->native_handle, NULL);
460 }
461
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (writer->zipstream.stream)
462 {
463 1 gate_object_release(writer->zipstream.stream);
464 }
465 1 gate_mem_clear(writer, sizeof(gate_zipwriter_t));
466 1 return ret;
467 }
468
469
470
471
472 /* zip reader */
473
474 3 gate_result_t gate_zipreader_create(gate_zipreader_t* reader, gate_stream_t* stream)
475 {
476 3 gate_result_t ret = GATE_RESULT_FAILED;
477
478 do
479 {
480 zlib_filefunc_def* file_functions;
481
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 if (!reader || !stream)
482 {
483 ret = GATE_RESULT_NULLPOINTER;
484 break;
485 }
486
487 3 gate_mem_clear(reader, sizeof(gate_zipreader_t));
488 3 reader->zipstream.stream = stream;
489 3 reader->zipstream.bytes_written = 0;
490 3 reader->zipstream.bytes_received = 0;
491
492 3 reader->zipstream.last_result = GATE_RESULT_OK;
493 3 reader->zipstream.stream = stream;
494 3 reader->zipstream.control_stream = NULL;
495
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))
496 {
497 3 reader->zipstream.control_stream = (gate_controlstream_t*)stream;
498 }
499 3 file_functions = (zlib_filefunc_def*)&reader->native_params;
500 3 file_functions->zopen_file = &gate_zipwriter_open_file_func;
501 3 file_functions->zread_file = &gate_zipwriter_read_file_func;
502 3 file_functions->zwrite_file = &gate_zipwriter_write_file_func;
503 3 file_functions->ztell_file = &gate_zipwriter_tell_file_func;
504 3 file_functions->zseek_file = &gate_zipwriter_seek_file_func;
505 3 file_functions->zclose_file = &gate_zipwriter_close_file_func;
506 3 file_functions->zerror_file = &gate_zipwriter_testerror_file_func;
507 3 file_functions->opaque = &reader->zipstream;
508
509 3 reader->native_handle = (void*)unzOpen2((char const*)&reader->zipstream, file_functions);
510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (NULL == reader->native_handle)
511 {
512 gate_mem_clear(reader, sizeof(gate_zipwriter_t*));
513 ret = GATE_RESULT_FAILED;
514 break;
515 }
516
517 3 gate_object_retain(reader->zipstream.stream);
518 3 ret = GATE_RESULT_OK;
519 } while (0);
520
521 3 return ret;
522 }
523
524 4 static gate_result_t gate_zipreader_build_entry(unzFile unz_handle, gate_zipentry_t* ptr_entry)
525 {
526 4 unz_file_info64 info = GATE_INIT_EMPTY;
527 gate_datetime_t dtm;
528 4 gate_time_t now = GATE_INIT_EMPTY;
529 gate_size_t pathlen;
530 int result;
531 4 gate_mem_clear(ptr_entry, sizeof(gate_zipentry_t));
532 4 result = unzGetCurrentFileInfo64(unz_handle, &info,
533 4 ptr_entry->path, sizeof(ptr_entry->path),
534 NULL, 0,
535 4 ptr_entry->comment, sizeof(ptr_entry->comment));
536
537
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (UNZ_OK != result)
538 {
539 GATE_DEBUG_TRACE("unzGetCurrentFileInfo64() failed");
540 return GATE_RESULT_FAILED;
541 }
542
543 4 gate_time_now(&now);
544
545 4 ptr_entry->crc = info.crc;
546 4 ptr_entry->version = info.version;
547 4 ptr_entry->flag = info.flag;
548 4 ptr_entry->compression_method = info.compression_method;
549 4 ptr_entry->attribs = zip_attribs_to_gate_attribs(info.external_fa);
550 4 ptr_entry->access = zip_attribs_to_gate_accessbits(info.external_fa);
551
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (!GATE_FLAG_ENABLED(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_FILE)
552
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 && !GATE_FLAG_ENABLED(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_DIRECTORY)
553
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 && !GATE_FLAG_ENABLED(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_LINK))
554 {
555 4 pathlen = gate_str_length_max(ptr_entry->path, sizeof(ptr_entry->path));
556
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (pathlen > 0)
557 {
558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (ptr_entry->path[pathlen - 1] == '/')
559 {
560 GATE_FLAG_SET(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_DIRECTORY, true);
561 }
562 else
563 {
564 4 GATE_FLAG_SET(ptr_entry->attribs, GATE_FILEENTRY_ATTRIB_FILE, true);
565 }
566 }
567 }
568 4 ptr_entry->size = info.uncompressed_size;
569 4 ptr_entry->compressed_size = info.compressed_size;
570 4 ptr_entry->modified_date.bias = 0;
571
572 4 dtm.date.year = (gate_uint16_t)info.tmu_date.tm_year;
573 4 dtm.date.month = (gate_uint8_t)(info.tmu_date.tm_mon + 1);
574 4 dtm.date.day = (gate_uint8_t)info.tmu_date.tm_mday;
575 4 dtm.time.hour = (gate_uint8_t)info.tmu_date.tm_hour;
576 4 dtm.time.minute = (gate_uint8_t)info.tmu_date.tm_min;
577 4 dtm.time.second = (gate_uint8_t)info.tmu_date.tm_sec;
578 4 dtm.time.microsecond = 0;
579 4 gate_date_to_time(&dtm, &ptr_entry->modified_date);
580 //ptr_entry->modified_date.bias = now.bias;
581 4 return GATE_RESULT_OK;
582 }
583
584
585 1 gate_result_t gate_zipreader_get_first_entry(gate_zipreader_t* reader, gate_zipentry_t* ptr_entry)
586 {
587 1 unzFile unz_handle = (unzFile)reader->native_handle;
588 1 int result = unzGoToFirstFile(unz_handle);
589
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (UNZ_OK != result)
590 {
591 GATE_DEBUG_TRACE("unzGoToFirstFile() failed");
592 return GATE_RESULT_FAILED;
593 }
594 1 reader->eof_reached = false;
595 1 return gate_zipreader_build_entry(unz_handle, ptr_entry);
596 }
597
598 1 gate_result_t gate_zipreader_get_next_entry(gate_zipreader_t* reader, gate_zipentry_t* ptr_entry)
599 {
600 1 unzFile unz_handle = (unzFile)reader->native_handle;
601 1 int result = unzGoToNextFile(unz_handle);
602
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (UNZ_END_OF_LIST_OF_FILE == result)
603 {
604 GATE_DEBUG_TRACE("unzGoToNextFile() == UNZ_END_OF_LIST_OF_FILE");
605 return GATE_RESULT_ENDOFSTREAM;
606 }
607
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (UNZ_OK != result)
608 {
609 GATE_DEBUG_TRACE("unzGoToNextFile() failed");
610 return GATE_RESULT_FAILED;
611 }
612 1 return gate_zipreader_build_entry(unz_handle, ptr_entry);
613 }
614 2 gate_result_t gate_zipreader_find_entry(gate_zipreader_t* reader, gate_string_t const* path, gate_zipentry_t* ptr_entry)
615 {
616 2 unzFile unz_handle = (unzFile)reader->native_handle;
617 int result;
618 char path_buffer[GATE_MAX_FILEPATH_LENGTH];
619 2 gate_string_to_buffer(path, path_buffer, sizeof(path_buffer));
620 2 result = unzLocateFile(unz_handle, path_buffer, 0);
621
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (UNZ_OK != result)
622 {
623 return GATE_RESULT_NOMATCH;
624 }
625 2 return gate_zipreader_build_entry(unz_handle, ptr_entry);
626 }
627 2 gate_result_t gate_zipreader_extract_content(gate_zipreader_t* reader, gate_stream_t* output_target)
628 {
629 2 gate_result_t ret = GATE_RESULT_FAILED;
630
631 do
632 {
633 2 unzFile unz_handle = (unzFile)reader->native_handle;
634 2 int result = unzOpenCurrentFile(unz_handle);
635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (UNZ_OK != result)
636 {
637 ret = GATE_RESULT_FAILED;
638 break;
639 }
640 2 ret = GATE_RESULT_OK;
641 for (;;)
642 2 {
643 char buffer[8192];
644 gate_size_t written;
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