Home | History | Annotate | Line # | Download | only in minizip
      1 /* zip.c -- IO on .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 for Zip64 support
      8          Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
      9 
     10          For more info read MiniZip_info.txt
     11 
     12          Changes
     13    Oct-2009 - Mathias Svensson - Remove old C style function prototypes
     14    Oct-2009 - Mathias Svensson - Added Zip64 Support when creating new file archives
     15    Oct-2009 - Mathias Svensson - Did some code cleanup and refactoring to get better overview of some functions.
     16    Oct-2009 - Mathias Svensson - Added zipRemoveExtraInfoBlock to strip extra field data from its ZIP64 data
     17                                  It is used when recreating zip archive with RAW when deleting items from a zip.
     18                                  ZIP64 data is automatically added to items that needs it, and existing ZIP64 data need to be removed.
     19    Oct-2009 - Mathias Svensson - Added support for BZIP2 as compression mode (bzip2 lib is required)
     20    Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
     21 
     22 */
     23 
     24 
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 #include <stdint.h>
     29 #include <time.h>
     30 #include "zlib.h"
     31 #include "zip.h"
     32 
     33 #ifdef STDC
     34 #  include <stddef.h>
     35 #endif
     36 #ifdef NO_ERRNO_H
     37     extern int errno;
     38 #else
     39 #   include <errno.h>
     40 #endif
     41 
     42 
     43 #ifndef local
     44 #  define local static
     45 #endif
     46 /* compile with -Dlocal if your debugger can't find static symbols */
     47 
     48 #ifndef VERSIONMADEBY
     49 # define VERSIONMADEBY   (0x0) /* platform dependent */
     50 #endif
     51 
     52 #ifndef Z_BUFSIZE
     53 #define Z_BUFSIZE (64*1024) //(16384)
     54 #endif
     55 
     56 #ifndef Z_MAXFILENAMEINZIP
     57 #define Z_MAXFILENAMEINZIP (256)
     58 #endif
     59 
     60 #ifndef ALLOC
     61 # define ALLOC(size) (malloc(size))
     62 #endif
     63 
     64 /*
     65 #define SIZECENTRALDIRITEM (0x2e)
     66 #define SIZEZIPLOCALHEADER (0x1e)
     67 */
     68 
     69 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
     70 
     71 
     72 // NOT sure that this work on ALL platform
     73 #define MAKEULONG64(a, b) ((ZPOS64_T)(((unsigned long)(a)) | ((ZPOS64_T)((unsigned long)(b))) << 32))
     74 
     75 #ifndef SEEK_CUR
     76 #define SEEK_CUR    1
     77 #endif
     78 
     79 #ifndef SEEK_END
     80 #define SEEK_END    2
     81 #endif
     82 
     83 #ifndef SEEK_SET
     84 #define SEEK_SET    0
     85 #endif
     86 
     87 #ifndef DEF_MEM_LEVEL
     88 #if MAX_MEM_LEVEL >= 8
     89 #  define DEF_MEM_LEVEL 8
     90 #else
     91 #  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
     92 #endif
     93 #endif
     94 const char zip_copyright[] =" zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
     95 
     96 
     97 #define SIZEDATA_INDATABLOCK (4096-(4*4))
     98 
     99 #define LOCALHEADERMAGIC    (0x04034b50)
    100 #define CENTRALHEADERMAGIC  (0x02014b50)
    101 #define ENDHEADERMAGIC      (0x06054b50)
    102 #define ZIP64ENDHEADERMAGIC      (0x6064b50)
    103 #define ZIP64ENDLOCHEADERMAGIC   (0x7064b50)
    104 
    105 #define FLAG_LOCALHEADER_OFFSET (0x06)
    106 #define CRC_LOCALHEADER_OFFSET  (0x0e)
    107 
    108 #define SIZECENTRALHEADER (0x2e) /* 46 */
    109 
    110 typedef struct linkedlist_datablock_internal_s
    111 {
    112   struct linkedlist_datablock_internal_s* next_datablock;
    113   uLong  avail_in_this_block;
    114   uLong  filled_in_this_block;
    115   uLong  unused; /* for future use and alignment */
    116   unsigned char data[SIZEDATA_INDATABLOCK];
    117 } linkedlist_datablock_internal;
    118 
    119 typedef struct linkedlist_data_s
    120 {
    121     linkedlist_datablock_internal* first_block;
    122     linkedlist_datablock_internal* last_block;
    123 } linkedlist_data;
    124 
    125 
    126 typedef struct
    127 {
    128     z_stream stream;            /* zLib stream structure for inflate */
    129 #ifdef HAVE_BZIP2
    130     bz_stream bstream;          /* bzLib stream structure for bziped */
    131 #endif
    132 
    133     int  stream_initialised;    /* 1 is stream is initialised */
    134     uInt pos_in_buffered_data;  /* last written byte in buffered_data */
    135 
    136     ZPOS64_T pos_local_header;     /* offset of the local header of the file
    137                                      currently writing */
    138     char* central_header;       /* central header data for the current file */
    139     uLong size_centralExtra;
    140     uLong size_centralheader;   /* size of the central header for cur file */
    141     uLong size_centralExtraFree; /* Extra bytes allocated to the centralheader but that are not used */
    142     uLong flag;                 /* flag of the file currently writing */
    143 
    144     int  method;                /* compression method of file currently wr.*/
    145     int  raw;                   /* 1 for directly writing raw data */
    146     Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
    147     uLong dosDate;
    148     uLong crc32;
    149     int  encrypt;
    150     int  zip64;               /* Add ZIP64 extended information in the extra field */
    151     ZPOS64_T pos_zip64extrainfo;
    152     ZPOS64_T totalCompressedData;
    153     ZPOS64_T totalUncompressedData;
    154 #ifndef NOCRYPT
    155     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
    156     const z_crc_t* pcrc_32_tab;
    157     unsigned crypt_header_size;
    158 #endif
    159 } curfile64_info;
    160 
    161 typedef struct
    162 {
    163     zlib_filefunc64_32_def z_filefunc;
    164     voidpf filestream;        /* io structure of the zipfile */
    165     linkedlist_data central_dir;/* datablock with central dir in construction*/
    166     int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
    167     curfile64_info ci;            /* info on the file currently writing */
    168 
    169     ZPOS64_T begin_pos;            /* position of the beginning of the zipfile */
    170     ZPOS64_T add_position_when_writing_offset;
    171     ZPOS64_T number_entry;
    172 
    173 #ifndef NO_ADDFILEINEXISTINGZIP
    174     char *globalcomment;
    175 #endif
    176 
    177 } zip64_internal;
    178 
    179 
    180 #ifndef NOCRYPT
    181 #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
    182 #include "crypt.h"
    183 #endif
    184 
    185 local linkedlist_datablock_internal* allocate_new_datablock(void) {
    186     linkedlist_datablock_internal* ldi;
    187     ldi = (linkedlist_datablock_internal*)
    188                  ALLOC(sizeof(linkedlist_datablock_internal));
    189     if (ldi!=NULL)
    190     {
    191         ldi->next_datablock = NULL ;
    192         ldi->filled_in_this_block = 0 ;
    193         ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
    194     }
    195     return ldi;
    196 }
    197 
    198 local void free_datablock(linkedlist_datablock_internal* ldi) {
    199     while (ldi!=NULL)
    200     {
    201         linkedlist_datablock_internal* ldinext = ldi->next_datablock;
    202         free(ldi);
    203         ldi = ldinext;
    204     }
    205 }
    206 
    207 local void init_linkedlist(linkedlist_data* ll) {
    208     ll->first_block = ll->last_block = NULL;
    209 }
    210 
    211 local void free_linkedlist(linkedlist_data* ll) {
    212     free_datablock(ll->first_block);
    213     ll->first_block = ll->last_block = NULL;
    214 }
    215 
    216 
    217 local int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len) {
    218     linkedlist_datablock_internal* ldi;
    219     const unsigned char* from_copy;
    220 
    221     if (ll==NULL)
    222         return ZIP_INTERNALERROR;
    223 
    224     if (ll->last_block == NULL)
    225     {
    226         ll->first_block = ll->last_block = allocate_new_datablock();
    227         if (ll->first_block == NULL)
    228             return ZIP_INTERNALERROR;
    229     }
    230 
    231     ldi = ll->last_block;
    232     from_copy = (const unsigned char*)buf;
    233 
    234     while (len>0)
    235     {
    236         uInt copy_this;
    237         uInt i;
    238         unsigned char* to_copy;
    239 
    240         if (ldi->avail_in_this_block==0)
    241         {
    242             ldi->next_datablock = allocate_new_datablock();
    243             if (ldi->next_datablock == NULL)
    244                 return ZIP_INTERNALERROR;
    245             ldi = ldi->next_datablock ;
    246             ll->last_block = ldi;
    247         }
    248 
    249         if (ldi->avail_in_this_block < len)
    250             copy_this = (uInt)ldi->avail_in_this_block;
    251         else
    252             copy_this = (uInt)len;
    253 
    254         to_copy = &(ldi->data[ldi->filled_in_this_block]);
    255 
    256         for (i=0;i<copy_this;i++)
    257             *(to_copy+i)=*(from_copy+i);
    258 
    259         ldi->filled_in_this_block += copy_this;
    260         ldi->avail_in_this_block -= copy_this;
    261         from_copy += copy_this ;
    262         len -= copy_this;
    263     }
    264     return ZIP_OK;
    265 }
    266 
    267 
    268 
    269 /****************************************************************************/
    270 
    271 #ifndef NO_ADDFILEINEXISTINGZIP
    272 /* ===========================================================================
    273    Inputs a long in LSB order to the given file
    274    nbByte == 1, 2 ,4 or 8 (byte, short or long, ZPOS64_T)
    275 */
    276 
    277 local int zip64local_putValue(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T x, int nbByte) {
    278     unsigned char buf[8];
    279     int n;
    280     for (n = 0; n < nbByte; n++)
    281     {
    282         buf[n] = (unsigned char)(x & 0xff);
    283         x >>= 8;
    284     }
    285     if (x != 0)
    286       {     /* data overflow - hack for ZIP64 (X Roche) */
    287       for (n = 0; n < nbByte; n++)
    288         {
    289           buf[n] = 0xff;
    290         }
    291       }
    292 
    293     if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,(uLong)nbByte)!=(uLong)nbByte)
    294         return ZIP_ERRNO;
    295     else
    296         return ZIP_OK;
    297 }
    298 
    299 local void zip64local_putValue_inmemory (void* dest, ZPOS64_T x, int nbByte) {
    300     unsigned char* buf=(unsigned char*)dest;
    301     int n;
    302     for (n = 0; n < nbByte; n++) {
    303         buf[n] = (unsigned char)(x & 0xff);
    304         x >>= 8;
    305     }
    306 
    307     if (x != 0)
    308     {     /* data overflow - hack for ZIP64 */
    309        for (n = 0; n < nbByte; n++)
    310        {
    311           buf[n] = 0xff;
    312        }
    313     }
    314 }
    315 
    316 /****************************************************************************/
    317 
    318 
    319 local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm) {
    320     uLong year = (uLong)ptm->tm_year;
    321     if (year>=1980)
    322         year-=1980;
    323     else if (year>=80)
    324         year-=80;
    325     return
    326       (uLong) (((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon+1)) + (512 * year)) << 16) |
    327         (((uLong)ptm->tm_sec/2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
    328 }
    329 
    330 
    331 /****************************************************************************/
    332 
    333 local int zip64local_getByte(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, int* pi) {
    334     unsigned char c;
    335     int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,&c,1);
    336     if (err==1)
    337     {
    338         *pi = (int)c;
    339         return ZIP_OK;
    340     }
    341     else
    342     {
    343         if (ZERROR64(*pzlib_filefunc_def,filestream))
    344             return ZIP_ERRNO;
    345         else
    346             return ZIP_EOF;
    347     }
    348 }
    349 
    350 
    351 /* ===========================================================================
    352    Reads a long in LSB order from the given gz_stream. Sets
    353 */
    354 local int zip64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) {
    355     uLong x ;
    356     int i = 0;
    357     int err;
    358 
    359     err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    360     x = (uLong)i;
    361 
    362     if (err==ZIP_OK)
    363         err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    364     x += ((uLong)i)<<8;
    365 
    366     if (err==ZIP_OK)
    367         *pX = x;
    368     else
    369         *pX = 0;
    370     return err;
    371 }
    372 
    373 local int zip64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, uLong* pX) {
    374     uLong x ;
    375     int i = 0;
    376     int err;
    377 
    378     err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    379     x = (uLong)i;
    380 
    381     if (err==ZIP_OK)
    382         err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    383     x += ((uLong)i)<<8;
    384 
    385     if (err==ZIP_OK)
    386         err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    387     x += ((uLong)i)<<16;
    388 
    389     if (err==ZIP_OK)
    390         err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    391     x += ((uLong)i)<<24;
    392 
    393     if (err==ZIP_OK)
    394         *pX = x;
    395     else
    396         *pX = 0;
    397     return err;
    398 }
    399 
    400 
    401 local int zip64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream, ZPOS64_T *pX) {
    402   ZPOS64_T x;
    403   int i = 0;
    404   int err;
    405 
    406   err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    407   x = (ZPOS64_T)i;
    408 
    409   if (err==ZIP_OK)
    410     err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    411   x += ((ZPOS64_T)i)<<8;
    412 
    413   if (err==ZIP_OK)
    414     err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    415   x += ((ZPOS64_T)i)<<16;
    416 
    417   if (err==ZIP_OK)
    418     err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    419   x += ((ZPOS64_T)i)<<24;
    420 
    421   if (err==ZIP_OK)
    422     err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    423   x += ((ZPOS64_T)i)<<32;
    424 
    425   if (err==ZIP_OK)
    426     err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    427   x += ((ZPOS64_T)i)<<40;
    428 
    429   if (err==ZIP_OK)
    430     err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    431   x += ((ZPOS64_T)i)<<48;
    432 
    433   if (err==ZIP_OK)
    434     err = zip64local_getByte(pzlib_filefunc_def,filestream,&i);
    435   x += ((ZPOS64_T)i)<<56;
    436 
    437   if (err==ZIP_OK)
    438     *pX = x;
    439   else
    440     *pX = 0;
    441 
    442   return err;
    443 }
    444 
    445 #ifndef BUFREADCOMMENT
    446 #define BUFREADCOMMENT (0x400)
    447 #endif
    448 /*
    449   Locate the Central directory of a zipfile (at the end, just before
    450     the global comment)
    451 */
    452 local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
    453   unsigned char* buf;
    454   ZPOS64_T uSizeFile;
    455   ZPOS64_T uBackRead;
    456   ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
    457   ZPOS64_T uPosFound=0;
    458 
    459   if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
    460     return 0;
    461 
    462 
    463   uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
    464 
    465   if (uMaxBack>uSizeFile)
    466     uMaxBack = uSizeFile;
    467 
    468   buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    469   if (buf==NULL)
    470     return 0;
    471 
    472   uBackRead = 4;
    473   while (uBackRead<uMaxBack)
    474   {
    475     uLong uReadSize;
    476     ZPOS64_T uReadPos ;
    477     int i;
    478     if (uBackRead+BUFREADCOMMENT>uMaxBack)
    479       uBackRead = uMaxBack;
    480     else
    481       uBackRead+=BUFREADCOMMENT;
    482     uReadPos = uSizeFile-uBackRead ;
    483 
    484     uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
    485       (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
    486     if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    487       break;
    488 
    489     if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
    490       break;
    491 
    492     for (i=(int)uReadSize-3; (i--)>0;)
    493       if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
    494         ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
    495       {
    496         uPosFound = uReadPos+(unsigned)i;
    497         break;
    498       }
    499 
    500     if (uPosFound!=0)
    501       break;
    502   }
    503   free(buf);
    504   return uPosFound;
    505 }
    506 
    507 /*
    508 Locate the End of Zip64 Central directory locator and from there find the CD of a zipfile (at the end, just before
    509 the global comment)
    510 */
    511 local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
    512   unsigned char* buf;
    513   ZPOS64_T uSizeFile;
    514   ZPOS64_T uBackRead;
    515   ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
    516   ZPOS64_T uPosFound=0;
    517   uLong uL;
    518   ZPOS64_T relativeOffset;
    519 
    520   if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
    521     return 0;
    522 
    523   uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
    524 
    525   if (uMaxBack>uSizeFile)
    526     uMaxBack = uSizeFile;
    527 
    528   buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    529   if (buf==NULL)
    530     return 0;
    531 
    532   uBackRead = 4;
    533   while (uBackRead<uMaxBack)
    534   {
    535     uLong uReadSize;
    536     ZPOS64_T uReadPos;
    537     int i;
    538     if (uBackRead+BUFREADCOMMENT>uMaxBack)
    539       uBackRead = uMaxBack;
    540     else
    541       uBackRead+=BUFREADCOMMENT;
    542     uReadPos = uSizeFile-uBackRead ;
    543 
    544     uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
    545       (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
    546     if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    547       break;
    548 
    549     if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
    550       break;
    551 
    552     for (i=(int)uReadSize-3; (i--)>0;)
    553     {
    554       // Signature "0x07064b50" Zip64 end of central directory locater
    555       if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
    556       {
    557         uPosFound = uReadPos+(unsigned)i;
    558         break;
    559       }
    560     }
    561 
    562       if (uPosFound!=0)
    563         break;
    564   }
    565 
    566   free(buf);
    567   if (uPosFound == 0)
    568     return 0;
    569 
    570   /* Zip64 end of central directory locator */
    571   if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
    572     return 0;
    573 
    574   /* the signature, already checked */
    575   if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
    576     return 0;
    577 
    578   /* number of the disk with the start of the zip64 end of central directory */
    579   if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
    580     return 0;
    581   if (uL != 0)
    582     return 0;
    583 
    584   /* relative offset of the zip64 end of central directory record */
    585   if (zip64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=ZIP_OK)
    586     return 0;
    587 
    588   /* total number of disks */
    589   if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
    590     return 0;
    591   if (uL != 1)
    592     return 0;
    593 
    594   /* Goto Zip64 end of central directory record */
    595   if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
    596     return 0;
    597 
    598   /* the signature */
    599   if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
    600     return 0;
    601 
    602   if (uL != 0x06064b50) // signature of 'Zip64 end of central directory'
    603     return 0;
    604 
    605   return relativeOffset;
    606 }
    607 
    608 local int LoadCentralDirectoryRecord(zip64_internal* pziinit) {
    609   int err=ZIP_OK;
    610   ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
    611 
    612   ZPOS64_T size_central_dir;     /* size of the central directory  */
    613   ZPOS64_T offset_central_dir;   /* offset of start of central directory */
    614   ZPOS64_T central_pos;
    615   uLong uL;
    616 
    617   uLong number_disk;          /* number of the current disk, used for
    618                               spanning ZIP, unsupported, always 0*/
    619   uLong number_disk_with_CD;  /* number of the disk with central dir, used
    620                               for spanning ZIP, unsupported, always 0*/
    621   ZPOS64_T number_entry;
    622   ZPOS64_T number_entry_CD;      /* total number of entries in
    623                                 the central dir
    624                                 (same than number_entry on nospan) */
    625   uLong VersionMadeBy;
    626   uLong VersionNeeded;
    627   uLong size_comment;
    628 
    629   int hasZIP64Record = 0;
    630 
    631   // check first if we find a ZIP64 record
    632   central_pos = zip64local_SearchCentralDir64(&pziinit->z_filefunc,pziinit->filestream);
    633   if(central_pos > 0)
    634   {
    635     hasZIP64Record = 1;
    636   }
    637   else if(central_pos == 0)
    638   {
    639     central_pos = zip64local_SearchCentralDir(&pziinit->z_filefunc,pziinit->filestream);
    640   }
    641 
    642 /* disable to allow appending to empty ZIP archive
    643         if (central_pos==0)
    644             err=ZIP_ERRNO;
    645 */
    646 
    647   if(hasZIP64Record)
    648   {
    649     ZPOS64_T sizeEndOfCentralDirectory;
    650     if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
    651       err=ZIP_ERRNO;
    652 
    653     /* the signature, already checked */
    654     if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)
    655       err=ZIP_ERRNO;
    656 
    657     /* size of zip64 end of central directory record */
    658     if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &sizeEndOfCentralDirectory)!=ZIP_OK)
    659       err=ZIP_ERRNO;
    660 
    661     /* version made by */
    662     if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionMadeBy)!=ZIP_OK)
    663       err=ZIP_ERRNO;
    664 
    665     /* version needed to extract */
    666     if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &VersionNeeded)!=ZIP_OK)
    667       err=ZIP_ERRNO;
    668 
    669     /* number of this disk */
    670     if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)
    671       err=ZIP_ERRNO;
    672 
    673     /* number of the disk with the start of the central directory */
    674     if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)
    675       err=ZIP_ERRNO;
    676 
    677     /* total number of entries in the central directory on this disk */
    678     if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream, &number_entry)!=ZIP_OK)
    679       err=ZIP_ERRNO;
    680 
    681     /* total number of entries in the central directory */
    682     if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&number_entry_CD)!=ZIP_OK)
    683       err=ZIP_ERRNO;
    684 
    685     if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))
    686       err=ZIP_BADZIPFILE;
    687 
    688     /* size of the central directory */
    689     if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&size_central_dir)!=ZIP_OK)
    690       err=ZIP_ERRNO;
    691 
    692     /* offset of start of central directory with respect to the
    693     starting disk number */
    694     if (zip64local_getLong64(&pziinit->z_filefunc, pziinit->filestream,&offset_central_dir)!=ZIP_OK)
    695       err=ZIP_ERRNO;
    696 
    697     // TODO..
    698     // read the comment from the standard central header.
    699     size_comment = 0;
    700   }
    701   else
    702   {
    703     // Read End of central Directory info
    704     if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    705       err=ZIP_ERRNO;
    706 
    707     /* the signature, already checked */
    708     if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream,&uL)!=ZIP_OK)
    709       err=ZIP_ERRNO;
    710 
    711     /* number of this disk */
    712     if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk)!=ZIP_OK)
    713       err=ZIP_ERRNO;
    714 
    715     /* number of the disk with the start of the central directory */
    716     if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream,&number_disk_with_CD)!=ZIP_OK)
    717       err=ZIP_ERRNO;
    718 
    719     /* total number of entries in the central dir on this disk */
    720     number_entry = 0;
    721     if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
    722       err=ZIP_ERRNO;
    723     else
    724       number_entry = uL;
    725 
    726     /* total number of entries in the central dir */
    727     number_entry_CD = 0;
    728     if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
    729       err=ZIP_ERRNO;
    730     else
    731       number_entry_CD = uL;
    732 
    733     if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0))
    734       err=ZIP_BADZIPFILE;
    735 
    736     /* size of the central directory */
    737     size_central_dir = 0;
    738     if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
    739       err=ZIP_ERRNO;
    740     else
    741       size_central_dir = uL;
    742 
    743     /* offset of start of central directory with respect to the starting disk number */
    744     offset_central_dir = 0;
    745     if (zip64local_getLong(&pziinit->z_filefunc, pziinit->filestream, &uL)!=ZIP_OK)
    746       err=ZIP_ERRNO;
    747     else
    748       offset_central_dir = uL;
    749 
    750 
    751     /* zipfile global comment length */
    752     if (zip64local_getShort(&pziinit->z_filefunc, pziinit->filestream, &size_comment)!=ZIP_OK)
    753       err=ZIP_ERRNO;
    754   }
    755 
    756   if ((central_pos<offset_central_dir+size_central_dir) &&
    757     (err==ZIP_OK))
    758     err=ZIP_BADZIPFILE;
    759 
    760   if (err!=ZIP_OK)
    761   {
    762     ZCLOSE64(pziinit->z_filefunc, pziinit->filestream);
    763     return ZIP_ERRNO;
    764   }
    765 
    766   if (size_comment>0)
    767   {
    768     pziinit->globalcomment = (char*)ALLOC(size_comment+1);
    769     if (pziinit->globalcomment)
    770     {
    771       size_comment = ZREAD64(pziinit->z_filefunc, pziinit->filestream, pziinit->globalcomment,size_comment);
    772       pziinit->globalcomment[size_comment]=0;
    773     }
    774   }
    775 
    776   byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir);
    777   pziinit->add_position_when_writing_offset = byte_before_the_zipfile;
    778 
    779   {
    780     ZPOS64_T size_central_dir_to_read = size_central_dir;
    781     size_t buf_size = SIZEDATA_INDATABLOCK;
    782     void* buf_read = (void*)ALLOC(buf_size);
    783     if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0)
    784       err=ZIP_ERRNO;
    785 
    786     while ((size_central_dir_to_read>0) && (err==ZIP_OK))
    787     {
    788       ZPOS64_T read_this = SIZEDATA_INDATABLOCK;
    789       if (read_this > size_central_dir_to_read)
    790         read_this = size_central_dir_to_read;
    791 
    792       if (ZREAD64(pziinit->z_filefunc, pziinit->filestream,buf_read,(uLong)read_this) != read_this)
    793         err=ZIP_ERRNO;
    794 
    795       if (err==ZIP_OK)
    796         err = add_data_in_datablock(&pziinit->central_dir,buf_read, (uLong)read_this);
    797 
    798       size_central_dir_to_read-=read_this;
    799     }
    800     free(buf_read);
    801   }
    802   pziinit->begin_pos = byte_before_the_zipfile;
    803   pziinit->number_entry = number_entry_CD;
    804 
    805   if (ZSEEK64(pziinit->z_filefunc, pziinit->filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0)
    806     err=ZIP_ERRNO;
    807 
    808   return err;
    809 }
    810 
    811 
    812 #endif /* !NO_ADDFILEINEXISTINGZIP*/
    813 
    814 
    815 /************************************************************/
    816 extern zipFile ZEXPORT zipOpen3(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_32_def* pzlib_filefunc64_32_def) {
    817     zip64_internal ziinit;
    818     zip64_internal* zi;
    819     int err=ZIP_OK;
    820 
    821     ziinit.z_filefunc.zseek32_file = NULL;
    822     ziinit.z_filefunc.ztell32_file = NULL;
    823     if (pzlib_filefunc64_32_def==NULL)
    824         fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
    825     else
    826         ziinit.z_filefunc = *pzlib_filefunc64_32_def;
    827 
    828     ziinit.filestream = ZOPEN64(ziinit.z_filefunc,
    829                   pathname,
    830                   (append == APPEND_STATUS_CREATE) ?
    831                   (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
    832                     (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
    833 
    834     if (ziinit.filestream == NULL)
    835         return NULL;
    836 
    837     if (append == APPEND_STATUS_CREATEAFTER)
    838         ZSEEK64(ziinit.z_filefunc,ziinit.filestream,0,SEEK_END);
    839 
    840     ziinit.begin_pos = ZTELL64(ziinit.z_filefunc,ziinit.filestream);
    841     ziinit.in_opened_file_inzip = 0;
    842     ziinit.ci.stream_initialised = 0;
    843     ziinit.number_entry = 0;
    844     ziinit.add_position_when_writing_offset = 0;
    845     init_linkedlist(&(ziinit.central_dir));
    846 
    847 
    848 
    849     zi = (zip64_internal*)ALLOC(sizeof(zip64_internal));
    850     if (zi==NULL)
    851     {
    852         ZCLOSE64(ziinit.z_filefunc,ziinit.filestream);
    853         return NULL;
    854     }
    855 
    856     /* now we add file in a zipfile */
    857 #    ifndef NO_ADDFILEINEXISTINGZIP
    858     ziinit.globalcomment = NULL;
    859     if (append == APPEND_STATUS_ADDINZIP)
    860     {
    861       // Read and Cache Central Directory Records
    862       err = LoadCentralDirectoryRecord(&ziinit);
    863     }
    864 
    865     if (globalcomment)
    866     {
    867       *globalcomment = ziinit.globalcomment;
    868     }
    869 #    endif /* !NO_ADDFILEINEXISTINGZIP*/
    870 
    871     if (err != ZIP_OK)
    872     {
    873 #    ifndef NO_ADDFILEINEXISTINGZIP
    874         free(ziinit.globalcomment);
    875 #    endif /* !NO_ADDFILEINEXISTINGZIP*/
    876         free(zi);
    877         return NULL;
    878     }
    879     else
    880     {
    881         *zi = ziinit;
    882         return (zipFile)zi;
    883     }
    884 }
    885 
    886 extern zipFile ZEXPORT zipOpen2(const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc32_def) {
    887     if (pzlib_filefunc32_def != NULL)
    888     {
    889         zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
    890         fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
    891         return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
    892     }
    893     else
    894         return zipOpen3(pathname, append, globalcomment, NULL);
    895 }
    896 
    897 extern zipFile ZEXPORT zipOpen2_64(const void *pathname, int append, zipcharpc* globalcomment, zlib_filefunc64_def* pzlib_filefunc_def) {
    898     if (pzlib_filefunc_def != NULL)
    899     {
    900         zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
    901         zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
    902         zlib_filefunc64_32_def_fill.ztell32_file = NULL;
    903         zlib_filefunc64_32_def_fill.zseek32_file = NULL;
    904         return zipOpen3(pathname, append, globalcomment, &zlib_filefunc64_32_def_fill);
    905     }
    906     else
    907         return zipOpen3(pathname, append, globalcomment, NULL);
    908 }
    909 
    910 
    911 
    912 extern zipFile ZEXPORT zipOpen(const char* pathname, int append) {
    913     return zipOpen3((const void*)pathname,append,NULL,NULL);
    914 }
    915 
    916 extern zipFile ZEXPORT zipOpen64(const void* pathname, int append) {
    917     return zipOpen3(pathname,append,NULL,NULL);
    918 }
    919 
    920 local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local) {
    921   /* write the local header */
    922   int err;
    923   uInt size_filename = (uInt)strlen(filename);
    924   uInt size_extrafield = size_extrafield_local;
    925 
    926   err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC, 4);
    927 
    928   if (err==ZIP_OK)
    929   {
    930     if(zi->ci.zip64)
    931       err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);/* version needed to extract */
    932     else
    933       err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
    934   }
    935 
    936   if (err==ZIP_OK)
    937     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
    938 
    939   if (err==ZIP_OK)
    940     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
    941 
    942   if (err==ZIP_OK)
    943     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
    944 
    945   // CRC / Compressed size / Uncompressed size will be filled in later and rewritten later
    946   if (err==ZIP_OK)
    947     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
    948   if (err==ZIP_OK)
    949   {
    950     if(zi->ci.zip64)
    951       err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* compressed size, unknown */
    952     else
    953       err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
    954   }
    955   if (err==ZIP_OK)
    956   {
    957     if(zi->ci.zip64)
    958       err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xFFFFFFFF,4); /* uncompressed size, unknown */
    959     else
    960       err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
    961   }
    962 
    963   if (err==ZIP_OK)
    964     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
    965 
    966   if(zi->ci.zip64)
    967   {
    968     size_extrafield += 20;
    969   }
    970 
    971   if (err==ZIP_OK)
    972     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield,2);
    973 
    974   if ((err==ZIP_OK) && (size_filename > 0))
    975   {
    976     if (ZWRITE64(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
    977       err = ZIP_ERRNO;
    978   }
    979 
    980   if ((err==ZIP_OK) && (size_extrafield_local > 0))
    981   {
    982     if (ZWRITE64(zi->z_filefunc, zi->filestream, extrafield_local, size_extrafield_local) != size_extrafield_local)
    983       err = ZIP_ERRNO;
    984   }
    985 
    986 
    987   if ((err==ZIP_OK) && (zi->ci.zip64))
    988   {
    989       // write the Zip64 extended info
    990       short HeaderID = 1;
    991       short DataSize = 16;
    992       ZPOS64_T CompressedSize = 0;
    993       ZPOS64_T UncompressedSize = 0;
    994 
    995       // Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file)
    996       zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream);
    997 
    998       err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2);
    999       err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize,2);
   1000 
   1001       err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8);
   1002       err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8);
   1003   }
   1004 
   1005   return err;
   1006 }
   1007 
   1008 /*
   1009  NOTE.
   1010  When writing RAW the ZIP64 extended information in extrafield_local and extrafield_global needs to be stripped
   1011  before calling this function it can be done with zipRemoveExtraInfoBlock
   1012 
   1013  It is not done here because then we need to realloc a new buffer since parameters are 'const' and I want to minimize
   1014  unnecessary allocations.
   1015  */
   1016 extern int ZEXPORT zipOpenNewFileInZip4_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
   1017                                            const void* extrafield_local, uInt size_extrafield_local,
   1018                                            const void* extrafield_global, uInt size_extrafield_global,
   1019                                            const char* comment, int method, int level, int raw,
   1020                                            int windowBits,int memLevel, int strategy,
   1021                                            const char* password, uLong crcForCrypting,
   1022                                            uLong versionMadeBy, uLong flagBase, int zip64) {
   1023     zip64_internal* zi;
   1024     uInt size_filename;
   1025     uInt size_comment;
   1026     uInt i;
   1027     int err = ZIP_OK;
   1028 
   1029 #    ifdef NOCRYPT
   1030     (crcForCrypting);
   1031     if (password != NULL)
   1032         return ZIP_PARAMERROR;
   1033 #    endif
   1034 
   1035     if (file == NULL)
   1036         return ZIP_PARAMERROR;
   1037 
   1038 #ifdef HAVE_BZIP2
   1039     if ((method!=0) && (method!=Z_DEFLATED) && (method!=Z_BZIP2ED))
   1040       return ZIP_PARAMERROR;
   1041 #else
   1042     if ((method!=0) && (method!=Z_DEFLATED))
   1043       return ZIP_PARAMERROR;
   1044 #endif
   1045 
   1046     // The filename and comment length must fit in 16 bits.
   1047     if ((filename!=NULL) && (strlen(filename)>0xffff))
   1048         return ZIP_PARAMERROR;
   1049     if ((comment!=NULL) && (strlen(comment)>0xffff))
   1050         return ZIP_PARAMERROR;
   1051     // The extra field length must fit in 16 bits. If the member also requires
   1052     // a Zip64 extra block, that will also need to fit within that 16-bit
   1053     // length, but that will be checked for later.
   1054     if ((size_extrafield_local>0xffff) || (size_extrafield_global>0xffff))
   1055         return ZIP_PARAMERROR;
   1056 
   1057     zi = (zip64_internal*)file;
   1058 
   1059     if (zi->in_opened_file_inzip == 1)
   1060     {
   1061         err = zipCloseFileInZip (file);
   1062         if (err != ZIP_OK)
   1063             return err;
   1064     }
   1065 
   1066     if (filename==NULL)
   1067         filename="-";
   1068 
   1069     if (comment==NULL)
   1070         size_comment = 0;
   1071     else
   1072         size_comment = (uInt)strlen(comment);
   1073 
   1074     size_filename = (uInt)strlen(filename);
   1075 
   1076     if (zipfi == NULL)
   1077         zi->ci.dosDate = 0;
   1078     else
   1079     {
   1080         if (zipfi->dosDate != 0)
   1081             zi->ci.dosDate = zipfi->dosDate;
   1082         else
   1083           zi->ci.dosDate = zip64local_TmzDateToDosDate(&zipfi->tmz_date);
   1084     }
   1085 
   1086     zi->ci.flag = flagBase;
   1087     if ((level==8) || (level==9))
   1088       zi->ci.flag |= 2;
   1089     if (level==2)
   1090       zi->ci.flag |= 4;
   1091     if (level==1)
   1092       zi->ci.flag |= 6;
   1093     if (password != NULL)
   1094       zi->ci.flag |= 1;
   1095 
   1096     zi->ci.crc32 = 0;
   1097     zi->ci.method = method;
   1098     zi->ci.encrypt = 0;
   1099     zi->ci.stream_initialised = 0;
   1100     zi->ci.pos_in_buffered_data = 0;
   1101     zi->ci.raw = raw;
   1102     zi->ci.pos_local_header = ZTELL64(zi->z_filefunc,zi->filestream);
   1103 
   1104     zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment;
   1105     zi->ci.size_centralExtraFree = 32; // Extra space we have reserved in case we need to add ZIP64 extra info data
   1106 
   1107     zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader + zi->ci.size_centralExtraFree);
   1108 
   1109     zi->ci.size_centralExtra = size_extrafield_global;
   1110     zip64local_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
   1111     /* version info */
   1112     zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)versionMadeBy,2);
   1113     zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
   1114     zip64local_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
   1115     zip64local_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
   1116     zip64local_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
   1117     zip64local_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
   1118     zip64local_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
   1119     zip64local_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
   1120     zip64local_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
   1121     zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
   1122     zip64local_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
   1123     zip64local_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
   1124 
   1125     if (zipfi==NULL)
   1126         zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
   1127     else
   1128         zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
   1129 
   1130     if (zipfi==NULL)
   1131         zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
   1132     else
   1133         zip64local_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
   1134 
   1135     if(zi->ci.pos_local_header >= 0xffffffff)
   1136       zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)0xffffffff,4);
   1137     else
   1138       zip64local_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header - zi->add_position_when_writing_offset,4);
   1139 
   1140     for (i=0;i<size_filename;i++)
   1141         *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
   1142 
   1143     for (i=0;i<size_extrafield_global;i++)
   1144         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
   1145               *(((const char*)extrafield_global)+i);
   1146 
   1147     for (i=0;i<size_comment;i++)
   1148         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
   1149               size_extrafield_global+i) = *(comment+i);
   1150     if (zi->ci.central_header == NULL)
   1151         return ZIP_INTERNALERROR;
   1152 
   1153     zi->ci.zip64 = zip64;
   1154     zi->ci.totalCompressedData = 0;
   1155     zi->ci.totalUncompressedData = 0;
   1156     zi->ci.pos_zip64extrainfo = 0;
   1157 
   1158     err = Write_LocalFileHeader(zi, filename, size_extrafield_local, extrafield_local);
   1159 
   1160 #ifdef HAVE_BZIP2
   1161     zi->ci.bstream.avail_in = (uInt)0;
   1162     zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
   1163     zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
   1164     zi->ci.bstream.total_in_hi32 = 0;
   1165     zi->ci.bstream.total_in_lo32 = 0;
   1166     zi->ci.bstream.total_out_hi32 = 0;
   1167     zi->ci.bstream.total_out_lo32 = 0;
   1168 #endif
   1169 
   1170     zi->ci.stream.avail_in = (uInt)0;
   1171     zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
   1172     zi->ci.stream.next_out = zi->ci.buffered_data;
   1173     zi->ci.stream.total_in = 0;
   1174     zi->ci.stream.total_out = 0;
   1175     zi->ci.stream.data_type = Z_BINARY;
   1176 
   1177 #ifdef HAVE_BZIP2
   1178     if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED || zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
   1179 #else
   1180     if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
   1181 #endif
   1182     {
   1183         if(zi->ci.method == Z_DEFLATED)
   1184         {
   1185           zi->ci.stream.zalloc = (alloc_func)0;
   1186           zi->ci.stream.zfree = (free_func)0;
   1187           zi->ci.stream.opaque = (voidpf)0;
   1188 
   1189           if (windowBits>0)
   1190               windowBits = -windowBits;
   1191 
   1192           err = deflateInit2(&zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy);
   1193 
   1194           if (err==Z_OK)
   1195               zi->ci.stream_initialised = Z_DEFLATED;
   1196         }
   1197         else if(zi->ci.method == Z_BZIP2ED)
   1198         {
   1199 #ifdef HAVE_BZIP2
   1200             // Init BZip stuff here
   1201           zi->ci.bstream.bzalloc = 0;
   1202           zi->ci.bstream.bzfree = 0;
   1203           zi->ci.bstream.opaque = (voidpf)0;
   1204 
   1205           err = BZ2_bzCompressInit(&zi->ci.bstream, level, 0,35);
   1206           if(err == BZ_OK)
   1207             zi->ci.stream_initialised = Z_BZIP2ED;
   1208 #endif
   1209         }
   1210 
   1211     }
   1212 
   1213 #    ifndef NOCRYPT
   1214     zi->ci.crypt_header_size = 0;
   1215     if ((err==Z_OK) && (password != NULL))
   1216     {
   1217         unsigned char bufHead[RAND_HEAD_LEN];
   1218         unsigned int sizeHead;
   1219         zi->ci.encrypt = 1;
   1220         zi->ci.pcrc_32_tab = get_crc_table();
   1221         /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
   1222 
   1223         sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
   1224         zi->ci.crypt_header_size = sizeHead;
   1225 
   1226         if (ZWRITE64(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
   1227                 err = ZIP_ERRNO;
   1228     }
   1229 #    endif
   1230 
   1231     if (err==Z_OK)
   1232         zi->in_opened_file_inzip = 1;
   1233     return err;
   1234 }
   1235 
   1236 extern int ZEXPORT zipOpenNewFileInZip4(zipFile file, const char* filename, const zip_fileinfo* zipfi,
   1237                                         const void* extrafield_local, uInt size_extrafield_local,
   1238                                         const void* extrafield_global, uInt size_extrafield_global,
   1239                                         const char* comment, int method, int level, int raw,
   1240                                         int windowBits,int memLevel, int strategy,
   1241                                         const char* password, uLong crcForCrypting,
   1242                                         uLong versionMadeBy, uLong flagBase) {
   1243     return zipOpenNewFileInZip4_64(file, filename, zipfi,
   1244                                    extrafield_local, size_extrafield_local,
   1245                                    extrafield_global, size_extrafield_global,
   1246                                    comment, method, level, raw,
   1247                                    windowBits, memLevel, strategy,
   1248                                    password, crcForCrypting, versionMadeBy, flagBase, 0);
   1249 }
   1250 
   1251 extern int ZEXPORT zipOpenNewFileInZip3(zipFile file, const char* filename, const zip_fileinfo* zipfi,
   1252                                         const void* extrafield_local, uInt size_extrafield_local,
   1253                                         const void* extrafield_global, uInt size_extrafield_global,
   1254                                         const char* comment, int method, int level, int raw,
   1255                                         int windowBits,int memLevel, int strategy,
   1256                                         const char* password, uLong crcForCrypting) {
   1257     return zipOpenNewFileInZip4_64(file, filename, zipfi,
   1258                                    extrafield_local, size_extrafield_local,
   1259                                    extrafield_global, size_extrafield_global,
   1260                                    comment, method, level, raw,
   1261                                    windowBits, memLevel, strategy,
   1262                                    password, crcForCrypting, VERSIONMADEBY, 0, 0);
   1263 }
   1264 
   1265 extern int ZEXPORT zipOpenNewFileInZip3_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
   1266                                          const void* extrafield_local, uInt size_extrafield_local,
   1267                                          const void* extrafield_global, uInt size_extrafield_global,
   1268                                          const char* comment, int method, int level, int raw,
   1269                                          int windowBits,int memLevel, int strategy,
   1270                                          const char* password, uLong crcForCrypting, int zip64) {
   1271     return zipOpenNewFileInZip4_64(file, filename, zipfi,
   1272                                    extrafield_local, size_extrafield_local,
   1273                                    extrafield_global, size_extrafield_global,
   1274                                    comment, method, level, raw,
   1275                                    windowBits, memLevel, strategy,
   1276                                    password, crcForCrypting, VERSIONMADEBY, 0, zip64);
   1277 }
   1278 
   1279 extern int ZEXPORT zipOpenNewFileInZip2(zipFile file, const char* filename, const zip_fileinfo* zipfi,
   1280                                         const void* extrafield_local, uInt size_extrafield_local,
   1281                                         const void* extrafield_global, uInt size_extrafield_global,
   1282                                         const char* comment, int method, int level, int raw) {
   1283     return zipOpenNewFileInZip4_64(file, filename, zipfi,
   1284                                    extrafield_local, size_extrafield_local,
   1285                                    extrafield_global, size_extrafield_global,
   1286                                    comment, method, level, raw,
   1287                                    -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
   1288                                    NULL, 0, VERSIONMADEBY, 0, 0);
   1289 }
   1290 
   1291 extern int ZEXPORT zipOpenNewFileInZip2_64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
   1292                                            const void* extrafield_local, uInt size_extrafield_local,
   1293                                            const void* extrafield_global, uInt size_extrafield_global,
   1294                                            const char* comment, int method, int level, int raw, int zip64) {
   1295     return zipOpenNewFileInZip4_64(file, filename, zipfi,
   1296                                    extrafield_local, size_extrafield_local,
   1297                                    extrafield_global, size_extrafield_global,
   1298                                    comment, method, level, raw,
   1299                                    -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
   1300                                    NULL, 0, VERSIONMADEBY, 0, zip64);
   1301 }
   1302 
   1303 extern int ZEXPORT zipOpenNewFileInZip64(zipFile file, const char* filename, const zip_fileinfo* zipfi,
   1304                                          const void* extrafield_local, uInt size_extrafield_local,
   1305                                          const void*extrafield_global, uInt size_extrafield_global,
   1306                                          const char* comment, int method, int level, int zip64) {
   1307     return zipOpenNewFileInZip4_64(file, filename, zipfi,
   1308                                    extrafield_local, size_extrafield_local,
   1309                                    extrafield_global, size_extrafield_global,
   1310                                    comment, method, level, 0,
   1311                                    -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
   1312                                    NULL, 0, VERSIONMADEBY, 0, zip64);
   1313 }
   1314 
   1315 extern int ZEXPORT zipOpenNewFileInZip(zipFile file, const char* filename, const zip_fileinfo* zipfi,
   1316                                        const void* extrafield_local, uInt size_extrafield_local,
   1317                                        const void*extrafield_global, uInt size_extrafield_global,
   1318                                        const char* comment, int method, int level) {
   1319     return zipOpenNewFileInZip4_64(file, filename, zipfi,
   1320                                    extrafield_local, size_extrafield_local,
   1321                                    extrafield_global, size_extrafield_global,
   1322                                    comment, method, level, 0,
   1323                                    -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
   1324                                    NULL, 0, VERSIONMADEBY, 0, 0);
   1325 }
   1326 
   1327 local int zip64FlushWriteBuffer(zip64_internal* zi) {
   1328     int err=ZIP_OK;
   1329 
   1330     if (zi->ci.encrypt != 0)
   1331     {
   1332 #ifndef NOCRYPT
   1333         uInt i;
   1334         int t;
   1335         for (i=0;i<zi->ci.pos_in_buffered_data;i++)
   1336             zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i],t);
   1337 #endif
   1338     }
   1339 
   1340     if (ZWRITE64(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data) != zi->ci.pos_in_buffered_data)
   1341       err = ZIP_ERRNO;
   1342 
   1343     zi->ci.totalCompressedData += zi->ci.pos_in_buffered_data;
   1344 
   1345 #ifdef HAVE_BZIP2
   1346     if(zi->ci.method == Z_BZIP2ED)
   1347     {
   1348       zi->ci.totalUncompressedData += zi->ci.bstream.total_in_lo32;
   1349       zi->ci.bstream.total_in_lo32 = 0;
   1350       zi->ci.bstream.total_in_hi32 = 0;
   1351     }
   1352     else
   1353 #endif
   1354     {
   1355       zi->ci.totalUncompressedData += zi->ci.stream.total_in;
   1356       zi->ci.stream.total_in = 0;
   1357     }
   1358 
   1359 
   1360     zi->ci.pos_in_buffered_data = 0;
   1361 
   1362     return err;
   1363 }
   1364 
   1365 extern int ZEXPORT zipWriteInFileInZip(zipFile file, const void* buf, unsigned int len) {
   1366     zip64_internal* zi;
   1367     int err=ZIP_OK;
   1368 
   1369     if (file == NULL)
   1370         return ZIP_PARAMERROR;
   1371     zi = (zip64_internal*)file;
   1372 
   1373     if (zi->in_opened_file_inzip == 0)
   1374         return ZIP_PARAMERROR;
   1375 
   1376     zi->ci.crc32 = crc32(zi->ci.crc32,buf,(uInt)len);
   1377 
   1378 #ifdef HAVE_BZIP2
   1379     if(zi->ci.method == Z_BZIP2ED && (!zi->ci.raw))
   1380     {
   1381       zi->ci.bstream.next_in = (void*)buf;
   1382       zi->ci.bstream.avail_in = len;
   1383       err = BZ_RUN_OK;
   1384 
   1385       while ((err==BZ_RUN_OK) && (zi->ci.bstream.avail_in>0))
   1386       {
   1387         if (zi->ci.bstream.avail_out == 0)
   1388         {
   1389           if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
   1390             err = ZIP_ERRNO;
   1391           zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
   1392           zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
   1393         }
   1394 
   1395 
   1396         if(err != BZ_RUN_OK)
   1397           break;
   1398 
   1399         if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
   1400         {
   1401           uLong uTotalOutBefore_lo = zi->ci.bstream.total_out_lo32;
   1402 //          uLong uTotalOutBefore_hi = zi->ci.bstream.total_out_hi32;
   1403           err=BZ2_bzCompress(&zi->ci.bstream,  BZ_RUN);
   1404 
   1405           zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore_lo) ;
   1406         }
   1407       }
   1408 
   1409       if(err == BZ_RUN_OK)
   1410         err = ZIP_OK;
   1411     }
   1412     else
   1413 #endif
   1414     {
   1415       zi->ci.stream.next_in = (Bytef*)(uintptr_t)buf;
   1416       zi->ci.stream.avail_in = len;
   1417 
   1418       while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
   1419       {
   1420           if (zi->ci.stream.avail_out == 0)
   1421           {
   1422               if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
   1423                   err = ZIP_ERRNO;
   1424               zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
   1425               zi->ci.stream.next_out = zi->ci.buffered_data;
   1426           }
   1427 
   1428 
   1429           if(err != ZIP_OK)
   1430               break;
   1431 
   1432           if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
   1433           {
   1434               uLong uTotalOutBefore = zi->ci.stream.total_out;
   1435               err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
   1436 
   1437               zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
   1438           }
   1439           else
   1440           {
   1441               uInt copy_this,i;
   1442               if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
   1443                   copy_this = zi->ci.stream.avail_in;
   1444               else
   1445                   copy_this = zi->ci.stream.avail_out;
   1446 
   1447               for (i = 0; i < copy_this; i++)
   1448                   *(((char*)zi->ci.stream.next_out)+i) =
   1449                       *(((const char*)zi->ci.stream.next_in)+i);
   1450               {
   1451                   zi->ci.stream.avail_in -= copy_this;
   1452                   zi->ci.stream.avail_out-= copy_this;
   1453                   zi->ci.stream.next_in+= copy_this;
   1454                   zi->ci.stream.next_out+= copy_this;
   1455                   zi->ci.stream.total_in+= copy_this;
   1456                   zi->ci.stream.total_out+= copy_this;
   1457                   zi->ci.pos_in_buffered_data += copy_this;
   1458               }
   1459           }
   1460       }// while(...)
   1461     }
   1462 
   1463     return err;
   1464 }
   1465 
   1466 extern int ZEXPORT zipCloseFileInZipRaw(zipFile file, uLong uncompressed_size, uLong crc32) {
   1467     return zipCloseFileInZipRaw64 (file, uncompressed_size, crc32);
   1468 }
   1469 
   1470 extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_size, uLong crc32) {
   1471     zip64_internal* zi;
   1472     ZPOS64_T compressed_size;
   1473     uLong invalidValue = 0xffffffff;
   1474     unsigned datasize = 0;
   1475     int err=ZIP_OK;
   1476 
   1477     if (file == NULL)
   1478         return ZIP_PARAMERROR;
   1479     zi = (zip64_internal*)file;
   1480 
   1481     if (zi->in_opened_file_inzip == 0)
   1482         return ZIP_PARAMERROR;
   1483     zi->ci.stream.avail_in = 0;
   1484 
   1485     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
   1486                 {
   1487                         while (err==ZIP_OK)
   1488                         {
   1489                                 uLong uTotalOutBefore;
   1490                                 if (zi->ci.stream.avail_out == 0)
   1491                                 {
   1492                                         if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
   1493                                                 err = ZIP_ERRNO;
   1494                                         zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
   1495                                         zi->ci.stream.next_out = zi->ci.buffered_data;
   1496                                 }
   1497                                 uTotalOutBefore = zi->ci.stream.total_out;
   1498                                 err=deflate(&zi->ci.stream,  Z_FINISH);
   1499                                 zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
   1500                         }
   1501                 }
   1502     else if ((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
   1503     {
   1504 #ifdef HAVE_BZIP2
   1505       err = BZ_FINISH_OK;
   1506       while (err==BZ_FINISH_OK)
   1507       {
   1508         uLong uTotalOutBefore;
   1509         if (zi->ci.bstream.avail_out == 0)
   1510         {
   1511           if (zip64FlushWriteBuffer(zi) == ZIP_ERRNO)
   1512             err = ZIP_ERRNO;
   1513           zi->ci.bstream.avail_out = (uInt)Z_BUFSIZE;
   1514           zi->ci.bstream.next_out = (char*)zi->ci.buffered_data;
   1515         }
   1516         uTotalOutBefore = zi->ci.bstream.total_out_lo32;
   1517         err=BZ2_bzCompress(&zi->ci.bstream,  BZ_FINISH);
   1518         if(err == BZ_STREAM_END)
   1519           err = Z_STREAM_END;
   1520 
   1521         zi->ci.pos_in_buffered_data += (uInt)(zi->ci.bstream.total_out_lo32 - uTotalOutBefore);
   1522       }
   1523 
   1524       if(err == BZ_FINISH_OK)
   1525         err = ZIP_OK;
   1526 #endif
   1527     }
   1528 
   1529     if (err==Z_STREAM_END)
   1530         err=ZIP_OK; /* this is normal */
   1531 
   1532     if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
   1533                 {
   1534         if (zip64FlushWriteBuffer(zi)==ZIP_ERRNO)
   1535             err = ZIP_ERRNO;
   1536                 }
   1537 
   1538     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
   1539     {
   1540         int tmp_err = deflateEnd(&zi->ci.stream);
   1541         if (err == ZIP_OK)
   1542             err = tmp_err;
   1543         zi->ci.stream_initialised = 0;
   1544     }
   1545 #ifdef HAVE_BZIP2
   1546     else if((zi->ci.method == Z_BZIP2ED) && (!zi->ci.raw))
   1547     {
   1548       int tmperr = BZ2_bzCompressEnd(&zi->ci.bstream);
   1549                         if (err==ZIP_OK)
   1550                                 err = tmperr;
   1551                         zi->ci.stream_initialised = 0;
   1552     }
   1553 #endif
   1554 
   1555     if (!zi->ci.raw)
   1556     {
   1557         crc32 = (uLong)zi->ci.crc32;
   1558         uncompressed_size = zi->ci.totalUncompressedData;
   1559     }
   1560     compressed_size = zi->ci.totalCompressedData;
   1561 
   1562 #    ifndef NOCRYPT
   1563     compressed_size += zi->ci.crypt_header_size;
   1564 #    endif
   1565 
   1566     // update Current Item crc and sizes,
   1567     if(compressed_size >= 0xffffffff || uncompressed_size >= 0xffffffff || zi->ci.pos_local_header >= 0xffffffff)
   1568     {
   1569       /*version Made by*/
   1570       zip64local_putValue_inmemory(zi->ci.central_header+4,(uLong)45,2);
   1571       /*version needed*/
   1572       zip64local_putValue_inmemory(zi->ci.central_header+6,(uLong)45,2);
   1573 
   1574     }
   1575 
   1576     zip64local_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
   1577 
   1578 
   1579     if(compressed_size >= 0xffffffff)
   1580       zip64local_putValue_inmemory(zi->ci.central_header+20, invalidValue,4); /*compr size*/
   1581     else
   1582       zip64local_putValue_inmemory(zi->ci.central_header+20, compressed_size,4); /*compr size*/
   1583 
   1584     /// set internal file attributes field
   1585     if (zi->ci.stream.data_type == Z_ASCII)
   1586         zip64local_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
   1587 
   1588     if(uncompressed_size >= 0xffffffff)
   1589       zip64local_putValue_inmemory(zi->ci.central_header+24, invalidValue,4); /*uncompr size*/
   1590     else
   1591       zip64local_putValue_inmemory(zi->ci.central_header+24, uncompressed_size,4); /*uncompr size*/
   1592 
   1593     // Add ZIP64 extra info field for uncompressed size
   1594     if(uncompressed_size >= 0xffffffff)
   1595       datasize += 8;
   1596 
   1597     // Add ZIP64 extra info field for compressed size
   1598     if(compressed_size >= 0xffffffff)
   1599       datasize += 8;
   1600 
   1601     // Add ZIP64 extra info field for relative offset to local file header of current file
   1602     if(zi->ci.pos_local_header >= 0xffffffff)
   1603       datasize += 8;
   1604 
   1605     if(datasize > 0)
   1606     {
   1607       char* p = NULL;
   1608 
   1609       if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
   1610       {
   1611         // we cannot write more data to the buffer that we have room for.
   1612         return ZIP_BADZIPFILE;
   1613       }
   1614 
   1615       p = zi->ci.central_header + zi->ci.size_centralheader;
   1616 
   1617       // Add Extra Information Header for 'ZIP64 information'
   1618       zip64local_putValue_inmemory(p, 0x0001, 2); // HeaderID
   1619       p += 2;
   1620       zip64local_putValue_inmemory(p, datasize, 2); // DataSize
   1621       p += 2;
   1622 
   1623       if(uncompressed_size >= 0xffffffff)
   1624       {
   1625         zip64local_putValue_inmemory(p, uncompressed_size, 8);
   1626         p += 8;
   1627       }
   1628 
   1629       if(compressed_size >= 0xffffffff)
   1630       {
   1631         zip64local_putValue_inmemory(p, compressed_size, 8);
   1632         p += 8;
   1633       }
   1634 
   1635       if(zi->ci.pos_local_header >= 0xffffffff)
   1636       {
   1637         zip64local_putValue_inmemory(p, zi->ci.pos_local_header, 8);
   1638         p += 8;
   1639       }
   1640 
   1641       // Update how much extra free space we got in the memory buffer
   1642       // and increase the centralheader size so the new ZIP64 fields are included
   1643       // ( 4 below is the size of HeaderID and DataSize field )
   1644       zi->ci.size_centralExtraFree -= datasize + 4;
   1645       zi->ci.size_centralheader += datasize + 4;
   1646 
   1647       // Update the extra info size field
   1648       zi->ci.size_centralExtra += datasize + 4;
   1649       zip64local_putValue_inmemory(zi->ci.central_header+30,(uLong)zi->ci.size_centralExtra,2);
   1650     }
   1651 
   1652     if (err==ZIP_OK)
   1653         err = add_data_in_datablock(&zi->central_dir, zi->ci.central_header, (uLong)zi->ci.size_centralheader);
   1654 
   1655     free(zi->ci.central_header);
   1656 
   1657     if (err==ZIP_OK)
   1658     {
   1659         // Update the LocalFileHeader with the new values.
   1660 
   1661         ZPOS64_T cur_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);
   1662 
   1663         if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
   1664             err = ZIP_ERRNO;
   1665 
   1666         if (err==ZIP_OK)
   1667             err = zip64local_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
   1668 
   1669         if(uncompressed_size >= 0xffffffff || compressed_size >= 0xffffffff )
   1670         {
   1671           if(zi->ci.pos_zip64extrainfo > 0)
   1672           {
   1673             // Update the size in the ZIP64 extended field.
   1674             if (ZSEEK64(zi->z_filefunc,zi->filestream, zi->ci.pos_zip64extrainfo + 4,ZLIB_FILEFUNC_SEEK_SET)!=0)
   1675               err = ZIP_ERRNO;
   1676 
   1677             if (err==ZIP_OK) /* compressed size, unknown */
   1678               err = zip64local_putValue(&zi->z_filefunc, zi->filestream, uncompressed_size, 8);
   1679 
   1680             if (err==ZIP_OK) /* uncompressed size, unknown */
   1681               err = zip64local_putValue(&zi->z_filefunc, zi->filestream, compressed_size, 8);
   1682           }
   1683           else
   1684               err = ZIP_BADZIPFILE; // Caller passed zip64 = 0, so no room for zip64 info -> fatal
   1685         }
   1686         else
   1687         {
   1688           if (err==ZIP_OK) /* compressed size, unknown */
   1689               err = zip64local_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
   1690 
   1691           if (err==ZIP_OK) /* uncompressed size, unknown */
   1692               err = zip64local_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
   1693         }
   1694 
   1695         if (ZSEEK64(zi->z_filefunc,zi->filestream, cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
   1696             err = ZIP_ERRNO;
   1697     }
   1698 
   1699     zi->number_entry ++;
   1700     zi->in_opened_file_inzip = 0;
   1701 
   1702     return err;
   1703 }
   1704 
   1705 extern int ZEXPORT zipCloseFileInZip(zipFile file) {
   1706     return zipCloseFileInZipRaw (file,0,0);
   1707 }
   1708 
   1709 local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip) {
   1710   int err = ZIP_OK;
   1711   ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset;
   1712 
   1713   err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDLOCHEADERMAGIC,4);
   1714 
   1715   /*num disks*/
   1716     if (err==ZIP_OK) /* number of the disk with the start of the central directory */
   1717       err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
   1718 
   1719   /*relative offset*/
   1720     if (err==ZIP_OK) /* Relative offset to the Zip64EndOfCentralDirectory */
   1721       err = zip64local_putValue(&zi->z_filefunc,zi->filestream, pos,8);
   1722 
   1723   /*total disks*/ /* Do not support spawning of disk so always say 1 here*/
   1724     if (err==ZIP_OK) /* number of the disk with the start of the central directory */
   1725       err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)1,4);
   1726 
   1727     return err;
   1728 }
   1729 
   1730 local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) {
   1731   int err = ZIP_OK;
   1732 
   1733   uLong Zip64DataSize = 44;
   1734 
   1735   err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ZIP64ENDHEADERMAGIC,4);
   1736 
   1737   if (err==ZIP_OK) /* size of this 'zip64 end of central directory' */
   1738     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)Zip64DataSize,8); // why ZPOS64_T of this ?
   1739 
   1740   if (err==ZIP_OK) /* version made by */
   1741     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
   1742 
   1743   if (err==ZIP_OK) /* version needed */
   1744     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)45,2);
   1745 
   1746   if (err==ZIP_OK) /* number of this disk */
   1747     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
   1748 
   1749   if (err==ZIP_OK) /* number of the disk with the start of the central directory */
   1750     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4);
   1751 
   1752   if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
   1753     err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
   1754 
   1755   if (err==ZIP_OK) /* total number of entries in the central dir */
   1756     err = zip64local_putValue(&zi->z_filefunc, zi->filestream, zi->number_entry, 8);
   1757 
   1758   if (err==ZIP_OK) /* size of the central directory */
   1759     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(ZPOS64_T)size_centraldir,8);
   1760 
   1761   if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
   1762   {
   1763     ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
   1764     err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (ZPOS64_T)pos,8);
   1765   }
   1766   return err;
   1767 }
   1768 
   1769 local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip) {
   1770   int err = ZIP_OK;
   1771 
   1772   /*signature*/
   1773   err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
   1774 
   1775   if (err==ZIP_OK) /* number of this disk */
   1776     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
   1777 
   1778   if (err==ZIP_OK) /* number of the disk with the start of the central directory */
   1779     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
   1780 
   1781   if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
   1782   {
   1783     {
   1784       if(zi->number_entry >= 0xFFFF)
   1785         err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record
   1786       else
   1787         err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
   1788     }
   1789   }
   1790 
   1791   if (err==ZIP_OK) /* total number of entries in the central dir */
   1792   {
   1793     if(zi->number_entry >= 0xFFFF)
   1794       err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)0xffff,2); // use value in ZIP64 record
   1795     else
   1796       err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
   1797   }
   1798 
   1799   if (err==ZIP_OK) /* size of the central directory */
   1800     err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
   1801 
   1802   if (err==ZIP_OK) /* offset of start of central directory with respect to the starting disk number */
   1803   {
   1804     ZPOS64_T pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
   1805     if(pos >= 0xffffffff)
   1806     {
   1807       err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)0xffffffff,4);
   1808     }
   1809     else
   1810       err = zip64local_putValue(&zi->z_filefunc,zi->filestream, (uLong)(centraldir_pos_inzip - zi->add_position_when_writing_offset),4);
   1811   }
   1812 
   1813    return err;
   1814 }
   1815 
   1816 local int Write_GlobalComment(zip64_internal* zi, const char* global_comment) {
   1817   int err = ZIP_OK;
   1818   uInt size_global_comment = 0;
   1819 
   1820   if(global_comment != NULL)
   1821     size_global_comment = (uInt)strlen(global_comment);
   1822 
   1823   err = zip64local_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
   1824 
   1825   if (err == ZIP_OK && size_global_comment > 0)
   1826   {
   1827     if (ZWRITE64(zi->z_filefunc,zi->filestream, global_comment, size_global_comment) != size_global_comment)
   1828       err = ZIP_ERRNO;
   1829   }
   1830   return err;
   1831 }
   1832 
   1833 extern int ZEXPORT zipClose(zipFile file, const char* global_comment) {
   1834     zip64_internal* zi;
   1835     int err = 0;
   1836     uLong size_centraldir = 0;
   1837     ZPOS64_T centraldir_pos_inzip;
   1838     ZPOS64_T pos;
   1839 
   1840     if (file == NULL)
   1841         return ZIP_PARAMERROR;
   1842 
   1843     zi = (zip64_internal*)file;
   1844 
   1845     if (zi->in_opened_file_inzip == 1)
   1846     {
   1847         err = zipCloseFileInZip (file);
   1848     }
   1849 
   1850 #ifndef NO_ADDFILEINEXISTINGZIP
   1851     if (global_comment==NULL)
   1852         global_comment = zi->globalcomment;
   1853 #endif
   1854 
   1855     centraldir_pos_inzip = ZTELL64(zi->z_filefunc,zi->filestream);
   1856 
   1857     if (err==ZIP_OK)
   1858     {
   1859         linkedlist_datablock_internal* ldi = zi->central_dir.first_block;
   1860         while (ldi!=NULL)
   1861         {
   1862             if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
   1863             {
   1864                 if (ZWRITE64(zi->z_filefunc,zi->filestream, ldi->data, ldi->filled_in_this_block) != ldi->filled_in_this_block)
   1865                     err = ZIP_ERRNO;
   1866             }
   1867 
   1868             size_centraldir += ldi->filled_in_this_block;
   1869             ldi = ldi->next_datablock;
   1870         }
   1871     }
   1872     free_linkedlist(&(zi->central_dir));
   1873 
   1874     pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
   1875     if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF)
   1876     {
   1877       ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
   1878       Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
   1879 
   1880       Write_Zip64EndOfCentralDirectoryLocator(zi, Zip64EOCDpos);
   1881     }
   1882 
   1883     if (err==ZIP_OK)
   1884       err = Write_EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
   1885 
   1886     if(err == ZIP_OK)
   1887       err = Write_GlobalComment(zi, global_comment);
   1888 
   1889     if (ZCLOSE64(zi->z_filefunc,zi->filestream) != 0)
   1890         if (err == ZIP_OK)
   1891             err = ZIP_ERRNO;
   1892 
   1893 #ifndef NO_ADDFILEINEXISTINGZIP
   1894     free(zi->globalcomment);
   1895 #endif
   1896     free(zi);
   1897 
   1898     return err;
   1899 }
   1900 
   1901 extern int ZEXPORT zipRemoveExtraInfoBlock(char* pData, int* dataLen, short sHeader) {
   1902   char* p = pData;
   1903   int size = 0;
   1904   char* pNewHeader;
   1905   char* pTmp;
   1906   short header;
   1907   short dataSize;
   1908 
   1909   int retVal = ZIP_OK;
   1910 
   1911   if(pData == NULL || dataLen == NULL || *dataLen < 4)
   1912     return ZIP_PARAMERROR;
   1913 
   1914   pNewHeader = (char*)ALLOC((unsigned)*dataLen);
   1915   pTmp = pNewHeader;
   1916 
   1917   while(p < (pData + *dataLen))
   1918   {
   1919     header = *(short*)p;
   1920     dataSize = *(((short*)p)+1);
   1921 
   1922     if( header == sHeader ) // Header found.
   1923     {
   1924       p += dataSize + 4; // skip it. do not copy to temp buffer
   1925     }
   1926     else
   1927     {
   1928       // Extra Info block should not be removed, So copy it to the temp buffer.
   1929       memcpy(pTmp, p, dataSize + 4);
   1930       p += dataSize + 4;
   1931       size += dataSize + 4;
   1932     }
   1933 
   1934   }
   1935 
   1936   if(size < *dataLen)
   1937   {
   1938     // clean old extra info block.
   1939     memset(pData,0, *dataLen);
   1940 
   1941     // copy the new extra info block over the old
   1942     if(size > 0)
   1943       memcpy(pData, pNewHeader, size);
   1944 
   1945     // set the new extra info size
   1946     *dataLen = size;
   1947 
   1948     retVal = ZIP_OK;
   1949   }
   1950   else
   1951     retVal = ZIP_ERRNO;
   1952 
   1953   free(pNewHeader);
   1954 
   1955   return retVal;
   1956 }
   1957