1 /* unzip.c -- IO for uncompress .zip files using zlib
2 Version 1.2.0, September 16th, 2017
3 part of the MiniZip project
5 Copyright (C) 2010-2017 Nathan Moinvaziri
6 Modifications for AES, PKWARE disk spanning
7 https://github.com/nmoinvaz/minizip
8 Copyright (C) 2009-2010 Mathias Svensson
9 Modifications for Zip64 support on both zip and unzip
11 Copyright (C) 2007-2008 Even Rouault
12 Modifications of Unzip for Zip64
13 Copyright (C) 1998-2010 Gilles Vollant
14 http://www.winimage.com/zLibDll/minizip.html
16 This program is distributed under the terms of the same license as zlib.
17 See the accompanying LICENSE file for the full text of the license.
34 # define AES_METHOD (99)
35 # define AES_PWVERIFYSIZE (2)
36 # define AES_MAXSALTLENGTH (16)
37 # define AES_AUTHCODESIZE (10)
38 # define AES_HEADERSIZE (11)
39 # define AES_KEYSIZE(mode) (64 + (mode * 64))
42 # include "aes/fileenc.h"
44 #ifdef HAVE_APPLE_COMPRESSION
45 # include <compression.h>
52 #define DISKHEADERMAGIC (0x08074b50)
53 #define LOCALHEADERMAGIC (0x04034b50)
54 #define CENTRALHEADERMAGIC (0x02014b50)
55 #define ENDHEADERMAGIC (0x06054b50)
56 #define ZIP64ENDHEADERMAGIC (0x06064b50)
57 #define ZIP64ENDLOCHEADERMAGIC (0x07064b50)
59 #define SIZECENTRALDIRITEM (0x2e)
60 #define SIZECENTRALHEADERLOCATOR (0x14)
61 #define SIZEZIPLOCALHEADER (0x1e)
63 #ifndef BUFREADCOMMENT
64 # define BUFREADCOMMENT (0x400)
68 # define UNZ_BUFSIZE (UINT16_MAX)
70 #ifndef UNZ_MAXFILENAMEINZIP
71 # define UNZ_MAXFILENAMEINZIP (256)
75 # define ALLOC(size) (malloc(size))
78 # define TRYFREE(p) {if (p) free(p);}
81 const char unz_copyright[] = " unzip 1.2.0 Copyright 1998-2017 - https://github.com/nmoinvaz/minizip";
83 /* unz_file_info_internal contain internal info about a file in zipfile*/
84 typedef struct unz_file_info64_internal_s
86 uint64_t offset_curfile; /* relative offset of local header 8 bytes */
87 uint64_t byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx) */
89 uint8_t aes_encryption_mode;
90 uint16_t aes_compression_method;
93 } unz_file_info64_internal;
95 /* file_in_zip_read_info_s contain internal information about a file in zipfile */
98 uint8_t *read_buffer; /* internal buffer for compressed data */
99 z_stream stream; /* zLib stream structure for inflate */
101 bz_stream bstream; /* bzLib stream structure for bziped */
103 #ifdef HAVE_APPLE_COMPRESSION
104 compression_stream astream; /* libcompression stream structure */
109 uint64_t pos_in_zipfile; /* position in byte on the zipfile, for fseek */
110 uint8_t stream_initialised; /* flag set if stream structure is initialised */
112 uint64_t offset_local_extrafield; /* offset of the local extra field */
113 uint16_t size_local_extrafield; /* size of the local extra field */
114 uint64_t pos_local_extrafield; /* position in the local extra field in read */
115 uint64_t total_out_64;
117 uint32_t crc32; /* crc32 of all data uncompressed */
118 uint32_t crc32_expected; /* crc32 we must obtain after decompress all */
119 uint64_t rest_read_compressed; /* number of byte to be decompressed */
120 uint64_t rest_read_uncompressed; /* number of byte to be obtained after decomp */
122 zlib_filefunc64_32_def z_filefunc;
124 voidpf filestream; /* io structore of the zipfile */
125 uint16_t compression_method; /* compression method (0==store) */
126 uint64_t byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx) */
128 } file_in_zip64_read_info_s;
130 /* unz64_s contain internal information about the zipfile */
133 zlib_filefunc64_32_def z_filefunc;
135 voidpf filestream; /* io structure of the current zipfile */
136 voidpf filestream_with_CD; /* io structure of the disk with the central directory */
138 unz_global_info64 gi; /* public global information */
140 uint64_t byte_before_the_zipfile; /* byte before the zipfile, (>0 for sfx) */
141 uint64_t num_file; /* number of the current file in the zipfile */
142 uint64_t pos_in_central_dir; /* pos of the current file in the central dir */
143 uint64_t current_file_ok; /* flag about the usability of the current file */
144 uint64_t central_pos; /* position of the beginning of the central dir */
145 uint32_t number_disk; /* number of the current disk, used for spanning ZIP */
146 uint64_t size_central_dir; /* size of the central directory */
147 uint64_t offset_central_dir; /* offset of start of central directory with
148 respect to the starting disk number */
150 unz_file_info64 cur_file_info; /* public info about the current file in zip*/
151 unz_file_info64_internal cur_file_info_internal;
152 /* private info about it*/
153 file_in_zip64_read_info_s *pfile_in_zip_read;
154 /* structure about the current file if we are decompressing it */
155 int is_zip64; /* is the current file zip64 */
157 uint32_t keys[3]; /* keys defining the pseudo-random sequence */
158 const z_crc_t *pcrc_32_tab;
162 /* Read a byte from a gz_stream; Return EOF for end of file. */
163 static int unzReadUInt8(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint8_t *value)
166 if (ZREAD64(*pzlib_filefunc_def, filestream, &c, 1) == 1)
172 if (ZERROR64(*pzlib_filefunc_def, filestream))
177 static int unzReadUInt16(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint16_t *value)
183 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
186 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
187 x |= ((uint16_t)c) << 8;
196 static int unzReadUInt32(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint32_t *value)
202 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
205 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
206 x |= ((uint32_t)c) << 8;
208 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
209 x |= ((uint32_t)c) << 16;
211 err = unzReadUInt8(pzlib_filefunc_def, filestream, &c);
212 x += ((uint32_t)c) << 24;
221 static int unzReadUInt64(const zlib_filefunc64_32_def *pzlib_filefunc_def, voidpf filestream, uint64_t *value)
227 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
230 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
231 x |= ((uint64_t)i) << 8;
233 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
234 x |= ((uint64_t)i) << 16;
236 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
237 x |= ((uint64_t)i) << 24;
239 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
240 x |= ((uint64_t)i) << 32;
242 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
243 x |= ((uint64_t)i) << 40;
245 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
246 x |= ((uint64_t)i) << 48;
248 err = unzReadUInt8(pzlib_filefunc_def, filestream, &i);
249 x |= ((uint64_t)i) << 56;
258 /* Locate the Central directory of a zip file (at the end, just before the global comment) */
259 static int unzSearchCentralDir(const zlib_filefunc64_32_def *pzlib_filefunc_def, uint64_t *pos_found, voidpf filestream)
261 uint8_t buf[BUFREADCOMMENT + 4];
262 uint64_t file_size = 0;
263 uint64_t back_read = 4;
264 uint64_t max_back = UINT16_MAX; /* maximum size of global comment */
265 uint32_t read_size = 0;
266 uint64_t read_pos = 0;
270 if (ZSEEK64(*pzlib_filefunc_def, filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
273 file_size = ZTELL64(*pzlib_filefunc_def, filestream);
275 if (max_back > file_size)
276 max_back = file_size;
278 while (back_read < max_back)
280 if (back_read + BUFREADCOMMENT > max_back)
281 back_read = max_back;
283 back_read += BUFREADCOMMENT;
285 read_pos = file_size - back_read;
286 read_size = ((BUFREADCOMMENT + 4) < (file_size - read_pos)) ?
287 (BUFREADCOMMENT + 4) : (uint32_t)(file_size - read_pos);
289 if (ZSEEK64(*pzlib_filefunc_def, filestream, read_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
291 if (ZREAD64(*pzlib_filefunc_def, filestream, buf, read_size) != read_size)
294 for (i = read_size - 3; (i--) > 0;)
295 if (((*(buf+i)) == (ENDHEADERMAGIC & 0xff)) &&
296 ((*(buf+i+1)) == (ENDHEADERMAGIC >> 8 & 0xff)) &&
297 ((*(buf+i+2)) == (ENDHEADERMAGIC >> 16 & 0xff)) &&
298 ((*(buf+i+3)) == (ENDHEADERMAGIC >> 24 & 0xff)))
300 *pos_found = read_pos+i;
308 /* Locate the Central directory 64 of a zipfile (at the end, just before the global comment) */
309 static int unzSearchCentralDir64(const zlib_filefunc64_32_def *pzlib_filefunc_def, uint64_t *offset, voidpf filestream,
310 const uint64_t endcentraloffset)
312 uint32_t value32 = 0;
315 /* Zip64 end of central directory locator */
316 if (ZSEEK64(*pzlib_filefunc_def, filestream, endcentraloffset - SIZECENTRALHEADERLOCATOR, ZLIB_FILEFUNC_SEEK_SET) != 0)
319 /* Read locator signature */
320 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
322 if (value32 != ZIP64ENDLOCHEADERMAGIC)
324 /* Number of the disk with the start of the zip64 end of central directory */
325 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
327 /* Relative offset of the zip64 end of central directory record */
328 if (unzReadUInt64(pzlib_filefunc_def, filestream, offset) != UNZ_OK)
330 /* Total number of disks */
331 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
333 /* Goto end of central directory record */
334 if (ZSEEK64(*pzlib_filefunc_def, filestream, *offset, ZLIB_FILEFUNC_SEEK_SET) != 0)
337 if (unzReadUInt32(pzlib_filefunc_def, filestream, &value32) != UNZ_OK)
339 if (value32 != ZIP64ENDHEADERMAGIC)
345 static unzFile unzOpenInternal(const void *path, zlib_filefunc64_32_def *pzlib_filefunc64_32_def)
347 unz64_internal us = {{{ 0 }}}; // (prevent warning from GCC bug 53119)
348 unz64_internal *s = NULL;
349 uint64_t central_pos = 0;
350 uint64_t central_pos64 = 0;
351 uint64_t number_entry_CD = 0;
352 uint16_t value16 = 0;
353 uint32_t value32 = 0;
354 uint64_t value64 = 0;
355 voidpf filestream = NULL;
359 if (pzlib_filefunc64_32_def == NULL)
360 fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
363 assert((pzlib_filefunc64_32_def->zopen32_file || pzlib_filefunc64_32_def->zfile_func64.zopen64_file) &&
364 (pzlib_filefunc64_32_def->zopendisk32_file || pzlib_filefunc64_32_def->zfile_func64.zopendisk64_file) &&
365 (pzlib_filefunc64_32_def->ztell32_file || pzlib_filefunc64_32_def->zfile_func64.ztell64_file) &&
366 (pzlib_filefunc64_32_def->zseek32_file || pzlib_filefunc64_32_def->zfile_func64.zseek64_file));
367 us.z_filefunc = *pzlib_filefunc64_32_def;
370 us.filestream = ZOPEN64(us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
372 if (us.filestream == NULL)
375 us.filestream_with_CD = us.filestream;
377 /* Search for end of central directory header */
378 err = unzSearchCentralDir(&us.z_filefunc, ¢ral_pos, us.filestream);
381 if (ZSEEK64(us.z_filefunc, us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
384 /* The signature, already checked */
385 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
387 /* Number of this disk */
388 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
390 us.number_disk = value16;
391 /* Number of the disk with the start of the central directory */
392 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
394 us.gi.number_disk_with_CD = value16;
395 /* Total number of entries in the central directory on this disk */
396 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
398 us.gi.number_entry = value16;
399 /* Total number of entries in the central directory */
400 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
402 number_entry_CD = value16;
403 if (number_entry_CD != us.gi.number_entry)
404 err = UNZ_BADZIPFILE;
405 /* Size of the central directory */
406 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
408 us.size_central_dir = value32;
409 /* Offset of start of central directory with respect to the starting disk number */
410 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
412 us.offset_central_dir = value32;
413 /* Zipfile comment length */
414 if (unzReadUInt16(&us.z_filefunc, us.filestream, &us.gi.size_comment) != UNZ_OK)
419 /* Search for Zip64 end of central directory header */
420 err64 = unzSearchCentralDir64(&us.z_filefunc, ¢ral_pos64, us.filestream, central_pos);
423 central_pos = central_pos64;
426 if (ZSEEK64(us.z_filefunc, us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
429 /* the signature, already checked */
430 if (unzReadUInt32(&us.z_filefunc, us.filestream, &value32) != UNZ_OK)
432 /* size of zip64 end of central directory record */
433 if (unzReadUInt64(&us.z_filefunc, us.filestream, &value64) != UNZ_OK)
435 /* version made by */
436 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
438 /* version needed to extract */
439 if (unzReadUInt16(&us.z_filefunc, us.filestream, &value16) != UNZ_OK)
441 /* number of this disk */
442 if (unzReadUInt32(&us.z_filefunc, us.filestream, &us.number_disk) != UNZ_OK)
444 /* number of the disk with the start of the central directory */
445 if (unzReadUInt32(&us.z_filefunc, us.filestream, &us.gi.number_disk_with_CD) != UNZ_OK)
447 /* total number of entries in the central directory on this disk */
448 if (unzReadUInt64(&us.z_filefunc, us.filestream, &us.gi.number_entry) != UNZ_OK)
450 /* total number of entries in the central directory */
451 if (unzReadUInt64(&us.z_filefunc, us.filestream, &number_entry_CD) != UNZ_OK)
453 if (number_entry_CD != us.gi.number_entry)
454 err = UNZ_BADZIPFILE;
455 /* size of the central directory */
456 if (unzReadUInt64(&us.z_filefunc, us.filestream, &us.size_central_dir) != UNZ_OK)
458 /* offset of start of central directory with respect to the starting disk number */
459 if (unzReadUInt64(&us.z_filefunc, us.filestream, &us.offset_central_dir) != UNZ_OK)
462 else if ((us.size_central_dir == UINT16_MAX) || (us.offset_central_dir == UINT32_MAX))
463 err = UNZ_BADZIPFILE;
469 if ((err == UNZ_OK) && (central_pos < us.offset_central_dir + us.size_central_dir))
470 err = UNZ_BADZIPFILE;
474 ZCLOSE64(us.z_filefunc, us.filestream);
478 if (us.gi.number_disk_with_CD == 0)
480 /* If there is only one disk open another stream so we don't have to seek between the CD
481 and the file headers constantly */
482 filestream = ZOPEN64(us.z_filefunc, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
483 if (filestream != NULL)
484 us.filestream = filestream;
487 /* Hack for zip files that have no respect for zip64
488 if ((central_pos > 0xffffffff) && (us.offset_central_dir < 0xffffffff))
489 us.offset_central_dir = central_pos - us.size_central_dir;*/
491 us.byte_before_the_zipfile = central_pos - (us.offset_central_dir + us.size_central_dir);
492 us.central_pos = central_pos;
494 s = (unz64_internal*)ALLOC(sizeof(unz64_internal));
499 // workaround incorrect count #184
500 s->gi.number_entry = unzCountEntries(s);
502 unzGoToFirstFile((unzFile)s);
507 extern unzFile ZEXPORT unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc32_def)
509 if (pzlib_filefunc32_def != NULL)
511 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill = {{ 0 }};
512 fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill, pzlib_filefunc32_def);
513 return unzOpenInternal(path, &zlib_filefunc64_32_def_fill);
515 return unzOpenInternal(path, NULL);
518 extern unzFile ZEXPORT unzOpen2_64(const void *path, zlib_filefunc64_def *pzlib_filefunc_def)
520 if (pzlib_filefunc_def != NULL)
522 zlib_filefunc64_32_def zlib_filefunc64_32_def_fill = {{ 0 }};
523 zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
524 return unzOpenInternal(path, &zlib_filefunc64_32_def_fill);
526 return unzOpenInternal(path, NULL);
529 extern unzFile ZEXPORT unzOpen(const char *path)
531 return unzOpenInternal(path, NULL);
534 extern unzFile ZEXPORT unzOpen64(const void *path)
536 return unzOpenInternal(path, NULL);
539 extern int ZEXPORT unzClose(unzFile file)
543 return UNZ_PARAMERROR;
544 s = (unz64_internal*)file;
546 if (s->pfile_in_zip_read != NULL)
547 unzCloseCurrentFile(file);
549 if ((s->filestream != NULL) && (s->filestream != s->filestream_with_CD))
550 ZCLOSE64(s->z_filefunc, s->filestream);
551 if (s->filestream_with_CD != NULL)
552 ZCLOSE64(s->z_filefunc, s->filestream_with_CD);
554 s->filestream = NULL;
555 s->filestream_with_CD = NULL;
560 /* Goto to the next available disk for spanned archives */
561 static int unzGoToNextDisk(unzFile file)
564 uint32_t number_disk_next = 0;
566 s = (unz64_internal*)file;
568 return UNZ_PARAMERROR;
569 number_disk_next = s->number_disk;
571 if ((s->pfile_in_zip_read != NULL) && (s->pfile_in_zip_read->rest_read_uncompressed > 0))
572 /* We are currently reading a file and we need the next sequential disk */
573 number_disk_next += 1;
575 /* Goto the disk for the current file */
576 number_disk_next = s->cur_file_info.disk_num_start;
578 if (number_disk_next != s->number_disk)
581 if ((s->filestream != NULL) && (s->filestream != s->filestream_with_CD))
582 ZCLOSE64(s->z_filefunc, s->filestream);
584 if (number_disk_next == s->gi.number_disk_with_CD)
586 s->filestream = s->filestream_with_CD;
590 s->filestream = ZOPENDISK64(s->z_filefunc, s->filestream_with_CD, number_disk_next,
591 ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING);
594 if (s->filestream == NULL)
597 s->number_disk = number_disk_next;
603 extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32)
605 unz64_internal *s = NULL;
607 return UNZ_PARAMERROR;
608 s = (unz64_internal*)file;
610 pglobal_info32->number_entry = (uint32_t)s->gi.number_entry;
611 pglobal_info32->size_comment = s->gi.size_comment;
612 pglobal_info32->number_disk_with_CD = s->gi.number_disk_with_CD;
616 extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64 *pglobal_info)
618 unz64_internal *s = NULL;
620 return UNZ_PARAMERROR;
621 s = (unz64_internal*)file;
622 *pglobal_info = s->gi;
626 extern int ZEXPORT unzGetGlobalComment(unzFile file, char *comment, uint16_t comment_size)
628 unz64_internal *s = NULL;
629 uint16_t bytes_to_read = comment_size;
631 return (int)UNZ_PARAMERROR;
632 s = (unz64_internal*)file;
634 if (bytes_to_read > s->gi.size_comment)
635 bytes_to_read = s->gi.size_comment;
637 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, s->central_pos + 22, ZLIB_FILEFUNC_SEEK_SET) != 0)
640 if (bytes_to_read > 0)
643 if (ZREAD64(s->z_filefunc, s->filestream_with_CD, comment, bytes_to_read) != bytes_to_read)
647 if ((comment != NULL) && (comment_size > s->gi.size_comment))
648 *(comment + s->gi.size_comment) = 0;
650 return (int)bytes_to_read;
653 static int unzGetCurrentFileInfoField(unzFile file, uint32_t *seek, void *field, uint16_t field_size, uint16_t size_file_field, int null_terminated_field)
655 unz64_internal *s = NULL;
656 uint32_t bytes_to_read = 0;
660 return (int)UNZ_PARAMERROR;
661 s = (unz64_internal*)file;
666 if (size_file_field < field_size)
668 if (null_terminated_field)
669 *((char *)field+size_file_field) = 0;
671 bytes_to_read = size_file_field;
674 bytes_to_read = field_size;
678 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, *seek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
684 if ((size_file_field > 0) && (field_size > 0))
686 if (ZREAD64(s->z_filefunc, s->filestream_with_CD, field, bytes_to_read) != bytes_to_read)
689 *seek += size_file_field - bytes_to_read;
693 *seek += size_file_field;
699 /* Get info about the current file in the zipfile, with internal only info */
700 static int unzGetCurrentFileInfoInternal(unzFile file, unz_file_info64 *pfile_info,
701 unz_file_info64_internal *pfile_info_internal, char *filename, uint16_t filename_size, void *extrafield,
702 uint16_t extrafield_size, char *comment, uint16_t comment_size)
704 unz64_internal *s = NULL;
705 unz_file_info64 file_info;
706 unz_file_info64_internal file_info_internal;
708 uint64_t current_pos = 0;
710 uint32_t extra_pos = 0;
711 uint16_t extra_header_id = 0;
712 uint16_t extra_data_size = 0;
713 uint16_t value16 = 0;
714 uint32_t value32 = 0;
715 uint64_t value64 = 0;
719 return UNZ_PARAMERROR;
720 s = (unz64_internal*)file;
722 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD,
723 s->pos_in_central_dir + s->byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
726 /* Check the magic */
729 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &magic) != UNZ_OK)
731 else if (magic != CENTRALHEADERMAGIC)
732 err = UNZ_BADZIPFILE;
735 /* Read central directory header */
736 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.version) != UNZ_OK)
738 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.version_needed) != UNZ_OK)
740 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.flag) != UNZ_OK)
742 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.compression_method) != UNZ_OK)
744 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.dos_date) != UNZ_OK)
746 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.crc) != UNZ_OK)
748 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &value32) != UNZ_OK)
750 file_info.compressed_size = value32;
751 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &value32) != UNZ_OK)
753 file_info.uncompressed_size = value32;
754 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.size_filename) != UNZ_OK)
756 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.size_file_extra) != UNZ_OK)
758 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.size_file_comment) != UNZ_OK)
760 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &value16) != UNZ_OK)
762 file_info.disk_num_start = value16;
763 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &file_info.internal_fa) != UNZ_OK)
765 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.external_fa) != UNZ_OK)
767 /* Relative offset of local header */
768 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &value32) != UNZ_OK)
771 file_info.size_file_extra_internal = 0;
772 file_info.disk_offset = value32;
773 file_info_internal.offset_curfile = value32;
775 file_info_internal.aes_compression_method = 0;
776 file_info_internal.aes_encryption_mode = 0;
777 file_info_internal.aes_version = 0;
781 err = unzGetCurrentFileInfoField(file, &seek, filename, filename_size, file_info.size_filename, 1);
783 /* Read extrafield */
785 err = unzGetCurrentFileInfoField(file, &seek, extrafield, extrafield_size, file_info.size_file_extra, 0);
787 if ((err == UNZ_OK) && (file_info.size_file_extra != 0))
791 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, seek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
797 /* We are going to parse the extra field so we need to move back */
798 current_pos = ZTELL64(s->z_filefunc, s->filestream_with_CD);
799 if (current_pos < file_info.size_file_extra)
801 current_pos -= file_info.size_file_extra;
802 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, current_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
805 while ((err != UNZ_ERRNO) && (extra_pos < file_info.size_file_extra))
807 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &extra_header_id) != UNZ_OK)
809 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &extra_data_size) != UNZ_OK)
812 /* ZIP64 extra fields */
813 if (extra_header_id == 0x0001)
815 /* Subtract size of ZIP64 field, since ZIP64 is handled internally */
816 file_info.size_file_extra_internal += 2 + 2 + extra_data_size;
818 if (file_info.uncompressed_size == UINT32_MAX)
820 if (unzReadUInt64(&s->z_filefunc, s->filestream_with_CD, &file_info.uncompressed_size) != UNZ_OK)
823 if (file_info.compressed_size == UINT32_MAX)
825 if (unzReadUInt64(&s->z_filefunc, s->filestream_with_CD, &file_info.compressed_size) != UNZ_OK)
828 if (file_info_internal.offset_curfile == UINT32_MAX)
830 /* Relative Header offset */
831 if (unzReadUInt64(&s->z_filefunc, s->filestream_with_CD, &value64) != UNZ_OK)
833 file_info_internal.offset_curfile = value64;
834 file_info.disk_offset = value64;
836 if (file_info.disk_num_start == UINT32_MAX)
838 /* Disk Start Number */
839 if (unzReadUInt32(&s->z_filefunc, s->filestream_with_CD, &file_info.disk_num_start) != UNZ_OK)
845 else if (extra_header_id == 0x9901)
849 /* Subtract size of AES field, since AES is handled internally */
850 file_info.size_file_extra_internal += 2 + 2 + extra_data_size;
852 /* Verify version info */
853 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &value16) != UNZ_OK)
855 /* Support AE-1 and AE-2 */
856 if (value16 != 1 && value16 != 2)
858 file_info_internal.aes_version = value16;
859 if (unzReadUInt8(&s->z_filefunc, s->filestream_with_CD, &value8) != UNZ_OK)
861 if ((char)value8 != 'A')
863 if (unzReadUInt8(&s->z_filefunc, s->filestream_with_CD, &value8) != UNZ_OK)
865 if ((char)value8 != 'E')
867 /* Get AES encryption strength and actual compression method */
868 if (unzReadUInt8(&s->z_filefunc, s->filestream_with_CD, &value8) != UNZ_OK)
870 file_info_internal.aes_encryption_mode = value8;
871 if (unzReadUInt16(&s->z_filefunc, s->filestream_with_CD, &value16) != UNZ_OK)
873 file_info_internal.aes_compression_method = value16;
878 if (ZSEEK64(s->z_filefunc, s->filestream_with_CD, extra_data_size, ZLIB_FILEFUNC_SEEK_CUR) != 0)
882 extra_pos += 2 + 2 + extra_data_size;
886 if (file_info.disk_num_start == s->gi.number_disk_with_CD)
887 file_info_internal.byte_before_the_zipfile = s->byte_before_the_zipfile;
889 file_info_internal.byte_before_the_zipfile = 0;
892 err = unzGetCurrentFileInfoField(file, &seek, comment, comment_size, file_info.size_file_comment, 1);
894 if ((err == UNZ_OK) && (pfile_info != NULL))
895 *pfile_info = file_info;
896 if ((err == UNZ_OK) && (pfile_info_internal != NULL))
897 *pfile_info_internal = file_info_internal;
902 extern int ZEXPORT unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *filename,
903 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
905 unz_file_info64 file_info64;
908 err = unzGetCurrentFileInfoInternal(file, &file_info64, NULL, filename, filename_size,
909 extrafield, extrafield_size, comment, comment_size);
911 if ((err == UNZ_OK) && (pfile_info != NULL))
913 pfile_info->version = file_info64.version;
914 pfile_info->version_needed = file_info64.version_needed;
915 pfile_info->flag = file_info64.flag;
916 pfile_info->compression_method = file_info64.compression_method;
917 pfile_info->dos_date = file_info64.dos_date;
918 pfile_info->crc = file_info64.crc;
920 pfile_info->size_filename = file_info64.size_filename;
921 pfile_info->size_file_extra = file_info64.size_file_extra - file_info64.size_file_extra_internal;
922 pfile_info->size_file_comment = file_info64.size_file_comment;
924 pfile_info->disk_num_start = (uint16_t)file_info64.disk_num_start;
925 pfile_info->internal_fa = file_info64.internal_fa;
926 pfile_info->external_fa = file_info64.external_fa;
928 pfile_info->compressed_size = (uint32_t)file_info64.compressed_size;
929 pfile_info->uncompressed_size = (uint32_t)file_info64.uncompressed_size;
934 extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file, unz_file_info64 * pfile_info, char *filename,
935 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
937 return unzGetCurrentFileInfoInternal(file, pfile_info, NULL, filename, filename_size,
938 extrafield, extrafield_size, comment, comment_size);
941 /* Read the local header of the current zipfile. Check the coherency of the local header and info in the
942 end of central directory about this file store in *piSizeVar the size of extra info in local header
943 (filename and size of extra field data) */
944 static int unzCheckCurrentFileCoherencyHeader(unz64_internal *s, uint32_t *psize_variable, uint64_t *poffset_local_extrafield,
945 uint16_t *psize_local_extrafield)
948 uint16_t value16 = 0;
949 uint32_t value32 = 0;
951 uint16_t size_filename = 0;
952 uint16_t size_extra_field = 0;
953 uint16_t compression_method = 0;
956 if (psize_variable == NULL)
957 return UNZ_PARAMERROR;
959 if (poffset_local_extrafield == NULL)
960 return UNZ_PARAMERROR;
961 *poffset_local_extrafield = 0;
962 if (psize_local_extrafield == NULL)
963 return UNZ_PARAMERROR;
964 *psize_local_extrafield = 0;
966 err = unzGoToNextDisk((unzFile)s);
970 if (ZSEEK64(s->z_filefunc, s->filestream, s->cur_file_info_internal.offset_curfile +
971 s->cur_file_info_internal.byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
976 if (unzReadUInt32(&s->z_filefunc, s->filestream, &magic) != UNZ_OK)
978 else if (magic != LOCALHEADERMAGIC)
979 err = UNZ_BADZIPFILE;
982 if (unzReadUInt16(&s->z_filefunc, s->filestream, &value16) != UNZ_OK)
984 if (unzReadUInt16(&s->z_filefunc, s->filestream, &value16) != UNZ_OK)
987 if (unzReadUInt16(&s->z_filefunc, s->filestream, &value16) != UNZ_OK)
989 else if ((err == UNZ_OK) && (value16 != s->cur_file_info.compression_method))
990 err = UNZ_BADZIPFILE;
992 compression_method = s->cur_file_info.compression_method;
994 if (compression_method == AES_METHOD)
995 compression_method = s->cur_file_info_internal.aes_compression_method;
998 if ((err == UNZ_OK) && (compression_method != 0) && (compression_method != Z_DEFLATED))
1001 if (compression_method != Z_BZIP2ED)
1003 err = UNZ_BADZIPFILE;
1006 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* date/time */
1008 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* crc */
1010 else if ((err == UNZ_OK) && (value32 != s->cur_file_info.crc) && ((flags & 8) == 0))
1011 err = UNZ_BADZIPFILE;
1012 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* size compr */
1014 else if ((value32 != UINT32_MAX) && (err == UNZ_OK) && (value32 != s->cur_file_info.compressed_size) && ((flags & 8) == 0))
1015 err = UNZ_BADZIPFILE;
1016 if (unzReadUInt32(&s->z_filefunc, s->filestream, &value32) != UNZ_OK) /* size uncompr */
1018 else if ((value32 != UINT32_MAX) && (err == UNZ_OK) && (value32 != s->cur_file_info.uncompressed_size) && ((flags & 8) == 0))
1019 err = UNZ_BADZIPFILE;
1020 if (unzReadUInt16(&s->z_filefunc, s->filestream, &size_filename) != UNZ_OK)
1023 *psize_variable += size_filename;
1025 if (unzReadUInt16(&s->z_filefunc, s->filestream, &size_extra_field) != UNZ_OK)
1028 *poffset_local_extrafield = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_filename;
1029 *psize_local_extrafield = size_extra_field;
1030 *psize_variable += size_extra_field;
1035 extern uint64_t ZEXPORT unzCountEntries(const unzFile file)
1040 unz64_internal s = *(unz64_internal*)file;
1042 s.pos_in_central_dir = s.offset_central_dir;
1044 while (UNZ_OK == unzGetCurrentFileInfoInternal(&s,
1046 &s.cur_file_info_internal,
1047 NULL, 0, NULL, 0, NULL, 0))
1049 s.pos_in_central_dir += SIZECENTRALDIRITEM
1050 + s.cur_file_info.size_filename
1051 + s.cur_file_info.size_file_extra
1052 + s.cur_file_info.size_file_comment;
1059 Open for reading data the current file in the zipfile.
1060 If there is no error and the file is opened, the return value is UNZ_OK.
1062 extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password)
1064 unz64_internal *s = NULL;
1065 file_in_zip64_read_info_s *pfile_in_zip_read_info = NULL;
1066 uint16_t compression_method = 0;
1067 uint64_t offset_local_extrafield = 0;
1068 uint16_t size_local_extrafield = 0;
1069 uint32_t size_variable = 0;
1074 if (password != NULL)
1075 return UNZ_PARAMERROR;
1078 return UNZ_PARAMERROR;
1079 s = (unz64_internal*)file;
1080 if (!s->current_file_ok)
1081 return UNZ_PARAMERROR;
1083 if (s->pfile_in_zip_read != NULL)
1084 unzCloseCurrentFile(file);
1086 if (unzCheckCurrentFileCoherencyHeader(s, &size_variable, &offset_local_extrafield, &size_local_extrafield) != UNZ_OK)
1087 return UNZ_BADZIPFILE;
1089 compression_method = s->cur_file_info.compression_method;
1091 if (compression_method == AES_METHOD)
1093 compression_method = s->cur_file_info_internal.aes_compression_method;
1094 if (password == NULL)
1096 return UNZ_PARAMERROR;
1102 *method = compression_method;
1107 switch (s->cur_file_info.flag & 0x06)
1109 case 6 : *level = 1; break;
1110 case 4 : *level = 2; break;
1111 case 2 : *level = 9; break;
1115 if ((compression_method != 0) && (compression_method != Z_DEFLATED))
1118 if (compression_method != Z_BZIP2ED)
1121 return UNZ_BADZIPFILE;
1125 pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
1126 if (pfile_in_zip_read_info == NULL)
1127 return UNZ_INTERNALERROR;
1129 pfile_in_zip_read_info->read_buffer = (uint8_t*)ALLOC(UNZ_BUFSIZE);
1130 if (pfile_in_zip_read_info->read_buffer == NULL)
1132 TRYFREE(pfile_in_zip_read_info);
1133 return UNZ_INTERNALERROR;
1136 pfile_in_zip_read_info->stream_initialised = 0;
1138 pfile_in_zip_read_info->filestream = s->filestream;
1139 pfile_in_zip_read_info->z_filefunc = s->z_filefunc;
1141 pfile_in_zip_read_info->raw = raw;
1142 pfile_in_zip_read_info->crc32 = 0;
1143 pfile_in_zip_read_info->crc32_expected = s->cur_file_info.crc;
1144 pfile_in_zip_read_info->total_out_64 = 0;
1145 pfile_in_zip_read_info->compression_method = compression_method;
1147 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1148 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1149 pfile_in_zip_read_info->pos_local_extrafield = 0;
1151 pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size;
1152 pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size;
1153 pfile_in_zip_read_info->byte_before_the_zipfile = 0;
1155 if (s->number_disk == s->gi.number_disk_with_CD)
1156 pfile_in_zip_read_info->byte_before_the_zipfile = s->byte_before_the_zipfile;
1158 pfile_in_zip_read_info->pos_in_zipfile = s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + size_variable;
1160 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1161 pfile_in_zip_read_info->stream.zfree = (free_func)0;
1162 pfile_in_zip_read_info->stream.opaque = (voidpf)s;
1163 pfile_in_zip_read_info->stream.total_out = 0;
1164 pfile_in_zip_read_info->stream.total_in = 0;
1165 pfile_in_zip_read_info->stream.next_in = NULL;
1166 pfile_in_zip_read_info->stream.avail_in = 0;
1170 if (compression_method == Z_BZIP2ED)
1173 pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
1174 pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
1175 pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
1176 pfile_in_zip_read_info->bstream.state = (voidpf)0;
1178 err = BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
1181 pfile_in_zip_read_info->stream_initialised = Z_BZIP2ED;
1185 TRYFREE(pfile_in_zip_read_info);
1189 pfile_in_zip_read_info->raw = 1;
1192 else if (compression_method == Z_DEFLATED)
1194 #ifdef HAVE_APPLE_COMPRESSION
1195 err = compression_stream_init(&pfile_in_zip_read_info->astream, COMPRESSION_STREAM_DECODE, COMPRESSION_ZLIB);
1196 if (err == COMPRESSION_STATUS_ERROR)
1197 err = UNZ_INTERNALERROR;
1201 err = inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1205 pfile_in_zip_read_info->stream_initialised = Z_DEFLATED;
1209 TRYFREE(pfile_in_zip_read_info);
1212 /* windowBits is passed < 0 to tell that there is no zlib header.
1213 * Note that in this case inflate *requires* an extra "dummy" byte
1214 * after the compressed stream in order to complete decompression and
1215 * return Z_STREAM_END.
1216 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1217 * size of both compressed and uncompressed data
1222 s->pfile_in_zip_read = pfile_in_zip_read_info;
1225 s->pcrc_32_tab = NULL;
1227 if ((password != NULL) && ((s->cur_file_info.flag & 1) != 0))
1229 if (ZSEEK64(s->z_filefunc, s->filestream,
1230 s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile,
1231 ZLIB_FILEFUNC_SEEK_SET) != 0)
1232 return UNZ_INTERNALERROR;
1234 if (s->cur_file_info.compression_method == AES_METHOD)
1236 unsigned char passverify_archive[AES_PWVERIFYSIZE];
1237 unsigned char passverify_password[AES_PWVERIFYSIZE];
1238 unsigned char salt_value[AES_MAXSALTLENGTH];
1239 uint32_t salt_length = 0;
1241 if ((s->cur_file_info_internal.aes_encryption_mode < 1) ||
1242 (s->cur_file_info_internal.aes_encryption_mode > 3))
1243 return UNZ_INTERNALERROR;
1245 salt_length = SALT_LENGTH(s->cur_file_info_internal.aes_encryption_mode);
1247 if (ZREAD64(s->z_filefunc, s->filestream, salt_value, salt_length) != salt_length)
1248 return UNZ_INTERNALERROR;
1249 if (ZREAD64(s->z_filefunc, s->filestream, passverify_archive, AES_PWVERIFYSIZE) != AES_PWVERIFYSIZE)
1250 return UNZ_INTERNALERROR;
1252 fcrypt_init(s->cur_file_info_internal.aes_encryption_mode, (uint8_t *)password,
1253 (uint32_t)strlen(password), salt_value, passverify_password, &s->pfile_in_zip_read->aes_ctx);
1255 if (memcmp(passverify_archive, passverify_password, AES_PWVERIFYSIZE) != 0)
1256 return UNZ_BADPASSWORD;
1258 s->pfile_in_zip_read->rest_read_compressed -= salt_length + AES_PWVERIFYSIZE;
1259 s->pfile_in_zip_read->rest_read_compressed -= AES_AUTHCODESIZE;
1261 s->pfile_in_zip_read->pos_in_zipfile += salt_length + AES_PWVERIFYSIZE;
1267 s->pcrc_32_tab = (const z_crc_t*)get_crc_table();
1268 init_keys(password, s->keys, s->pcrc_32_tab);
1270 if (ZREAD64(s->z_filefunc, s->filestream, source, 12) < 12)
1271 return UNZ_INTERNALERROR;
1273 for (i = 0; i < 12; i++)
1274 zdecode(s->keys, s->pcrc_32_tab, source[i]);
1275 uint8_t expected = (s->cur_file_info.flag & (1 << 3)) ?
1276 s->cur_file_info.dos_date >> 8 :
1277 s->cur_file_info.crc >> 24;
1278 uint8_t actual = (uint8_t)source[11];
1279 if (expected != actual) {
1280 return UNZ_BADPASSWORD;
1283 s->pfile_in_zip_read->rest_read_compressed -= 12;
1284 s->pfile_in_zip_read->pos_in_zipfile += 12;
1292 extern int ZEXPORT unzOpenCurrentFile(unzFile file)
1294 return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1297 extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char *password)
1299 return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1302 extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int *method, int *level, int raw)
1304 return unzOpenCurrentFile3(file, method, level, raw, NULL);
1307 /* Read bytes from the current file.
1308 buf contain buffer where data must be copied
1309 len the size of buf.
1311 return the number of byte copied if some bytes are copied
1312 return 0 if the end of file was reached
1313 return <0 with error code if there is an error (UNZ_ERRNO for IO error, or zLib error for uncompress error) */
1314 extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, uint32_t len)
1316 unz64_internal *s = NULL;
1321 return UNZ_PARAMERROR;
1322 s = (unz64_internal*)file;
1324 if (s->pfile_in_zip_read == NULL)
1325 return UNZ_PARAMERROR;
1326 if (s->pfile_in_zip_read->read_buffer == NULL)
1327 return UNZ_END_OF_LIST_OF_FILE;
1330 // avail_out is uInt, so uint32_t len might allow requesting a larger buffer than zlib can support
1332 return UNZ_PARAMERROR;
1334 s->pfile_in_zip_read->stream.next_out = (uint8_t*)buf;
1335 s->pfile_in_zip_read->stream.avail_out = (uInt)len;
1337 if ((s->pfile_in_zip_read->compression_method == 0) || (s->pfile_in_zip_read->raw))
1339 if (len > s->pfile_in_zip_read->rest_read_compressed + s->pfile_in_zip_read->stream.avail_in)
1340 s->pfile_in_zip_read->stream.avail_out = (uInt)s->pfile_in_zip_read->rest_read_compressed +
1341 s->pfile_in_zip_read->stream.avail_in;
1346 if (s->pfile_in_zip_read->stream.avail_in == 0)
1348 uint32_t bytes_to_read = UNZ_BUFSIZE;
1349 uint32_t bytes_not_read = 0;
1350 uint32_t bytes_read = 0;
1351 uint32_t total_bytes_read = 0;
1353 if (s->pfile_in_zip_read->stream.next_in != NULL)
1354 bytes_not_read = (uint32_t)(s->pfile_in_zip_read->read_buffer + UNZ_BUFSIZE -
1355 s->pfile_in_zip_read->stream.next_in);
1356 bytes_to_read -= bytes_not_read;
1357 if (bytes_not_read > 0)
1358 memmove(s->pfile_in_zip_read->read_buffer, s->pfile_in_zip_read->stream.next_in, bytes_not_read);
1359 if (s->pfile_in_zip_read->rest_read_compressed < bytes_to_read)
1360 bytes_to_read = (uint32_t)s->pfile_in_zip_read->rest_read_compressed;
1362 while (total_bytes_read != bytes_to_read)
1364 if (ZSEEK64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream,
1365 s->pfile_in_zip_read->pos_in_zipfile + s->pfile_in_zip_read->byte_before_the_zipfile,
1366 ZLIB_FILEFUNC_SEEK_SET) != 0)
1369 bytes_read = ZREAD64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream,
1370 s->pfile_in_zip_read->read_buffer + bytes_not_read + total_bytes_read,
1371 bytes_to_read - total_bytes_read);
1373 total_bytes_read += bytes_read;
1374 s->pfile_in_zip_read->pos_in_zipfile += bytes_read;
1376 if (bytes_read == 0)
1378 if (ZERROR64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream))
1381 err = unzGoToNextDisk(file);
1385 s->pfile_in_zip_read->pos_in_zipfile = 0;
1386 s->pfile_in_zip_read->filestream = s->filestream;
1391 if ((s->cur_file_info.flag & 1) != 0)
1394 if (s->cur_file_info.compression_method == AES_METHOD)
1396 fcrypt_decrypt(s->pfile_in_zip_read->read_buffer, bytes_to_read, &s->pfile_in_zip_read->aes_ctx);
1400 if (s->pcrc_32_tab != NULL)
1404 for (i = 0; i < total_bytes_read; i++)
1405 s->pfile_in_zip_read->read_buffer[i] =
1406 zdecode(s->keys, s->pcrc_32_tab, s->pfile_in_zip_read->read_buffer[i]);
1411 s->pfile_in_zip_read->rest_read_compressed -= total_bytes_read;
1412 s->pfile_in_zip_read->stream.next_in = (uint8_t*)s->pfile_in_zip_read->read_buffer;
1413 s->pfile_in_zip_read->stream.avail_in = (uInt)(bytes_not_read + total_bytes_read);
1416 if ((s->pfile_in_zip_read->compression_method == 0) || (s->pfile_in_zip_read->raw))
1421 if ((s->pfile_in_zip_read->stream.avail_in == 0) &&
1422 (s->pfile_in_zip_read->rest_read_compressed == 0))
1423 return (read == 0) ? UNZ_EOF : read;
1425 if (s->pfile_in_zip_read->stream.avail_out < s->pfile_in_zip_read->stream.avail_in)
1426 copy = s->pfile_in_zip_read->stream.avail_out;
1428 copy = s->pfile_in_zip_read->stream.avail_in;
1430 for (i = 0; i < copy; i++)
1431 *(s->pfile_in_zip_read->stream.next_out + i) =
1432 *(s->pfile_in_zip_read->stream.next_in + i);
1434 s->pfile_in_zip_read->total_out_64 = s->pfile_in_zip_read->total_out_64 + copy;
1435 s->pfile_in_zip_read->rest_read_uncompressed -= copy;
1436 s->pfile_in_zip_read->crc32 = (uint32_t)crc32(s->pfile_in_zip_read->crc32,
1437 s->pfile_in_zip_read->stream.next_out, copy);
1439 s->pfile_in_zip_read->stream.avail_in -= copy;
1440 s->pfile_in_zip_read->stream.avail_out -= copy;
1441 s->pfile_in_zip_read->stream.next_out += copy;
1442 s->pfile_in_zip_read->stream.next_in += copy;
1443 s->pfile_in_zip_read->stream.total_out += copy;
1447 else if (s->pfile_in_zip_read->compression_method == Z_BZIP2ED)
1450 uint64_t total_out_before = 0;
1451 uint64_t total_out_after = 0;
1452 uint64_t out_bytes = 0;
1453 const uint8_t *buf_before = NULL;
1455 s->pfile_in_zip_read->bstream.next_in = (char*)s->pfile_in_zip_read->stream.next_in;
1456 s->pfile_in_zip_read->bstream.avail_in = s->pfile_in_zip_read->stream.avail_in;
1457 s->pfile_in_zip_read->bstream.total_in_lo32 = (uint32_t)s->pfile_in_zip_read->stream.total_in;
1458 s->pfile_in_zip_read->bstream.total_in_hi32 = s->pfile_in_zip_read->stream.total_in >> 32;
1460 s->pfile_in_zip_read->bstream.next_out = (char*)s->pfile_in_zip_read->stream.next_out;
1461 s->pfile_in_zip_read->bstream.avail_out = s->pfile_in_zip_read->stream.avail_out;
1462 s->pfile_in_zip_read->bstream.total_out_lo32 = (uint32_t)s->pfile_in_zip_read->stream.total_out;
1463 s->pfile_in_zip_read->bstream.total_out_hi32 = s->pfile_in_zip_read->stream.total_out >> 32;
1465 total_out_before = s->pfile_in_zip_read->bstream.total_out_lo32 +
1466 (((uint32_t)s->pfile_in_zip_read->bstream.total_out_hi32) << 32);
1467 buf_before = (const uint8_t*)s->pfile_in_zip_read->bstream.next_out;
1469 err = BZ2_bzDecompress(&s->pfile_in_zip_read->bstream);
1471 total_out_after = s->pfile_in_zip_read->bstream.total_out_lo32 +
1472 (((uint32_t)s->pfile_in_zip_read->bstream.total_out_hi32) << 32);
1474 out_bytes = total_out_after - total_out_before;
1476 s->pfile_in_zip_read->total_out_64 = s->pfile_in_zip_read->total_out_64 + out_bytes;
1477 s->pfile_in_zip_read->rest_read_uncompressed -= out_bytes;
1478 s->pfile_in_zip_read->crc32 = crc32(s->pfile_in_zip_read->crc32, buf_before, (uint32_t)out_bytes);
1480 read += (uint32_t)out_bytes;
1482 s->pfile_in_zip_read->stream.next_in = (uint8_t*)s->pfile_in_zip_read->bstream.next_in;
1483 s->pfile_in_zip_read->stream.avail_in = s->pfile_in_zip_read->bstream.avail_in;
1484 s->pfile_in_zip_read->stream.total_in = s->pfile_in_zip_read->bstream.total_in_lo32;
1485 s->pfile_in_zip_read->stream.next_out = (uint8_t*)s->pfile_in_zip_read->bstream.next_out;
1486 s->pfile_in_zip_read->stream.avail_out = s->pfile_in_zip_read->bstream.avail_out;
1487 s->pfile_in_zip_read->stream.total_out = s->pfile_in_zip_read->bstream.total_out_lo32;
1489 if (err == BZ_STREAM_END)
1490 return (read == 0) ? UNZ_EOF : read;
1495 #ifdef HAVE_APPLE_COMPRESSION
1498 uint64_t total_out_before = 0;
1499 uint64_t total_out_after = 0;
1500 uint64_t out_bytes = 0;
1501 const uint8_t *buf_before = NULL;
1503 s->pfile_in_zip_read->astream.src_ptr = s->pfile_in_zip_read->stream.next_in;
1504 s->pfile_in_zip_read->astream.src_size = s->pfile_in_zip_read->stream.avail_in;
1505 s->pfile_in_zip_read->astream.dst_ptr = s->pfile_in_zip_read->stream.next_out;
1506 s->pfile_in_zip_read->astream.dst_size = len;
1508 total_out_before = s->pfile_in_zip_read->stream.total_out;
1509 buf_before = s->pfile_in_zip_read->stream.next_out;
1511 compression_status status;
1512 compression_stream_flags flags;
1514 if (s->pfile_in_zip_read->stream.avail_in == 0)
1516 flags = COMPRESSION_STREAM_FINALIZE;
1519 status = compression_stream_process(&s->pfile_in_zip_read->astream, flags);
1521 total_out_after = len - s->pfile_in_zip_read->astream.dst_size;
1522 out_bytes = total_out_after - total_out_before;
1524 s->pfile_in_zip_read->total_out_64 += out_bytes;
1525 s->pfile_in_zip_read->rest_read_uncompressed -= out_bytes;
1526 s->pfile_in_zip_read->crc32 =
1527 crc32(s->pfile_in_zip_read->crc32, buf_before, (uint32_t)out_bytes);
1529 read += (uint32_t)out_bytes;
1531 s->pfile_in_zip_read->stream.next_in = s->pfile_in_zip_read->astream.src_ptr;
1532 s->pfile_in_zip_read->stream.avail_in = s->pfile_in_zip_read->astream.src_size;
1533 s->pfile_in_zip_read->stream.next_out = s->pfile_in_zip_read->astream.dst_ptr;
1534 s->pfile_in_zip_read->stream.avail_out = s->pfile_in_zip_read->astream.dst_size;
1536 if (status == COMPRESSION_STATUS_END)
1537 return (read == 0) ? UNZ_EOF : read;
1538 if (status == COMPRESSION_STATUS_ERROR)
1539 return Z_DATA_ERROR;
1545 uint64_t total_out_before = 0;
1546 uint64_t total_out_after = 0;
1547 uint64_t out_bytes = 0;
1548 const uint8_t *buf_before = NULL;
1549 int flush = Z_SYNC_FLUSH;
1551 total_out_before = s->pfile_in_zip_read->stream.total_out;
1552 buf_before = s->pfile_in_zip_read->stream.next_out;
1555 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1556 pfile_in_zip_read_info->stream.avail_out) &&
1557 (pfile_in_zip_read_info->rest_read_compressed == 0))
1560 err = inflate(&s->pfile_in_zip_read->stream, flush);
1562 if ((err >= 0) && (s->pfile_in_zip_read->stream.msg != NULL))
1565 total_out_after = s->pfile_in_zip_read->stream.total_out;
1566 out_bytes = total_out_after - total_out_before;
1568 s->pfile_in_zip_read->total_out_64 += out_bytes;
1569 s->pfile_in_zip_read->rest_read_uncompressed -= out_bytes;
1570 s->pfile_in_zip_read->crc32 =
1571 (uint32_t)crc32(s->pfile_in_zip_read->crc32, buf_before, (uint32_t)out_bytes);
1573 read += (uint32_t)out_bytes;
1575 if (err == Z_STREAM_END)
1576 return (read == 0) ? UNZ_EOF : read;
1582 while (s->pfile_in_zip_read->stream.avail_out > 0);
1589 extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, uint32_t len)
1591 unz64_internal *s = NULL;
1592 uint64_t size_to_read = 0;
1593 uint32_t read_now = 0;
1596 return UNZ_PARAMERROR;
1597 s = (unz64_internal*)file;
1598 if (s->pfile_in_zip_read == NULL)
1599 return UNZ_PARAMERROR;
1601 size_to_read = s->pfile_in_zip_read->size_local_extrafield - s->pfile_in_zip_read->pos_local_extrafield;
1604 return (int)size_to_read;
1606 if (len > size_to_read)
1607 read_now = (uint32_t)size_to_read;
1614 if (ZSEEK64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream,
1615 s->pfile_in_zip_read->offset_local_extrafield + s->pfile_in_zip_read->pos_local_extrafield,
1616 ZLIB_FILEFUNC_SEEK_SET) != 0)
1619 if (ZREAD64(s->pfile_in_zip_read->z_filefunc, s->pfile_in_zip_read->filestream, buf, read_now) != read_now)
1622 return (int)read_now;
1625 extern int ZEXPORT unzCloseCurrentFile(unzFile file)
1627 unz64_internal *s = NULL;
1628 file_in_zip64_read_info_s *pfile_in_zip_read_info = NULL;
1632 return UNZ_PARAMERROR;
1633 s = (unz64_internal*)file;
1634 pfile_in_zip_read_info = s->pfile_in_zip_read;
1635 if (pfile_in_zip_read_info == NULL)
1636 return UNZ_PARAMERROR;
1639 if (s->cur_file_info.compression_method == AES_METHOD)
1641 unsigned char authcode[AES_AUTHCODESIZE];
1642 unsigned char rauthcode[AES_AUTHCODESIZE];
1644 if (ZREAD64(s->z_filefunc, s->filestream, authcode, AES_AUTHCODESIZE) != AES_AUTHCODESIZE)
1647 if (fcrypt_end(rauthcode, &s->pfile_in_zip_read->aes_ctx) != AES_AUTHCODESIZE)
1649 if (memcmp(authcode, rauthcode, AES_AUTHCODESIZE) != 0)
1652 /* AES zip version AE-1 will expect a valid crc as well */
1653 if ((s->cur_file_info.compression_method != AES_METHOD) ||
1654 (s->cur_file_info_internal.aes_version == 0x0001))
1657 if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1658 (!pfile_in_zip_read_info->raw))
1660 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_expected)
1665 TRYFREE(pfile_in_zip_read_info->read_buffer);
1666 pfile_in_zip_read_info->read_buffer = NULL;
1667 if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
1669 #ifdef HAVE_APPLE_COMPRESSION
1670 if (compression_stream_destroy)
1671 compression_stream_destroy(&pfile_in_zip_read_info->astream);
1673 inflateEnd(&pfile_in_zip_read_info->stream);
1677 else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
1678 BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
1681 pfile_in_zip_read_info->stream_initialised = 0;
1682 TRYFREE(pfile_in_zip_read_info);
1684 s->pfile_in_zip_read = NULL;
1689 extern int ZEXPORT unzGoToFirstFile2(unzFile file, unz_file_info64 *pfile_info, char *filename,
1690 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
1692 unz64_internal *s = NULL;
1696 return UNZ_PARAMERROR;
1697 s = (unz64_internal*)file;
1699 if (s->gi.number_entry == 0)
1700 return UNZ_END_OF_LIST_OF_FILE;
1702 s->pos_in_central_dir = s->offset_central_dir;
1705 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal,
1706 filename, filename_size, extrafield, extrafield_size, comment, comment_size);
1708 s->current_file_ok = (err == UNZ_OK);
1709 if ((err == UNZ_OK) && (pfile_info != NULL))
1710 memcpy(pfile_info, &s->cur_file_info, sizeof(unz_file_info64));
1715 extern int ZEXPORT unzGoToFirstFile(unzFile file)
1717 return unzGoToFirstFile2(file, NULL, NULL, 0, NULL, 0, NULL, 0);
1720 extern int ZEXPORT unzGoToNextFile2(unzFile file, unz_file_info64 *pfile_info, char *filename,
1721 uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment, uint16_t comment_size)
1723 unz64_internal *s = NULL;
1727 return UNZ_PARAMERROR;
1728 s = (unz64_internal*)file;
1730 if (!s->current_file_ok)
1731 return UNZ_END_OF_LIST_OF_FILE;
1732 if (s->gi.number_entry != UINT16_MAX) /* 2^16 files overflow hack */
1734 if (s->num_file+1 == s->gi.number_entry)
1735 return UNZ_END_OF_LIST_OF_FILE;
1738 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
1739 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment;
1742 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal,
1743 filename, filename_size, extrafield, extrafield_size, comment, comment_size);
1745 s->current_file_ok = (err == UNZ_OK);
1746 if ((err == UNZ_OK) && (pfile_info != NULL))
1747 memcpy(pfile_info, &s->cur_file_info, sizeof(unz_file_info64));
1752 extern int ZEXPORT unzGoToNextFile(unzFile file)
1754 return unzGoToNextFile2(file, NULL, NULL, 0, NULL, 0, NULL, 0);
1757 extern int ZEXPORT unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func)
1759 unz64_internal *s = NULL;
1760 unz_file_info64 cur_file_info_saved;
1761 unz_file_info64_internal cur_file_info_internal_saved;
1762 uint64_t num_file_saved = 0;
1763 uint64_t pos_in_central_dir_saved = 0;
1764 char current_filename[UNZ_MAXFILENAMEINZIP+1];
1768 return UNZ_PARAMERROR;
1769 if (strlen(filename) >= UNZ_MAXFILENAMEINZIP)
1770 return UNZ_PARAMERROR;
1771 s = (unz64_internal*)file;
1772 if (!s->current_file_ok)
1773 return UNZ_END_OF_LIST_OF_FILE;
1775 /* Save the current state */
1776 num_file_saved = s->num_file;
1777 pos_in_central_dir_saved = s->pos_in_central_dir;
1778 cur_file_info_saved = s->cur_file_info;
1779 cur_file_info_internal_saved = s->cur_file_info_internal;
1781 err = unzGoToFirstFile2(file, NULL, current_filename, sizeof(current_filename)-1, NULL, 0, NULL, 0);
1783 while (err == UNZ_OK)
1785 if (filename_compare_func != NULL)
1786 err = filename_compare_func(file, current_filename, filename);
1788 err = strcmp(current_filename, filename);
1791 err = unzGoToNextFile2(file, NULL, current_filename, sizeof(current_filename)-1, NULL, 0, NULL, 0);
1794 /* We failed, so restore the state of the 'current file' to where we were. */
1795 s->num_file = num_file_saved;
1796 s->pos_in_central_dir = pos_in_central_dir_saved;
1797 s->cur_file_info = cur_file_info_saved;
1798 s->cur_file_info_internal = cur_file_info_internal_saved;
1802 extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos *file_pos)
1804 unz64_file_pos file_pos64;
1805 int err = unzGetFilePos64(file, &file_pos64);
1808 file_pos->pos_in_zip_directory = (uint32_t)file_pos64.pos_in_zip_directory;
1809 file_pos->num_of_file = (uint32_t)file_pos64.num_of_file;
1814 extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos *file_pos)
1816 unz64_file_pos file_pos64;
1817 if (file_pos == NULL)
1818 return UNZ_PARAMERROR;
1819 file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
1820 file_pos64.num_of_file = file_pos->num_of_file;
1821 return unzGoToFilePos64(file, &file_pos64);
1824 extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos *file_pos)
1826 unz64_internal *s = NULL;
1828 if (file == NULL || file_pos == NULL)
1829 return UNZ_PARAMERROR;
1830 s = (unz64_internal*)file;
1831 if (!s->current_file_ok)
1832 return UNZ_END_OF_LIST_OF_FILE;
1834 file_pos->pos_in_zip_directory = s->pos_in_central_dir;
1835 file_pos->num_of_file = s->num_file;
1839 extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos *file_pos)
1841 unz64_internal *s = NULL;
1844 if (file == NULL || file_pos == NULL)
1845 return UNZ_PARAMERROR;
1846 s = (unz64_internal*)file;
1848 /* Jump to the right spot */
1849 s->pos_in_central_dir = file_pos->pos_in_zip_directory;
1850 s->num_file = file_pos->num_of_file;
1852 /* Set the current file */
1853 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0);
1854 /* Return results */
1855 s->current_file_ok = (err == UNZ_OK);
1859 extern int32_t ZEXPORT unzGetOffset(unzFile file)
1861 uint64_t offset64 = 0;
1864 return UNZ_PARAMERROR;
1865 offset64 = unzGetOffset64(file);
1866 return (int32_t)offset64;
1869 extern int64_t ZEXPORT unzGetOffset64(unzFile file)
1871 unz64_internal *s = NULL;
1874 return UNZ_PARAMERROR;
1875 s = (unz64_internal*)file;
1876 if (!s->current_file_ok)
1878 if (s->gi.number_entry != 0 && s->gi.number_entry != UINT16_MAX)
1880 if (s->num_file == s->gi.number_entry)
1883 return s->pos_in_central_dir;
1886 extern int ZEXPORT unzSetOffset(unzFile file, uint32_t pos)
1888 return unzSetOffset64(file, pos);
1891 extern int ZEXPORT unzSetOffset64(unzFile file, uint64_t pos)
1893 unz64_internal *s = NULL;
1897 return UNZ_PARAMERROR;
1898 s = (unz64_internal*)file;
1899 s->pos_in_central_dir = pos;
1900 s->num_file = s->gi.number_entry; /* hack */
1902 err = unzGetCurrentFileInfoInternal(file, &s->cur_file_info, &s->cur_file_info_internal, NULL, 0, NULL, 0, NULL, 0);
1904 s->current_file_ok = (err == UNZ_OK);
1908 extern int32_t ZEXPORT unzTell(unzFile file)
1910 unz64_internal *s = NULL;
1912 return UNZ_PARAMERROR;
1913 s = (unz64_internal*)file;
1914 if (s->pfile_in_zip_read == NULL)
1915 return UNZ_PARAMERROR;
1916 return (int32_t)s->pfile_in_zip_read->stream.total_out;
1919 extern int64_t ZEXPORT unzTell64(unzFile file)
1921 unz64_internal *s = NULL;
1923 return UNZ_PARAMERROR;
1924 s = (unz64_internal*)file;
1925 if (s->pfile_in_zip_read == NULL)
1926 return UNZ_PARAMERROR;
1927 return s->pfile_in_zip_read->total_out_64;
1930 extern int ZEXPORT unzSeek(unzFile file, uint32_t offset, int origin)
1932 return unzSeek64(file, offset, origin);
1935 extern int ZEXPORT unzSeek64(unzFile file, uint64_t offset, int origin)
1937 unz64_internal *s = NULL;
1938 uint64_t stream_pos_begin = 0;
1939 uint64_t stream_pos_end = 0;
1940 uint64_t position = 0;
1941 int is_within_buffer = 0;
1944 return UNZ_PARAMERROR;
1945 s = (unz64_internal*)file;
1947 if (s->pfile_in_zip_read == NULL)
1949 if (s->pfile_in_zip_read->compression_method != 0)
1952 if (origin == SEEK_SET)
1954 else if (origin == SEEK_CUR)
1955 position = s->pfile_in_zip_read->total_out_64 + offset;
1956 else if (origin == SEEK_END)
1957 position = s->cur_file_info.compressed_size + offset;
1959 return UNZ_PARAMERROR;
1961 if (position > s->cur_file_info.compressed_size)
1962 return UNZ_PARAMERROR;
1964 stream_pos_end = s->pfile_in_zip_read->pos_in_zipfile;
1965 stream_pos_begin = stream_pos_end;
1967 if (stream_pos_begin > UNZ_BUFSIZE)
1968 stream_pos_begin -= UNZ_BUFSIZE;
1970 stream_pos_begin = 0;
1973 (s->pfile_in_zip_read->stream.avail_in != 0) &&
1974 (s->pfile_in_zip_read->rest_read_compressed != 0 || s->cur_file_info.compressed_size < UNZ_BUFSIZE) &&
1975 (position >= stream_pos_begin && position < stream_pos_end);
1977 if (is_within_buffer)
1979 s->pfile_in_zip_read->stream.next_in += position - s->pfile_in_zip_read->total_out_64;
1980 s->pfile_in_zip_read->stream.avail_in = (uInt)(stream_pos_end - position);
1984 s->pfile_in_zip_read->stream.avail_in = 0;
1985 s->pfile_in_zip_read->stream.next_in = 0;
1987 s->pfile_in_zip_read->pos_in_zipfile = s->pfile_in_zip_read->offset_local_extrafield + position;
1988 s->pfile_in_zip_read->rest_read_compressed = s->cur_file_info.compressed_size - position;
1991 s->pfile_in_zip_read->rest_read_uncompressed -= (position - s->pfile_in_zip_read->total_out_64);
1992 s->pfile_in_zip_read->stream.total_out = (uint32_t)position;
1993 s->pfile_in_zip_read->total_out_64 = position;
1998 extern int ZEXPORT unzEndOfFile(unzFile file)
2000 unz64_internal *s = NULL;
2002 return UNZ_PARAMERROR;
2003 s = (unz64_internal*)file;
2004 if (s->pfile_in_zip_read == NULL)
2005 return UNZ_PARAMERROR;
2006 if (s->pfile_in_zip_read->rest_read_uncompressed == 0)