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