zip.c

Go to the documentation of this file.
00001 /* zip.c -- IO on .zip files using zlib 
00002    Version 0.15 beta, Mar 19th, 1998,
00003 
00004    Modified by Ryan Nunn. Nov 9th 2001
00005 
00006    Read zip.h for more info
00007 */
00008 
00009 /* Added by Ryan Nunn */
00010 #ifdef HAVE_CONFIG_H
00011 #  include <config.h>
00012 #endif
00013 
00014 #ifdef HAVE_ZIP_SUPPORT
00015 
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <string.h>
00019 #include "zlib.h"
00020 #include "zip.h"
00021 
00022 /* Added by Ryan Nunn to overcome DEF_MEM_LEVEL being undeclared */
00023 #if MAX_MEM_LEVEL >= 8
00024 #  define DEF_MEM_LEVEL 8
00025 #else
00026 #  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
00027 #endif
00028 
00029 #ifdef STDC
00030 #  include <stddef.h>
00031 #  include <string.h>
00032 #  include <stdlib.h>
00033 #endif
00034 #ifdef NO_ERRNO_H
00035     extern int errno;
00036 #else
00037 #   include <errno.h>
00038 #endif
00039 
00040 /* Added by Max Horn - work around a work around in zlib 1.1.3 on MacOS */
00041 #if defined(MACOS) || defined(TARGET_OS_MAC)
00042 typedef unsigned char  Byte;  /* 8 bits */
00043 #endif
00044 
00045 #ifndef VERSIONMADEBY
00046 # define VERSIONMADEBY   (0x0) /* platform depedent */
00047 #endif
00048 
00049 #ifndef Z_BUFSIZE
00050 #define Z_BUFSIZE (16384)
00051 #endif
00052 
00053 #ifndef Z_MAXFILENAMEINZIP
00054 #define Z_MAXFILENAMEINZIP (256)
00055 #endif
00056 
00057 #ifndef ALLOC
00058 # define ALLOC(size) (malloc(size))
00059 #endif
00060 #ifndef TRYFREE
00061 # define TRYFREE(p) {if (p) free(p);}
00062 #endif
00063 
00064 /*
00065 #define SIZECENTRALDIRITEM (0x2e)
00066 #define SIZEZIPLOCALHEADER (0x1e)
00067 */
00068 
00069 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
00070 
00071 #ifndef SEEK_CUR
00072 #define SEEK_CUR    1
00073 #endif
00074 
00075 #ifndef SEEK_END
00076 #define SEEK_END    2
00077 #endif
00078 
00079 #ifndef SEEK_SET
00080 #define SEEK_SET    0
00081 #endif
00082 
00083 const char zip_copyright[] =
00084    " zip 0.15 Copyright 1998 Gilles Vollant ";
00085 
00086 
00087 #define SIZEDATA_INDATABLOCK (4096-(4*4))
00088 
00089 #define LOCALHEADERMAGIC    (0x04034b50)
00090 #define CENTRALHEADERMAGIC  (0x02014b50)
00091 #define ENDHEADERMAGIC      (0x06054b50)
00092 
00093 #define FLAG_LOCALHEADER_OFFSET (0x06)
00094 #define CRC_LOCALHEADER_OFFSET  (0x0e)
00095 
00096 #define SIZECENTRALHEADER (0x2e) /* 46 */
00097 
00098 typedef struct linkedlist_datablock_internal_s
00099 {
00100   struct linkedlist_datablock_internal_s* next_datablock;
00101   uLong  avail_in_this_block;
00102   uLong  filled_in_this_block;
00103   uLong  unused; /* for future use and alignement */
00104   unsigned char data[SIZEDATA_INDATABLOCK];
00105 } linkedlist_datablock_internal;
00106 
00107 typedef struct linkedlist_data_s
00108 {
00109     linkedlist_datablock_internal* first_block;
00110     linkedlist_datablock_internal* last_block;
00111 } linkedlist_data;
00112 
00113 typedef struct
00114 {
00115   z_stream stream;            /* zLib stream structure for inflate */
00116     int  stream_initialised;    /* 1 is stream is initialised */
00117     uInt pos_in_buffered_data;  /* last written byte in buffered_data */
00118 
00119     uLong pos_local_header;     /* offset of the local header of the file 
00120                                      currenty writing */
00121     char* central_header;       /* central header data for the current file */
00122     uLong size_centralheader;   /* size of the central header for cur file */
00123     uLong flag;                 /* flag of the file currently writing */
00124 
00125     int  method;                /* compression method of file currenty wr.*/
00126     Byte buffered_data[Z_BUFSIZE];/* buffer contain compressed data to be writ*/
00127     uLong dosDate;
00128     uLong crc32;
00129 } curfile_info;
00130 
00131 typedef struct
00132 {
00133     FILE * filezip;
00134     linkedlist_data central_dir;/* datablock with central dir in construction*/
00135     int  in_opened_file_inzip;  /* 1 if a file in the zip is currently writ.*/
00136     curfile_info ci;            /* info on the file curretly writing */
00137 
00138     uLong begin_pos;            /* position of the beginning of the zipfile */
00139     uLong number_entry;
00140 } zip_internal;
00141 
00142 static linkedlist_datablock_internal* allocate_new_datablock()
00143 {
00144     linkedlist_datablock_internal* ldi;
00145     ldi = (linkedlist_datablock_internal*)
00146                  ALLOC(sizeof(linkedlist_datablock_internal));
00147     if (ldi!=NULL)
00148     {
00149         ldi->next_datablock = NULL ;
00150         ldi->filled_in_this_block = 0 ;
00151         ldi->avail_in_this_block = SIZEDATA_INDATABLOCK ;
00152     }
00153     return ldi;
00154 }
00155 
00156 static void free_datablock(linkedlist_datablock_internal* ldi)
00157 {
00158     while (ldi!=NULL)
00159     {
00160         linkedlist_datablock_internal* ldinext = ldi->next_datablock;
00161         TRYFREE(ldi);
00162         ldi = ldinext;
00163     }
00164 }
00165 
00166 static void init_linkedlist(linkedlist_data* ll)
00167 {
00168     ll->first_block = ll->last_block = NULL;
00169 }
00170 
00171 static void free_linkedlist(linkedlist_data* ll)
00172 {
00173     free_datablock(ll->first_block);
00174     ll->first_block = ll->last_block = NULL;
00175 }
00176 
00177 
00178 static int add_data_in_datablock(linkedlist_data* ll, const void* buf, uLong len)
00179 {
00180     linkedlist_datablock_internal* ldi;
00181     const unsigned char* from_copy;
00182 
00183     if (ll==NULL)
00184         return ZIP_INTERNALERROR;
00185 
00186     if (ll->last_block == NULL)
00187     {
00188         ll->first_block = ll->last_block = allocate_new_datablock();
00189         if (ll->first_block == NULL)
00190             return ZIP_INTERNALERROR;
00191     }
00192 
00193     ldi = ll->last_block;
00194     from_copy = (unsigned char*)buf;
00195 
00196     while (len>0)
00197     {
00198         uInt copy_this;
00199         uInt i;
00200         unsigned char* to_copy;
00201 
00202         if (ldi->avail_in_this_block==0)
00203         {
00204             ldi->next_datablock = allocate_new_datablock();
00205             if (ldi->next_datablock == NULL)
00206                 return ZIP_INTERNALERROR;
00207             ldi = ldi->next_datablock ;
00208             ll->last_block = ldi;
00209         }
00210 
00211         if (ldi->avail_in_this_block < len)
00212             copy_this = (uInt)ldi->avail_in_this_block;
00213         else
00214             copy_this = (uInt)len;
00215 
00216         to_copy = &(ldi->data[ldi->filled_in_this_block]);
00217 
00218         for (i=0;i<copy_this;i++)
00219             *(to_copy+i)=*(from_copy+i);
00220 
00221         ldi->filled_in_this_block += copy_this;
00222         ldi->avail_in_this_block -= copy_this;
00223         from_copy += copy_this ;
00224         len -= copy_this;
00225     }
00226     return ZIP_OK;
00227 }
00228 
00229 
00230 static int write_datablock(FILE* fout, linkedlist_data* ll)
00231 {
00232     linkedlist_datablock_internal* ldi;
00233     ldi = ll->first_block;
00234     while (ldi!=NULL)
00235     {
00236         if (ldi->filled_in_this_block > 0)
00237             if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,1,fout)!=1)
00238                 return ZIP_ERRNO;
00239         ldi = ldi->next_datablock;
00240     }
00241     return ZIP_OK;
00242 }
00243 
00244 /****************************************************************************/
00245 
00246 /* ===========================================================================
00247    Outputs a long in LSB order to the given file
00248    nbByte == 1, 2 or 4 (byte, short or long)
00249 */
00250 
00251 static int ziplocal_putValue (FILE *file, uLong x, int nbByte);
00252 static int ziplocal_putValue (FILE *file, uLong x, int nbByte)
00253 {
00254     unsigned char buf[4];
00255     int n;
00256     for (n = 0; n < nbByte; n++) {
00257         buf[n] = (unsigned char)(x & 0xff);
00258         x >>= 8;
00259     }
00260     if (fwrite(buf,nbByte,1,file)!=1)
00261         return ZIP_ERRNO;
00262     else
00263         return ZIP_OK;
00264 }
00265 
00266 static void ziplocal_putValue_inmemory (void* dest, uLong x, int nbByte);
00267 static void ziplocal_putValue_inmemory (void* dest, uLong x, int nbByte)
00268 {
00269     unsigned char* buf=(unsigned char*)dest;
00270     int n;
00271     for (n = 0; n < nbByte; n++) {
00272         buf[n] = (unsigned char)(x & 0xff);
00273         x >>= 8;
00274     }
00275 }
00276 /****************************************************************************/
00277 
00278 
00279 static uLong ziplocal_TmzDateToDosDate(const tm_zip* ptm, uLong uLongdosDate)
00280 {
00281     uLong year = (uLong)ptm->tm_year;
00282     if (year>1980)
00283         year-=1980;
00284     else if (year>80)
00285         year-=80;
00286     return
00287       (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
00288         ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
00289 }
00290 
00291 
00292 /****************************************************************************/
00293 
00294 extern zipFile ZEXPORT zipOpen (const char *pathname, int append)
00295 {
00296     zip_internal ziinit;
00297     zip_internal* zi;
00298 
00299     ziinit.filezip = NULL;
00300 
00301 /* Start changes by Ryan Nunn to fix append mode bug */
00302 
00303     /* If append, use r+b mode, will fail if not exist */
00304     if (append != 0)
00305       ziinit.filezip = fopen(pathname,"r+b");
00306 
00307     /* If not append, or failed, use wb */
00308     if (ziinit.filezip == NULL)
00309       ziinit.filezip = fopen(pathname,"wb");
00310 
00311     /* Still doesn't exist, means can't create */
00312     if (ziinit.filezip == NULL)
00313         return NULL;
00314 
00315     /* Make sure we are at the end of the file */
00316     fseek (ziinit.filezip, 0, SEEK_END);
00317 
00318 /* End changes by Ryan Nunn to fix append mode bug */
00319 
00320     ziinit.begin_pos = ftell(ziinit.filezip);
00321     ziinit.in_opened_file_inzip = 0;
00322     ziinit.ci.stream_initialised = 0;
00323     ziinit.number_entry = 0;
00324     init_linkedlist(&(ziinit.central_dir));
00325 
00326 
00327     zi = (zip_internal*)ALLOC(sizeof(zip_internal));
00328     if (zi==NULL)
00329     {
00330         fclose(ziinit.filezip);
00331         return NULL;
00332     }
00333 
00334     *zi = ziinit;
00335     return (zipFile)zi;
00336 }
00337 
00338 extern int ZEXPORT zipOpenNewFileInZip (zipFile file,
00339              const char* filename,
00340              const zip_fileinfo* zipfi,
00341              const void* extrafield_local,
00342              uInt size_extrafield_local,
00343              const void* extrafield_global,
00344              uInt size_extrafield_global,
00345              const char* comment,
00346              int method,
00347              int level)
00348 {
00349     zip_internal* zi;
00350     uInt size_filename;
00351     uInt size_comment;
00352     uInt i;
00353     int err = ZIP_OK;
00354 
00355     if (file == NULL)
00356         return ZIP_PARAMERROR;
00357     if ((method!=0) && (method!=Z_DEFLATED))
00358         return ZIP_PARAMERROR;
00359 
00360     zi = (zip_internal*)file;
00361 
00362     if (zi->in_opened_file_inzip == 1)
00363     {
00364         err = zipCloseFileInZip (file);
00365         if (err != ZIP_OK)
00366             return err;
00367     }
00368 
00369 
00370     if (filename==NULL)
00371         filename="-";
00372 
00373     if (comment==NULL)
00374         size_comment = 0;
00375     else
00376         size_comment = strlen(comment);
00377 
00378     size_filename = strlen(filename);
00379 
00380     if (zipfi == NULL)
00381         zi->ci.dosDate = 0;
00382     else
00383     {
00384         if (zipfi->dosDate != 0)
00385             zi->ci.dosDate = zipfi->dosDate;
00386         else zi->ci.dosDate = ziplocal_TmzDateToDosDate(&zipfi->tmz_date,zipfi->dosDate);
00387     }
00388 
00389     zi->ci.flag = 0;
00390     if ((level==8) || (level==9))
00391       zi->ci.flag |= 2;
00392     if ((level==2))
00393       zi->ci.flag |= 4;
00394     if ((level==1))
00395       zi->ci.flag |= 6;
00396 
00397     zi->ci.crc32 = 0;
00398     zi->ci.method = method;
00399     zi->ci.stream_initialised = 0;
00400     zi->ci.pos_in_buffered_data = 0;
00401     zi->ci.pos_local_header = ftell(zi->filezip);
00402     zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + 
00403                                       size_extrafield_global + size_comment;
00404     zi->ci.central_header = (char*)ALLOC((uInt)zi->ci.size_centralheader);
00405 
00406     ziplocal_putValue_inmemory(zi->ci.central_header,(uLong)CENTRALHEADERMAGIC,4);
00407     /* version info */
00408     ziplocal_putValue_inmemory(zi->ci.central_header+4,(uLong)VERSIONMADEBY,2);
00409     ziplocal_putValue_inmemory(zi->ci.central_header+6,(uLong)20,2);
00410     ziplocal_putValue_inmemory(zi->ci.central_header+8,(uLong)zi->ci.flag,2);
00411     ziplocal_putValue_inmemory(zi->ci.central_header+10,(uLong)zi->ci.method,2);
00412     ziplocal_putValue_inmemory(zi->ci.central_header+12,(uLong)zi->ci.dosDate,4);
00413     ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)0,4); /*crc*/
00414     ziplocal_putValue_inmemory(zi->ci.central_header+20,(uLong)0,4); /*compr size*/
00415     ziplocal_putValue_inmemory(zi->ci.central_header+24,(uLong)0,4); /*uncompr size*/
00416     ziplocal_putValue_inmemory(zi->ci.central_header+28,(uLong)size_filename,2);
00417     ziplocal_putValue_inmemory(zi->ci.central_header+30,(uLong)size_extrafield_global,2);
00418     ziplocal_putValue_inmemory(zi->ci.central_header+32,(uLong)size_comment,2);
00419     ziplocal_putValue_inmemory(zi->ci.central_header+34,(uLong)0,2); /*disk nm start*/
00420 
00421     if (zipfi==NULL)
00422         ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)0,2); 
00423     else
00424         ziplocal_putValue_inmemory(zi->ci.central_header+36,(uLong)zipfi->internal_fa,2); 
00425 
00426     if (zipfi==NULL)
00427         ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)0,4); 
00428     else
00429         ziplocal_putValue_inmemory(zi->ci.central_header+38,(uLong)zipfi->external_fa,4);
00430 
00431     ziplocal_putValue_inmemory(zi->ci.central_header+42,(uLong)zi->ci.pos_local_header,4);
00432 
00433     for (i=0;i<size_filename;i++)
00434         *(zi->ci.central_header+SIZECENTRALHEADER+i) = *(filename+i);
00435 
00436     for (i=0;i<size_extrafield_global;i++)
00437         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+i) =
00438               *(((const char*)extrafield_global)+i);
00439 
00440     for (i=0;i<size_comment;i++)
00441         *(zi->ci.central_header+SIZECENTRALHEADER+size_filename+
00442               size_extrafield_global+i) = *(filename+i);
00443     if (zi->ci.central_header == NULL)
00444         return ZIP_INTERNALERROR;
00445 
00446     /* write the local header */
00447     err = ziplocal_putValue(zi->filezip,(uLong)LOCALHEADERMAGIC,4);
00448 
00449     if (err==ZIP_OK)
00450         err = ziplocal_putValue(zi->filezip,(uLong)20,2);/* version needed to extract */
00451     if (err==ZIP_OK)
00452         err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.flag,2);
00453 
00454     if (err==ZIP_OK)
00455         err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.method,2);
00456 
00457     if (err==ZIP_OK)
00458         err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.dosDate,4);
00459 
00460     if (err==ZIP_OK)
00461         err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* crc 32, unknown */
00462     if (err==ZIP_OK)
00463         err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* compressed size, unknown */
00464     if (err==ZIP_OK)
00465         err = ziplocal_putValue(zi->filezip,(uLong)0,4); /* uncompressed size, unknown */
00466 
00467     if (err==ZIP_OK)
00468         err = ziplocal_putValue(zi->filezip,(uLong)size_filename,2);
00469 
00470     if (err==ZIP_OK)
00471         err = ziplocal_putValue(zi->filezip,(uLong)size_extrafield_local,2);
00472 
00473     if ((err==ZIP_OK) && (size_filename>0))
00474         if (fwrite(filename,(uInt)size_filename,1,zi->filezip)!=1)
00475                 err = ZIP_ERRNO;
00476 
00477     if ((err==ZIP_OK) && (size_extrafield_local>0))
00478         if (fwrite(extrafield_local,(uInt)size_extrafield_local,1,zi->filezip)
00479                                                                            !=1)
00480                 err = ZIP_ERRNO;
00481 
00482     zi->ci.stream.avail_in = (uInt)0;
00483     zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
00484     zi->ci.stream.next_out = zi->ci.buffered_data;
00485     zi->ci.stream.total_in = 0;
00486     zi->ci.stream.total_out = 0;
00487 
00488     if ((err==ZIP_OK) && (zi->ci.method == Z_DEFLATED))
00489     {
00490         zi->ci.stream.zalloc = (alloc_func)0;
00491         zi->ci.stream.zfree = (free_func)0;
00492         zi->ci.stream.opaque = (voidpf)0;
00493 
00494         err = deflateInit2(&zi->ci.stream, level,
00495                Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0);
00496 
00497         if (err==Z_OK)
00498             zi->ci.stream_initialised = 1;
00499     }
00500 
00501 
00502     if (err==Z_OK)
00503         zi->in_opened_file_inzip = 1;
00504     return err;
00505 }
00506 
00507 extern int ZEXPORT zipWriteInFileInZip (zipFile file, const voidp buf, unsigned len)
00508 {
00509     zip_internal* zi;
00510     int err=ZIP_OK;
00511 
00512     if (file == NULL)
00513         return ZIP_PARAMERROR;
00514     zi = (zip_internal*)file;
00515 
00516     if (zi->in_opened_file_inzip == 0)
00517         return ZIP_PARAMERROR;
00518 
00519     zi->ci.stream.next_in = (Bytef *)buf;
00520     zi->ci.stream.avail_in = len;
00521     zi->ci.crc32 = crc32(zi->ci.crc32,(Bytef *)buf,len);
00522 
00523     while ((err==ZIP_OK) && (zi->ci.stream.avail_in>0))
00524     {
00525         if (zi->ci.stream.avail_out == 0)
00526         {
00527             if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
00528                                                                            !=1)
00529                 err = ZIP_ERRNO;
00530             zi->ci.pos_in_buffered_data = 0;
00531             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
00532             zi->ci.stream.next_out = zi->ci.buffered_data;
00533         }
00534 
00535         if (zi->ci.method == Z_DEFLATED)
00536         {
00537             uLong uTotalOutBefore = zi->ci.stream.total_out;
00538             err=deflate(&zi->ci.stream,  Z_NO_FLUSH);
00539             zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
00540 
00541         }
00542         else
00543         {
00544             uInt copy_this,i;
00545             if (zi->ci.stream.avail_in < zi->ci.stream.avail_out)
00546                 copy_this = zi->ci.stream.avail_in;
00547             else
00548                 copy_this = zi->ci.stream.avail_out;
00549             for (i=0;i<copy_this;i++)
00550                 *(((char*)zi->ci.stream.next_out)+i) =
00551                     *(((const char*)zi->ci.stream.next_in)+i);
00552             {
00553                 zi->ci.stream.avail_in -= copy_this;
00554                 zi->ci.stream.avail_out-= copy_this;
00555                 zi->ci.stream.next_in+= copy_this;
00556                 zi->ci.stream.next_out+= copy_this;
00557                 zi->ci.stream.total_in+= copy_this;
00558                 zi->ci.stream.total_out+= copy_this;
00559                 zi->ci.pos_in_buffered_data += copy_this;
00560             }
00561         }
00562     }
00563 
00564     return 0;
00565 }
00566 
00567 extern int ZEXPORT zipCloseFileInZip (zipFile file)
00568 {
00569     zip_internal* zi;
00570     int err=ZIP_OK;
00571 
00572     if (file == NULL)
00573         return ZIP_PARAMERROR;
00574     zi = (zip_internal*)file;
00575 
00576     if (zi->in_opened_file_inzip == 0)    
00577         return ZIP_PARAMERROR;
00578     zi->ci.stream.avail_in = 0;
00579     
00580     if (zi->ci.method == Z_DEFLATED)
00581         while (err==ZIP_OK)
00582     {
00583         uLong uTotalOutBefore;
00584         if (zi->ci.stream.avail_out == 0)
00585         {
00586             if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
00587                                                                            !=1)
00588                 err = ZIP_ERRNO;
00589             zi->ci.pos_in_buffered_data = 0;
00590             zi->ci.stream.avail_out = (uInt)Z_BUFSIZE;
00591             zi->ci.stream.next_out = zi->ci.buffered_data;
00592         }
00593         uTotalOutBefore = zi->ci.stream.total_out;
00594         err=deflate(&zi->ci.stream,  Z_FINISH);
00595         zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
00596     }
00597 
00598     if (err==Z_STREAM_END)
00599         err=ZIP_OK; /* this is normal */
00600 
00601     if ((zi->ci.pos_in_buffered_data>0) && (err==ZIP_OK))
00602         if (fwrite(zi->ci.buffered_data,(uInt)zi->ci.pos_in_buffered_data,1,zi->filezip)
00603                                                                        !=1)
00604             err = ZIP_ERRNO;
00605 
00606     if ((zi->ci.method == Z_DEFLATED) && (err==ZIP_OK))
00607     {
00608         err=deflateEnd(&zi->ci.stream);
00609         zi->ci.stream_initialised = 0;
00610     }
00611 
00612     ziplocal_putValue_inmemory(zi->ci.central_header+16,(uLong)zi->ci.crc32,4); /*crc*/
00613     ziplocal_putValue_inmemory(zi->ci.central_header+20,
00614                                 (uLong)zi->ci.stream.total_out,4); /*compr size*/
00615     ziplocal_putValue_inmemory(zi->ci.central_header+24,
00616                                 (uLong)zi->ci.stream.total_in,4); /*uncompr size*/
00617 
00618     if (err==ZIP_OK)
00619         err = add_data_in_datablock(&zi->central_dir,zi->ci.central_header,
00620                                        (uLong)zi->ci.size_centralheader);
00621     free(zi->ci.central_header);
00622 
00623     if (err==ZIP_OK)
00624     {
00625         long cur_pos_inzip = ftell(zi->filezip);
00626       if (fseek(zi->filezip,
00627                   zi->ci.pos_local_header + 14,SEEK_SET)!=0)
00628         err = ZIP_ERRNO;
00629 
00630         if (err==ZIP_OK)
00631             err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.crc32,4); /* crc 32, unknown */
00632 
00633         if (err==ZIP_OK) /* compressed size, unknown */
00634             err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_out,4); 
00635 
00636         if (err==ZIP_OK) /* uncompressed size, unknown */
00637             err = ziplocal_putValue(zi->filezip,(uLong)zi->ci.stream.total_in,4);
00638 
00639       if (fseek(zi->filezip,
00640                   cur_pos_inzip,SEEK_SET)!=0)
00641         err = ZIP_ERRNO;
00642     }
00643 
00644     zi->number_entry ++;
00645     zi->in_opened_file_inzip = 0;
00646 
00647     return err;
00648 }
00649 
00650 extern int ZEXPORT zipClose (zipFile file, const char* global_comment)
00651 {
00652     zip_internal* zi;
00653     int err = 0;
00654     uLong size_centraldir = 0;
00655     uLong centraldir_pos_inzip ;
00656     uInt size_global_comment;
00657     if (file == NULL)
00658         return ZIP_PARAMERROR;
00659     zi = (zip_internal*)file;
00660 
00661     if (zi->in_opened_file_inzip == 1)
00662     {
00663         err = zipCloseFileInZip (file);
00664     }
00665 
00666     if (global_comment==NULL)
00667         size_global_comment = 0;
00668     else
00669         size_global_comment = strlen(global_comment);
00670 
00671 
00672     centraldir_pos_inzip = ftell(zi->filezip);
00673     if (err==ZIP_OK)
00674     {
00675         linkedlist_datablock_internal* ldi = zi->central_dir.first_block ;
00676         while (ldi!=NULL)
00677         {
00678             if ((err==ZIP_OK) && (ldi->filled_in_this_block>0))
00679                 if (fwrite(ldi->data,(uInt)ldi->filled_in_this_block,
00680                                         1,zi->filezip) !=1 )
00681                     err = ZIP_ERRNO;
00682 
00683             size_centraldir += ldi->filled_in_this_block;
00684             ldi = ldi->next_datablock;
00685         }
00686     }
00687     free_datablock(zi->central_dir.first_block);
00688 
00689     if (err==ZIP_OK) /* Magic End */
00690         err = ziplocal_putValue(zi->filezip,(uLong)ENDHEADERMAGIC,4);
00691 
00692     if (err==ZIP_OK) /* number of this disk */
00693         err = ziplocal_putValue(zi->filezip,(uLong)0,2);
00694 
00695     if (err==ZIP_OK) /* number of the disk with the start of the central directory */
00696         err = ziplocal_putValue(zi->filezip,(uLong)0,2);
00697 
00698     if (err==ZIP_OK) /* total number of entries in the central dir on this disk */
00699         err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2);
00700 
00701     if (err==ZIP_OK) /* total number of entries in the central dir */
00702         err = ziplocal_putValue(zi->filezip,(uLong)zi->number_entry,2);
00703 
00704     if (err==ZIP_OK) /* size of the central directory */
00705         err = ziplocal_putValue(zi->filezip,(uLong)size_centraldir,4);
00706 
00707     if (err==ZIP_OK) /* offset of start of central directory with respect to the 
00708                           starting disk number */
00709         err = ziplocal_putValue(zi->filezip,(uLong)centraldir_pos_inzip ,4);
00710 
00711     if (err==ZIP_OK) /* zipfile comment length */
00712         err = ziplocal_putValue(zi->filezip,(uLong)size_global_comment,2);
00713 
00714     if ((err==ZIP_OK) && (size_global_comment>0))
00715         if (fwrite(global_comment,(uInt)size_global_comment,1,zi->filezip) !=1 )
00716                 err = ZIP_ERRNO;
00717     fclose(zi->filezip);
00718     TRYFREE(zi);
00719 
00720     return err;
00721 }
00722 
00723 /* Added by Ryan Nunn */
00724 #endif /*HAVE_ZIP_SUPPORT*/

Generated on Mon Jul 9 14:42:45 2007 for ExultEngine by  doxygen 1.5.1