home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / zlib / contrib / minizip / zip.c < prev    next >
C/C++ Source or Header  |  1999-10-12  |  22KB  |  717 lines

  1. /* zip.c -- IO on .zip files using zlib 
  2.    Version 0.15 beta, Mar 19th, 1998,
  3.  
  4.    Read zip.h for more info
  5. */
  6.  
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "zlib.h"
  12. #include "zip.h"
  13.  
  14. #ifdef STDC
  15. #  include <stddef.h>
  16. #  include <string.h>
  17. #  include <stdlib.h>
  18. #endif
  19. #ifdef NO_ERRNO_H
  20.     extern int errno;
  21. #else
  22. #   include <errno.h>
  23. #endif
  24.  
  25.  
  26. #ifndef local
  27. #  define local static
  28. #endif
  29. /* compile with -Dlocal if your debugger can't find static symbols */
  30.  
  31. #ifndef VERSIONMADEBY
  32. # define VERSIONMADEBY   (0x0) /* platform depedent */
  33. #endif
  34.  
  35. #ifndef Z_BUFSIZE
  36. #define Z_BUFSIZE (16384)
  37. #endif
  38.  
  39. #ifndef Z_MAXFILENAMEINZIP
  40. #define Z_MAXFILENAMEINZIP (256)
  41. #endif
  42.  
  43. #ifndef ALLOC
  44. # define ALLOC(size) (malloc(size))
  45. #endif
  46. #ifndef TRYFREE
  47. # define TRYFREE(p) {if (p) free(p);}
  48. #endif
  49.  
  50. /*
  51. #define SIZECENTRALDIRITEM (0x2e)
  52. #define SIZEZIPLOCALHEADER (0x1e)
  53. */
  54.  
  55. /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
  56.  
  57. #ifndef SEEK_CUR
  58. #define SEEK_CUR    1
  59. #endif
  60.  
  61. #ifndef SEEK_END
  62. #define SEEK_END    2
  63. #endif
  64.  
  65. #ifndef SEEK_SET
  66. #define SEEK_SET    0
  67. #endif
  68.  
  69. const char zip_copyright[] =
  70.    " zip 0.15 Copyright 1998 Gilles Vollant ";
  71.  
  72.  
  73. #define SIZEDATA_INDATABLOCK (4096-(4*4))
  74.  
  75. #define LOCALHEADERMAGIC    (0x04034b50)
  76. #define CENTRALHEADERMAGIC  (0x02014b50)
  77. #define ENDHEADERMAGIC      (0x06054b50)
  78.  
  79. #define FLAG_LOCALHEADER_OFFSET (0x06)
  80. #define CRC_LOCALHEADER_OFFSET  (0x0e)
  81.  
  82. #define SIZECENTRALHEADER (0x2e) /* 46 */
  83.  
  84. typedef struct linkedlist_datablock_internal_s
  85. {
  86.   struct linkedlist_datablock_internal_s* next_datablock;
  87.   uLong  avail_in_this_block;
  88.   uLong  filled_in_this_block;
  89.   uLong  unused; /* for future use and alignement */
  90.   unsigned char data[SIZEDATA_INDATABLOCK];
  91. } linkedlist_datablock_internal;
  92.  
  93. typedef struct linkedlist_data_s
  94. {
  95.     linkedlist_datablock_internal* first_block;
  96.     linkedlist_datablock_internal* last_block;
  97. } linkedlist_data;
  98.  
  99.  
  100. typedef struct
  101. {
  102.     z_stream stream;            /* zLib stream structure for inflate */
  103.     int  stream_initialised;    /* 1 is stream is initialised */
  104.     uInt pos_in_buffered_data;  /* last written byte in buffered_data */
  105.  
  106.     uLong pos_local_header;     /* offset of the local header of the file 
  107.                                      currenty writing */
  108.     char* central_header;       /* central header data for the current file */
  109.     uLong size_centralheader;   /* size of the central header for cur file */
  110.     uLong flag;                 /* flag of the file currently writing */
  111.  
  112.     int  method;                /* compression method of file currenty wr.*/
  113.     Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
  114.     uLong dosDate;
  115.     uLong crc32;
  116. } curfile_info;
  117.  
  118. typedef struct
  119. {
  120.     FILE * filezip;
  121.     linkedlist_data central_dir;/* datablock with central dir in construction*/
  122.     int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
  123.     curfile_info ci;            /* info on the file curretly writing */
  124.  
  125.     uLong begin_pos;            /* position of the beginning of the zipfile */
  126.     uLong number_entry;
  127. } zip_internal;
  128.  
  129. local linkedlist_datablock_internal* allocate_new_datablock()
  130. {
  131.     linkedlist_datablock_internal* ldi;
  132.     ldi = (linkedlist_datablock_internal*)
  133.                  ALLOC(sizeof(linkedlist_datablock_internal));
  134.     if (ldi!=NULL)
  135.     {
  136.         ldi->next_datablock = NULL ;
  137.         ldi->filled_in_this_block = 0 ;
  138.         ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
  139.     }
  140.     return ldi;
  141. }
  142.  
  143. local void free_datablock(ldi)
  144.     linkedlist_datablock_internal* ldi;
  145. {
  146.     while (ldi!=NULL)
  147.     {
  148.         linkedlist_datablock_internal* ldinext = ldi->next_datablock;
  149.         TRYFREE(ldi);
  150.         ldi = ldinext;
  151.     }
  152. }
  153.  
  154. local void init_linkedlist(ll)
  155.     linkedlist_data* ll;
  156. {
  157.     ll->first_block = ll->last_block = NULL;
  158. }
  159.  
  160. local void free_linkedlist(ll)
  161.     linkedlist_data* ll;
  162. {
  163.     free_datablock(ll->first_block);
  164.     ll->first_block = ll->last_block = NULL;
  165. }
  166.  
  167.  
  168. local int add_data_in_datablock(ll,buf,len)
  169.     linkedlist_data* ll;    
  170.     const void* buf;
  171.     uLong len;
  172. {
  173.     linkedlist_datablock_internal* ldi;
  174.     const unsigned char* from_copy;
  175.  
  176.     if (ll==NULL)
  177.         return ZIP_INTERNALERROR;
  178.  
  179.     if (ll->last_block == NULL)
  180.     {
  181.         ll->first_block = ll->last_block = allocate_new_datablock();
  182.         if (ll->first_block == NULL)
  183.             return ZIP_INTERNALERROR;
  184.     }
  185.  
  186.     ldi = ll->last_block;
  187.     from_copy = (unsigned char*)buf;
  188.  
  189.     while (len>0)
  190.     {
  191.         uInt copy_this;
  192.         uInt i;
  193.         unsigned char* to_copy;
  194.  
  195.         if (ldi->avail_in_this_block==0)
  196.         {
  197.             ldi->next_datablock = allocate_new_datablock();
  198.             if (ldi->next_datablock == NULL)
  199.                 return ZIP_INTERNALERROR;
  200.             ldi = ldi->next_datablock ;
  201.             ll->last_block = ldi;
  202.         }
  203.  
  204.         if (ldi->avail_in_this_block < len)
  205.             copy_this = (uInt)ldi->avail_in_this_block;
  206.         else
  207.             copy_this = (uInt)len;
  208.  
  209.         to_copy = &(ldi->data[ldi->filled_in_this_block]);
  210.  
  211.         for (i=0;i<copy_this;i++)
  212.             *(to_copy+i)=*(from_copy+i);
  213.  
  214.         ldi->filled_in_this_block += copy_this;
  215.         ldi->avail_in_this_block -= copy_this;
  216.         from_copy += copy_this ;
  217.         len -= copy_this;
  218.     }
  219.     return ZIP_OK;
  220. }
  221.  
  222.  
  223. local int write_datablock(fout,ll)
  224.     FILE * fout;
  225.     linkedlist_data* ll;    
  226. {
  227.     linkedlist_datablock_internal* ldi;
  228.     ldi = ll->first_block;
  229.     while (ldi!=NULL)
  230.     {
  231.         if (ldi->filled_in_this_block > 0)
  232.             if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,1,fout)!=1)
  233.                 return ZIP_ERRNO;
  234.         ldi = ldi->next_datablock;
  235.     }
  236.     return ZIP_OK;
  237. }
  238.  
  239. /****************************************************************************/
  240.  
  241. /* ===========================================================================
  242.    Outputs a long in LSB order to the given file
  243.    nbByte == 1, 2 or 4 (byte, short or long)
  244. */
  245. local int ziplocal_putValue (file, x, nbByte)
  246.     FILE *file;
  247.     uLong x;
  248.     int nbByte;
  249. {
  250.     unsigned char buf[4];
  251.     int n;
  252.     for (n = 0; n < nbByte; n++) {
  253.         buf[n] = (unsigned char)(x & 0xff);
  254.         x >>= 8;
  255.     }
  256.     if (fwrite(buf,nbByte,1,file)!=1)
  257.         return ZIP_ERRNO;
  258.     else
  259.         return ZIP_OK;
  260. }
  261.  
  262.  
  263. local void ziplocal_putValue_inmemory (dest, x, nbByte)
  264.     void* dest;
  265.     uLong x;
  266.     int nbByte;
  267. {
  268.     unsigned char* buf=(unsigned char*)dest;
  269.     int n;
  270.     for (n = 0; n < nbByte; n++) {
  271.         buf[n] = (unsigned char)(x & 0xff);
  272.         x >>= 8;
  273.     }
  274. }
  275. /****************************************************************************/
  276.  
  277.  
  278. local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
  279.     tm_zip* ptm;
  280.     uLong dosDate;
  281. {
  282.     uLong year = (uLong)ptm->tm_year;
  283.     if (year>1980)
  284.         year-=1980;
  285.     else if (year>80)
  286.         year-=80;
  287.     return
  288.       (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
  289.         ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
  290. }
  291.  
  292.  
  293. /****************************************************************************/
  294.  
  295. extern zipFile ZEXPORT zipOpen (pathname, append)
  296.     const char *pathname;
  297.     int append;
  298. {
  299.     zip_internal ziinit;
  300.     zip_internal* zi;
  301.  
  302.     ziinit.filezip = fopen(pathname,(append == 0) ? "wb" : "ab");
  303.     if (ziinit.filezip == NULL)
  304.         return NULL;
  305.     ziinit.begin_pos = ftell(ziinit.filezip);
  306.     ziinit.in_opened_file_inzip = 0;
  307.     ziinit.ci.stream_initialised = 0;
  308.     ziinit.number_entry = 0;
  309.     init_linkedlist(&(ziinit.central_dir));
  310.  
  311.  
  312.     zi = (zip_internal*)ALLOC(sizeof(zip_internal));
  313.     if (zi==NULL)
  314.     {
  315.         fclose(ziinit.filezip);
  316.         return NULL;
  317.     }
  318.  
  319.     *zi = ziinit;
  320.     return (zipFile)zi;
  321. }
  322.  
  323. extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, 
  324.                                         extrafield_local, size_extrafield_local,
  325.                                         extrafield_global, size_extrafield_global,
  326.                                         comment, method, level)
  327.     zipFile file;
  328.     const char* filename;
  329.     const zip_fileinfo* zipfi;
  330.     const void* extrafield_local;
  331.     uInt size_extrafield_local;
  332.     const void* extrafield_global;
  333.     uInt size_extrafield_global;
  334.     const char* comment;
  335.     int method;
  336.     int level;
  337. {
  338.     zip_internal* zi;
  339.     uInt size_filename;
  340.     uInt size_comment;
  341.     uInt i;
  342.     int err = ZIP_OK;
  343.  
  344.     if (file == NULL)
  345.         return ZIP_PARAMERROR;
  346.     if ((method!=0) && (method!=Z_DEFLATED))
  347.         return ZIP_PARAMERROR;
  348.  
  349.     zi = (zip_internal*)file;
  350.  
  351.     if (zi->in_opened_file_inzip == 1)
  352.     {
  353.         err = zipCloseFileInZip (file);
  354.         if (err != ZIP_OK)
  355.             return err;
  356.     }
  357.  
  358.  
  359.     if (filename==NULL)
  360.         filename="-";
  361.  
  362.     if (comment==NULL)
  363.         size_comment = 0;
  364.     else
  365.         size_comment = strlen(comment);
  366.  
  367.     size_filename = strlen(filename);
  368.  
  369.     if (zipfi == NULL)
  370.         zi->ci.dosDate = 0;
  371.     else
  372.     {
  373.         if (zipfi->dosDate != 0)
  374.             zi->ci.dosDate = zipfi->dosDate;
  375.         else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
  376.     }
  377.  
  378.     zi->ci.flag = 0;
  379.     if ((level==8) || (level==9))
  380.       zi->ci.flag |= 2;
  381.     if ((level==2))
  382.       zi->ci.flag |= 4;
  383.     if ((level==1))
  384.       zi->ci.flag |= 6;
  385.  
  386.     zi->ci.crc32 = 0;
  387.     zi->ci.method = method;
  388.     zi->ci.stream_initialised = 0;
  389.     zi->ci.pos_in_buffered_data = 0;
  390.     zi->ci.pos_local_header = ftell(zi->filezip);
  391.     zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + 
  392.                                       size_extrafield_global + size_comment;
  393.     zi->ci.central_header = (char*)ALLOC(zi->ci.size_centralheader);
  394.  
  395.     ziplocal_putValue_inmemory(zi->ci.central_header,CENTRALHEADERMAGIC,4);
  396.     /* version info */
  397.     ziplocal_putValue_inmemory(zi->ci.central_header+4,VERSIONMADEBY,2);
  398.     ziplocal_putValue_inmemory(zi->ci.central_header+6,20,2);
  399.     ziplocal_putValue_inmemory(zi->ci.central_header+8,zi->ci.flag,2);
  400.     ziplocal_putValue_inmemory(zi->ci.central_header+10,zi->ci.method,2);
  401.     ziplocal_putValue_inmemory(zi->ci.central_header+12,zi->ci.dosDate,4);
  402.     ziplocal_putValue_inmemory(zi->ci.central_header+16,0,4); /*crc*/
  403.     ziplocal_putValue_inmemory(zi->ci.central_header+20,0,4); /*compr size*/
  404.     ziplocal_putValue_inmemory(zi->ci.central_header+24,0,4); /*uncompr size*/
  405.     ziplocal_putValue_inmemory(zi->ci.central_header+28,size_filename,2);
  406.     ziplocal_putValue_inmemory(zi->ci.central_header+30,size_extrafield_global,2);
  407.     ziplocal_putValue_inmemory(zi->ci.central_header+32,size_comment,2);
  408.     ziplocal_putValue_inmemory(zi->ci.central_header+34,0,2); /*disk nm start*/
  409.  
  410.     if (zipfi==NULL)
  411.         ziplocal_putValue_inmemory(zi->ci.central_header+36,0,2); 
  412.     else
  413.         ziplocal_putValue_inmemory(zi->ci.central_header+36,zipfi->internal_fa,2); 
  414.  
  415.     if (zipfi==NULL)
  416.         ziplocal_putValue_inmemory(zi->ci.central_header+38,0,4); 
  417.     else
  418.         ziplocal_putValue_inmemory(zi->ci.central_header+38,zipfi->external_fa,4);
  419.  
  420.     ziplocal_putValue_inmemory(zi->ci.central_header+42,zi->ci.pos_local_header,4);
  421.  
  422.     for (i=0;i<size_filename;i++)
  423.         *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
  424.  
  425.     for (i=0;i<size_extrafield_global;i++)
  426.         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
  427.               *(((const char*)extrafield_global)+i);
  428.  
  429.     for (i=0;i<size_comment;i++)
  430.         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
  431.               size_extrafield_global+i) = *(filename+i);
  432.     if (zi->ci.central_header == NULL)
  433.         return ZIP_INTERNALERROR;
  434.  
  435.     /* write the local header */
  436.     err = ziplocal_putValue(zi->filezip,LOCALHEADERMAGIC,4);
  437.  
  438.     if (err==ZIP_OK)
  439.         err = ziplocal_putValue(zi->filezip,20,2);/* version needed to extract */
  440.     if (err==ZIP_OK)
  441.         err = ziplocal_putValue(zi->filezip,zi->ci.flag,2);
  442.  
  443.     if (err==ZIP_OK)
  444.         err = ziplocal_putValue(zi->filezip,zi->ci.method,2);
  445.  
  446.     if (err==ZIP_OK)
  447.         err = ziplocal_putValue(zi->filezip,zi->ci.dosDate,4);
  448.  
  449.     if (err==ZIP_OK)
  450.         err = ziplocal_putValue(zi->filezip,0,4); /* crc 32, unknown */
  451.     if (err==ZIP_OK)
  452.         err = ziplocal_putValue(zi->filezip,0,4); /* compressed size, unknown */
  453.     if (err==ZIP_OK)
  454.         err = ziplocal_putValue(zi->filezip,0,4); /* uncompressed size, unknown */
  455.  
  456.     if (err==ZIP_OK)
  457.         err = ziplocal_putValue(zi->filezip,(uLong)size_filename,2);
  458.  
  459.     if (err==ZIP_OK)
  460.         err = ziplocal_putValue(zi->filezip,(uLong)size_extrafield_local,2);
  461.  
  462.     if ((err==ZIP_OK) && (size_filename>0))
  463.         if (fwrite(filename,(uInt)size_filename,1,zi->filezip)!=1)
  464.                 err = ZIP_ERRNO;
  465.  
  466.     if ((err==ZIP_OK) && (size_extrafield_local>0))
  467.         if (fwrite(extrafield_local,(uInt)size_extrafield_local,1,zi->filezip)
  468.                                                                            !=1)
  469.                 err = ZIP_ERRNO;
  470.  
  471.     zi->ci.stream.avail_in = (uInt)0;
  472.     zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
  473.     zi->ci.stream.next_out = zi->ci.buffered_data;
  474.     zi->ci.stream.total_in = 0;
  475.     zi->ci.stream.total_out = 0;
  476.  
  477.     if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED))
  478.     {
  479.         zi->ci.stream.zalloc = (alloc_func)0;
  480.         zi->ci.stream.zfree = (free_func)0;
  481.         zi->ci.stream.opaque = (voidpf)0;
  482.  
  483.         err = deflateInit2(&zi->ci.stream, level,
  484.                Z_DEFLATED, -MAX_WBITS, /*DEF_MEM_LEVEL*/8, 0);
  485.  
  486.         if (err==Z_OK)
  487.             zi->ci.stream_initialised = 1;
  488.     }
  489.  
  490.  
  491.     if (err==Z_OK)
  492.         zi->in_opened_file_inzip = 1;
  493.     return err;
  494. }
  495.  
  496. extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
  497.     zipFile file;
  498.     const voidp buf;
  499.     unsigned len;
  500. {
  501.     zip_internal* zi;
  502.     int err=ZIP_OK;
  503.  
  504.     if (file == NULL)
  505.         return ZIP_PARAMERROR;
  506.     zi = (zip_internal*)file;
  507.  
  508.     if (zi->in_opened_file_inzip == 0)
  509.         return ZIP_PARAMERROR;
  510.  
  511.     zi->ci.stream.next_in = buf;
  512.     zi->ci.stream.avail_in = len;
  513.     zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
  514.  
  515.     while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
  516.     {
  517.         if (zi->ci.stream.avail_out == 0)
  518.         {
  519.             if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
  520.                                                                            !=1)
  521.                 err = ZIP_ERRNO;
  522.             zi->ci.pos_in_buffered_data = 0;
  523.             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
  524.             zi->ci.stream.next_out = zi->ci.buffered_data;
  525.         }
  526.  
  527.         if (zi->ci.method == Z_DEFLATED)
  528.         {
  529.             uLong uTotalOutBefore = zi->ci.stream.total_out;
  530.             err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
  531.             zi->ci.pos_in_buffered_data += zi->ci.stream.total_out - uTotalOutBefore ;
  532.  
  533.         }
  534.         else
  535.         {
  536.             uInt copy_this,i;
  537.             if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
  538.                 copy_this = zi->ci.stream.avail_in;
  539.             else
  540.                 copy_this = zi->ci.stream.avail_out;
  541.             for (i=0;i<copy_this;i++)
  542.                 *(((char*)zi->ci.stream.next_out)+i) =
  543.                     *(((const char*)zi->ci.stream.next_in)+i);
  544.             {
  545.                 zi->ci.stream.avail_in -= copy_this;
  546.                 zi->ci.stream.avail_out-= copy_this;
  547.                 zi->ci.stream.next_in+= copy_this;
  548.                 zi->ci.stream.next_out+= copy_this;
  549.                 zi->ci.stream.total_in+= copy_this;
  550.                 zi->ci.stream.total_out+= copy_this;
  551.                 zi->ci.pos_in_buffered_data += copy_this;
  552.             }
  553.         }
  554.     }
  555.  
  556.     return 0;
  557. }
  558.  
  559. extern int ZEXPORT zipCloseFileInZip (file)
  560.     zipFile file;
  561. {
  562.     zip_internal* zi;
  563.     int err=ZIP_OK;
  564.  
  565.     if (file == NULL)
  566.         return ZIP_PARAMERROR;
  567.     zi = (zip_internal*)file;
  568.  
  569.     if (zi->in_opened_file_inzip == 0)    
  570.         return ZIP_PARAMERROR;
  571.     zi->ci.stream.avail_in = 0;
  572.     
  573.     if (zi->ci.method == Z_DEFLATED)
  574.         while (err==ZIP_OK)
  575.     {
  576.         uLong uTotalOutBefore;
  577.         if (zi->ci.stream.avail_out == 0)
  578.         {
  579.             if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
  580.                                                                            !=1)
  581.                 err = ZIP_ERRNO;
  582.             zi->ci.pos_in_buffered_data = 0;
  583.             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
  584.             zi->ci.stream.next_out = zi->ci.buffered_data;
  585.         }
  586.         uTotalOutBefore = zi->ci.stream.total_out;
  587.         err=deflate(&zi->ci.stream,  Z_FINISH);
  588.         zi->ci.pos_in_buffered_data += zi->ci.stream.total_out - uTotalOutBefore ;
  589.     }
  590.  
  591.     if (err==Z_STREAM_END)
  592.         err=ZIP_OK; /* this is normal */
  593.  
  594.     if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
  595.         if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
  596.                                                                        !=1)
  597.             err = ZIP_ERRNO;
  598.  
  599.     if ((zi->ci.method == Z_DEFLATED) && (err==ZIP_OK))
  600.     {
  601.         err=deflateEnd(&zi->ci.stream);
  602.         zi->ci.stream_initialised = 0;
  603.     }
  604.  
  605.     ziplocal_putValue_inmemory(zi->ci.central_header+16,zi->ci.crc32,4); /*crc*/
  606.     ziplocal_putValue_inmemory(zi->ci.central_header+20,
  607.                                 zi->ci.stream.total_out,4); /*compr size*/
  608.     ziplocal_putValue_inmemory(zi->ci.central_header+24,
  609.                                 zi->ci.stream.total_in,4); /*uncompr size*/
  610.  
  611.     if (err==ZIP_OK)
  612.         err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
  613.                                        (uLong)zi->ci.size_centralheader);
  614.     free(zi->ci.central_header);
  615.  
  616.     if (err==ZIP_OK)
  617.     {
  618.         long cur_pos_inzip = ftell(zi->filezip);
  619.         if (fseek(zi->filezip,
  620.                   zi->ci.pos_local_header + 14,SEEK_SET)!=0)
  621.             err = ZIP_ERRNO;
  622.  
  623.         if (err==ZIP_OK)
  624.             err = ziplocal_putValue(zi->filezip,zi->ci.crc32,4); /* crc 32, unknown */
  625.  
  626.         if (err==ZIP_OK) /* compressed size, unknown */
  627.             err = ziplocal_putValue(zi->filezip,zi->ci.stream.total_out,4); 
  628.  
  629.         if (err==ZIP_OK) /* uncompressed size, unknown */
  630.             err = ziplocal_putValue(zi->filezip,zi->ci.stream.total_in,4);
  631.  
  632.         if (fseek(zi->filezip,
  633.                   cur_pos_inzip,SEEK_SET)!=0)
  634.             err = ZIP_ERRNO;
  635.     }
  636.  
  637.     zi->number_entry ++;
  638.     zi->in_opened_file_inzip = 0;
  639.  
  640.     return err;
  641. }
  642.  
  643. extern int ZEXPORT zipClose (file, global_comment)
  644.     zipFile file;
  645.     const char* global_comment;
  646. {
  647.     zip_internal* zi;
  648.     int err = 0;
  649.     uLong size_centraldir = 0;
  650.     uLong centraldir_pos_inzip ;
  651.     uInt size_global_comment;
  652.     if (file == NULL)
  653.         return ZIP_PARAMERROR;
  654.     zi = (zip_internal*)file;
  655.  
  656.     if (zi->in_opened_file_inzip == 1)
  657.     {
  658.         err = zipCloseFileInZip (file);
  659.     }
  660.  
  661.     if (global_comment==NULL)
  662.         size_global_comment = 0;
  663.     else
  664.         size_global_comment = strlen(global_comment);
  665.  
  666.  
  667.     centraldir_pos_inzip = ftell(zi->filezip);
  668.     if (err==ZIP_OK)
  669.     {
  670.         linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
  671.         while (ldi!=NULL)
  672.         {
  673.             if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
  674.                 if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,
  675.                                         1,zi->filezip) !=1 )
  676.                     err = ZIP_ERRNO;
  677.  
  678.             size_centraldir += ldi->filled_in_this_block;
  679.             ldi = ldi->next_datablock;
  680.         }
  681.     }
  682.     free_datablock(zi->central_dir.first_block);
  683.  
  684.     if (err==ZIP_OK) /* Magic End */
  685.         err = ziplocal_putValue(zi->filezip,ENDHEADERMAGIC,4);
  686.  
  687.     if (err==ZIP_OK) /* number of this disk */
  688.         err = ziplocal_putValue(zi->filezip,0,2);
  689.  
  690.     if (err==ZIP_OK) /* number of the disk with the start of the central directory */
  691.         err = ziplocal_putValue(zi->filezip,0,2);
  692.  
  693.     if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
  694.         err = ziplocal_putValue(zi->filezip,zi->number_entry,2);
  695.  
  696.     if (err==ZIP_OK) /* total number of entries in the central dir */
  697.         err = ziplocal_putValue(zi->filezip,zi->number_entry,2);
  698.  
  699.     if (err==ZIP_OK) /* size of the central directory */
  700.         err = ziplocal_putValue(zi->filezip,size_centraldir,4);
  701.  
  702.     if (err==ZIP_OK) /* offset of start of central directory with respect to the 
  703.                             starting disk number */
  704.         err = ziplocal_putValue(zi->filezip,centraldir_pos_inzip ,4);
  705.  
  706.     if (err==ZIP_OK) /* zipfile comment length */
  707.         err = ziplocal_putValue(zi->filezip,(uLong)size_global_comment,2);
  708.  
  709.     if ((err==ZIP_OK) && (size_global_comment>0))
  710.         if (fwrite(global_comment,(uInt)size_global_comment,1,zi->filezip) !=1 )
  711.                 err = ZIP_ERRNO;
  712.     fclose(zi->filezip);
  713.     TRYFREE(zi);
  714.  
  715.     return err;
  716. }
  717.