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