Home | History | Annotate | Download | only in minizip
      1 /* zip.c -- IO on .zip files using zlib
      2    Version 1.01e, February 12th, 2005
      3 
      4    27 Dec 2004 Rolf Kalbermatter
      5    Modification to zipOpen2 to support globalComment retrieval.
      6 
      7    Copyright (C) 1998-2005 Gilles Vollant
      8 
      9    Read zip.h for more info
     10 */
     11 
     12 
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 #include <time.h>
     17 #if defined(USE_SYSTEM_ZLIB)
     18 #include <zlib.h>
     19 #else
     20 #include "third_party/zlib/zlib.h"
     21 #endif
     22 #include "zip.h"
     23 
     24 #ifdef STDC
     25 #  include <stddef.h>
     26 #  include <string.h>
     27 #  include <stdlib.h>
     28 #endif
     29 #ifdef NO_ERRNO_H
     30     extern int errno;
     31 #else
     32 #   include <errno.h>
     33 #endif
     34 
     35 
     36 #ifndef local
     37 #  define local static
     38 #endif
     39 /* compile with -Dlocal if your debugger can't find static symbols */
     40 
     41 #ifndef VERSIONMADEBY
     42 # define VERSIONMADEBY   (0x0) /* platform depedent */
     43 #endif
     44 
     45 #ifndef Z_BUFSIZE
     46 #define Z_BUFSIZE (16384)
     47 #endif
     48 
     49 #ifndef Z_MAXFILENAMEINZIP
     50 #define Z_MAXFILENAMEINZIP (256)
     51 #endif
     52 
     53 #ifndef ALLOC
     54 # define ALLOC(size) (malloc(size))
     55 #endif
     56 #ifndef TRYFREE
     57 # define TRYFREE(p) {if (p) free(p);}
     58 #endif
     59 
     60 /*
     61 #define SIZECENTRALDIRITEM (0x2e)
     62 #define SIZEZIPLOCALHEADER (0x1e)
     63 */
     64 
     65 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
     66 
     67 #ifndef SEEK_CUR
     68 #define SEEK_CUR    1
     69 #endif
     70 
     71 #ifndef SEEK_END
     72 #define SEEK_END    2
     73 #endif
     74 
     75 #ifndef SEEK_SET
     76 #define SEEK_SET    0
     77 #endif
     78 
     79 #ifndef DEF_MEM_LEVEL
     80 #if MAX_MEM_LEVEL >= 8
     81 #  define DEF_MEM_LEVEL 8
     82 #else
     83 #  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
     84 #endif
     85 #endif
     86 const char zip_copyright[] =
     87    " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
     88 
     89 
     90 #define SIZEDATA_INDATABLOCK (4096-(4*4))
     91 
     92 #define LOCALHEADERMAGIC    (0x04034b50)
     93 #define CENTRALHEADERMAGIC  (0x02014b50)
     94 #define ENDHEADERMAGIC      (0x06054b50)
     95 
     96 #define FLAG_LOCALHEADER_OFFSET (0x06)
     97 #define CRC_LOCALHEADER_OFFSET  (0x0e)
     98 
     99 #define SIZECENTRALHEADER (0x2e) /* 46 */
    100 
    101 typedef struct linkedlist_datablock_internal_s
    102 {
    103   struct linkedlist_datablock_internal_s* next_datablock;
    104   uLong  avail_in_this_block;
    105   uLong  filled_in_this_block;
    106   uLong  unused; /* for future use and alignement */
    107   unsigned char data[SIZEDATA_INDATABLOCK];
    108 } linkedlist_datablock_internal;
    109 
    110 typedef struct linkedlist_data_s
    111 {
    112     linkedlist_datablock_internal* first_block;
    113     linkedlist_datablock_internal* last_block;
    114 } linkedlist_data;
    115 
    116 
    117 typedef struct
    118 {
    119     z_stream stream;            /* zLib stream structure for inflate */
    120     int  stream_initialised;    /* 1 is stream is initialised */
    121     uInt pos_in_buffered_data;  /* last written byte in buffered_data */
    122 
    123     uLong pos_local_header;     /* offset of the local header of the file
    124                                      currenty writing */
    125     char* central_header;       /* central header data for the current file */
    126     uLong size_centralheader;   /* size of the central header for cur file */
    127     uLong flag;                 /* flag of the file currently writing */
    128 
    129     int  method;                /* compression method of file currenty wr.*/
    130     int  raw;                   /* 1 for directly writing raw data */
    131     Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
    132     uLong dosDate;
    133     uLong crc32;
    134     int  encrypt;
    135 #ifndef NOCRYPT
    136     unsigned long keys[3];     /* keys defining the pseudo-random sequence */
    137     const unsigned long* pcrc_32_tab;
    138     int crypt_header_size;
    139 #endif
    140 } curfile_info;
    141 
    142 typedef struct
    143 {
    144     zlib_filefunc_def z_filefunc;
    145     voidpf filestream;        /* io structore of the zipfile */
    146     linkedlist_data central_dir;/* datablock with central dir in construction*/
    147     int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
    148     curfile_info ci;            /* info on the file curretly writing */
    149 
    150     uLong begin_pos;            /* position of the beginning of the zipfile */
    151     uLong add_position_when_writting_offset;
    152     uLong number_entry;
    153 #ifndef NO_ADDFILEINEXISTINGZIP
    154     char *globalcomment;
    155 #endif
    156 } zip_internal;
    157 
    158 
    159 
    160 #ifndef NOCRYPT
    161 #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
    162 #include "crypt.h"
    163 #endif
    164 
    165 local linkedlist_datablock_internal* allocate_new_datablock()
    166 {
    167     linkedlist_datablock_internal* ldi;
    168     ldi = (linkedlist_datablock_internal*)
    169                  ALLOC(sizeof(linkedlist_datablock_internal));
    170     if (ldi!=NULL)
    171     {
    172         ldi->next_datablock = NULL ;
    173         ldi->filled_in_this_block = 0 ;
    174         ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
    175     }
    176     return ldi;
    177 }
    178 
    179 local void free_datablock(ldi)
    180     linkedlist_datablock_internal* ldi;
    181 {
    182     while (ldi!=NULL)
    183     {
    184         linkedlist_datablock_internal* ldinext = ldi->next_datablock;
    185         TRYFREE(ldi);
    186         ldi = ldinext;
    187     }
    188 }
    189 
    190 local void init_linkedlist(ll)
    191     linkedlist_data* ll;
    192 {
    193     ll->first_block = ll->last_block = NULL;
    194 }
    195 
    196 local void free_linkedlist(ll)
    197     linkedlist_data* ll;
    198 {
    199     free_datablock(ll->first_block);
    200     ll->first_block = ll->last_block = NULL;
    201 }
    202 
    203 
    204 local int add_data_in_datablock(ll,buf,len)
    205     linkedlist_data* ll;
    206     const void* buf;
    207     uLong len;
    208 {
    209     linkedlist_datablock_internal* ldi;
    210     const unsigned char* from_copy;
    211 
    212     if (ll==NULL)
    213         return ZIP_INTERNALERROR;
    214 
    215     if (ll->last_block == NULL)
    216     {
    217         ll->first_block = ll->last_block = allocate_new_datablock();
    218         if (ll->first_block == NULL)
    219             return ZIP_INTERNALERROR;
    220     }
    221 
    222     ldi = ll->last_block;
    223     from_copy = (unsigned char*)buf;
    224 
    225     while (len>0)
    226     {
    227         uInt copy_this;
    228         uInt i;
    229         unsigned char* to_copy;
    230 
    231         if (ldi->avail_in_this_block==0)
    232         {
    233             ldi->next_datablock = allocate_new_datablock();
    234             if (ldi->next_datablock == NULL)
    235                 return ZIP_INTERNALERROR;
    236             ldi = ldi->next_datablock ;
    237             ll->last_block = ldi;
    238         }
    239 
    240         if (ldi->avail_in_this_block < len)
    241             copy_this = (uInt)ldi->avail_in_this_block;
    242         else
    243             copy_this = (uInt)len;
    244 
    245         to_copy = &(ldi->data[ldi->filled_in_this_block]);
    246 
    247         for (i=0;i<copy_this;i++)
    248             *(to_copy+i)=*(from_copy+i);
    249 
    250         ldi->filled_in_this_block += copy_this;
    251         ldi->avail_in_this_block -= copy_this;
    252         from_copy += copy_this ;
    253         len -= copy_this;
    254     }
    255     return ZIP_OK;
    256 }
    257 
    258 
    259 
    260 /****************************************************************************/
    261 
    262 #ifndef NO_ADDFILEINEXISTINGZIP
    263 /* ===========================================================================
    264    Inputs a long in LSB order to the given file
    265    nbByte == 1, 2 or 4 (byte, short or long)
    266 */
    267 
    268 local int ziplocal_putValue OF((const zlib_filefunc_def* pzlib_filefunc_def,
    269                                 voidpf filestream, uLong x, int nbByte));
    270 local int ziplocal_putValue (pzlib_filefunc_def, filestream, x, nbByte)
    271     const zlib_filefunc_def* pzlib_filefunc_def;
    272     voidpf filestream;
    273     uLong x;
    274     int nbByte;
    275 {
    276     unsigned char buf[4];
    277     int n;
    278     for (n = 0; n < nbByte; n++)
    279     {
    280         buf[n] = (unsigned char)(x & 0xff);
    281         x >>= 8;
    282     }
    283     if (x != 0)
    284       {     /* data overflow - hack for ZIP64 (X Roche) */
    285       for (n = 0; n < nbByte; n++)
    286         {
    287           buf[n] = 0xff;
    288         }
    289       }
    290 
    291     if (ZWRITE(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
    292         return ZIP_ERRNO;
    293     else
    294         return ZIP_OK;
    295 }
    296 
    297 local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
    298 local void ziplocal_putValue_inmemory (dest, x, nbByte)
    299     void* dest;
    300     uLong x;
    301     int nbByte;
    302 {
    303     unsigned char* buf=(unsigned char*)dest;
    304     int n;
    305     for (n = 0; n < nbByte; n++) {
    306         buf[n] = (unsigned char)(x & 0xff);
    307         x >>= 8;
    308     }
    309 
    310     if (x != 0)
    311     {     /* data overflow - hack for ZIP64 */
    312        for (n = 0; n < nbByte; n++)
    313        {
    314           buf[n] = 0xff;
    315        }
    316     }
    317 }
    318 
    319 /****************************************************************************/
    320 
    321 
    322 local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
    323     const tm_zip* ptm;
    324     uLong dosDate;
    325 {
    326     uLong year = (uLong)ptm->tm_year;
    327     if (year>1980)
    328         year-=1980;
    329     else if (year>80)
    330         year-=80;
    331     return
    332       (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
    333         ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
    334 }
    335 
    336 
    337 /****************************************************************************/
    338 
    339 local int ziplocal_getByte OF((
    340     const zlib_filefunc_def* pzlib_filefunc_def,
    341     voidpf filestream,
    342     int *pi));
    343 
    344 local int ziplocal_getByte(pzlib_filefunc_def,filestream,pi)
    345     const zlib_filefunc_def* pzlib_filefunc_def;
    346     voidpf filestream;
    347     int *pi;
    348 {
    349     unsigned char c;
    350     int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1);
    351     if (err==1)
    352     {
    353         *pi = (int)c;
    354         return ZIP_OK;
    355     }
    356     else
    357     {
    358         if (ZERROR(*pzlib_filefunc_def,filestream))
    359             return ZIP_ERRNO;
    360         else
    361             return ZIP_EOF;
    362     }
    363 }
    364 
    365 
    366 /* ===========================================================================
    367    Reads a long in LSB order from the given gz_stream. Sets
    368 */
    369 local int ziplocal_getShort OF((
    370     const zlib_filefunc_def* pzlib_filefunc_def,
    371     voidpf filestream,
    372     uLong *pX));
    373 
    374 local int ziplocal_getShort (pzlib_filefunc_def,filestream,pX)
    375     const zlib_filefunc_def* pzlib_filefunc_def;
    376     voidpf filestream;
    377     uLong *pX;
    378 {
    379     uLong x ;
    380     int i;
    381     int err;
    382 
    383     err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
    384     x = (uLong)i;
    385 
    386     if (err==ZIP_OK)
    387         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
    388     x += ((uLong)i)<<8;
    389 
    390     if (err==ZIP_OK)
    391         *pX = x;
    392     else
    393         *pX = 0;
    394     return err;
    395 }
    396 
    397 local int ziplocal_getLong OF((
    398     const zlib_filefunc_def* pzlib_filefunc_def,
    399     voidpf filestream,
    400     uLong *pX));
    401 
    402 local int ziplocal_getLong (pzlib_filefunc_def,filestream,pX)
    403     const zlib_filefunc_def* pzlib_filefunc_def;
    404     voidpf filestream;
    405     uLong *pX;
    406 {
    407     uLong x ;
    408     int i;
    409     int err;
    410 
    411     err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
    412     x = (uLong)i;
    413 
    414     if (err==ZIP_OK)
    415         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
    416     x += ((uLong)i)<<8;
    417 
    418     if (err==ZIP_OK)
    419         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
    420     x += ((uLong)i)<<16;
    421 
    422     if (err==ZIP_OK)
    423         err = ziplocal_getByte(pzlib_filefunc_def,filestream,&i);
    424     x += ((uLong)i)<<24;
    425 
    426     if (err==ZIP_OK)
    427         *pX = x;
    428     else
    429         *pX = 0;
    430     return err;
    431 }
    432 
    433 #ifndef BUFREADCOMMENT
    434 #define BUFREADCOMMENT (0x400)
    435 #endif
    436 /*
    437   Locate the Central directory of a zipfile (at the end, just before
    438     the global comment)
    439 */
    440 local uLong ziplocal_SearchCentralDir OF((
    441     const zlib_filefunc_def* pzlib_filefunc_def,
    442     voidpf filestream));
    443 
    444 local uLong ziplocal_SearchCentralDir(pzlib_filefunc_def,filestream)
    445     const zlib_filefunc_def* pzlib_filefunc_def;
    446     voidpf filestream;
    447 {
    448     unsigned char* buf;
    449     uLong uSizeFile;
    450     uLong uBackRead;
    451     uLong uMaxBack=0xffff; /* maximum size of global comment */
    452     uLong uPosFound=0;
    453 
    454     if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
    455         return 0;
    456 
    457 
    458     uSizeFile = ZTELL(*pzlib_filefunc_def,filestream);
    459 
    460     if (uMaxBack>uSizeFile)
    461         uMaxBack = uSizeFile;
    462 
    463     buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    464     if (buf==NULL)
    465         return 0;
    466 
    467     uBackRead = 4;
    468     while (uBackRead<uMaxBack)
    469     {
    470         uLong uReadSize,uReadPos ;
    471         int i;
    472         if (uBackRead+BUFREADCOMMENT>uMaxBack)
    473             uBackRead = uMaxBack;
    474         else
    475             uBackRead+=BUFREADCOMMENT;
    476         uReadPos = uSizeFile-uBackRead ;
    477 
    478         uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
    479                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
    480         if (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    481             break;
    482 
    483         if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
    484             break;
    485 
    486         for (i=(int)uReadSize-3; (i--)>0;)
    487             if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
    488                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
    489             {
    490                 uPosFound = uReadPos+i;
    491                 break;
    492             }
    493 
    494         if (uPosFound!=0)
    495             break;
    496     }
    497     TRYFREE(buf);
    498     return uPosFound;
    499 }
    500 #endif /* !NO_ADDFILEINEXISTINGZIP*/
    501 
    502 /************************************************************/
    503 extern zipFile ZEXPORT zipOpen2 (pathname, append, globalcomment, pzlib_filefunc_def)
    504     const char *pathname;
    505     int append;
    506     zipcharpc* globalcomment;
    507     zlib_filefunc_def* pzlib_filefunc_def;
    508 {
    509     zip_internal ziinit;
    510     zip_internal* zi;
    511     int err=ZIP_OK;
    512 
    513 
    514     if (pzlib_filefunc_def==NULL)
    515         fill_fopen_filefunc(&ziinit.z_filefunc);
    516     else
    517         ziinit.z_filefunc = *pzlib_filefunc_def;
    518 
    519     ziinit.filestream = (*(ziinit.z_filefunc.zopen_file))
    520                  (ziinit.z_filefunc.opaque,
    521                   pathname,
    522                   (append == APPEND_STATUS_CREATE) ?
    523                   (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) :
    524                     (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING));
    525 
    526     if (ziinit.filestream == NULL)
    527         return NULL;
    528     ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream);
    529     ziinit.in_opened_file_inzip = 0;
    530     ziinit.ci.stream_initialised = 0;
    531     ziinit.number_entry = 0;
    532     ziinit.add_position_when_writting_offset = 0;
    533     init_linkedlist(&(ziinit.central_dir));
    534 
    535 
    536     zi = (zip_internal*)ALLOC(sizeof(zip_internal));
    537     if (zi==NULL)
    538     {
    539         ZCLOSE(ziinit.z_filefunc,ziinit.filestream);
    540         return NULL;
    541     }
    542 
    543     /* now we add file in a zipfile */
    544 #    ifndef NO_ADDFILEINEXISTINGZIP
    545     ziinit.globalcomment = NULL;
    546     if (append == APPEND_STATUS_ADDINZIP)
    547     {
    548         uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
    549 
    550         uLong size_central_dir;     /* size of the central directory  */
    551         uLong offset_central_dir;   /* offset of start of central directory */
    552         uLong central_pos,uL;
    553 
    554         uLong number_disk;          /* number of the current dist, used for
    555                                     spaning ZIP, unsupported, always 0*/
    556         uLong number_disk_with_CD;  /* number the the disk with central dir, used
    557                                     for spaning ZIP, unsupported, always 0*/
    558         uLong number_entry;
    559         uLong number_entry_CD;      /* total number of entries in
    560                                     the central dir
    561                                     (same than number_entry on nospan) */
    562         uLong size_comment;
    563 
    564         central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream);
    565         if (central_pos==0)
    566             err=ZIP_ERRNO;
    567 
    568         if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
    569                                         central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
    570             err=ZIP_ERRNO;
    571 
    572         /* the signature, already checked */
    573         if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK)
    574             err=ZIP_ERRNO;
    575 
    576         /* number of this disk */
    577         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK)
    578             err=ZIP_ERRNO;
    579 
    580         /* number of the disk with the start of the central directory */
    581         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK)
    582             err=ZIP_ERRNO;
    583 
    584         /* total number of entries in the central dir on this disk */
    585         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK)
    586             err=ZIP_ERRNO;
    587 
    588         /* total number of entries in the central dir */
    589         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK)
    590             err=ZIP_ERRNO;
    591 
    592         if ((number_entry_CD!=number_entry) ||
    593             (number_disk_with_CD!=0) ||
    594             (number_disk!=0))
    595             err=ZIP_BADZIPFILE;
    596 
    597         /* size of the central directory */
    598         if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK)
    599             err=ZIP_ERRNO;
    600 
    601         /* offset of start of central directory with respect to the
    602             starting disk number */
    603         if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK)
    604             err=ZIP_ERRNO;
    605 
    606         /* zipfile global comment length */
    607         if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK)
    608             err=ZIP_ERRNO;
    609 
    610         if ((central_pos<offset_central_dir+size_central_dir) &&
    611             (err==ZIP_OK))
    612             err=ZIP_BADZIPFILE;
    613 
    614         if (err!=ZIP_OK)
    615         {
    616             ZCLOSE(ziinit.z_filefunc, ziinit.filestream);
    617             return NULL;
    618         }
    619 
    620         if (size_comment>0)
    621         {
    622             ziinit.globalcomment = ALLOC(size_comment+1);
    623             if (ziinit.globalcomment)
    624             {
    625                size_comment = ZREAD(ziinit.z_filefunc, ziinit.filestream,ziinit.globalcomment,size_comment);
    626                ziinit.globalcomment[size_comment]=0;
    627             }
    628         }
    629 
    630         byte_before_the_zipfile = central_pos -
    631                                 (offset_central_dir+size_central_dir);
    632         ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
    633 
    634         {
    635             uLong size_central_dir_to_read = size_central_dir;
    636             size_t buf_size = SIZEDATA_INDATABLOCK;
    637             void* buf_read = (void*)ALLOC(buf_size);
    638             if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
    639                   offset_central_dir + byte_before_the_zipfile,
    640                   ZLIB_FILEFUNC_SEEK_SET) != 0)
    641                   err=ZIP_ERRNO;
    642 
    643             while ((size_central_dir_to_read>0) && (err==ZIP_OK))
    644             {
    645                 uLong read_this = SIZEDATA_INDATABLOCK;
    646                 if (read_this > size_central_dir_to_read)
    647                     read_this = size_central_dir_to_read;
    648                 if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this)
    649                     err=ZIP_ERRNO;
    650 
    651                 if (err==ZIP_OK)
    652                     err = add_data_in_datablock(&ziinit.central_dir,buf_read,
    653                                                 (uLong)read_this);
    654                 size_central_dir_to_read-=read_this;
    655             }
    656             TRYFREE(buf_read);
    657         }
    658         ziinit.begin_pos = byte_before_the_zipfile;
    659         ziinit.number_entry = number_entry_CD;
    660 
    661         if (ZSEEK(ziinit.z_filefunc, ziinit.filestream,
    662                   offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
    663             err=ZIP_ERRNO;
    664     }
    665 
    666     if (globalcomment)
    667     {
    668       *globalcomment = ziinit.globalcomment;
    669     }
    670 #    endif /* !NO_ADDFILEINEXISTINGZIP*/
    671 
    672     if (err != ZIP_OK)
    673     {
    674 #    ifndef NO_ADDFILEINEXISTINGZIP
    675         TRYFREE(ziinit.globalcomment);
    676 #    endif /* !NO_ADDFILEINEXISTINGZIP*/
    677         TRYFREE(zi);
    678         return NULL;
    679     }
    680     else
    681     {
    682         *zi = ziinit;
    683         return (zipFile)zi;
    684     }
    685 }
    686 
    687 extern zipFile ZEXPORT zipOpen (pathname, append)
    688     const char *pathname;
    689     int append;
    690 {
    691     return zipOpen2(pathname,append,NULL,NULL);
    692 }
    693 
    694 extern int ZEXPORT zipOpenNewFileInZip3 (file, filename, zipfi,
    695                                          extrafield_local, size_extrafield_local,
    696                                          extrafield_global, size_extrafield_global,
    697                                          comment, method, level, raw,
    698                                          windowBits, memLevel, strategy,
    699                                          password, crcForCrypting)
    700     zipFile file;
    701     const char* filename;
    702     const zip_fileinfo* zipfi;
    703     const void* extrafield_local;
    704     uInt size_extrafield_local;
    705     const void* extrafield_global;
    706     uInt size_extrafield_global;
    707     const char* comment;
    708     int method;
    709     int level;
    710     int raw;
    711     int windowBits;
    712     int memLevel;
    713     int strategy;
    714     const char* password;
    715     uLong crcForCrypting;
    716 {
    717     zip_internal* zi;
    718     uInt size_filename;
    719     uInt size_comment;
    720     uInt i;
    721     int err = ZIP_OK;
    722 
    723 #    ifdef NOCRYPT
    724     if (password != NULL)
    725         return ZIP_PARAMERROR;
    726 #    endif
    727 
    728     if (file == NULL)
    729         return ZIP_PARAMERROR;
    730     if ((method!=0) && (method!=Z_DEFLATED))
    731         return ZIP_PARAMERROR;
    732 
    733     zi = (zip_internal*)file;
    734 
    735     if (zi->in_opened_file_inzip == 1)
    736     {
    737         err = zipCloseFileInZip (file);
    738         if (err != ZIP_OK)
    739             return err;
    740     }
    741 
    742 
    743     if (filename==NULL)
    744         filename="-";
    745 
    746     if (comment==NULL)
    747         size_comment = 0;
    748     else
    749         size_comment = (uInt)strlen(comment);
    750 
    751     size_filename = (uInt)strlen(filename);
    752 
    753     if (zipfi == NULL)
    754         zi->ci.dosDate = 0;
    755     else
    756     {
    757         if (zipfi->dosDate != 0)
    758             zi->ci.dosDate = zipfi->dosDate;
    759         else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
    760     }
    761 
    762     zi->ci.flag = 0;
    763     if ((level==8) || (level==9))
    764       zi->ci.flag |= 2;
    765     if ((level==2))
    766       zi->ci.flag |= 4;
    767     if ((level==1))
    768       zi->ci.flag |= 6;
    769     if (password != NULL)
    770       zi->ci.flag |= 1;
    771 
    772     zi->ci.crc32 = 0;
    773     zi->ci.method = method;
    774     zi->ci.encrypt = 0;
    775     zi->ci.stream_initialised = 0;
    776     zi->ci.pos_in_buffered_data = 0;
    777     zi->ci.raw = raw;
    778     zi->ci.pos_local_header = ZTELL(zi->z_filefunc,zi->filestream) ;
    779     zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename +
    780                                       size_extrafield_global + size_comment;
    781     zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
    782 
    783     ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
    784     /* version info */
    785     ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
    786     ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
    787     ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
    788     ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
    789     ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
    790     ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
    791     ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
    792     ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
    793     ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
    794     ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
    795     ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
    796     ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
    797 
    798     if (zipfi==NULL)
    799         ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2);
    800     else
    801         ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2);
    802 
    803     if (zipfi==NULL)
    804         ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4);
    805     else
    806         ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
    807 
    808     ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header- zi->add_position_when_writting_offset,4);
    809 
    810     for (i=0;i<size_filename;i++)
    811         *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
    812 
    813     for (i=0;i<size_extrafield_global;i++)
    814         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
    815               *(((const char*)extrafield_global)+i);
    816 
    817     for (i=0;i<size_comment;i++)
    818         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
    819               size_extrafield_global+i) = *(comment+i);
    820     if (zi->ci.central_header == NULL)
    821         return ZIP_INTERNALERROR;
    822 
    823     /* write the local header */
    824     err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)LOCALHEADERMAGIC,4);
    825 
    826     if (err==ZIP_OK)
    827         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)20,2);/* version needed to extract */
    828     if (err==ZIP_OK)
    829         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.flag,2);
    830 
    831     if (err==ZIP_OK)
    832         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.method,2);
    833 
    834     if (err==ZIP_OK)
    835         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->ci.dosDate,4);
    836 
    837     if (err==ZIP_OK)
    838         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* crc 32, unknown */
    839     if (err==ZIP_OK)
    840         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* compressed size, unknown */
    841     if (err==ZIP_OK)
    842         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,4); /* uncompressed size, unknown */
    843 
    844     if (err==ZIP_OK)
    845         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_filename,2);
    846 
    847     if (err==ZIP_OK)
    848         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_extrafield_local,2);
    849 
    850     if ((err==ZIP_OK) && (size_filename>0))
    851         if (ZWRITE(zi->z_filefunc,zi->filestream,filename,size_filename)!=size_filename)
    852                 err = ZIP_ERRNO;
    853 
    854     if ((err==ZIP_OK) && (size_extrafield_local>0))
    855         if (ZWRITE(zi->z_filefunc,zi->filestream,extrafield_local,size_extrafield_local)
    856                                                                            !=size_extrafield_local)
    857                 err = ZIP_ERRNO;
    858 
    859     zi->ci.stream.avail_in = (uInt)0;
    860     zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
    861     zi->ci.stream.next_out = zi->ci.buffered_data;
    862     zi->ci.stream.total_in = 0;
    863     zi->ci.stream.total_out = 0;
    864 
    865     if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
    866     {
    867         zi->ci.stream.zalloc = (alloc_func)0;
    868         zi->ci.stream.zfree = (free_func)0;
    869         zi->ci.stream.opaque = (voidpf)0;
    870 
    871         if (windowBits>0)
    872             windowBits = -windowBits;
    873 
    874         err = deflateInit2(&zi->ci.stream, level,
    875                Z_DEFLATED, windowBits, memLevel, strategy);
    876 
    877         if (err==Z_OK)
    878             zi->ci.stream_initialised = 1;
    879     }
    880 #    ifndef NOCRYPT
    881     zi->ci.crypt_header_size = 0;
    882     if ((err==Z_OK) && (password != NULL))
    883     {
    884         unsigned char bufHead[RAND_HEAD_LEN];
    885         unsigned int sizeHead;
    886         zi->ci.encrypt = 1;
    887         zi->ci.pcrc_32_tab = get_crc_table();
    888         /*init_keys(password,zi->ci.keys,zi->ci.pcrc_32_tab);*/
    889 
    890         sizeHead=crypthead(password,bufHead,RAND_HEAD_LEN,zi->ci.keys,zi->ci.pcrc_32_tab,crcForCrypting);
    891         zi->ci.crypt_header_size = sizeHead;
    892 
    893         if (ZWRITE(zi->z_filefunc,zi->filestream,bufHead,sizeHead) != sizeHead)
    894                 err = ZIP_ERRNO;
    895     }
    896 #    endif
    897 
    898     if (err==Z_OK)
    899         zi->in_opened_file_inzip = 1;
    900     return err;
    901 }
    902 
    903 extern int ZEXPORT zipOpenNewFileInZip2(file, filename, zipfi,
    904                                         extrafield_local, size_extrafield_local,
    905                                         extrafield_global, size_extrafield_global,
    906                                         comment, method, level, raw)
    907     zipFile file;
    908     const char* filename;
    909     const zip_fileinfo* zipfi;
    910     const void* extrafield_local;
    911     uInt size_extrafield_local;
    912     const void* extrafield_global;
    913     uInt size_extrafield_global;
    914     const char* comment;
    915     int method;
    916     int level;
    917     int raw;
    918 {
    919     return zipOpenNewFileInZip3 (file, filename, zipfi,
    920                                  extrafield_local, size_extrafield_local,
    921                                  extrafield_global, size_extrafield_global,
    922                                  comment, method, level, raw,
    923                                  -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
    924                                  NULL, 0);
    925 }
    926 
    927 extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi,
    928                                         extrafield_local, size_extrafield_local,
    929                                         extrafield_global, size_extrafield_global,
    930                                         comment, method, level)
    931     zipFile file;
    932     const char* filename;
    933     const zip_fileinfo* zipfi;
    934     const void* extrafield_local;
    935     uInt size_extrafield_local;
    936     const void* extrafield_global;
    937     uInt size_extrafield_global;
    938     const char* comment;
    939     int method;
    940     int level;
    941 {
    942     return zipOpenNewFileInZip2 (file, filename, zipfi,
    943                                  extrafield_local, size_extrafield_local,
    944                                  extrafield_global, size_extrafield_global,
    945                                  comment, method, level, 0);
    946 }
    947 
    948 local int zipFlushWriteBuffer(zi)
    949   zip_internal* zi;
    950 {
    951     int err=ZIP_OK;
    952 
    953     if (zi->ci.encrypt != 0)
    954     {
    955 #ifndef NOCRYPT
    956         uInt i;
    957         int t;
    958         for (i=0;i<zi->ci.pos_in_buffered_data;i++)
    959             zi->ci.buffered_data[i] = zencode(zi->ci.keys, zi->ci.pcrc_32_tab,
    960                                        zi->ci.buffered_data[i],t);
    961 #endif
    962     }
    963     if (ZWRITE(zi->z_filefunc,zi->filestream,zi->ci.buffered_data,zi->ci.pos_in_buffered_data)
    964                                                                     !=zi->ci.pos_in_buffered_data)
    965       err = ZIP_ERRNO;
    966     zi->ci.pos_in_buffered_data = 0;
    967     return err;
    968 }
    969 
    970 extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
    971     zipFile file;
    972     const void* buf;
    973     unsigned len;
    974 {
    975     zip_internal* zi;
    976     int err=ZIP_OK;
    977 
    978     if (file == NULL)
    979         return ZIP_PARAMERROR;
    980     zi = (zip_internal*)file;
    981 
    982     if (zi->in_opened_file_inzip == 0)
    983         return ZIP_PARAMERROR;
    984 
    985     zi->ci.stream.next_in = (void*)buf;
    986     zi->ci.stream.avail_in = len;
    987     zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
    988 
    989     while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
    990     {
    991         if (zi->ci.stream.avail_out == 0)
    992         {
    993             if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
    994                 err = ZIP_ERRNO;
    995             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
    996             zi->ci.stream.next_out = zi->ci.buffered_data;
    997         }
    998 
    999 
   1000         if(err != ZIP_OK)
   1001             break;
   1002 
   1003         if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
   1004         {
   1005             uLong uTotalOutBefore = zi->ci.stream.total_out;
   1006             err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
   1007             zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
   1008 
   1009         }
   1010         else
   1011         {
   1012             uInt copy_this,i;
   1013             if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
   1014                 copy_this = zi->ci.stream.avail_in;
   1015             else
   1016                 copy_this = zi->ci.stream.avail_out;
   1017             for (i=0;i<copy_this;i++)
   1018                 *(((char*)zi->ci.stream.next_out)+i) =
   1019                     *(((const char*)zi->ci.stream.next_in)+i);
   1020             {
   1021                 zi->ci.stream.avail_in -= copy_this;
   1022                 zi->ci.stream.avail_out-= copy_this;
   1023                 zi->ci.stream.next_in+= copy_this;
   1024                 zi->ci.stream.next_out+= copy_this;
   1025                 zi->ci.stream.total_in+= copy_this;
   1026                 zi->ci.stream.total_out+= copy_this;
   1027                 zi->ci.pos_in_buffered_data += copy_this;
   1028             }
   1029         }
   1030     }
   1031 
   1032     return err;
   1033 }
   1034 
   1035 extern int ZEXPORT zipCloseFileInZipRaw (file, uncompressed_size, crc32)
   1036     zipFile file;
   1037     uLong uncompressed_size;
   1038     uLong crc32;
   1039 {
   1040     zip_internal* zi;
   1041     uLong compressed_size;
   1042     int err=ZIP_OK;
   1043 
   1044     if (file == NULL)
   1045         return ZIP_PARAMERROR;
   1046     zi = (zip_internal*)file;
   1047 
   1048     if (zi->in_opened_file_inzip == 0)
   1049         return ZIP_PARAMERROR;
   1050     zi->ci.stream.avail_in = 0;
   1051 
   1052     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
   1053         while (err==ZIP_OK)
   1054     {
   1055         uLong uTotalOutBefore;
   1056         if (zi->ci.stream.avail_out == 0)
   1057         {
   1058             if (zipFlushWriteBuffer(zi) == ZIP_ERRNO)
   1059                 err = ZIP_ERRNO;
   1060             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
   1061             zi->ci.stream.next_out = zi->ci.buffered_data;
   1062         }
   1063         uTotalOutBefore = zi->ci.stream.total_out;
   1064         err=deflate(&zi->ci.stream,  Z_FINISH);
   1065         zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
   1066     }
   1067 
   1068     if (err==Z_STREAM_END)
   1069         err=ZIP_OK; /* this is normal */
   1070 
   1071     if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
   1072         if (zipFlushWriteBuffer(zi)==ZIP_ERRNO)
   1073             err = ZIP_ERRNO;
   1074 
   1075     if ((zi->ci.method == Z_DEFLATED) && (!zi->ci.raw))
   1076     {
   1077         err=deflateEnd(&zi->ci.stream);
   1078         zi->ci.stream_initialised = 0;
   1079     }
   1080 
   1081     if (!zi->ci.raw)
   1082     {
   1083         crc32 = (uLong)zi->ci.crc32;
   1084         uncompressed_size = (uLong)zi->ci.stream.total_in;
   1085     }
   1086     compressed_size = (uLong)zi->ci.stream.total_out;
   1087 #    ifndef NOCRYPT
   1088     compressed_size += zi->ci.crypt_header_size;
   1089 #    endif
   1090 
   1091     ziplocal_putValue_inmemory(zi->ci.central_header+16,crc32,4); /*crc*/
   1092     ziplocal_putValue_inmemory(zi->ci.central_header+20,
   1093                                 compressed_size,4); /*compr size*/
   1094     if (zi->ci.stream.data_type == Z_ASCII)
   1095         ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)Z_ASCII,2);
   1096     ziplocal_putValue_inmemory(zi->ci.central_header+24,
   1097                                 uncompressed_size,4); /*uncompr size*/
   1098 
   1099     if (err==ZIP_OK)
   1100         err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
   1101                                        (uLong)zi->ci.size_centralheader);
   1102     free(zi->ci.central_header);
   1103 
   1104     if (err==ZIP_OK)
   1105     {
   1106         long cur_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
   1107         if (ZSEEK(zi->z_filefunc,zi->filestream,
   1108                   zi->ci.pos_local_header + 14,ZLIB_FILEFUNC_SEEK_SET)!=0)
   1109             err = ZIP_ERRNO;
   1110 
   1111         if (err==ZIP_OK)
   1112             err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,crc32,4); /* crc 32, unknown */
   1113 
   1114         if (err==ZIP_OK) /* compressed size, unknown */
   1115             err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,compressed_size,4);
   1116 
   1117         if (err==ZIP_OK) /* uncompressed size, unknown */
   1118             err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,uncompressed_size,4);
   1119 
   1120         if (ZSEEK(zi->z_filefunc,zi->filestream,
   1121                   cur_pos_inzip,ZLIB_FILEFUNC_SEEK_SET)!=0)
   1122             err = ZIP_ERRNO;
   1123     }
   1124 
   1125     zi->number_entry ++;
   1126     zi->in_opened_file_inzip = 0;
   1127 
   1128     return err;
   1129 }
   1130 
   1131 extern int ZEXPORT zipCloseFileInZip (file)
   1132     zipFile file;
   1133 {
   1134     return zipCloseFileInZipRaw (file,0,0);
   1135 }
   1136 
   1137 extern int ZEXPORT zipClose (file, global_comment)
   1138     zipFile file;
   1139     const char* global_comment;
   1140 {
   1141     zip_internal* zi;
   1142     int err = 0;
   1143     uLong size_centraldir = 0;
   1144     uLong centraldir_pos_inzip;
   1145     uInt size_global_comment;
   1146     if (file == NULL)
   1147         return ZIP_PARAMERROR;
   1148     zi = (zip_internal*)file;
   1149 
   1150     if (zi->in_opened_file_inzip == 1)
   1151     {
   1152         err = zipCloseFileInZip (file);
   1153     }
   1154 
   1155 #ifndef NO_ADDFILEINEXISTINGZIP
   1156     if (global_comment==NULL)
   1157         global_comment = zi->globalcomment;
   1158 #endif
   1159     if (global_comment==NULL)
   1160         size_global_comment = 0;
   1161     else
   1162         size_global_comment = (uInt)strlen(global_comment);
   1163 
   1164     centraldir_pos_inzip = ZTELL(zi->z_filefunc,zi->filestream);
   1165     if (err==ZIP_OK)
   1166     {
   1167         linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
   1168         while (ldi!=NULL)
   1169         {
   1170             if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
   1171                 if (ZWRITE(zi->z_filefunc,zi->filestream,
   1172                            ldi->data,ldi->filled_in_this_block)
   1173                               !=ldi->filled_in_this_block )
   1174                     err = ZIP_ERRNO;
   1175 
   1176             size_centraldir += ldi->filled_in_this_block;
   1177             ldi = ldi->next_datablock;
   1178         }
   1179     }
   1180     free_datablock(zi->central_dir.first_block);
   1181 
   1182     if (err==ZIP_OK) /* Magic End */
   1183         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)ENDHEADERMAGIC,4);
   1184 
   1185     if (err==ZIP_OK) /* number of this disk */
   1186         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
   1187 
   1188     if (err==ZIP_OK) /* number of the disk with the start of the central directory */
   1189         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)0,2);
   1190 
   1191     if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
   1192         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
   1193 
   1194     if (err==ZIP_OK) /* total number of entries in the central dir */
   1195         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)zi->number_entry,2);
   1196 
   1197     if (err==ZIP_OK) /* size of the central directory */
   1198         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_centraldir,4);
   1199 
   1200     if (err==ZIP_OK) /* offset of start of central directory with respect to the
   1201                             starting disk number */
   1202         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,
   1203                                 (uLong)(centraldir_pos_inzip - zi->add_position_when_writting_offset),4);
   1204 
   1205     if (err==ZIP_OK) /* zipfile comment length */
   1206         err = ziplocal_putValue(&zi->z_filefunc,zi->filestream,(uLong)size_global_comment,2);
   1207 
   1208     if ((err==ZIP_OK) && (size_global_comment>0))
   1209         if (ZWRITE(zi->z_filefunc,zi->filestream,
   1210                    global_comment,size_global_comment) != size_global_comment)
   1211                 err = ZIP_ERRNO;
   1212 
   1213     if (ZCLOSE(zi->z_filefunc,zi->filestream) != 0)
   1214         if (err == ZIP_OK)
   1215             err = ZIP_ERRNO;
   1216 
   1217 #ifndef NO_ADDFILEINEXISTINGZIP
   1218     TRYFREE(zi->globalcomment);
   1219 #endif
   1220     TRYFREE(zi);
   1221 
   1222     return err;
   1223 }
   1224