all repos — mgba @ 81a52403a3583039f4e571f1516cd0efe4872c4b

mGBA Game Boy Advance Emulator

src/third-party/zlib/contrib/minizip/unzip.c (view raw)

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