summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Buren <braewoods+rb@braewoods.net>2021-07-05 17:08:55 +0000
committerJames Buren <braewoods+rb@braewoods.net>2021-07-05 19:30:05 +0000
commitb87e75f768eba3ccdf422a5082c91097a0b72b5b (patch)
tree5770da0da23e9a176010fa1e422e8b85743793d8
parent2acf8db3e14e8c81f27cb0cea5b366678693c7b3 (diff)
downloadrockbox-b87e75f768eba3ccdf422a5082c91097a0b72b5b.tar.gz
rockbox-b87e75f768eba3ccdf422a5082c91097a0b72b5b.zip
zip: import initial module
This provides rudimentary support for parsing the contents of a ZIP file. For now this just supports uncompressed file entries but DEFLATE support is planned. This also only implements a low level public API so more work will be needed to make it usable by application code. Change-Id: Ia68b3078e5276666a0e5023f4bc7a9f94272738a
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/common/zip.c705
-rw-r--r--firmware/include/zip.h64
3 files changed, 770 insertions, 0 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 5fcf83fff1..109a40b161 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -268,6 +268,7 @@ common/structec.c
268common/timefuncs.c 268common/timefuncs.c
269common/unicode.c 269common/unicode.c
270common/vuprintf.c 270common/vuprintf.c
271common/zip.c
271 272
272/* Display */ 273/* Display */
273scroll_engine.c 274scroll_engine.c
diff --git a/firmware/common/zip.c b/firmware/common/zip.c
new file mode 100644
index 0000000000..e3ffd90af2
--- /dev/null
+++ b/firmware/common/zip.c
@@ -0,0 +1,705 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 by James Buren
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "zip.h"
23#include <string.h>
24#include "file.h"
25#include "system.h"
26#include "core_alloc.h"
27#include "timefuncs.h"
28#include "crc32.h"
29#include "rbendian.h"
30
31#define zip_core_alloc(N) core_alloc_ex("zip",(N),&dummy_ops)
32
33static struct buflib_callbacks dummy_ops;
34
35enum {
36 ZIP_SIG_ED = 0x06054b50,
37 ZIP_SIG_CD = 0x02014b50,
38 ZIP_SIG_LF = 0x04034b50,
39 ZIP_BIT_DD = 0x0008,
40 ZIP_METHOD_STORE = 0x0000,
41 ZIP_MAX_LENGTH = 0xffff,
42 ZIP_BUFFER_SIZE = 4096,
43};
44
45enum {
46 ZIP_STATE_INITIAL,
47 ZIP_STATE_ED_ENTER,
48 ZIP_STATE_ED_EXIT,
49 ZIP_STATE_CD_ENTER,
50 ZIP_STATE_CD_EXIT,
51 ZIP_STATE_LF_ENTER,
52 ZIP_STATE_LF_EXIT,
53};
54
55struct zip_ed_disk {
56 uint32_t signature;
57 uint16_t disk_number;
58 uint16_t disk_number_cd;
59 uint16_t disk_entries_cd;
60 uint16_t cd_entries;
61 uint32_t cd_size;
62 uint32_t cd_offset;
63 uint16_t comment_length;
64 // comment block (variable length)
65} __attribute__((packed));
66
67struct zip_ed {
68 uint32_t cd_size;
69 uint32_t cd_offset;
70 uint16_t cd_entries;
71};
72
73struct zip_cd_disk {
74 uint32_t signature;
75 uint16_t version_madeby;
76 uint16_t version_needed;
77 uint16_t flags;
78 uint16_t method;
79 uint16_t time;
80 uint16_t date;
81 uint32_t crc;
82 uint32_t compressed_size;
83 uint32_t uncompressed_size;
84 uint16_t name_length;
85 uint16_t extra_length;
86 uint16_t comment_length;
87 uint16_t disk_number;
88 uint16_t internal_attributes;
89 uint32_t external_attributes;
90 uint32_t lf_offset;
91 // name block (variable length)
92 // extra block (variable length)
93 // comment block (variable length)
94} __attribute__((packed));
95
96struct zip_cd {
97 uint32_t crc;
98 uint32_t compressed_size;
99 uint32_t uncompressed_size;
100 uint32_t lf_offset;
101};
102
103struct zip_lf_disk {
104 uint32_t signature;
105 uint16_t version_needed;
106 uint16_t flags;
107 uint16_t method;
108 uint16_t time;
109 uint16_t date;
110 uint32_t crc;
111 uint32_t compressed_size;
112 uint32_t uncompressed_size;
113 uint16_t name_length;
114 uint16_t extra_length;
115 // name block (variable length)
116 // extra block (variable length)
117} __attribute__((packed));
118
119struct zip_lf {
120 uint16_t flags;
121 uint16_t method;
122 uint16_t time;
123 uint16_t date;
124 uint32_t crc;
125 uint32_t compressed_size;
126 uint32_t uncompressed_size;
127 uint16_t name_length;
128 char name[MAX_PATH];
129};
130
131struct zip {
132 ssize_t (*read) (struct zip*, void*, size_t);
133 off_t (*seek) (struct zip*, off_t, int);
134 off_t (*size) (struct zip*);
135 void (*close) (struct zip*);
136 int zip_handle;
137 int state;
138 zip_callback cb;
139 struct zip_args args;
140 void* ctx;
141 struct zip_ed ed;
142 int cds_handle;
143 struct zip_cd* cds;
144 struct zip_lf lf;
145};
146
147struct zip_file {
148 struct zip base;
149 int file;
150};
151
152struct zip_mem {
153 struct zip base;
154 int mem_handle;
155 const uint8_t* mem;
156 off_t mem_offset;
157 off_t mem_size;
158};
159
160static int zip_read_ed(struct zip* z) {
161 const off_t file_size = z->size(z);
162 const off_t max_size = sizeof(struct zip_ed_disk) + ZIP_MAX_LENGTH;
163 const off_t read_size = MIN(file_size, max_size);
164 const uint32_t sig = htole32(ZIP_SIG_ED);
165 int mem_handle = -1;
166 uint8_t* mem;
167 off_t i = read_size - sizeof(struct zip_ed_disk);
168 const struct zip_ed_disk* edd;
169 uint16_t disk_number;
170 uint16_t disk_number_cd;
171 uint16_t disk_entries_cd;
172 uint16_t cd_entries;
173 struct zip_ed* ed = &z->ed;
174 int rv;
175
176 z->state = ZIP_STATE_ED_ENTER;
177
178 if (file_size < (off_t) sizeof(struct zip_ed_disk)) {
179 rv = -2;
180 goto bail;
181 }
182
183 if ((mem_handle = zip_core_alloc(read_size)) < 0) {
184 rv = -3;
185 goto bail;
186 }
187
188 mem = core_get_data(mem_handle);
189
190 if (z->seek(z, -read_size, SEEK_END) < 0) {
191 rv = -4;
192 goto bail;
193 }
194
195 if (z->read(z, mem, read_size) != read_size) {
196 rv = -5;
197 goto bail;
198 }
199
200 for (; i >= 0; i--)
201 if (memcmp(mem + i, &sig, sizeof(uint32_t)) == 0)
202 break;
203
204 if (i < 0) {
205 rv = -6;
206 goto bail;
207 }
208
209 edd = (struct zip_ed_disk*) (mem + i);
210 disk_number = letoh16(edd->disk_number);
211 disk_number_cd = letoh16(edd->disk_number_cd);
212 disk_entries_cd = letoh16(edd->disk_entries_cd);
213 cd_entries = letoh16(edd->cd_entries);
214
215 if (disk_number != 0 || disk_number_cd != 0 || disk_entries_cd != cd_entries) {
216 rv = -7;
217 goto bail;
218 }
219
220 ed->cd_size = letoh32(edd->cd_size);
221 ed->cd_offset = letoh32(edd->cd_offset);
222 ed->cd_entries = cd_entries;
223
224 z->state = ZIP_STATE_ED_EXIT;
225 rv = 0;
226
227bail:
228 if (mem_handle >= 0)
229 core_free(mem_handle);
230 return rv;
231}
232
233static int zip_read_cd(struct zip* z, bool use_cb) {
234 const struct zip_ed* ed = &z->ed;
235 const uint32_t cd_size = ed->cd_size;
236 const uint32_t cd_offset = ed->cd_offset;
237 const uint16_t cd_entries = ed->cd_entries;
238 const uint32_t sig = htole32(ZIP_SIG_CD);
239 int cds_handle = -1;
240 int mem_handle = -1;
241 struct zip_cd* cds;
242 uint8_t* mem;
243 struct zip_lf* lf = &z->lf;
244 struct zip_args* args = &z->args;
245 struct zip_cd_disk* cdd;
246 struct zip_cd* cd;
247 uint16_t name_length;
248 int rv;
249
250 z->state = ZIP_STATE_CD_ENTER;
251
252 if ((cds_handle = zip_core_alloc(sizeof(struct zip_cd) * cd_entries)) < 0) {
253 rv = -7;
254 goto bail;
255 }
256
257 if ((mem_handle = zip_core_alloc(cd_size)) < 0) {
258 rv = -8;
259 goto bail;
260 }
261
262 cds = core_get_data(cds_handle);
263 mem = core_get_data(mem_handle);
264
265 if (z->seek(z, cd_offset, SEEK_SET) < 0) {
266 rv = -9;
267 goto bail;
268 }
269
270 if (z->read(z, mem, cd_size) != (ssize_t) cd_size) {
271 rv = -10;
272 goto bail;
273 }
274
275 if (use_cb) {
276 args->entries = cd_entries;
277 args->name = lf->name;
278 args->block = NULL;
279 args->block_size = 0;
280 args->read_size = 0;
281 }
282
283 cdd = (struct zip_cd_disk*) mem;
284
285 for (uint16_t i = 0; i < cd_entries; i++) {
286 if (cdd->signature != sig) {
287 rv = -11;
288 goto bail;
289 }
290
291 cd = &cds[i];
292
293 cd->crc = letoh32(cdd->crc);
294 cd->compressed_size = letoh32(cdd->compressed_size);
295 cd->uncompressed_size = letoh32(cdd->uncompressed_size);
296 cd->lf_offset = letoh32(cdd->lf_offset);
297
298 mem += sizeof(struct zip_cd_disk);
299 name_length = letoh16(cdd->name_length);
300 if (use_cb) {
301 if (name_length >= sizeof(lf->name)) {
302 rv = -12;
303 goto bail;
304 }
305
306 args->entry = i + 1;
307 args->file_size = cd->uncompressed_size;
308 args->modts = dostime_mktime(letoh16(cdd->date), letoh16(cdd->time));
309
310 memcpy(lf->name, mem, name_length);
311 lf->name[name_length] = '\0';
312
313 if ((rv = z->cb(args, ZIP_PASS_SHALLOW, z->ctx)) > 0)
314 goto bail;
315 }
316 mem += name_length;
317 mem += letoh16(cdd->extra_length);
318 mem += letoh16(cdd->comment_length);
319 cdd = (struct zip_cd_disk*) mem;
320 }
321
322 z->cds_handle = cds_handle;
323 z->cds = cds;
324 z->state = ZIP_STATE_CD_EXIT;
325 rv = 0;
326
327bail:
328 if (rv != 0 && cds_handle >= 0)
329 core_free(cds_handle);
330 if (mem_handle >= 0)
331 core_free(mem_handle);
332 return rv;
333}
334
335static int zip_read_lf(struct zip* z, uint16_t i) {
336 const uint32_t sig = htole32(ZIP_SIG_LF);
337 const struct zip_cd* cd = &z->cds[i];
338 struct zip_lf* lf = &z->lf;
339 struct zip_lf_disk lfd;
340 uint16_t name_length;
341
342 if (z->seek(z, cd->lf_offset, SEEK_SET) < 0)
343 return -14;
344
345 if (z->read(z, &lfd, sizeof(struct zip_lf_disk)) != sizeof(struct zip_lf_disk))
346 return -15;
347
348 if (lfd.signature != sig)
349 return -16;
350
351 name_length = letoh16(lfd.name_length);
352
353 if (name_length >= sizeof(lf->name))
354 return -17;
355
356 if (z->read(z, lf->name, name_length) != name_length)
357 return -18;
358
359 if (z->seek(z, letoh16(lfd.extra_length), SEEK_CUR) < 0)
360 return -19;
361
362 lf->flags = letoh16(lfd.flags);
363 lf->method = letoh16(lfd.method);
364 lf->time = letoh16(lfd.time);
365 lf->date = letoh16(lfd.date);
366 lf->crc = letoh32(lfd.crc);
367 lf->compressed_size = letoh32(lfd.compressed_size);
368 lf->uncompressed_size = letoh32(lfd.uncompressed_size);
369 lf->name_length = name_length;
370 lf->name[name_length] = '\0';
371
372 if ((lf->flags & ZIP_BIT_DD) == ZIP_BIT_DD) {
373 lf->crc = cd->crc;
374 lf->compressed_size = cd->compressed_size;
375 lf->uncompressed_size = cd->uncompressed_size;
376 }
377
378 return 0;
379}
380
381static int zip_read_store(struct zip* z, void* mem, uint32_t mem_size) {
382 const struct zip_lf* lf = &z->lf;
383 struct zip_args* args = &z->args;
384 uint32_t file_size = lf->uncompressed_size;
385 uint32_t block_size = mem_size;
386 uint32_t crc = 0xffffffff;
387 int rv;
388
389 if (lf->compressed_size != lf->uncompressed_size)
390 return -21;
391
392 args->block = mem;
393 args->block_size = block_size;
394 args->read_size = 0;
395
396 do {
397 if (block_size > file_size) {
398 args->block_size = block_size = file_size;
399 }
400
401 if (z->read(z, mem, block_size) != (off_t) block_size)
402 return -22;
403
404 args->read_size += block_size;
405 crc = crc_32r(mem, block_size, crc);
406
407 if ((rv = z->cb(args, ZIP_PASS_DATA, z->ctx)) != 0)
408 return (rv < 0) ? 0 : rv;
409
410 file_size -= block_size;
411 } while (file_size > 0);
412
413 if (~crc != lf->crc)
414 return -24;
415
416 return 0;
417}
418
419static int zip_read_entry(struct zip* z, uint16_t i, void* mem, uint32_t mem_size) {
420 const struct zip_lf* lf = &z->lf;
421 struct zip_args* args = &z->args;
422 int rv;
423
424 if ((rv = zip_read_lf(z, i)) != 0)
425 return rv;
426
427 args->entry = i + 1;
428 args->file_size = lf->uncompressed_size;
429 args->modts = dostime_mktime(lf->date, lf->time);
430 args->block = NULL;
431 args->block_size = 0;
432 args->read_size = 0;
433
434 if ((rv = z->cb(&z->args, ZIP_PASS_START, z->ctx)) != 0)
435 return (rv < 0) ? 0 : rv;
436
437 if (lf->uncompressed_size == 0)
438 goto skip_data;
439
440 if (lf->method == ZIP_METHOD_STORE) {
441 if ((rv = zip_read_store(z, mem, mem_size)) != 0)
442 return rv;
443 } else {
444 return -20;
445 }
446
447skip_data:
448 args->block = NULL;
449 args->block_size = 0;
450 args->read_size = 0;
451
452 if ((rv = z->cb(args, ZIP_PASS_END, z->ctx)) != 0)
453 return (rv < 0) ? 0 : rv;
454
455 return 0;
456}
457
458static int zip_read_entries(struct zip* z) {
459 const struct zip_ed* ed = &z->ed;
460 const uint16_t cd_entries = ed->cd_entries;
461 struct zip_lf* lf = &z->lf;
462 struct zip_args* args = &z->args;
463 uint32_t mem_size = ZIP_BUFFER_SIZE;
464 int mem_handle;
465 void* mem;
466 int rv;
467
468 z->state = ZIP_STATE_LF_ENTER;
469
470 if ((mem_handle = zip_core_alloc(mem_size)) < 0) {
471 rv = -13;
472 goto bail;
473 }
474
475 mem = core_get_data(mem_handle);
476
477 args->entries = cd_entries;
478 args->name = lf->name;
479
480 for (uint16_t i = 0; i < cd_entries; i++)
481 if ((rv = zip_read_entry(z, i, mem, mem_size)) > 0)
482 goto bail;
483
484 z->state = ZIP_STATE_LF_EXIT;
485 rv = 0;
486
487bail:
488 if (mem_handle >= 0)
489 core_free(mem_handle);
490 return rv;
491}
492
493static void zip_init(struct zip* z, int zip_handle) {
494 z->zip_handle = zip_handle;
495 z->state = ZIP_STATE_INITIAL;
496 z->cb = NULL;
497 memset(&z->args, 0, sizeof(struct zip_args));
498 z->ctx = NULL;
499 memset(&z->ed, 0, sizeof(struct zip_ed));
500 z->cds_handle = -1;
501 z->cds = NULL;
502 memset(&z->lf, 0, sizeof(struct zip_lf));
503}
504
505static ssize_t zip_file_read(struct zip* zh, void* mem, size_t mem_size) {
506 struct zip_file* z = (struct zip_file*) zh;
507
508 return read(z->file, mem, mem_size);
509}
510
511static off_t zip_file_seek(struct zip* zh, off_t offset, int whence) {
512 struct zip_file* z = (struct zip_file*) zh;
513
514 return lseek(z->file, offset, whence);
515}
516
517static off_t zip_file_size(struct zip* zh) {
518 struct zip_file* z = (struct zip_file*) zh;
519
520 return filesize(z->file);
521}
522
523static void zip_file_close(struct zip* zh) {
524 struct zip_file* z = (struct zip_file*) zh;
525
526 close(z->file);
527}
528
529static void zip_file_init(struct zip_file* z, int zip_handle, int file) {
530 struct zip* zh = &z->base;
531
532 zh->read = zip_file_read;
533 zh->seek = zip_file_seek;
534 zh->size = zip_file_size;
535 zh->close = zip_file_close;
536 zip_init(zh, zip_handle);
537
538 z->file = file;
539}
540
541static ssize_t zip_mem_read(struct zip* zh, void* mem, size_t mem_size) {
542 struct zip_mem* z = (struct zip_mem*) zh;
543 off_t bytes = z->mem_size - z->mem_offset;
544 off_t read_size = MIN(bytes, (off_t) mem_size);
545
546 memcpy(mem, z->mem + z->mem_offset, read_size);
547 z->mem_offset += read_size;
548
549 return read_size;
550}
551
552static off_t zip_mem_seek(struct zip* zh, off_t offset, int whence) {
553 struct zip_mem* z = (struct zip_mem*) zh;
554 off_t new_offset;
555
556 switch (whence) {
557 case SEEK_SET:
558 new_offset = offset;
559 break;
560
561 case SEEK_CUR:
562 new_offset = z->mem_offset + offset;
563 break;
564
565 case SEEK_END:
566 new_offset = z->mem_size + offset;
567 break;
568
569 default:
570 new_offset = -1;
571 break;
572 }
573
574 if (new_offset < 0 || new_offset > z->mem_size)
575 return -1;
576
577 z->mem_offset = new_offset;
578
579 return new_offset;
580}
581
582static off_t zip_mem_size(struct zip* zh) {
583 struct zip_mem* z = (struct zip_mem*) zh;
584
585 return z->mem_size;
586}
587
588static void zip_mem_close(struct zip* zh) {
589 struct zip_mem* z = (struct zip_mem*) zh;
590
591 core_free(z->mem_handle);
592}
593
594static void zip_mem_init(struct zip_mem* z, int zip_handle, int mem_handle, const void* mem, off_t mem_size) {
595 struct zip* zh = &z->base;
596
597 zh->read = zip_mem_read;
598 zh->seek = zip_mem_seek;
599 zh->size = zip_mem_size;
600 zh->close = zip_mem_close;
601 zip_init(zh, zip_handle);
602
603 z->mem_handle = mem_handle;
604 z->mem = mem;
605 z->mem_offset = 0;
606 z->mem_size = mem_size;
607}
608
609struct zip* zip_open(const char* name, bool try_mem) {
610 int file = -1;
611 int mem_handle = -1;
612 int zip_handle = -1;
613 off_t mem_size;
614 void* mem;
615 void* zip;
616
617 if (name == NULL || name[0] == '\0')
618 goto bail;
619
620 if ((file = open(name, O_RDONLY)) < 0)
621 goto bail;
622
623 if (try_mem && (mem_handle = zip_core_alloc(mem_size = filesize(file))) >= 0) {
624 if ((zip_handle = zip_core_alloc(sizeof(struct zip_mem))) < 0)
625 goto bail;
626
627 mem = core_get_data(mem_handle);
628
629 if (read(file, mem, mem_size) != mem_size)
630 goto bail;
631
632 close(file);
633
634 zip = core_get_data(zip_handle);
635
636 zip_mem_init(zip, zip_handle, mem_handle, mem, mem_size);
637 } else {
638 if ((zip_handle = zip_core_alloc(sizeof(struct zip_file))) < 0)
639 goto bail;
640
641 zip = core_get_data(zip_handle);
642
643 zip_file_init(zip, zip_handle, file);
644 }
645
646 return zip;
647
648bail:
649 if (file >= 0)
650 close(file);
651 if (mem_handle >= 0)
652 core_free(mem_handle);
653 if (zip_handle >= 0)
654 core_free(zip_handle);
655 return NULL;
656}
657
658int zip_read_shallow(struct zip* z, zip_callback cb, void* ctx) {
659 int rv;
660
661 if (z == NULL || z->state != ZIP_STATE_INITIAL || cb == NULL)
662 return -1;
663
664 z->cb = cb;
665 z->ctx = ctx;
666
667 if ((rv = zip_read_ed(z)) != 0)
668 return rv;
669
670 return zip_read_cd(z, true);
671}
672
673int zip_read_deep(struct zip* z, zip_callback cb, void* ctx) {
674 int rv;
675
676 if (z == NULL || (z->state != ZIP_STATE_INITIAL && z->state != ZIP_STATE_CD_EXIT) || cb == NULL)
677 return -1;
678
679 z->cb = cb;
680 z->ctx = ctx;
681
682 if (z->state == ZIP_STATE_CD_EXIT)
683 goto read_entries;
684
685 if ((rv = zip_read_ed(z)) != 0)
686 return rv;
687
688 if ((rv = zip_read_cd(z, false)) != 0)
689 return rv;
690
691read_entries:
692 return zip_read_entries(z);
693}
694
695void zip_close(struct zip* z) {
696 if (z == NULL)
697 return;
698
699 z->close(z);
700
701 if (z->cds_handle >= 0)
702 core_free(z->cds_handle);
703
704 core_free(z->zip_handle);
705}
diff --git a/firmware/include/zip.h b/firmware/include/zip.h
new file mode 100644
index 0000000000..e58466dff0
--- /dev/null
+++ b/firmware/include/zip.h
@@ -0,0 +1,64 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 by James Buren
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef _ZIP_H_
23#define _ZIP_H_
24
25#include <stdbool.h>
26#include <stdint.h>
27#include <time.h>
28
29enum {
30 ZIP_PASS_SHALLOW,
31 ZIP_PASS_START,
32 ZIP_PASS_DATA,
33 ZIP_PASS_END,
34};
35
36struct zip;
37
38struct zip_args {
39 uint16_t entry;
40 uint16_t entries;
41 char* name;
42 uint32_t file_size;
43 time_t modts;
44 void* block;
45 uint32_t block_size;
46 uint32_t read_size;
47};
48
49typedef int (*zip_callback) (const struct zip_args* args, int pass, void* ctx);
50
51// open a handle for the given full file name path
52struct zip* zip_open(const char* name, bool try_mem);
53
54// quick read of only directory index
55int zip_read_shallow(struct zip* z, zip_callback cb, void* ctx);
56
57// slow read of whole archive
58// this can also pickup where a successful shallow read leftoff
59int zip_read_deep(struct zip* z, zip_callback cb, void* ctx);
60
61// returns system resources
62void zip_close(struct zip* z);
63
64#endif