git subrepo pull (merge) --force deps/libchdr
[pcsx_rearmed.git] / deps / libchdr / deps / zlib-1.3.1 / contrib / minizip / unzip.c
1 /* unzip.c -- IO for uncompress .zip files using zlib
2    Version 1.1, February 14h, 2010
3    part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
4
5          Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
6
7          Modifications of Unzip for Zip64
8          Copyright (C) 2007-2008 Even Rouault
9
10          Modifications for Zip64 support on both zip and unzip
11          Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
12
13          For more info read MiniZip_info.txt
14
15
16   ------------------------------------------------------------------------------------
17   Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
18   compatibility with older software. The following is from the original crypt.c.
19   Code woven in by Terry Thorsen 1/2003.
20
21   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
22
23   See the accompanying file LICENSE, version 2000-Apr-09 or later
24   (the contents of which are also included in zip.h) for terms of use.
25   If, for some reason, all these files are missing, the Info-ZIP license
26   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
27
28         crypt.c (full version) by Info-ZIP.      Last revised:  [see crypt.h]
29
30   The encryption/decryption parts of this source code (as opposed to the
31   non-echoing password parts) were originally written in Europe.  The
32   whole source package can be freely distributed, including from the USA.
33   (Prior to January 2000, re-export from the US was a violation of US law.)
34
35         This encryption code is a direct transcription of the algorithm from
36   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
37   file (appnote.txt) is distributed with the PKZIP program (even in the
38   version without encryption capabilities).
39
40         ------------------------------------------------------------------------------------
41
42         Changes in unzip.c
43
44         2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos
45   2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*
46   2007-2008 - Even Rouault - Remove old C style function prototypes
47   2007-2008 - Even Rouault - Add unzip support for ZIP64
48
49         Copyright (C) 2007-2008 Even Rouault
50
51
52   Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
53   Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
54                                 should only read the compressed/uncompressed size from the Zip64 format if
55                                 the size from normal header was 0xFFFFFFFF
56   Oct-2009 - Mathias Svensson - Applied some bug fixes from patches received from Gilles Vollant
57   Oct-2009 - Mathias Svensson - Applied support to unzip files with compression method BZIP2 (bzip2 lib is required)
58                                 Patch created by Daniel Borca
59
60   Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
61
62   Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson
63
64 */
65
66
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70
71 #ifndef NOUNCRYPT
72         #define NOUNCRYPT
73 #endif
74
75 #include "zlib.h"
76 #include "unzip.h"
77
78 #ifdef STDC
79 #  include <stddef.h>
80 #endif
81 #ifdef NO_ERRNO_H
82     extern int errno;
83 #else
84 #   include <errno.h>
85 #endif
86
87
88 #ifndef local
89 #  define local static
90 #endif
91 /* compile with -Dlocal if your debugger can't find static symbols */
92
93
94 #ifndef CASESENSITIVITYDEFAULT_NO
95 #  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
96 #    define CASESENSITIVITYDEFAULT_NO
97 #  endif
98 #endif
99
100
101 #ifndef UNZ_BUFSIZE
102 #define UNZ_BUFSIZE (16384)
103 #endif
104
105 #ifndef UNZ_MAXFILENAMEINZIP
106 #define UNZ_MAXFILENAMEINZIP (256)
107 #endif
108
109 #ifndef ALLOC
110 # define ALLOC(size) (malloc(size))
111 #endif
112
113 #define SIZECENTRALDIRITEM (0x2e)
114 #define SIZEZIPLOCALHEADER (0x1e)
115
116
117 const char unz_copyright[] =
118    " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
119
120 /* unz_file_info64_internal contain internal info about a file in zipfile*/
121 typedef struct unz_file_info64_internal_s
122 {
123     ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
124 } unz_file_info64_internal;
125
126
127 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
128     when reading and decompress it */
129 typedef struct
130 {
131     char  *read_buffer;         /* internal buffer for compressed data */
132     z_stream stream;            /* zLib stream structure for inflate */
133
134 #ifdef HAVE_BZIP2
135     bz_stream bstream;          /* bzLib stream structure for bziped */
136 #endif
137
138     ZPOS64_T pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
139     uLong stream_initialised;   /* flag set if stream structure is initialised*/
140
141     ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
142     uInt  size_local_extrafield;/* size of the local extra field */
143     ZPOS64_T pos_local_extrafield;   /* position in the local extra field in read*/
144     ZPOS64_T total_out_64;
145
146     uLong crc32;                /* crc32 of all data uncompressed */
147     uLong crc32_wait;           /* crc32 we must obtain after decompress all */
148     ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
149     ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
150     zlib_filefunc64_32_def z_filefunc;
151     voidpf filestream;        /* io structure of the zipfile */
152     uLong compression_method;   /* compression method (0==store) */
153     ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
154     int   raw;
155 } file_in_zip64_read_info_s;
156
157
158 /* unz64_s contain internal information about the zipfile
159 */
160 typedef struct
161 {
162     zlib_filefunc64_32_def z_filefunc;
163     int is64bitOpenFunction;
164     voidpf filestream;        /* io structure of the zipfile */
165     unz_global_info64 gi;       /* public global information */
166     ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
167     ZPOS64_T num_file;             /* number of the current file in the zipfile*/
168     ZPOS64_T pos_in_central_dir;   /* pos of the current file in the central dir*/
169     ZPOS64_T current_file_ok;      /* flag about the usability of the current file*/
170     ZPOS64_T central_pos;          /* position of the beginning of the central dir*/
171
172     ZPOS64_T size_central_dir;     /* size of the central directory  */
173     ZPOS64_T offset_central_dir;   /* offset of start of central directory with
174                                    respect to the starting disk number */
175
176     unz_file_info64 cur_file_info; /* public info about the current file in zip*/
177     unz_file_info64_internal cur_file_info_internal; /* private info about it*/
178     file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
179                                         file if we are decompressing it */
180     int encrypted;
181
182     int isZip64;
183
184 #    ifndef NOUNCRYPT
185     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
186     const z_crc_t* pcrc_32_tab;
187 #    endif
188 } unz64_s;
189
190
191 #ifndef NOUNCRYPT
192 #include "crypt.h"
193 #endif
194
195
196 /* ===========================================================================
197    Reads a long in LSB order from the given gz_stream. Sets
198 */
199
200 local int unz64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def,
201                               voidpf filestream,
202                               uLong *pX) {
203     unsigned char c[2];
204     int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,2);
205     if (err==2)
206     {
207         *pX = c[0] | ((uLong)c[1] << 8);
208         return UNZ_OK;
209     }
210     else
211     {
212         *pX = 0;
213         if (ZERROR64(*pzlib_filefunc_def,filestream))
214             return UNZ_ERRNO;
215         else
216             return UNZ_EOF;
217     }
218 }
219
220 local int unz64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def,
221                              voidpf filestream,
222                              uLong *pX) {
223     unsigned char c[4];
224     int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,4);
225     if (err==4)
226     {
227         *pX = c[0] | ((uLong)c[1] << 8) | ((uLong)c[2] << 16) | ((uLong)c[3] << 24);
228         return UNZ_OK;
229     }
230     else
231     {
232         *pX = 0;
233         if (ZERROR64(*pzlib_filefunc_def,filestream))
234             return UNZ_ERRNO;
235         else
236             return UNZ_EOF;
237     }
238 }
239
240
241 local int unz64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
242                                voidpf filestream,
243                                ZPOS64_T *pX) {
244     unsigned char c[8];
245     int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,8);
246     if (err==8)
247     {
248         *pX = c[0] | ((ZPOS64_T)c[1] << 8) | ((ZPOS64_T)c[2] << 16) | ((ZPOS64_T)c[3] << 24)
249             | ((ZPOS64_T)c[4] << 32) | ((ZPOS64_T)c[5] << 40) | ((ZPOS64_T)c[6] << 48) | ((ZPOS64_T)c[7] << 56);
250         return UNZ_OK;
251     }
252     else
253     {
254         *pX = 0;
255         if (ZERROR64(*pzlib_filefunc_def,filestream))
256             return UNZ_ERRNO;
257         else
258             return UNZ_EOF;
259     }
260 }
261
262 /* My own strcmpi / strcasecmp */
263 local int strcmpcasenosensitive_internal(const char* fileName1, const char* fileName2) {
264     for (;;)
265     {
266         char c1=*(fileName1++);
267         char c2=*(fileName2++);
268         if ((c1>='a') && (c1<='z'))
269             c1 -= 0x20;
270         if ((c2>='a') && (c2<='z'))
271             c2 -= 0x20;
272         if (c1=='\0')
273             return ((c2=='\0') ? 0 : -1);
274         if (c2=='\0')
275             return 1;
276         if (c1<c2)
277             return -1;
278         if (c1>c2)
279             return 1;
280     }
281 }
282
283
284 #ifdef  CASESENSITIVITYDEFAULT_NO
285 #define CASESENSITIVITYDEFAULTVALUE 2
286 #else
287 #define CASESENSITIVITYDEFAULTVALUE 1
288 #endif
289
290 #ifndef STRCMPCASENOSENTIVEFUNCTION
291 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
292 #endif
293
294 /*
295    Compare two filenames (fileName1,fileName2).
296    If iCaseSensitivity = 1, comparison is case sensitive (like strcmp)
297    If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi
298                                                                 or strcasecmp)
299    If iCaseSensitivity = 0, case sensitivity is default of your operating system
300         (like 1 on Unix, 2 on Windows)
301
302 */
303 extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
304                                              const char*  fileName2,
305                                              int iCaseSensitivity) {
306     if (iCaseSensitivity==0)
307         iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
308
309     if (iCaseSensitivity==1)
310         return strcmp(fileName1,fileName2);
311
312     return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
313 }
314
315 #ifndef BUFREADCOMMENT
316 #define BUFREADCOMMENT (0x400)
317 #endif
318
319 #ifndef CENTRALDIRINVALID
320 #define CENTRALDIRINVALID ((ZPOS64_T)(-1))
321 #endif
322
323 /*
324   Locate the Central directory of a zipfile (at the end, just before
325     the global comment)
326 */
327 local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
328     unsigned char* buf;
329     ZPOS64_T uSizeFile;
330     ZPOS64_T uBackRead;
331     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
332     ZPOS64_T uPosFound=CENTRALDIRINVALID;
333
334     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
335         return CENTRALDIRINVALID;
336
337
338     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
339
340     if (uMaxBack>uSizeFile)
341         uMaxBack = uSizeFile;
342
343     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
344     if (buf==NULL)
345         return CENTRALDIRINVALID;
346
347     uBackRead = 4;
348     while (uBackRead<uMaxBack)
349     {
350         uLong uReadSize;
351         ZPOS64_T uReadPos ;
352         int i;
353         if (uBackRead+BUFREADCOMMENT>uMaxBack)
354             uBackRead = uMaxBack;
355         else
356             uBackRead+=BUFREADCOMMENT;
357         uReadPos = uSizeFile-uBackRead ;
358
359         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
360                      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
361         if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
362             break;
363
364         if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
365             break;
366
367         for (i=(int)uReadSize-3; (i--)>0;)
368             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
369                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
370             {
371                 uPosFound = uReadPos+(unsigned)i;
372                 break;
373             }
374
375         if (uPosFound!=CENTRALDIRINVALID)
376             break;
377     }
378     free(buf);
379     return uPosFound;
380 }
381
382
383 /*
384   Locate the Central directory 64 of a zipfile (at the end, just before
385     the global comment)
386 */
387 local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
388                                              voidpf filestream) {
389     unsigned char* buf;
390     ZPOS64_T uSizeFile;
391     ZPOS64_T uBackRead;
392     ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
393     ZPOS64_T uPosFound=CENTRALDIRINVALID;
394     uLong uL;
395                 ZPOS64_T relativeOffset;
396
397     if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
398         return CENTRALDIRINVALID;
399
400
401     uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
402
403     if (uMaxBack>uSizeFile)
404         uMaxBack = uSizeFile;
405
406     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
407     if (buf==NULL)
408         return CENTRALDIRINVALID;
409
410     uBackRead = 4;
411     while (uBackRead<uMaxBack)
412     {
413         uLong uReadSize;
414         ZPOS64_T uReadPos;
415         int i;
416         if (uBackRead+BUFREADCOMMENT>uMaxBack)
417             uBackRead = uMaxBack;
418         else
419             uBackRead+=BUFREADCOMMENT;
420         uReadPos = uSizeFile-uBackRead ;
421
422         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
423                      (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
424         if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
425             break;
426
427         if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
428             break;
429
430         for (i=(int)uReadSize-3; (i--)>0;)
431             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
432                 ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
433             {
434                 uPosFound = uReadPos+(unsigned)i;
435                 break;
436             }
437
438         if (uPosFound!=CENTRALDIRINVALID)
439             break;
440     }
441     free(buf);
442     if (uPosFound == CENTRALDIRINVALID)
443         return CENTRALDIRINVALID;
444
445     /* Zip64 end of central directory locator */
446     if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
447         return CENTRALDIRINVALID;
448
449     /* the signature, already checked */
450     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
451         return CENTRALDIRINVALID;
452
453     /* number of the disk with the start of the zip64 end of central directory */
454     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
455         return CENTRALDIRINVALID;
456     if (uL != 0)
457         return CENTRALDIRINVALID;
458
459     /* relative offset of the zip64 end of central directory record */
460     if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
461         return CENTRALDIRINVALID;
462
463     /* total number of disks */
464     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
465         return CENTRALDIRINVALID;
466     if (uL != 1)
467         return CENTRALDIRINVALID;
468
469     /* Goto end of central directory record */
470     if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
471         return CENTRALDIRINVALID;
472
473      /* the signature */
474     if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
475         return CENTRALDIRINVALID;
476
477     if (uL != 0x06064b50)
478         return CENTRALDIRINVALID;
479
480     return relativeOffset;
481 }
482
483 /*
484   Open a Zip file. path contain the full pathname (by example,
485      on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
486      "zlib/zlib114.zip".
487      If the zipfile cannot be opened (file doesn't exist or in not valid), the
488        return value is NULL.
489      Else, the return value is a unzFile Handle, usable with other function
490        of this unzip package.
491 */
492 local unzFile unzOpenInternal(const void *path,
493                               zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
494                               int is64bitOpenFunction) {
495     unz64_s us;
496     unz64_s *s;
497     ZPOS64_T central_pos;
498     uLong   uL;
499
500     uLong number_disk;          /* number of the current disk, used for
501                                    spanning ZIP, unsupported, always 0*/
502     uLong number_disk_with_CD;  /* number the disk with central dir, used
503                                    for spanning ZIP, unsupported, always 0*/
504     ZPOS64_T number_entry_CD;      /* total number of entries in
505                                    the central dir
506                                    (same than number_entry on nospan) */
507
508     int err=UNZ_OK;
509
510     if (unz_copyright[0]!=' ')
511         return NULL;
512
513     us.z_filefunc.zseek32_file = NULL;
514     us.z_filefunc.ztell32_file = NULL;
515     if (pzlib_filefunc64_32_def==NULL)
516         fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
517     else
518         us.z_filefunc = *pzlib_filefunc64_32_def;
519     us.is64bitOpenFunction = is64bitOpenFunction;
520
521
522
523     us.filestream = ZOPEN64(us.z_filefunc,
524                                                  path,
525                                                  ZLIB_FILEFUNC_MODE_READ |
526                                                  ZLIB_FILEFUNC_MODE_EXISTING);
527     if (us.filestream==NULL)
528         return NULL;
529
530     central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
531     if (central_pos!=CENTRALDIRINVALID)
532     {
533         uLong uS;
534         ZPOS64_T uL64;
535
536         us.isZip64 = 1;
537
538         if (ZSEEK64(us.z_filefunc, us.filestream,
539                                       central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
540         err=UNZ_ERRNO;
541
542         /* the signature, already checked */
543         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
544             err=UNZ_ERRNO;
545
546         /* size of zip64 end of central directory record */
547         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
548             err=UNZ_ERRNO;
549
550         /* version made by */
551         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
552             err=UNZ_ERRNO;
553
554         /* version needed to extract */
555         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
556             err=UNZ_ERRNO;
557
558         /* number of this disk */
559         if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
560             err=UNZ_ERRNO;
561
562         /* number of the disk with the start of the central directory */
563         if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
564             err=UNZ_ERRNO;
565
566         /* total number of entries in the central directory on this disk */
567         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
568             err=UNZ_ERRNO;
569
570         /* total number of entries in the central directory */
571         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
572             err=UNZ_ERRNO;
573
574         if ((number_entry_CD!=us.gi.number_entry) ||
575             (number_disk_with_CD!=0) ||
576             (number_disk!=0))
577             err=UNZ_BADZIPFILE;
578
579         /* size of the central directory */
580         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
581             err=UNZ_ERRNO;
582
583         /* offset of start of central directory with respect to the
584           starting disk number */
585         if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
586             err=UNZ_ERRNO;
587
588         us.gi.size_comment = 0;
589     }
590     else
591     {
592         central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
593         if (central_pos==CENTRALDIRINVALID)
594             err=UNZ_ERRNO;
595
596         us.isZip64 = 0;
597
598         if (ZSEEK64(us.z_filefunc, us.filestream,
599                                         central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
600             err=UNZ_ERRNO;
601
602         /* the signature, already checked */
603         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
604             err=UNZ_ERRNO;
605
606         /* number of this disk */
607         if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
608             err=UNZ_ERRNO;
609
610         /* number of the disk with the start of the central directory */
611         if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
612             err=UNZ_ERRNO;
613
614         /* total number of entries in the central dir on this disk */
615         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
616             err=UNZ_ERRNO;
617         us.gi.number_entry = uL;
618
619         /* total number of entries in the central dir */
620         if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
621             err=UNZ_ERRNO;
622         number_entry_CD = uL;
623
624         if ((number_entry_CD!=us.gi.number_entry) ||
625             (number_disk_with_CD!=0) ||
626             (number_disk!=0))
627             err=UNZ_BADZIPFILE;
628
629         /* size of the central directory */
630         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
631             err=UNZ_ERRNO;
632         us.size_central_dir = uL;
633
634         /* offset of start of central directory with respect to the
635             starting disk number */
636         if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
637             err=UNZ_ERRNO;
638         us.offset_central_dir = uL;
639
640         /* zipfile comment length */
641         if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
642             err=UNZ_ERRNO;
643     }
644
645     if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
646         (err==UNZ_OK))
647         err=UNZ_BADZIPFILE;
648
649     if (err!=UNZ_OK)
650     {
651         ZCLOSE64(us.z_filefunc, us.filestream);
652         return NULL;
653     }
654
655     us.byte_before_the_zipfile = central_pos -
656                             (us.offset_central_dir+us.size_central_dir);
657     us.central_pos = central_pos;
658     us.pfile_in_zip_read = NULL;
659     us.encrypted = 0;
660
661
662     s=(unz64_s*)ALLOC(sizeof(unz64_s));
663     if( s != NULL)
664     {
665         *s=us;
666         unzGoToFirstFile((unzFile)s);
667     }
668     return (unzFile)s;
669 }
670
671
672 extern unzFile ZEXPORT unzOpen2(const char *path,
673                                 zlib_filefunc_def* pzlib_filefunc32_def) {
674     if (pzlib_filefunc32_def != NULL)
675     {
676         zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
677         fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
678         return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
679     }
680     else
681         return unzOpenInternal(path, NULL, 0);
682 }
683
684 extern unzFile ZEXPORT unzOpen2_64(const void *path,
685                                    zlib_filefunc64_def* pzlib_filefunc_def) {
686     if (pzlib_filefunc_def != NULL)
687     {
688         zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
689         zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
690         zlib_filefunc64_32_def_fill.ztell32_file = NULL;
691         zlib_filefunc64_32_def_fill.zseek32_file = NULL;
692         return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
693     }
694     else
695         return unzOpenInternal(path, NULL, 1);
696 }
697
698 extern unzFile ZEXPORT unzOpen(const char *path) {
699     return unzOpenInternal(path, NULL, 0);
700 }
701
702 extern unzFile ZEXPORT unzOpen64(const void *path) {
703     return unzOpenInternal(path, NULL, 1);
704 }
705
706 /*
707   Close a ZipFile opened with unzOpen.
708   If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
709     these files MUST be closed with unzCloseCurrentFile before call unzClose.
710   return UNZ_OK if there is no problem. */
711 extern int ZEXPORT unzClose(unzFile file) {
712     unz64_s* s;
713     if (file==NULL)
714         return UNZ_PARAMERROR;
715     s=(unz64_s*)file;
716
717     if (s->pfile_in_zip_read!=NULL)
718         unzCloseCurrentFile(file);
719
720     ZCLOSE64(s->z_filefunc, s->filestream);
721     free(s);
722     return UNZ_OK;
723 }
724
725
726 /*
727   Write info about the ZipFile in the *pglobal_info structure.
728   No preparation of the structure is needed
729   return UNZ_OK if there is no problem. */
730 extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64* pglobal_info) {
731     unz64_s* s;
732     if (file==NULL)
733         return UNZ_PARAMERROR;
734     s=(unz64_s*)file;
735     *pglobal_info=s->gi;
736     return UNZ_OK;
737 }
738
739 extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32) {
740     unz64_s* s;
741     if (file==NULL)
742         return UNZ_PARAMERROR;
743     s=(unz64_s*)file;
744     /* to do : check if number_entry is not truncated */
745     pglobal_info32->number_entry = (uLong)s->gi.number_entry;
746     pglobal_info32->size_comment = s->gi.size_comment;
747     return UNZ_OK;
748 }
749 /*
750    Translate date/time from Dos format to tm_unz (readable more easily)
751 */
752 local void unz64local_DosDateToTmuDate(ZPOS64_T ulDosDate, tm_unz* ptm) {
753     ZPOS64_T uDate;
754     uDate = (ZPOS64_T)(ulDosDate>>16);
755     ptm->tm_mday = (int)(uDate&0x1f) ;
756     ptm->tm_mon =  (int)((((uDate)&0x1E0)/0x20)-1) ;
757     ptm->tm_year = (int)(((uDate&0x0FE00)/0x0200)+1980) ;
758
759     ptm->tm_hour = (int) ((ulDosDate &0xF800)/0x800);
760     ptm->tm_min =  (int) ((ulDosDate&0x7E0)/0x20) ;
761     ptm->tm_sec =  (int) (2*(ulDosDate&0x1f)) ;
762 }
763
764 /*
765   Get Info about the current file in the zipfile, with internal only info
766 */
767 local int unz64local_GetCurrentFileInfoInternal(unzFile file,
768                                                 unz_file_info64 *pfile_info,
769                                                 unz_file_info64_internal
770                                                 *pfile_info_internal,
771                                                 char *szFileName,
772                                                 uLong fileNameBufferSize,
773                                                 void *extraField,
774                                                 uLong extraFieldBufferSize,
775                                                 char *szComment,
776                                                 uLong commentBufferSize) {
777     unz64_s* s;
778     unz_file_info64 file_info;
779     unz_file_info64_internal file_info_internal;
780     int err=UNZ_OK;
781     uLong uMagic;
782     long lSeek=0;
783     uLong uL;
784
785     if (file==NULL)
786         return UNZ_PARAMERROR;
787     s=(unz64_s*)file;
788     if (ZSEEK64(s->z_filefunc, s->filestream,
789               s->pos_in_central_dir+s->byte_before_the_zipfile,
790               ZLIB_FILEFUNC_SEEK_SET)!=0)
791         err=UNZ_ERRNO;
792
793
794     /* we check the magic */
795     if (err==UNZ_OK)
796     {
797         if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
798             err=UNZ_ERRNO;
799         else if (uMagic!=0x02014b50)
800             err=UNZ_BADZIPFILE;
801     }
802
803     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
804         err=UNZ_ERRNO;
805
806     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
807         err=UNZ_ERRNO;
808
809     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
810         err=UNZ_ERRNO;
811
812     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
813         err=UNZ_ERRNO;
814
815     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
816         err=UNZ_ERRNO;
817
818     unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
819
820     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
821         err=UNZ_ERRNO;
822
823     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
824         err=UNZ_ERRNO;
825     file_info.compressed_size = uL;
826
827     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
828         err=UNZ_ERRNO;
829     file_info.uncompressed_size = uL;
830
831     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
832         err=UNZ_ERRNO;
833
834     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
835         err=UNZ_ERRNO;
836
837     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
838         err=UNZ_ERRNO;
839
840     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
841         err=UNZ_ERRNO;
842
843     if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
844         err=UNZ_ERRNO;
845
846     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
847         err=UNZ_ERRNO;
848
849                 // relative offset of local header
850     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
851         err=UNZ_ERRNO;
852     file_info_internal.offset_curfile = uL;
853
854     lSeek+=file_info.size_filename;
855     if ((err==UNZ_OK) && (szFileName!=NULL))
856     {
857         uLong uSizeRead ;
858         if (file_info.size_filename<fileNameBufferSize)
859         {
860             *(szFileName+file_info.size_filename)='\0';
861             uSizeRead = file_info.size_filename;
862         }
863         else
864             uSizeRead = fileNameBufferSize;
865
866         if ((file_info.size_filename>0) && (fileNameBufferSize>0))
867             if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
868                 err=UNZ_ERRNO;
869         lSeek -= uSizeRead;
870     }
871
872     // Read extrafield
873     if ((err==UNZ_OK) && (extraField!=NULL))
874     {
875         ZPOS64_T uSizeRead ;
876         if (file_info.size_file_extra<extraFieldBufferSize)
877             uSizeRead = file_info.size_file_extra;
878         else
879             uSizeRead = extraFieldBufferSize;
880
881         if (lSeek!=0)
882         {
883             if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
884                 lSeek=0;
885             else
886                 err=UNZ_ERRNO;
887         }
888
889         if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
890             if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)
891                 err=UNZ_ERRNO;
892
893         lSeek += file_info.size_file_extra - (uLong)uSizeRead;
894     }
895     else
896         lSeek += file_info.size_file_extra;
897
898
899     if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
900     {
901                                 uLong acc = 0;
902
903         // since lSeek now points to after the extra field we need to move back
904         lSeek -= file_info.size_file_extra;
905
906         if (lSeek!=0)
907         {
908             if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
909                 lSeek=0;
910             else
911                 err=UNZ_ERRNO;
912         }
913
914         while(acc < file_info.size_file_extra)
915         {
916             uLong headerId;
917                                                 uLong dataSize;
918
919             if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
920                 err=UNZ_ERRNO;
921
922             if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
923                 err=UNZ_ERRNO;
924
925             /* ZIP64 extra fields */
926             if (headerId == 0x0001)
927             {
928                 if(file_info.uncompressed_size == MAXU32)
929                 {
930                     if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
931                         err=UNZ_ERRNO;
932                 }
933
934                 if(file_info.compressed_size == MAXU32)
935                 {
936                     if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
937                         err=UNZ_ERRNO;
938                 }
939
940                 if(file_info_internal.offset_curfile == MAXU32)
941                 {
942                     /* Relative Header offset */
943                     if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
944                         err=UNZ_ERRNO;
945                 }
946
947                 if(file_info.disk_num_start == 0xffff)
948                 {
949                     /* Disk Start Number */
950                     if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
951                         err=UNZ_ERRNO;
952                 }
953
954             }
955             else
956             {
957                 if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
958                     err=UNZ_ERRNO;
959             }
960
961             acc += 2 + 2 + dataSize;
962         }
963     }
964
965     if ((err==UNZ_OK) && (szComment!=NULL))
966     {
967         uLong uSizeRead ;
968         if (file_info.size_file_comment<commentBufferSize)
969         {
970             *(szComment+file_info.size_file_comment)='\0';
971             uSizeRead = file_info.size_file_comment;
972         }
973         else
974             uSizeRead = commentBufferSize;
975
976         if (lSeek!=0)
977         {
978             if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
979                 lSeek=0;
980             else
981                 err=UNZ_ERRNO;
982         }
983
984         if ((file_info.size_file_comment>0) && (commentBufferSize>0))
985             if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
986                 err=UNZ_ERRNO;
987         lSeek+=file_info.size_file_comment - uSizeRead;
988     }
989     else
990         lSeek+=file_info.size_file_comment;
991
992
993     if ((err==UNZ_OK) && (pfile_info!=NULL))
994         *pfile_info=file_info;
995
996     if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
997         *pfile_info_internal=file_info_internal;
998
999     return err;
1000 }
1001
1002
1003
1004 /*
1005   Write info about the ZipFile in the *pglobal_info structure.
1006   No preparation of the structure is needed
1007   return UNZ_OK if there is no problem.
1008 */
1009 extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file,
1010                                            unz_file_info64 * pfile_info,
1011                                            char * szFileName, uLong fileNameBufferSize,
1012                                            void *extraField, uLong extraFieldBufferSize,
1013                                            char* szComment,  uLong commentBufferSize) {
1014     return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
1015                                                  szFileName,fileNameBufferSize,
1016                                                  extraField,extraFieldBufferSize,
1017                                                  szComment,commentBufferSize);
1018 }
1019
1020 extern int ZEXPORT unzGetCurrentFileInfo(unzFile file,
1021                                          unz_file_info * pfile_info,
1022                                          char * szFileName, uLong fileNameBufferSize,
1023                                          void *extraField, uLong extraFieldBufferSize,
1024                                          char* szComment,  uLong commentBufferSize) {
1025     int err;
1026     unz_file_info64 file_info64;
1027     err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,
1028                                                 szFileName,fileNameBufferSize,
1029                                                 extraField,extraFieldBufferSize,
1030                                                 szComment,commentBufferSize);
1031     if ((err==UNZ_OK) && (pfile_info != NULL))
1032     {
1033         pfile_info->version = file_info64.version;
1034         pfile_info->version_needed = file_info64.version_needed;
1035         pfile_info->flag = file_info64.flag;
1036         pfile_info->compression_method = file_info64.compression_method;
1037         pfile_info->dosDate = file_info64.dosDate;
1038         pfile_info->crc = file_info64.crc;
1039
1040         pfile_info->size_filename = file_info64.size_filename;
1041         pfile_info->size_file_extra = file_info64.size_file_extra;
1042         pfile_info->size_file_comment = file_info64.size_file_comment;
1043
1044         pfile_info->disk_num_start = file_info64.disk_num_start;
1045         pfile_info->internal_fa = file_info64.internal_fa;
1046         pfile_info->external_fa = file_info64.external_fa;
1047
1048         pfile_info->tmu_date = file_info64.tmu_date;
1049
1050
1051         pfile_info->compressed_size = (uLong)file_info64.compressed_size;
1052         pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
1053
1054     }
1055     return err;
1056 }
1057 /*
1058   Set the current file of the zipfile to the first file.
1059   return UNZ_OK if there is no problem
1060 */
1061 extern int ZEXPORT unzGoToFirstFile(unzFile file) {
1062     int err=UNZ_OK;
1063     unz64_s* s;
1064     if (file==NULL)
1065         return UNZ_PARAMERROR;
1066     s=(unz64_s*)file;
1067     s->pos_in_central_dir=s->offset_central_dir;
1068     s->num_file=0;
1069     err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1070                                              &s->cur_file_info_internal,
1071                                              NULL,0,NULL,0,NULL,0);
1072     s->current_file_ok = (err == UNZ_OK);
1073     return err;
1074 }
1075
1076 /*
1077   Set the current file of the zipfile to the next file.
1078   return UNZ_OK if there is no problem
1079   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
1080 */
1081 extern int ZEXPORT unzGoToNextFile(unzFile file) {
1082     unz64_s* s;
1083     int err;
1084
1085     if (file==NULL)
1086         return UNZ_PARAMERROR;
1087     s=(unz64_s*)file;
1088     if (!s->current_file_ok)
1089         return UNZ_END_OF_LIST_OF_FILE;
1090     if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
1091       if (s->num_file+1==s->gi.number_entry)
1092         return UNZ_END_OF_LIST_OF_FILE;
1093
1094     s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
1095             s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
1096     s->num_file++;
1097     err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1098                                                &s->cur_file_info_internal,
1099                                                NULL,0,NULL,0,NULL,0);
1100     s->current_file_ok = (err == UNZ_OK);
1101     return err;
1102 }
1103
1104
1105 /*
1106   Try locate the file szFileName in the zipfile.
1107   For the iCaseSensitivity signification, see unzStringFileNameCompare
1108
1109   return value :
1110   UNZ_OK if the file is found. It becomes the current file.
1111   UNZ_END_OF_LIST_OF_FILE if the file is not found
1112 */
1113 extern int ZEXPORT unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity) {
1114     unz64_s* s;
1115     int err;
1116
1117     /* We remember the 'current' position in the file so that we can jump
1118      * back there if we fail.
1119      */
1120     unz_file_info64 cur_file_infoSaved;
1121     unz_file_info64_internal cur_file_info_internalSaved;
1122     ZPOS64_T num_fileSaved;
1123     ZPOS64_T pos_in_central_dirSaved;
1124
1125
1126     if (file==NULL)
1127         return UNZ_PARAMERROR;
1128
1129     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
1130         return UNZ_PARAMERROR;
1131
1132     s=(unz64_s*)file;
1133     if (!s->current_file_ok)
1134         return UNZ_END_OF_LIST_OF_FILE;
1135
1136     /* Save the current state */
1137     num_fileSaved = s->num_file;
1138     pos_in_central_dirSaved = s->pos_in_central_dir;
1139     cur_file_infoSaved = s->cur_file_info;
1140     cur_file_info_internalSaved = s->cur_file_info_internal;
1141
1142     err = unzGoToFirstFile(file);
1143
1144     while (err == UNZ_OK)
1145     {
1146         char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
1147         err = unzGetCurrentFileInfo64(file,NULL,
1148                                     szCurrentFileName,sizeof(szCurrentFileName)-1,
1149                                     NULL,0,NULL,0);
1150         if (err == UNZ_OK)
1151         {
1152             if (unzStringFileNameCompare(szCurrentFileName,
1153                                             szFileName,iCaseSensitivity)==0)
1154                 return UNZ_OK;
1155             err = unzGoToNextFile(file);
1156         }
1157     }
1158
1159     /* We failed, so restore the state of the 'current file' to where we
1160      * were.
1161      */
1162     s->num_file = num_fileSaved ;
1163     s->pos_in_central_dir = pos_in_central_dirSaved ;
1164     s->cur_file_info = cur_file_infoSaved;
1165     s->cur_file_info_internal = cur_file_info_internalSaved;
1166     return err;
1167 }
1168
1169
1170 /*
1171 ///////////////////////////////////////////
1172 // Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
1173 // I need random access
1174 //
1175 // Further optimization could be realized by adding an ability
1176 // to cache the directory in memory. The goal being a single
1177 // comprehensive file read to put the file I need in a memory.
1178 */
1179
1180 /*
1181 typedef struct unz_file_pos_s
1182 {
1183     ZPOS64_T pos_in_zip_directory;   // offset in file
1184     ZPOS64_T num_of_file;            // # of file
1185 } unz_file_pos;
1186 */
1187
1188 extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) {
1189     unz64_s* s;
1190
1191     if (file==NULL || file_pos==NULL)
1192         return UNZ_PARAMERROR;
1193     s=(unz64_s*)file;
1194     if (!s->current_file_ok)
1195         return UNZ_END_OF_LIST_OF_FILE;
1196
1197     file_pos->pos_in_zip_directory  = s->pos_in_central_dir;
1198     file_pos->num_of_file           = s->num_file;
1199
1200     return UNZ_OK;
1201 }
1202
1203 extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos* file_pos) {
1204     unz64_file_pos file_pos64;
1205     int err = unzGetFilePos64(file,&file_pos64);
1206     if (err==UNZ_OK)
1207     {
1208         file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
1209         file_pos->num_of_file = (uLong)file_pos64.num_of_file;
1210     }
1211     return err;
1212 }
1213
1214 extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) {
1215     unz64_s* s;
1216     int err;
1217
1218     if (file==NULL || file_pos==NULL)
1219         return UNZ_PARAMERROR;
1220     s=(unz64_s*)file;
1221
1222     /* jump to the right spot */
1223     s->pos_in_central_dir = file_pos->pos_in_zip_directory;
1224     s->num_file           = file_pos->num_of_file;
1225
1226     /* set the current file */
1227     err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1228                                                &s->cur_file_info_internal,
1229                                                NULL,0,NULL,0,NULL,0);
1230     /* return results */
1231     s->current_file_ok = (err == UNZ_OK);
1232     return err;
1233 }
1234
1235 extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos* file_pos) {
1236     unz64_file_pos file_pos64;
1237     if (file_pos == NULL)
1238         return UNZ_PARAMERROR;
1239
1240     file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
1241     file_pos64.num_of_file = file_pos->num_of_file;
1242     return unzGoToFilePos64(file,&file_pos64);
1243 }
1244
1245 /*
1246 // Unzip Helper Functions - should be here?
1247 ///////////////////////////////////////////
1248 */
1249
1250 /*
1251   Read the local header of the current zipfile
1252   Check the coherency of the local header and info in the end of central
1253         directory about this file
1254   store in *piSizeVar the size of extra info in local header
1255         (filename and size of extra field data)
1256 */
1257 local int unz64local_CheckCurrentFileCoherencyHeader(unz64_s* s, uInt* piSizeVar,
1258                                                      ZPOS64_T * poffset_local_extrafield,
1259                                                      uInt  * psize_local_extrafield) {
1260     uLong uMagic,uData,uFlags;
1261     uLong size_filename;
1262     uLong size_extra_field;
1263     int err=UNZ_OK;
1264
1265     *piSizeVar = 0;
1266     *poffset_local_extrafield = 0;
1267     *psize_local_extrafield = 0;
1268
1269     if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
1270                                 s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
1271         return UNZ_ERRNO;
1272
1273
1274     if (err==UNZ_OK)
1275     {
1276         if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
1277             err=UNZ_ERRNO;
1278         else if (uMagic!=0x04034b50)
1279             err=UNZ_BADZIPFILE;
1280     }
1281
1282     if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1283         err=UNZ_ERRNO;
1284 /*
1285     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1286         err=UNZ_BADZIPFILE;
1287 */
1288     if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
1289         err=UNZ_ERRNO;
1290
1291     if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
1292         err=UNZ_ERRNO;
1293     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
1294         err=UNZ_BADZIPFILE;
1295
1296     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
1297 /* #ifdef HAVE_BZIP2 */
1298                          (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
1299 /* #endif */
1300                          (s->cur_file_info.compression_method!=Z_DEFLATED))
1301         err=UNZ_BADZIPFILE;
1302
1303     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
1304         err=UNZ_ERRNO;
1305
1306     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
1307         err=UNZ_ERRNO;
1308     else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0))
1309         err=UNZ_BADZIPFILE;
1310
1311     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
1312         err=UNZ_ERRNO;
1313     else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0))
1314         err=UNZ_BADZIPFILE;
1315
1316     if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
1317         err=UNZ_ERRNO;
1318     else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0))
1319         err=UNZ_BADZIPFILE;
1320
1321     if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
1322         err=UNZ_ERRNO;
1323     else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
1324         err=UNZ_BADZIPFILE;
1325
1326     *piSizeVar += (uInt)size_filename;
1327
1328     if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
1329         err=UNZ_ERRNO;
1330     *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1331                                     SIZEZIPLOCALHEADER + size_filename;
1332     *psize_local_extrafield = (uInt)size_extra_field;
1333
1334     *piSizeVar += (uInt)size_extra_field;
1335
1336     return err;
1337 }
1338
1339 /*
1340   Open for reading data the current file in the zipfile.
1341   If there is no error and the file is opened, the return value is UNZ_OK.
1342 */
1343 extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int* method,
1344                                        int* level, int raw, const char* password) {
1345     int err=UNZ_OK;
1346     uInt iSizeVar;
1347     unz64_s* s;
1348     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1349     ZPOS64_T offset_local_extrafield;  /* offset of the local extra field */
1350     uInt  size_local_extrafield;    /* size of the local extra field */
1351 #    ifndef NOUNCRYPT
1352     char source[12];
1353 #    else
1354     if (password != NULL)
1355         return UNZ_PARAMERROR;
1356 #    endif
1357
1358     if (file==NULL)
1359         return UNZ_PARAMERROR;
1360     s=(unz64_s*)file;
1361     if (!s->current_file_ok)
1362         return UNZ_PARAMERROR;
1363
1364     if (s->pfile_in_zip_read != NULL)
1365         unzCloseCurrentFile(file);
1366
1367     if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1368         return UNZ_BADZIPFILE;
1369
1370     pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
1371     if (pfile_in_zip_read_info==NULL)
1372         return UNZ_INTERNALERROR;
1373
1374     pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1375     pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1376     pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1377     pfile_in_zip_read_info->pos_local_extrafield=0;
1378     pfile_in_zip_read_info->raw=raw;
1379
1380     if (pfile_in_zip_read_info->read_buffer==NULL)
1381     {
1382         free(pfile_in_zip_read_info);
1383         return UNZ_INTERNALERROR;
1384     }
1385
1386     pfile_in_zip_read_info->stream_initialised=0;
1387
1388     if (method!=NULL)
1389         *method = (int)s->cur_file_info.compression_method;
1390
1391     if (level!=NULL)
1392     {
1393         *level = 6;
1394         switch (s->cur_file_info.flag & 0x06)
1395         {
1396           case 6 : *level = 1; break;
1397           case 4 : *level = 2; break;
1398           case 2 : *level = 9; break;
1399         }
1400     }
1401
1402     if ((s->cur_file_info.compression_method!=0) &&
1403 /* #ifdef HAVE_BZIP2 */
1404         (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
1405 /* #endif */
1406         (s->cur_file_info.compression_method!=Z_DEFLATED))
1407
1408         err=UNZ_BADZIPFILE;
1409
1410     pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1411     pfile_in_zip_read_info->crc32=0;
1412     pfile_in_zip_read_info->total_out_64=0;
1413     pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
1414     pfile_in_zip_read_info->filestream=s->filestream;
1415     pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
1416     pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1417
1418     pfile_in_zip_read_info->stream.total_out = 0;
1419
1420     if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw))
1421     {
1422 #ifdef HAVE_BZIP2
1423       pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
1424       pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
1425       pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
1426       pfile_in_zip_read_info->bstream.state = (voidpf)0;
1427
1428       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1429       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1430       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1431       pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1432       pfile_in_zip_read_info->stream.avail_in = 0;
1433
1434       err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
1435       if (err == Z_OK)
1436         pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
1437       else
1438       {
1439         free(pfile_in_zip_read_info->read_buffer);
1440         free(pfile_in_zip_read_info);
1441         return err;
1442       }
1443 #else
1444       pfile_in_zip_read_info->raw=1;
1445 #endif
1446     }
1447     else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
1448     {
1449       pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1450       pfile_in_zip_read_info->stream.zfree = (free_func)0;
1451       pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1452       pfile_in_zip_read_info->stream.next_in = 0;
1453       pfile_in_zip_read_info->stream.avail_in = 0;
1454
1455       err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1456       if (err == Z_OK)
1457         pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
1458       else
1459       {
1460         free(pfile_in_zip_read_info->read_buffer);
1461         free(pfile_in_zip_read_info);
1462         return err;
1463       }
1464         /* windowBits is passed < 0 to tell that there is no zlib header.
1465          * Note that in this case inflate *requires* an extra "dummy" byte
1466          * after the compressed stream in order to complete decompression and
1467          * return Z_STREAM_END.
1468          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1469          * size of both compressed and uncompressed data
1470          */
1471     }
1472     pfile_in_zip_read_info->rest_read_compressed =
1473             s->cur_file_info.compressed_size ;
1474     pfile_in_zip_read_info->rest_read_uncompressed =
1475             s->cur_file_info.uncompressed_size ;
1476
1477
1478     pfile_in_zip_read_info->pos_in_zipfile =
1479             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1480               iSizeVar;
1481
1482     pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1483
1484     s->pfile_in_zip_read = pfile_in_zip_read_info;
1485                 s->encrypted = 0;
1486
1487 #    ifndef NOUNCRYPT
1488     if (password != NULL)
1489     {
1490         int i;
1491         s->pcrc_32_tab = get_crc_table();
1492         init_keys(password,s->keys,s->pcrc_32_tab);
1493         if (ZSEEK64(s->z_filefunc, s->filestream,
1494                   s->pfile_in_zip_read->pos_in_zipfile +
1495                      s->pfile_in_zip_read->byte_before_the_zipfile,
1496                   SEEK_SET)!=0)
1497             return UNZ_INTERNALERROR;
1498         if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)
1499             return UNZ_INTERNALERROR;
1500
1501         for (i = 0; i<12; i++)
1502             zdecode(s->keys,s->pcrc_32_tab,source[i]);
1503
1504         s->pfile_in_zip_read->pos_in_zipfile+=12;
1505         s->encrypted=1;
1506     }
1507 #    endif
1508
1509
1510     return UNZ_OK;
1511 }
1512
1513 extern int ZEXPORT unzOpenCurrentFile(unzFile file) {
1514     return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1515 }
1516
1517 extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char* password) {
1518     return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
1519 }
1520
1521 extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int* method, int* level, int raw) {
1522     return unzOpenCurrentFile3(file, method, level, raw, NULL);
1523 }
1524
1525 /** Addition for GDAL : START */
1526
1527 extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file) {
1528     unz64_s* s;
1529     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1530     s=(unz64_s*)file;
1531     if (file==NULL)
1532         return 0; //UNZ_PARAMERROR;
1533     pfile_in_zip_read_info=s->pfile_in_zip_read;
1534     if (pfile_in_zip_read_info==NULL)
1535         return 0; //UNZ_PARAMERROR;
1536     return pfile_in_zip_read_info->pos_in_zipfile +
1537                          pfile_in_zip_read_info->byte_before_the_zipfile;
1538 }
1539
1540 /** Addition for GDAL : END */
1541
1542 /*
1543   Read bytes from the current file.
1544   buf contain buffer where data must be copied
1545   len the size of buf.
1546
1547   return the number of byte copied if some bytes are copied
1548   return 0 if the end of file was reached
1549   return <0 with error code if there is an error
1550     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1551 */
1552 extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
1553     int err=UNZ_OK;
1554     uInt iRead = 0;
1555     unz64_s* s;
1556     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1557     if (file==NULL)
1558         return UNZ_PARAMERROR;
1559     s=(unz64_s*)file;
1560     pfile_in_zip_read_info=s->pfile_in_zip_read;
1561
1562     if (pfile_in_zip_read_info==NULL)
1563         return UNZ_PARAMERROR;
1564
1565
1566     if (pfile_in_zip_read_info->read_buffer == NULL)
1567         return UNZ_END_OF_LIST_OF_FILE;
1568     if (len==0)
1569         return 0;
1570
1571     pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1572
1573     pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1574
1575     if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
1576         (!(pfile_in_zip_read_info->raw)))
1577         pfile_in_zip_read_info->stream.avail_out =
1578             (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1579
1580     if ((len>pfile_in_zip_read_info->rest_read_compressed+
1581            pfile_in_zip_read_info->stream.avail_in) &&
1582          (pfile_in_zip_read_info->raw))
1583         pfile_in_zip_read_info->stream.avail_out =
1584             (uInt)pfile_in_zip_read_info->rest_read_compressed+
1585             pfile_in_zip_read_info->stream.avail_in;
1586
1587     while (pfile_in_zip_read_info->stream.avail_out>0)
1588     {
1589         if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1590             (pfile_in_zip_read_info->rest_read_compressed>0))
1591         {
1592             uInt uReadThis = UNZ_BUFSIZE;
1593             if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1594                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1595             if (uReadThis == 0)
1596                 return UNZ_EOF;
1597             if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
1598                       pfile_in_zip_read_info->filestream,
1599                       pfile_in_zip_read_info->pos_in_zipfile +
1600                          pfile_in_zip_read_info->byte_before_the_zipfile,
1601                          ZLIB_FILEFUNC_SEEK_SET)!=0)
1602                 return UNZ_ERRNO;
1603             if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
1604                       pfile_in_zip_read_info->filestream,
1605                       pfile_in_zip_read_info->read_buffer,
1606                       uReadThis)!=uReadThis)
1607                 return UNZ_ERRNO;
1608
1609
1610 #            ifndef NOUNCRYPT
1611             if(s->encrypted)
1612             {
1613                 uInt i;
1614                 for(i=0;i<uReadThis;i++)
1615                   pfile_in_zip_read_info->read_buffer[i] =
1616                       zdecode(s->keys,s->pcrc_32_tab,
1617                               pfile_in_zip_read_info->read_buffer[i]);
1618             }
1619 #            endif
1620
1621
1622             pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1623
1624             pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1625
1626             pfile_in_zip_read_info->stream.next_in =
1627                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1628             pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1629         }
1630
1631         if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
1632         {
1633             uInt uDoCopy,i ;
1634
1635             if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
1636                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1637                 return (iRead==0) ? UNZ_EOF : (int)iRead;
1638
1639             if (pfile_in_zip_read_info->stream.avail_out <
1640                             pfile_in_zip_read_info->stream.avail_in)
1641                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1642             else
1643                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1644
1645             for (i=0;i<uDoCopy;i++)
1646                 *(pfile_in_zip_read_info->stream.next_out+i) =
1647                         *(pfile_in_zip_read_info->stream.next_in+i);
1648
1649             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
1650
1651             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1652                                 pfile_in_zip_read_info->stream.next_out,
1653                                 uDoCopy);
1654             pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1655             pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1656             pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1657             pfile_in_zip_read_info->stream.next_out += uDoCopy;
1658             pfile_in_zip_read_info->stream.next_in += uDoCopy;
1659             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1660             iRead += uDoCopy;
1661         }
1662         else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
1663         {
1664 #ifdef HAVE_BZIP2
1665             uLong uTotalOutBefore,uTotalOutAfter;
1666             const Bytef *bufBefore;
1667             uLong uOutThis;
1668
1669             pfile_in_zip_read_info->bstream.next_in        = (char*)pfile_in_zip_read_info->stream.next_in;
1670             pfile_in_zip_read_info->bstream.avail_in       = pfile_in_zip_read_info->stream.avail_in;
1671             pfile_in_zip_read_info->bstream.total_in_lo32  = pfile_in_zip_read_info->stream.total_in;
1672             pfile_in_zip_read_info->bstream.total_in_hi32  = 0;
1673             pfile_in_zip_read_info->bstream.next_out       = (char*)pfile_in_zip_read_info->stream.next_out;
1674             pfile_in_zip_read_info->bstream.avail_out      = pfile_in_zip_read_info->stream.avail_out;
1675             pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
1676             pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
1677
1678             uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
1679             bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
1680
1681             err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
1682
1683             uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
1684             uOutThis = uTotalOutAfter-uTotalOutBefore;
1685
1686             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
1687
1688             pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));
1689             pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
1690             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1691
1692             pfile_in_zip_read_info->stream.next_in   = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
1693             pfile_in_zip_read_info->stream.avail_in  = pfile_in_zip_read_info->bstream.avail_in;
1694             pfile_in_zip_read_info->stream.total_in  = pfile_in_zip_read_info->bstream.total_in_lo32;
1695             pfile_in_zip_read_info->stream.next_out  = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
1696             pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
1697             pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
1698
1699             if (err==BZ_STREAM_END)
1700               return (iRead==0) ? UNZ_EOF : iRead;
1701             if (err!=BZ_OK)
1702               break;
1703 #endif
1704         } // end Z_BZIP2ED
1705         else
1706         {
1707             ZPOS64_T uTotalOutBefore,uTotalOutAfter;
1708             const Bytef *bufBefore;
1709             ZPOS64_T uOutThis;
1710             int flush=Z_SYNC_FLUSH;
1711
1712             uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1713             bufBefore = pfile_in_zip_read_info->stream.next_out;
1714
1715             /*
1716             if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1717                      pfile_in_zip_read_info->stream.avail_out) &&
1718                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1719                 flush = Z_FINISH;
1720             */
1721             err=inflate(&pfile_in_zip_read_info->stream,flush);
1722
1723             if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
1724               err = Z_DATA_ERROR;
1725
1726             uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1727             /* Detect overflow, because z_stream.total_out is uLong (32 bits) */
1728             if (uTotalOutAfter<uTotalOutBefore)
1729                 uTotalOutAfter += 1LL << 32; /* Add maximum value of uLong + 1 */
1730             uOutThis = uTotalOutAfter-uTotalOutBefore;
1731
1732             pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
1733
1734             pfile_in_zip_read_info->crc32 =
1735                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1736                         (uInt)(uOutThis));
1737
1738             pfile_in_zip_read_info->rest_read_uncompressed -=
1739                 uOutThis;
1740
1741             iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1742
1743             if (err==Z_STREAM_END)
1744                 return (iRead==0) ? UNZ_EOF : (int)iRead;
1745             if (err!=Z_OK)
1746                 break;
1747         }
1748     }
1749
1750     if (err==Z_OK)
1751         return (int)iRead;
1752     return err;
1753 }
1754
1755
1756 /*
1757   Give the current position in uncompressed data
1758 */
1759 extern z_off_t ZEXPORT unztell(unzFile file) {
1760     unz64_s* s;
1761     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1762     if (file==NULL)
1763         return UNZ_PARAMERROR;
1764     s=(unz64_s*)file;
1765     pfile_in_zip_read_info=s->pfile_in_zip_read;
1766
1767     if (pfile_in_zip_read_info==NULL)
1768         return UNZ_PARAMERROR;
1769
1770     return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1771 }
1772
1773 extern ZPOS64_T ZEXPORT unztell64(unzFile file) {
1774
1775     unz64_s* s;
1776     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1777     if (file==NULL)
1778         return (ZPOS64_T)-1;
1779     s=(unz64_s*)file;
1780     pfile_in_zip_read_info=s->pfile_in_zip_read;
1781
1782     if (pfile_in_zip_read_info==NULL)
1783         return (ZPOS64_T)-1;
1784
1785     return pfile_in_zip_read_info->total_out_64;
1786 }
1787
1788
1789 /*
1790   return 1 if the end of file was reached, 0 elsewhere
1791 */
1792 extern int ZEXPORT unzeof(unzFile file) {
1793     unz64_s* s;
1794     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1795     if (file==NULL)
1796         return UNZ_PARAMERROR;
1797     s=(unz64_s*)file;
1798     pfile_in_zip_read_info=s->pfile_in_zip_read;
1799
1800     if (pfile_in_zip_read_info==NULL)
1801         return UNZ_PARAMERROR;
1802
1803     if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1804         return 1;
1805     else
1806         return 0;
1807 }
1808
1809
1810
1811 /*
1812 Read extra field from the current file (opened by unzOpenCurrentFile)
1813 This is the local-header version of the extra field (sometimes, there is
1814 more info in the local-header version than in the central-header)
1815
1816   if buf==NULL, it return the size of the local extra field that can be read
1817
1818   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1819     buf.
1820   the return value is the number of bytes copied in buf, or (if <0)
1821     the error code
1822 */
1823 extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) {
1824     unz64_s* s;
1825     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1826     uInt read_now;
1827     ZPOS64_T size_to_read;
1828
1829     if (file==NULL)
1830         return UNZ_PARAMERROR;
1831     s=(unz64_s*)file;
1832     pfile_in_zip_read_info=s->pfile_in_zip_read;
1833
1834     if (pfile_in_zip_read_info==NULL)
1835         return UNZ_PARAMERROR;
1836
1837     size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1838                 pfile_in_zip_read_info->pos_local_extrafield);
1839
1840     if (buf==NULL)
1841         return (int)size_to_read;
1842
1843     if (len>size_to_read)
1844         read_now = (uInt)size_to_read;
1845     else
1846         read_now = (uInt)len ;
1847
1848     if (read_now==0)
1849         return 0;
1850
1851     if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
1852               pfile_in_zip_read_info->filestream,
1853               pfile_in_zip_read_info->offset_local_extrafield +
1854               pfile_in_zip_read_info->pos_local_extrafield,
1855               ZLIB_FILEFUNC_SEEK_SET)!=0)
1856         return UNZ_ERRNO;
1857
1858     if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
1859               pfile_in_zip_read_info->filestream,
1860               buf,read_now)!=read_now)
1861         return UNZ_ERRNO;
1862
1863     return (int)read_now;
1864 }
1865
1866 /*
1867   Close the file in zip opened with unzOpenCurrentFile
1868   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1869 */
1870 extern int ZEXPORT unzCloseCurrentFile(unzFile file) {
1871     int err=UNZ_OK;
1872
1873     unz64_s* s;
1874     file_in_zip64_read_info_s* pfile_in_zip_read_info;
1875     if (file==NULL)
1876         return UNZ_PARAMERROR;
1877     s=(unz64_s*)file;
1878     pfile_in_zip_read_info=s->pfile_in_zip_read;
1879
1880     if (pfile_in_zip_read_info==NULL)
1881         return UNZ_PARAMERROR;
1882
1883
1884     if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
1885         (!pfile_in_zip_read_info->raw))
1886     {
1887         if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1888             err=UNZ_CRCERROR;
1889     }
1890
1891
1892     free(pfile_in_zip_read_info->read_buffer);
1893     pfile_in_zip_read_info->read_buffer = NULL;
1894     if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
1895         inflateEnd(&pfile_in_zip_read_info->stream);
1896 #ifdef HAVE_BZIP2
1897     else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
1898         BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
1899 #endif
1900
1901
1902     pfile_in_zip_read_info->stream_initialised = 0;
1903     free(pfile_in_zip_read_info);
1904
1905     s->pfile_in_zip_read=NULL;
1906
1907     return err;
1908 }
1909
1910
1911 /*
1912   Get the global comment string of the ZipFile, in the szComment buffer.
1913   uSizeBuf is the size of the szComment buffer.
1914   return the number of byte copied or an error code <0
1915 */
1916 extern int ZEXPORT unzGetGlobalComment(unzFile file, char * szComment, uLong uSizeBuf) {
1917     unz64_s* s;
1918     uLong uReadThis ;
1919     if (file==NULL)
1920         return (int)UNZ_PARAMERROR;
1921     s=(unz64_s*)file;
1922
1923     uReadThis = uSizeBuf;
1924     if (uReadThis>s->gi.size_comment)
1925         uReadThis = s->gi.size_comment;
1926
1927     if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
1928         return UNZ_ERRNO;
1929
1930     if (uReadThis>0)
1931     {
1932       *szComment='\0';
1933       if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
1934         return UNZ_ERRNO;
1935     }
1936
1937     if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1938         *(szComment+s->gi.size_comment)='\0';
1939     return (int)uReadThis;
1940 }
1941
1942 /* Additions by RX '2004 */
1943 extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) {
1944     unz64_s* s;
1945
1946     if (file==NULL)
1947           return 0; //UNZ_PARAMERROR;
1948     s=(unz64_s*)file;
1949     if (!s->current_file_ok)
1950       return 0;
1951     if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
1952       if (s->num_file==s->gi.number_entry)
1953          return 0;
1954     return s->pos_in_central_dir;
1955 }
1956
1957 extern uLong ZEXPORT unzGetOffset(unzFile file) {
1958     ZPOS64_T offset64;
1959
1960     if (file==NULL)
1961           return 0; //UNZ_PARAMERROR;
1962     offset64 = unzGetOffset64(file);
1963     return (uLong)offset64;
1964 }
1965
1966 extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) {
1967     unz64_s* s;
1968     int err;
1969
1970     if (file==NULL)
1971         return UNZ_PARAMERROR;
1972     s=(unz64_s*)file;
1973
1974     s->pos_in_central_dir = pos;
1975     s->num_file = s->gi.number_entry;      /* hack */
1976     err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1977                                               &s->cur_file_info_internal,
1978                                               NULL,0,NULL,0,NULL,0);
1979     s->current_file_ok = (err == UNZ_OK);
1980     return err;
1981 }
1982
1983 extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) {
1984     return unzSetOffset64(file,pos);
1985 }