Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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