home *** CD-ROM | disk | FTP | other *** search
/ Freelog 11 / Freelog011.iso / Bas / Compression / ZLib / contrib / minizip / zip.c < prev    next >
C/C++ Source or Header  |  1998-06-19  |  22KB  |  719 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.  
  246. local int ziplocal_putValue OF((FILE *file, uLong x, int nbByte));
  247. local int ziplocal_putValue (file, x, nbByte)
  248.     FILE *file;
  249.     uLong x;
  250.     int nbByte;
  251. {
  252.     unsigned char buf[4];
  253.     int n;
  254.     for (n = 0; n < nbByte; n++) {
  255.         buf[n] = (unsigned char)(x & 0xff);
  256.         x >>= 8;
  257.     }
  258.     if (fwrite(buf,nbByte,1,file)!=1)
  259.         return ZIP_ERRNO;
  260.     else
  261.         return ZIP_OK;
  262. }
  263.  
  264. local void ziplocal_putValue_inmemory OF((void* dest, uLong x, int nbByte));
  265. local void ziplocal_putValue_inmemory (dest, x, nbByte)
  266.     void* dest;
  267.     uLong x;
  268.     int nbByte;
  269. {
  270.     unsigned char* buf=(unsigned char*)dest;
  271.     int n;
  272.     for (n = 0; n < nbByte; n++) {
  273.         buf[n] = (unsigned char)(x & 0xff);
  274.         x >>= 8;
  275.     }
  276. }
  277. /****************************************************************************/
  278.  
  279.  
  280. local uLong ziplocal_TmzDateToDosDate(ptm,dosDate)
  281.     tm_zip* ptm;
  282.     uLong dosDate;
  283. {
  284.     uLong year = (uLong)ptm->tm_year;
  285.     if (year>1980)
  286.         year-=1980;
  287.     else if (year>80)
  288.         year-=80;
  289.     return
  290.       (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
  291.         ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
  292. }
  293.  
  294.  
  295. /****************************************************************************/
  296.  
  297. extern zipFile ZEXPORT zipOpen (pathname, append)
  298.     const char *pathname;
  299.     int append;
  300. {
  301.     zip_internal ziinit;
  302.     zip_internal* zi;
  303.  
  304.     ziinit.filezip = fopen(pathname,(append == 0) ? "wb" : "ab");
  305.     if (ziinit.filezip == NULL)
  306.         return NULL;
  307.     ziinit.begin_pos = ftell(ziinit.filezip);
  308.     ziinit.in_opened_file_inzip = 0;
  309.     ziinit.ci.stream_initialised = 0;
  310.     ziinit.number_entry = 0;
  311.     init_linkedlist(&(ziinit.central_dir));
  312.  
  313.  
  314.     zi = (zip_internal*)ALLOC(sizeof(zip_internal));
  315.     if (zi==NULL)
  316.     {
  317.         fclose(ziinit.filezip);
  318.         return NULL;
  319.     }
  320.  
  321.     *zi = ziinit;
  322.     return (zipFile)zi;
  323. }
  324.  
  325. extern int ZEXPORT zipOpenNewFileInZip (file, filename, zipfi, 
  326.                                         extrafield_local, size_extrafield_local,
  327.                                         extrafield_global, size_extrafield_global,
  328.                                         comment, method, level)
  329.     zipFile file;
  330.     const char* filename;
  331.     const zip_fileinfo* zipfi;
  332.     const void* extrafield_local;
  333.     uInt size_extrafield_local;
  334.     const void* extrafield_global;
  335.     uInt size_extrafield_global;
  336.     const char* comment;
  337.     int method;
  338.     int level;
  339. {
  340.     zip_internal* zi;
  341.     uInt size_filename;
  342.     uInt size_comment;
  343.     uInt i;
  344.     int err = ZIP_OK;
  345.  
  346.     if (file == NULL)
  347.         return ZIP_PARAMERROR;
  348.     if ((method!=0) && (method!=Z_DEFLATED))
  349.         return ZIP_PARAMERROR;
  350.  
  351.     zi = (zip_internal*)file;
  352.  
  353.     if (zi->in_opened_file_inzip == 1)
  354.     {
  355.         err = zipCloseFileInZip (file);
  356.         if (err != ZIP_OK)
  357.             return err;
  358.     }
  359.  
  360.  
  361.     if (filename==NULL)
  362.         filename="-";
  363.  
  364.     if (comment==NULL)
  365.         size_comment = 0;
  366.     else
  367.         size_comment = strlen(comment);
  368.  
  369.     size_filename = strlen(filename);
  370.  
  371.     if (zipfi == NULL)
  372.         zi->ci.dosDate = 0;
  373.     else
  374.     {
  375.         if (zipfi->dosDate != 0)
  376.             zi->ci.dosDate = zipfi->dosDate;
  377.         else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
  378.     }
  379.  
  380.     zi->ci.flag = 0;
  381.     if ((level==8) || (level==9))
  382.       zi->ci.flag |= 2;
  383.     if ((level==2))
  384.       zi->ci.flag |= 4;
  385.     if ((level==1))
  386.       zi->ci.flag |= 6;
  387.  
  388.     zi->ci.crc32 = 0;
  389.     zi->ci.method = method;
  390.     zi->ci.stream_initialised = 0;
  391.     zi->ci.pos_in_buffered_data = 0;
  392.     zi->ci.pos_local_header = ftell(zi->filezip);
  393.     zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + 
  394.                                       size_extrafield_global + size_comment;
  395.     zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
  396.  
  397.     ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
  398.     /* version info */
  399.     ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
  400.     ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
  401.     ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
  402.     ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
  403.     ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
  404.     ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
  405.     ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
  406.     ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
  407.     ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
  408.     ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
  409.     ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
  410.     ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
  411.  
  412.     if (zipfi==NULL)
  413.         ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); 
  414.     else
  415.         ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); 
  416.  
  417.     if (zipfi==NULL)
  418.         ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); 
  419.     else
  420.         ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
  421.  
  422.     ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header,4);
  423.  
  424.     for (i=0;i<size_filename;i++)
  425.         *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
  426.  
  427.     for (i=0;i<size_extrafield_global;i++)
  428.         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
  429.               *(((const char*)extrafield_global)+i);
  430.  
  431.     for (i=0;i<size_comment;i++)
  432.         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
  433.               size_extrafield_global+i) = *(filename+i);
  434.     if (zi->ci.central_header == NULL)
  435.         return ZIP_INTERNALERROR;
  436.  
  437.     /* write the local header */
  438.     err = ziplocal_putValue(zi->filezip,(uLong)LOCALHEADERMAGIC,4);
  439.  
  440.     if (err==ZIP_OK)
  441.         err = ziplocal_putValue(zi->filezip,(uLong)20,2);/* version needed to extract */
  442.     if (err==ZIP_OK)
  443.         err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.flag,2);
  444.  
  445.     if (err==ZIP_OK)
  446.         err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.method,2);
  447.  
  448.     if (err==ZIP_OK)
  449.         err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.dosDate,4);
  450.  
  451.     if (err==ZIP_OK)
  452.         err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* crc 32, unknown */
  453.     if (err==ZIP_OK)
  454.         err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* compressed size, unknown */
  455.     if (err==ZIP_OK)
  456.         err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* uncompressed size, unknown */
  457.  
  458.     if (err==ZIP_OK)
  459.         err = ziplocal_putValue(zi->filezip,(uLong)size_filename,2);
  460.  
  461.     if (err==ZIP_OK)
  462.         err = ziplocal_putValue(zi->filezip,(uLong)size_extrafield_local,2);
  463.  
  464.     if ((err==ZIP_OK) && (size_filename>0))
  465.         if (fwrite(filename,(uInt)size_filename,1,zi->filezip)!=1)
  466.                 err = ZIP_ERRNO;
  467.  
  468.     if ((err==ZIP_OK) && (size_extrafield_local>0))
  469.         if (fwrite(extrafield_local,(uInt)size_extrafield_local,1,zi->filezip)
  470.                                                                            !=1)
  471.                 err = ZIP_ERRNO;
  472.  
  473.     zi->ci.stream.avail_in = (uInt)0;
  474.     zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
  475.     zi->ci.stream.next_out = zi->ci.buffered_data;
  476.     zi->ci.stream.total_in = 0;
  477.     zi->ci.stream.total_out = 0;
  478.  
  479.     if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED))
  480.     {
  481.         zi->ci.stream.zalloc = (alloc_func)0;
  482.         zi->ci.stream.zfree = (free_func)0;
  483.         zi->ci.stream.opaque = (voidpf)0;
  484.  
  485.         err = deflateInit2(&zi->ci.stream, level,
  486.                Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
  487.  
  488.         if (err==Z_OK)
  489.             zi->ci.stream_initialised = 1;
  490.     }
  491.  
  492.  
  493.     if (err==Z_OK)
  494.         zi->in_opened_file_inzip = 1;
  495.     return err;
  496. }
  497.  
  498. extern int ZEXPORT zipWriteInFileInZip (file, buf, len)
  499.     zipFile file;
  500.     const voidp buf;
  501.     unsigned len;
  502. {
  503.     zip_internal* zi;
  504.     int err=ZIP_OK;
  505.  
  506.     if (file == NULL)
  507.         return ZIP_PARAMERROR;
  508.     zi = (zip_internal*)file;
  509.  
  510.     if (zi->in_opened_file_inzip == 0)
  511.         return ZIP_PARAMERROR;
  512.  
  513.     zi->ci.stream.next_in = buf;
  514.     zi->ci.stream.avail_in = len;
  515.     zi->ci.crc32 = crc32(zi->ci.crc32,buf,len);
  516.  
  517.     while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
  518.     {
  519.         if (zi->ci.stream.avail_out == 0)
  520.         {
  521.             if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
  522.                                                                            !=1)
  523.                 err = ZIP_ERRNO;
  524.             zi->ci.pos_in_buffered_data = 0;
  525.             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
  526.             zi->ci.stream.next_out = zi->ci.buffered_data;
  527.         }
  528.  
  529.         if (zi->ci.method == Z_DEFLATED)
  530.         {
  531.             uLong uTotalOutBefore = zi->ci.stream.total_out;
  532.             err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
  533.             zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
  534.  
  535.         }
  536.         else
  537.         {
  538.             uInt copy_this,i;
  539.             if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
  540.                 copy_this = zi->ci.stream.avail_in;
  541.             else
  542.                 copy_this = zi->ci.stream.avail_out;
  543.             for (i=0;i<copy_this;i++)
  544.                 *(((char*)zi->ci.stream.next_out)+i) =
  545.                     *(((const char*)zi->ci.stream.next_in)+i);
  546.             {
  547.                 zi->ci.stream.avail_in -= copy_this;
  548.                 zi->ci.stream.avail_out-= copy_this;
  549.                 zi->ci.stream.next_in+= copy_this;
  550.                 zi->ci.stream.next_out+= copy_this;
  551.                 zi->ci.stream.total_in+= copy_this;
  552.                 zi->ci.stream.total_out+= copy_this;
  553.                 zi->ci.pos_in_buffered_data += copy_this;
  554.             }
  555.         }
  556.     }
  557.  
  558.     return 0;
  559. }
  560.  
  561. extern int ZEXPORT zipCloseFileInZip (file)
  562.     zipFile file;
  563. {
  564.     zip_internal* zi;
  565.     int err=ZIP_OK;
  566.  
  567.     if (file == NULL)
  568.         return ZIP_PARAMERROR;
  569.     zi = (zip_internal*)file;
  570.  
  571.     if (zi->in_opened_file_inzip == 0)    
  572.         return ZIP_PARAMERROR;
  573.     zi->ci.stream.avail_in = 0;
  574.     
  575.     if (zi->ci.method == Z_DEFLATED)
  576.         while (err==ZIP_OK)
  577.     {
  578.         uLong uTotalOutBefore;
  579.         if (zi->ci.stream.avail_out == 0)
  580.         {
  581.             if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
  582.                                                                            !=1)
  583.                 err = ZIP_ERRNO;
  584.             zi->ci.pos_in_buffered_data = 0;
  585.             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
  586.             zi->ci.stream.next_out = zi->ci.buffered_data;
  587.         }
  588.         uTotalOutBefore = zi->ci.stream.total_out;
  589.         err=deflate(&zi->ci.stream,  Z_FINISH);
  590.         zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
  591.     }
  592.  
  593.     if (err==Z_STREAM_END)
  594.         err=ZIP_OK; /* this is normal */
  595.  
  596.     if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
  597.         if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
  598.                                                                        !=1)
  599.             err = ZIP_ERRNO;
  600.  
  601.     if ((zi->ci.method == Z_DEFLATED) && (err==ZIP_OK))
  602.     {
  603.         err=deflateEnd(&zi->ci.stream);
  604.         zi->ci.stream_initialised = 0;
  605.     }
  606.  
  607.     ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)zi->ci.crc32,4); /*crc*/
  608.     ziplocal_putValue_inmemory(zi->ci.central_header+20,
  609.                                 (uLong)zi->ci.stream.total_out,4); /*compr size*/
  610.     ziplocal_putValue_inmemory(zi->ci.central_header+24,
  611.                                 (uLong)zi->ci.stream.total_in,4); /*uncompr size*/
  612.  
  613.     if (err==ZIP_OK)
  614.         err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
  615.                                        (uLong)zi->ci.size_centralheader);
  616.     free(zi->ci.central_header);
  617.  
  618.     if (err==ZIP_OK)
  619.     {
  620.         long cur_pos_inzip = ftell(zi->filezip);
  621.         if (fseek(zi->filezip,
  622.                   zi->ci.pos_local_header + 14,SEEK_SET)!=0)
  623.             err = ZIP_ERRNO;
  624.  
  625.         if (err==ZIP_OK)
  626.             err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.crc32,4); /* crc 32, unknown */
  627.  
  628.         if (err==ZIP_OK) /* compressed size, unknown */
  629.             err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_out,4); 
  630.  
  631.         if (err==ZIP_OK) /* uncompressed size, unknown */
  632.             err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_in,4);
  633.  
  634.         if (fseek(zi->filezip,
  635.                   cur_pos_inzip,SEEK_SET)!=0)
  636.             err = ZIP_ERRNO;
  637.     }
  638.  
  639.     zi->number_entry ++;
  640.     zi->in_opened_file_inzip = 0;
  641.  
  642.     return err;
  643. }
  644.  
  645. extern int ZEXPORT zipClose (file, global_comment)
  646.     zipFile file;
  647.     const char* global_comment;
  648. {
  649.     zip_internal* zi;
  650.     int err = 0;
  651.     uLong size_centraldir = 0;
  652.     uLong centraldir_pos_inzip ;
  653.     uInt size_global_comment;
  654.     if (file == NULL)
  655.         return ZIP_PARAMERROR;
  656.     zi = (zip_internal*)file;
  657.  
  658.     if (zi->in_opened_file_inzip == 1)
  659.     {
  660.         err = zipCloseFileInZip (file);
  661.     }
  662.  
  663.     if (global_comment==NULL)
  664.         size_global_comment = 0;
  665.     else
  666.         size_global_comment = strlen(global_comment);
  667.  
  668.  
  669.     centraldir_pos_inzip = ftell(zi->filezip);
  670.     if (err==ZIP_OK)
  671.     {
  672.         linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
  673.         while (ldi!=NULL)
  674.         {
  675.             if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
  676.                 if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,
  677.                                         1,zi->filezip) !=1 )
  678.                     err = ZIP_ERRNO;
  679.  
  680.             size_centraldir += ldi->filled_in_this_block;
  681.             ldi = ldi->next_datablock;
  682.         }
  683.     }
  684.     free_datablock(zi->central_dir.first_block);
  685.  
  686.     if (err==ZIP_OK) /* Magic End */
  687.         err = ziplocal_putValue(zi->filezip,(uLong)ENDHEADERMAGIC,4);
  688.  
  689.     if (err==ZIP_OK) /* number of this disk */
  690.         err = ziplocal_putValue(zi->filezip,(uLong)0,2);
  691.  
  692.     if (err==ZIP_OK) /* number of the disk with the start of the central directory */
  693.         err = ziplocal_putValue(zi->filezip,(uLong)0,2);
  694.  
  695.     if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
  696.         err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2);
  697.  
  698.     if (err==ZIP_OK) /* total number of entries in the central dir */
  699.         err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2);
  700.  
  701.     if (err==ZIP_OK) /* size of the central directory */
  702.         err = ziplocal_putValue(zi->filezip,(uLong)size_centraldir,4);
  703.  
  704.     if (err==ZIP_OK) /* offset of start of central directory with respect to the 
  705.                             starting disk number */
  706.         err = ziplocal_putValue(zi->filezip,(uLong)centraldir_pos_inzip ,4);
  707.  
  708.     if (err==ZIP_OK) /* zipfile comment length */
  709.         err = ziplocal_putValue(zi->filezip,(uLong)size_global_comment,2);
  710.  
  711.     if ((err==ZIP_OK) && (size_global_comment>0))
  712.         if (fwrite(global_comment,(uInt)size_global_comment,1,zi->filezip) !=1 )
  713.                 err = ZIP_ERRNO;
  714.     fclose(zi->filezip);
  715.     TRYFREE(zi);
  716.  
  717.     return err;
  718. }
  719.