PageRenderTime 325ms CodeModel.GetById 51ms app.highlight 209ms RepoModel.GetById 52ms app.codeStats 1ms

/src/libtomahawk/thirdparty/quazip/quazip/zip.c

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