65
66
* This function does primary initialization of a disk-buffer struct.
68
zzip_disk_init(ZZIP_DISK* disk, void* buffer, zzip_size_t buflen)
69
zzip_disk_init(ZZIP_DISK * disk, void *buffer, zzip_size_t buflen)
70
disk->buffer = (zzip_byte_t*) buffer;
71
disk->endbuf = (zzip_byte_t*) buffer + buflen;
71
disk->buffer = (zzip_byte_t *) buffer;
72
disk->endbuf = (zzip_byte_t *) buffer + buflen;
72
73
disk->reserved = 0;
80
81
/** => zzip_disk_mmap
81
82
* This function allocates a new disk-buffer with => malloc(3)
83
zzip__new__ ZZIP_DISK*
84
zzip__new__ ZZIP_DISK *
84
85
zzip_disk_new(void)
86
ZZIP_DISK* disk = malloc(sizeof(disk));
87
if (! disk) return disk;
88
zzip_disk_init (disk, 0, 0);
87
ZZIP_DISK *disk = malloc(sizeof(disk));
90
zzip_disk_init(disk, 0, 0);
96
98
* successful then a newly allocated ZZIP_DISK* is returned with
97
99
* disk->buffer pointing to the mapview of the zipdisk content.
99
zzip__new__ ZZIP_DISK*
101
zzip__new__ ZZIP_DISK *
100
102
zzip_disk_mmap(int fd)
103
if (fstat (fd, &st) || ! st.st_size) return 0;
104
___ ZZIP_DISK* disk = zzip_disk_new (); if (! disk) return 0;
105
disk->buffer = _zzip_mmap (& disk->mapped, fd, 0, st.st_size);
106
if (disk->buffer == MAP_FAILED) { free (disk); return 0; }
105
if (fstat(fd, &st) || ! st.st_size)
107
___ ZZIP_DISK *disk = zzip_disk_new();
110
disk->buffer = _zzip_mmap(&disk->mapped, fd, 0, st.st_size);
111
if (disk->buffer == MAP_FAILED)
112
{ free (disk); return 0; }
107
113
disk->endbuf = disk->buffer + st.st_size;
111
118
/** => zzip_disk_mmap
113
120
* munmap(2) on the buffer area and => free(3) on the ZZIP_DISK structure.
116
zzip_disk_munmap(ZZIP_DISK* disk)
123
zzip_disk_munmap(ZZIP_DISK * disk)
118
if (! disk) return 0;
119
_zzip_munmap (disk->mapped, disk->buffer, disk->endbuf-disk->buffer);
127
_zzip_munmap(disk->mapped, disk->buffer, disk->endbuf - disk->buffer);
129
137
* memory block. Only if that fails too then we return null. Since handling
130
138
* of disk->buffer is ambigous it should not be snatched away please.
132
ZZIP_DISK* zzip__new__
133
zzip_disk_open(char* filename)
140
ZZIP_DISK *zzip__new__
141
zzip_disk_open(char *filename)
135
143
# ifndef O_BINARY
136
144
# define O_BINARY 0
139
if (stat (filename, &st) || ! st.st_size) return 0;
140
___ int fd = open (filename, O_RDONLY|O_BINARY);
141
if (fd <= 0) return 0;
142
___ ZZIP_DISK* disk = zzip_disk_mmap (fd);
143
if (disk) return disk;
144
___ zzip_byte_t* buffer = malloc (st.st_size);
145
if (! buffer) return 0;
146
if ((st.st_size == read (fd, buffer, st.st_size)) &&
147
(disk = zzip_disk_new ()))
147
if (stat(filename, &st) || ! st.st_size)
149
___ int fd = open(filename, O_RDONLY | O_BINARY);
152
___ ZZIP_DISK *disk = zzip_disk_mmap(fd);
155
___ zzip_byte_t *buffer = malloc(st.st_size);
158
if ((st.st_size == read(fd, buffer, st.st_size)) &&
159
(disk = zzip_disk_new()))
149
disk->buffer = buffer;
150
disk->endbuf = buffer+st.st_size;
153
return disk; ____;____;____;
161
disk->buffer = buffer;
162
disk->endbuf = buffer + st.st_size;
156
172
/** => zzip_disk_mmap
160
176
* and it dumps the handle struct as well.
163
zzip_disk_close(ZZIP_DISK* disk)
179
zzip_disk_close(ZZIP_DISK * disk)
165
if (! disk) return 0;
166
if (disk->mapped != -1) return zzip_disk_munmap (disk);
183
if (disk->mapped != -1)
184
return zzip_disk_munmap(disk);
172
190
/* ====================================================================== */
173
192
/* helper functions */
175
194
#ifdef ZZIP_HAVE_STRNDUP
176
195
#define _zzip_strndup strndup
178
198
/* if your system does not have strndup: */
179
zzip__new__ static char* _zzip_strndup(char* p, size_t maxlen)
199
zzip__new__ static char *
200
_zzip_strndup(char *p, size_t maxlen)
182
___ zzip_byte_t* r = malloc (maxlen+1);
184
strncpy (r, p, maxlen);
204
___ zzip_byte_t *r = malloc(maxlen + 1);
207
strncpy(r, p, maxlen);
185
208
r[maxlen] = '\0';
190
214
#if defined ZZIP_HAVE_STRCASECMP || defined strcasecmp
191
215
#define _zzip_strcasecmp strcasecmp
193
218
/* if your system does not have strcasecmp: */
194
static int _zzip_strcasecmp(char* __zzip_restrict a, char* _zzip_restrict b)
220
_zzip_strcasecmp(char *__zzip_restrict a, char *_zzip_restrict b)
196
if (! a) return (b) ? 1 : 0;
200
int v = tolower(*a) - tolower(*b);
228
int v = tolower(*a) - tolower(*b);
213
245
* the data block right after the file_header. Only disk->buffer would be
214
246
* needed to perform the seek but we check the mmapped range end as well.
217
zzip_disk_entry_to_data(ZZIP_DISK* disk, struct zzip_disk_entry* entry)
249
zzip_disk_entry_to_data(ZZIP_DISK * disk, struct zzip_disk_entry * entry)
219
struct zzip_file_header* file =
220
zzip_disk_entry_to_file_header(disk, entry);
221
if (file) return zzip_file_header_to_data (file);
251
struct zzip_file_header *file = zzip_disk_entry_to_file_header(disk, entry);
253
return zzip_file_header_to_data(file);
226
258
* This function does half the job of => zzip_disk_entry_to_data where it
227
259
* can augment with => zzip_file_header_to_data helper from format/fetch.h
229
struct zzip_file_header*
230
zzip_disk_entry_to_file_header(ZZIP_DISK* disk, struct zzip_disk_entry* entry)
261
struct zzip_file_header *
262
zzip_disk_entry_to_file_header(ZZIP_DISK * disk, struct zzip_disk_entry *entry)
232
zzip_byte_t* file_header = /* (struct zzip_file_header*) */
233
(disk->buffer + zzip_disk_entry_fileoffset (entry));
234
if (disk->buffer > file_header || file_header >= disk->endbuf)
236
return (struct zzip_file_header*) file_header;
264
zzip_byte_t *file_header = /* (struct zzip_file_header*) */
265
(disk->buffer + zzip_disk_entry_fileoffset(entry));
266
if (disk->buffer > file_header || file_header >= disk->endbuf)
268
return (struct zzip_file_header *) file_header;
239
271
/** => zzip_disk_entry_to_data
243
275
* in the zip central directory but if not then we fallback to the filename
244
276
* given in the file_header of each compressed data portion.
247
zzip_disk_entry_strdup_name(ZZIP_DISK* disk, struct zzip_disk_entry* entry)
279
zzip_disk_entry_strdup_name(ZZIP_DISK * disk, struct zzip_disk_entry *entry)
249
if (! disk || ! entry) return 0;
281
if (! disk || ! entry)
251
___ char* name; zzip_size_t len;
252
struct zzip_file_header* file;
253
if ((len = zzip_disk_entry_namlen (entry)))
254
name = zzip_disk_entry_to_filename (entry);
255
else if ((file = zzip_disk_entry_to_file_header (disk, entry)) &&
256
(len = zzip_file_header_namlen (file)))
257
name = zzip_file_header_to_filename (file);
286
struct zzip_file_header *file;
287
if ((len = zzip_disk_entry_namlen(entry)))
288
name = zzip_disk_entry_to_filename(entry);
289
else if ((file = zzip_disk_entry_to_file_header(disk, entry)) &&
290
(len = zzip_file_header_namlen(file)))
291
name = zzip_file_header_to_filename(file);
261
if ((zzip_byte_t*) name < disk->buffer ||
262
(zzip_byte_t*) name+len > disk->endbuf)
265
return _zzip_strndup (name, len); ____;
295
if ((zzip_byte_t *) name < disk->buffer ||
296
(zzip_byte_t *) name + len > disk->endbuf)
299
return _zzip_strndup(name, len);
268
303
/** => zzip_disk_entry_to_data
269
304
* This function is similar creating a reference to a zero terminated
270
305
* string but it can only exist in the zip central directory entry.
273
zzip_disk_entry_strdup_comment(ZZIP_DISK* disk, struct zzip_disk_entry* entry)
308
zzip_disk_entry_strdup_comment(ZZIP_DISK * disk, struct zzip_disk_entry *entry)
275
if (! disk || ! entry) return 0;
310
if (! disk || ! entry)
277
___ char* text; zzip_size_t len;
278
if ((len = zzip_disk_entry_comment (entry)))
279
text = zzip_disk_entry_to_comment (entry);
315
if ((len = zzip_disk_entry_comment(entry)))
316
text = zzip_disk_entry_to_comment(entry);
283
if ((zzip_byte_t*) text < disk->buffer ||
284
(zzip_byte_t*) text+len > disk->endbuf)
287
return _zzip_strndup (text, len); ____;
320
if ((zzip_byte_t *) text < disk->buffer ||
321
(zzip_byte_t *) text + len > disk->endbuf)
324
return _zzip_strndup(text, len);
290
328
/* ====================================================================== */
316
354
* catch a common brokeness with zip archives that still allows us to find
317
355
* the start of the zip central directory.
319
struct zzip_disk_entry*
320
zzip_disk_findfirst(ZZIP_DISK* disk)
357
struct zzip_disk_entry *
358
zzip_disk_findfirst(ZZIP_DISK * disk)
322
if (disk->buffer > disk->endbuf-sizeof(struct zzip_disk_trailer))
324
___ zzip_byte_t* p = disk->endbuf-sizeof(struct zzip_disk_trailer);
325
for (; p >= disk->buffer ; p--)
360
if (disk->buffer > disk->endbuf - sizeof(struct zzip_disk_trailer))
362
___ zzip_byte_t *p = disk->endbuf - sizeof(struct zzip_disk_trailer);
363
for (; p >= disk->buffer; p--)
327
zzip_byte_t* root; /* (struct zzip_disk_entry*) */
328
if (zzip_disk_trailer_check_magic(p)) {
329
root = disk->buffer + zzip_disk_trailer_get_rootseek (
330
(struct zzip_disk_trailer*)p);
332
{ /* the first disk_entry is after the disk_trailer? can't be! */
333
zzip_size_t rootsize = zzip_disk_trailer_get_rootsize (
334
(struct zzip_disk_trailer*)p);
335
if (disk->buffer+rootsize > p) continue;
336
/* a common brokeness that can be fixed: we just assume the
337
* central directory was written directly before the trailer:*/
340
} else if (zzip_disk64_trailer_check_magic(p)) {
341
if (sizeof(void*) < 8) return 0; /* EOVERFLOW */
342
root = disk->buffer + zzip_disk64_trailer_get_rootseek (
343
(struct zzip_disk64_trailer*)p);
344
if (root > p) continue;
365
zzip_byte_t *root; /* (struct zzip_disk_entry*) */
366
if (zzip_disk_trailer_check_magic(p))
368
struct zzip_disk_trailer *trailer = (struct zzip_disk_trailer *) p;
369
root = disk->buffer + zzip_disk_trailer_get_rootseek(trailer);
372
/* the first disk_entry is after the disk_trailer? can't be! */
373
zzip_size_t rootsize = zzip_disk_trailer_get_rootsize(trailer);
374
if (disk->buffer + rootsize > p)
376
/* a common brokeness that can be fixed: we just assume the
377
* central directory was written directly before the trailer:*/
380
} else if (zzip_disk64_trailer_check_magic(p))
382
struct zzip_disk64_trailer *trailer =
383
(struct zzip_disk64_trailer *) p;
384
if (sizeof(void *) < 8)
385
return 0; /* EOVERFLOW */
386
root = disk->buffer + zzip_disk64_trailer_get_rootseek(trailer);
347
if (root < disk->buffer) continue;
348
if (zzip_disk_entry_check_magic(root))
349
return (struct zzip_disk_entry*) root;
394
if (root < disk->buffer)
396
if (zzip_disk_entry_check_magic(root))
397
return (struct zzip_disk_entry *) root;
357
405
* (e.g. from zzip_disk_findfirst) and returns the next entry within in
358
406
* the given bounds of the mmapped file area.
360
struct zzip_disk_entry*
361
zzip_disk_findnext(ZZIP_DISK* disk, struct zzip_disk_entry* entry)
408
struct zzip_disk_entry *
409
zzip_disk_findnext(ZZIP_DISK * disk, struct zzip_disk_entry *entry)
363
if ((zzip_byte_t*)entry < disk->buffer ||
364
(zzip_byte_t*)entry > disk->endbuf-sizeof(entry) ||
365
! zzip_disk_entry_check_magic (entry) ||
366
zzip_disk_entry_sizeto_end (entry) > 64*1024)
368
entry = zzip_disk_entry_to_next_entry (entry);
369
if ((zzip_byte_t*)entry > disk->endbuf-sizeof(entry) ||
370
! zzip_disk_entry_check_magic (entry) ||
371
zzip_disk_entry_sizeto_end (entry) > 64*1024 ||
372
zzip_disk_entry_skipto_end (entry) + sizeof(entry) > disk->endbuf)
411
if ((zzip_byte_t *) entry < disk->buffer ||
412
(zzip_byte_t *) entry > disk->endbuf - sizeof(entry) ||
413
! zzip_disk_entry_check_magic(entry) ||
414
zzip_disk_entry_sizeto_end(entry) > 64 * 1024)
416
entry = zzip_disk_entry_to_next_entry(entry);
417
if ((zzip_byte_t *) entry > disk->endbuf - sizeof(entry) ||
418
! zzip_disk_entry_check_magic(entry) ||
419
zzip_disk_entry_sizeto_end(entry) > 64 * 1024 ||
420
zzip_disk_entry_skipto_end(entry) + sizeof(entry) > disk->endbuf)
378
426
/** search for files in the (mmapped) zip central directory
385
433
* entries with a special "compare" function (if null then a doubled search
386
434
* is rather useless with this variant of _findfile).
388
struct zzip_disk_entry*
389
zzip_disk_findfile(ZZIP_DISK* disk, char* filename,
390
struct zzip_disk_entry* after, zzip_strcmp_fn_t compare)
436
struct zzip_disk_entry *
437
zzip_disk_findfile(ZZIP_DISK * disk, char *filename,
438
struct zzip_disk_entry *after, zzip_strcmp_fn_t compare)
392
struct zzip_disk_entry* entry = (! after ? zzip_disk_findfirst (disk)
393
: zzip_disk_findnext (disk, after));
395
compare = (zzip_strcmp_fn_t)( (disk->flags&1) ?
396
(_zzip_strcasecmp) : (strcmp));
397
for (; entry ; entry = zzip_disk_findnext (disk, entry))
440
struct zzip_disk_entry *entry = (! after ? zzip_disk_findfirst(disk)
441
: zzip_disk_findnext(disk, after));
443
compare = (zzip_strcmp_fn_t) ((disk->flags & 1) ?
444
(_zzip_strcasecmp) : (strcmp));
445
for (; entry; entry = zzip_disk_findnext(disk, entry))
399
/* filenames within zip files are often not null-terminated! */
400
char* realname = zzip_disk_entry_strdup_name (disk, entry);
401
if (realname && ! compare(filename, realname))
447
/* filenames within zip files are often not null-terminated! */
448
char *realname = zzip_disk_entry_strdup_name(disk, entry);
449
if (realname && ! compare(filename, realname))
421
469
* matching entry, or the last disk_entry return-value to find the
422
470
* next entry matching the given filespec.
424
struct zzip_disk_entry*
425
zzip_disk_findmatch(ZZIP_DISK* disk, char* filespec,
426
struct zzip_disk_entry* after,
427
zzip_fnmatch_fn_t compare, int flags)
472
struct zzip_disk_entry *
473
zzip_disk_findmatch(ZZIP_DISK * disk, char *filespec,
474
struct zzip_disk_entry *after,
475
zzip_fnmatch_fn_t compare, int flags)
429
struct zzip_disk_entry* entry = (! after ? zzip_disk_findfirst (disk)
430
: zzip_disk_findnext (disk, after));
432
compare = (zzip_fnmatch_fn_t) _zzip_fnmatch;
433
if (disk->flags&1) disk->flags |= _zzip_fnmatch_CASEFOLD;
477
struct zzip_disk_entry *entry = (! after ? zzip_disk_findfirst(disk)
478
: zzip_disk_findnext(disk, after));
481
compare = (zzip_fnmatch_fn_t) _zzip_fnmatch;
483
disk->flags |= _zzip_fnmatch_CASEFOLD;
435
for (; entry ; entry = zzip_disk_findnext (disk, entry))
485
for (; entry; entry = zzip_disk_findnext(disk, entry))
437
/* filenames within zip files are often not null-terminated! */
438
char* realname = zzip_disk_entry_strdup_name(disk, entry);
439
if (realname && ! compare(filespec, realname, flags))
487
/* filenames within zip files are often not null-terminated! */
488
char *realname = zzip_disk_entry_strdup_name(disk, entry);
489
if (realname && ! compare(filespec, realname, flags))
459
509
* _read() operations will be able to get the next data portion or
460
510
* return an eof condition for that file part wrapped in the zip archive.
462
zzip__new__ ZZIP_DISK_FILE*
463
zzip_disk_entry_fopen (ZZIP_DISK* disk, ZZIP_DISK_ENTRY* entry)
512
zzip__new__ ZZIP_DISK_FILE *
513
zzip_disk_entry_fopen(ZZIP_DISK * disk, ZZIP_DISK_ENTRY * entry)
465
515
/* keep this in sync with zzip_mem_entry_fopen */
466
struct zzip_file_header* header =
467
zzip_disk_entry_to_file_header (disk, entry);
468
if (! header) return 0;
469
___ ZZIP_DISK_FILE* file = malloc(sizeof(ZZIP_DISK_FILE));
470
if (! file) return file;
516
struct zzip_file_header *header =
517
zzip_disk_entry_to_file_header(disk, entry);
520
___ ZZIP_DISK_FILE *file = malloc(sizeof(ZZIP_DISK_FILE));
471
523
file->buffer = disk->buffer;
472
524
file->endbuf = disk->endbuf;
473
file->avail = zzip_file_header_usize (header);
525
file->avail = zzip_file_header_usize(header);
475
if (! file->avail || zzip_file_header_data_stored (header))
476
{ file->stored = zzip_file_header_to_data (header); return file; }
527
if (! file->avail || zzip_file_header_data_stored(header))
528
{ file->stored = zzip_file_header_to_data (header); return file; }
478
530
file->stored = 0;
479
531
file->zlib.opaque = 0;
480
532
file->zlib.zalloc = Z_NULL;
481
533
file->zlib.zfree = Z_NULL;
482
file->zlib.avail_in = zzip_file_header_csize (header);
483
file->zlib.next_in = zzip_file_header_to_data (header);
485
if (! zzip_file_header_data_deflated (header) ||
486
inflateInit2 (& file->zlib, -MAX_WBITS) != Z_OK)
487
{ free (file); return 0; }
534
file->zlib.avail_in = zzip_file_header_csize(header);
535
file->zlib.next_in = zzip_file_header_to_data(header);
537
if (! zzip_file_header_data_deflated(header) ||
538
inflateInit2(&file->zlib, -MAX_WBITS) != Z_OK)
539
{ free (file); return 0; }
492
545
/** openening a file part wrapped within a (mmapped) zip archive
495
548
* the zip central directory with => zzip_disk_findfile and whatever
496
549
* is found first is given to => zzip_disk_entry_fopen
498
zzip__new__ ZZIP_DISK_FILE*
499
zzip_disk_fopen (ZZIP_DISK* disk, char* filename)
551
zzip__new__ ZZIP_DISK_FILE *
552
zzip_disk_fopen(ZZIP_DISK * disk, char *filename)
501
ZZIP_DISK_ENTRY* entry = zzip_disk_findfile (disk, filename, 0, 0);
502
if (! entry) return 0; else return zzip_disk_entry_fopen (disk, entry);
554
ZZIP_DISK_ENTRY *entry = zzip_disk_findfile(disk, filename, 0, 0);
558
return zzip_disk_entry_fopen(disk, entry);
511
567
* with => zzip_disk_feof for the difference.
514
zzip_disk_fread (void* ptr, zzip_size_t sized, zzip_size_t nmemb,
515
ZZIP_DISK_FILE* file)
570
zzip_disk_fread(void *ptr, zzip_size_t sized, zzip_size_t nmemb,
571
ZZIP_DISK_FILE * file)
517
zzip_size_t size = sized*nmemb;
518
if (size > file->avail) size = file->avail;
573
zzip_size_t size = sized * nmemb;
574
if (size > file->avail)
519
576
if (file->stored)
521
memcpy (ptr, file->stored, size);
522
file->stored += size;
578
memcpy(ptr, file->stored, size);
579
file->stored += size;
527
file->zlib.avail_out = sized*nmemb;
584
file->zlib.avail_out = sized * nmemb;
528
585
file->zlib.next_out = ptr;
529
586
___ zzip_size_t total_old = file->zlib.total_out;
530
___ int err = inflate (& file->zlib, Z_NO_FLUSH);
587
___ int err = inflate(&file->zlib, Z_NO_FLUSH);
531
588
if (err == Z_STREAM_END)
533
590
else if (err == Z_OK)
534
file->avail -= file->zlib.total_out - total_old;
591
file->avail -= file->zlib.total_out - total_old;
537
594
return file->zlib.total_out - total_old;
541
599
/** => zzip_disk_fopen
556
614
* This function allows to distinguish an error from an eof condition.
557
615
* Actually, if we found an error but we did already reach eof then we
558
616
* just keep on saying that it was an eof, so the app can just continue.
561
zzip_disk_feof (ZZIP_DISK_FILE* file)
619
zzip_disk_feof(ZZIP_DISK_FILE * file)
563
621
return ! file || ! file->avail;