zip.c
上传用户:zlt_tm
上传日期:2007-01-06
资源大小:214k
文件大小:21k
源码类别:

压缩解压

开发平台:

WINDOWS

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