faster zip implementation, works only for one zip archive right now, since there...
[cacao.git] / unzip.c
1 #include "config.h"
2 #ifdef USE_ZLIB
3
4 /* unzip.c -- IO on .zip files using zlib 
5    Version 0.15 beta, Mar 19th, 1998,
6
7    Read unzip.h for more info
8 */
9
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include "zlib.h"
15 #include "unzip.h"
16
17 #ifdef STDC
18 #  include <stddef.h>
19 #  include <string.h>
20 #  include <stdlib.h>
21 #endif
22 #ifdef NO_ERRNO_H
23     extern int errno;
24 #else
25 #   include <errno.h>
26 #endif
27
28
29 #include "global.h"
30 #include "tables.h"
31
32 #ifndef local
33 #  define local static
34 #endif
35 /* compile with -Dlocal if your debugger can't find static symbols */
36
37
38
39 #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
40                       !defined(CASESENSITIVITYDEFAULT_NO)
41 #define CASESENSITIVITYDEFAULT_NO
42 #endif
43
44
45 #ifndef UNZ_BUFSIZE
46 #define UNZ_BUFSIZE (16384)
47 #endif
48
49 #ifndef UNZ_MAXFILENAMEINZIP
50 #define UNZ_MAXFILENAMEINZIP (256)
51 #endif
52
53 #ifndef ALLOC
54 # define ALLOC(size) (malloc(size))
55 #endif
56 #ifndef TRYFREE
57 # define TRYFREE(p) {if (p) free(p);}
58 #endif
59
60 #define SIZECENTRALDIRITEM (0x2e)
61 #define SIZEZIPLOCALHEADER (0x1e)
62
63
64 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
65
66 #ifndef SEEK_CUR
67 #define SEEK_CUR    1
68 #endif
69
70 #ifndef SEEK_END
71 #define SEEK_END    2
72 #endif
73
74 #ifndef SEEK_SET
75 #define SEEK_SET    0
76 #endif
77
78 const char unz_copyright[] =
79    " unzip 0.15 Copyright 1998 Gilles Vollant ";
80
81 /* unz_file_info_interntal contain internal info about a file in zipfile*/
82 typedef struct unz_file_info_internal_s
83 {
84     uLong offset_curfile;/* relative offset of local header 4 bytes */
85 } unz_file_info_internal;
86
87
88 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
89     when reading and decompress it */
90 typedef struct
91 {
92         char  *read_buffer;         /* internal buffer for compressed data */
93         z_stream stream;            /* zLib stream structure for inflate */
94
95         uLong pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
96         uLong stream_initialised;   /* flag set if stream structure is initialised*/
97
98         uLong offset_local_extrafield;/* offset of the local extra field */
99         uInt  size_local_extrafield;/* size of the local extra field */
100         uLong pos_local_extrafield;   /* position in the local extra field in read*/
101
102         uLong crc32;                /* crc32 of all data uncompressed */
103         uLong crc32_wait;           /* crc32 we must obtain after decompress all */
104         uLong rest_read_compressed; /* number of byte to be decompressed */
105         uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
106         FILE* file;                 /* io structore of the zipfile */
107         uLong compression_method;   /* compression method (0==store) */
108         uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
109 } file_in_zip_read_info_s;
110
111
112 /*JOWENN*/
113 typedef struct cacao_entry
114 {
115         struct cacao_entry *next;
116         utf *name;
117         uLong pos;
118 } cacao_entry_s;
119
120 /* unz_s contain internal information about the zipfile
121 */
122 typedef struct
123 {
124         FILE* file;                 /* io structore of the zipfile */
125         unz_global_info gi;       /* public global information */
126         uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
127         uLong num_file;             /* number of the current file in the zipfile*/
128         uLong pos_in_central_dir;   /* pos of the current file in the central dir*/
129         uLong current_file_ok;      /* flag about the usability of the current file*/
130         uLong central_pos;          /* position of the beginning of the central dir*/
131
132         uLong size_central_dir;     /* size of the central directory  */
133         uLong offset_central_dir;   /* offset of start of central directory with
134                                                                    respect to the starting disk number */
135
136         unz_file_info cur_file_info; /* public info about the current file in zip*/
137         unz_file_info_internal cur_file_info_internal; /* private info about it*/
138         file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
139                                             file if we are decompressing it */
140         cacao_entry_s *cacao_dir_list;
141 } unz_s;
142
143
144 /* ===========================================================================
145      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
146    for end of file.
147    IN assertion: the stream s has been sucessfully opened for reading.
148 */
149
150
151 local int unzlocal_getByte(fin,pi)
152         FILE *fin;
153         int *pi;
154 {
155     unsigned char c;
156         int err = fread(&c, 1, 1, fin);
157     if (err==1)
158     {
159         *pi = (int)c;
160         return UNZ_OK;
161     }
162     else
163     {
164         if (ferror(fin)) 
165             return UNZ_ERRNO;
166         else
167             return UNZ_EOF;
168     }
169 }
170
171
172 /* ===========================================================================
173    Reads a long in LSB order from the given gz_stream. Sets 
174 */
175 local int unzlocal_getShort (fin,pX)
176         FILE* fin;
177     uLong *pX;
178 {
179     uLong x ;
180     int i;
181     int err;
182
183     err = unzlocal_getByte(fin,&i);
184     x = (uLong)i;
185     
186     if (err==UNZ_OK)
187         err = unzlocal_getByte(fin,&i);
188     x += ((uLong)i)<<8;
189    
190     if (err==UNZ_OK)
191         *pX = x;
192     else
193         *pX = 0;
194     return err;
195 }
196
197 local int unzlocal_getLong (fin,pX)
198         FILE* fin;
199     uLong *pX;
200 {
201     uLong x ;
202     int i;
203     int err;
204
205     err = unzlocal_getByte(fin,&i);
206     x = (uLong)i;
207     
208     if (err==UNZ_OK)
209         err = unzlocal_getByte(fin,&i);
210     x += ((uLong)i)<<8;
211
212     if (err==UNZ_OK)
213         err = unzlocal_getByte(fin,&i);
214     x += ((uLong)i)<<16;
215
216     if (err==UNZ_OK)
217         err = unzlocal_getByte(fin,&i);
218     x += ((uLong)i)<<24;
219    
220     if (err==UNZ_OK)
221         *pX = x;
222     else
223         *pX = 0;
224     return err;
225 }
226
227
228 /* My own strcmpi / strcasecmp */
229 local int strcmpcasenosensitive_internal (fileName1,fileName2)
230         const char* fileName1;
231         const char* fileName2;
232 {
233         for (;;)
234         {
235                 char c1=*(fileName1++);
236                 char c2=*(fileName2++);
237                 if ((c1>='a') && (c1<='z'))
238                         c1 -= 0x20;
239                 if ((c2>='a') && (c2<='z'))
240                         c2 -= 0x20;
241                 if (c1=='\0')
242                         return ((c2=='\0') ? 0 : -1);
243                 if (c2=='\0')
244                         return 1;
245                 if (c1<c2)
246                         return -1;
247                 if (c1>c2)
248                         return 1;
249         }
250 }
251
252
253 #ifdef  CASESENSITIVITYDEFAULT_NO
254 #define CASESENSITIVITYDEFAULTVALUE 2
255 #else
256 #define CASESENSITIVITYDEFAULTVALUE 1
257 #endif
258
259 #ifndef STRCMPCASENOSENTIVEFUNCTION
260 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
261 #endif
262
263 /* 
264    Compare two filename (fileName1,fileName2).
265    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
266    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
267                                                                 or strcasecmp)
268    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
269         (like 1 on Unix, 2 on Windows)
270
271 */
272 extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
273         const char* fileName1;
274         const char* fileName2;
275         int iCaseSensitivity;
276 {
277         if (iCaseSensitivity==0)
278                 iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
279
280         if (iCaseSensitivity==1)
281                 return strcmp(fileName1,fileName2);
282
283         return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
284
285
286 #define BUFREADCOMMENT (0x400)
287
288 /*
289   Locate the Central directory of a zipfile (at the end, just before
290     the global comment)
291 */
292 local uLong unzlocal_SearchCentralDir(fin)
293         FILE *fin;
294 {
295         unsigned char* buf;
296         uLong uSizeFile;
297         uLong uBackRead;
298         uLong uMaxBack=0xffff; /* maximum size of global comment */
299         uLong uPosFound=0;
300         
301         if (fseek(fin,0,SEEK_END) != 0)
302                 return 0;
303
304
305         uSizeFile = ftell( fin );
306         
307         if (uMaxBack>uSizeFile)
308                 uMaxBack = uSizeFile;
309
310         buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
311         if (buf==NULL)
312                 return 0;
313
314         uBackRead = 4;
315         while (uBackRead<uMaxBack)
316         {
317                 uLong uReadSize,uReadPos ;
318                 int i;
319                 if (uBackRead+BUFREADCOMMENT>uMaxBack) 
320                         uBackRead = uMaxBack;
321                 else
322                         uBackRead+=BUFREADCOMMENT;
323                 uReadPos = uSizeFile-uBackRead ;
324                 
325                 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 
326                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
327                 if (fseek(fin,uReadPos,SEEK_SET)!=0)
328                         break;
329
330                 if (fread(buf,(uInt)uReadSize,1,fin)!=1)
331                         break;
332
333                 for (i=(int)uReadSize-3; (i--)>0;)
334                         if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && 
335                                 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
336                         {
337                                 uPosFound = uReadPos+i;
338                                 break;
339                         }
340
341                 if (uPosFound!=0)
342                         break;
343         }
344         TRYFREE(buf);
345         return uPosFound;
346 }
347
348 /*
349   Open a Zip file. path contain the full pathname (by example,
350      on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
351          "zlib/zlib109.zip".
352          If the zipfile cannot be opened (file don't exist or in not valid), the
353            return value is NULL.
354      Else, the return value is a unzFile Handle, usable with other function
355            of this unzip package.
356 */
357 extern unzFile ZEXPORT unzOpen (path)
358         const char *path;
359 {
360         unz_s us;
361         unz_s *s;
362         uLong central_pos,uL;
363         FILE * fin ;
364
365         uLong number_disk;          /* number of the current dist, used for 
366                                                                    spaning ZIP, unsupported, always 0*/
367         uLong number_disk_with_CD;  /* number the the disk with central dir, used
368                                                                    for spaning ZIP, unsupported, always 0*/
369         uLong number_entry_CD;      /* total number of entries in
370                                        the central dir 
371                                        (same than number_entry on nospan) */
372
373         int err=UNZ_OK;
374
375     if (unz_copyright[0]!=' ')
376         return NULL;
377
378     fin=fopen(path,"rb");
379         if (fin==NULL)
380                 return NULL;
381
382         central_pos = unzlocal_SearchCentralDir(fin);
383         if (central_pos==0)
384                 err=UNZ_ERRNO;
385
386         if (fseek(fin,central_pos,SEEK_SET)!=0)
387                 err=UNZ_ERRNO;
388
389         /* the signature, already checked */
390         if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
391                 err=UNZ_ERRNO;
392
393         /* number of this disk */
394         if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
395                 err=UNZ_ERRNO;
396
397         /* number of the disk with the start of the central directory */
398         if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
399                 err=UNZ_ERRNO;
400
401         /* total number of entries in the central dir on this disk */
402         if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
403                 err=UNZ_ERRNO;
404
405         /* total number of entries in the central dir */
406         if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
407                 err=UNZ_ERRNO;
408
409         if ((number_entry_CD!=us.gi.number_entry) ||
410                 (number_disk_with_CD!=0) ||
411                 (number_disk!=0))
412                 err=UNZ_BADZIPFILE;
413
414         /* size of the central directory */
415         if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
416                 err=UNZ_ERRNO;
417         /* offset of start of central directory with respect to the 
418               starting disk number */
419         if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
420                 err=UNZ_ERRNO;
421
422         /* zipfile comment length */
423         if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
424                 err=UNZ_ERRNO;
425
426         if ((central_pos<us.offset_central_dir+us.size_central_dir) && 
427                 (err==UNZ_OK))
428                 err=UNZ_BADZIPFILE;
429
430         if (err!=UNZ_OK)
431         {
432                 fclose(fin);
433                 return NULL;
434         }
435
436         us.file=fin;
437         us.byte_before_the_zipfile = central_pos -
438                                     (us.offset_central_dir+us.size_central_dir);
439         us.central_pos = central_pos;
440     us.pfile_in_zip_read = NULL;
441         
442
443         s=(unz_s*)ALLOC(sizeof(unz_s));
444         *s=us;
445
446         cacao_create_directoryList(s);
447
448         unzGoToFirstFile((unzFile)s);   
449         return (unzFile)s;      
450 }
451
452
453 /*
454   Close a ZipFile opened with unzipOpen.
455   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
456     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
457   return UNZ_OK if there is no problem. */
458 extern int ZEXPORT unzClose (file)
459         unzFile file;
460 {
461         unz_s* s;
462         if (file==NULL)
463                 return UNZ_PARAMERROR;
464         s=(unz_s*)file;
465
466     if (s->pfile_in_zip_read!=NULL)
467         unzCloseCurrentFile(file);
468
469         fclose(s->file);
470         TRYFREE(s);
471         return UNZ_OK;
472 }
473
474
475 /*
476   Write info about the ZipFile in the *pglobal_info structure.
477   No preparation of the structure is needed
478   return UNZ_OK if there is no problem. */
479 extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
480         unzFile file;
481         unz_global_info *pglobal_info;
482 {
483         unz_s* s;
484         if (file==NULL)
485                 return UNZ_PARAMERROR;
486         s=(unz_s*)file;
487         *pglobal_info=s->gi;
488         return UNZ_OK;
489 }
490
491
492 /*
493    Translate date/time from Dos format to tm_unz (readable more easilty)
494 */
495 local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
496     uLong ulDosDate;
497     tm_unz* ptm;
498 {
499     uLong uDate;
500     uDate = (uLong)(ulDosDate>>16);
501     ptm->tm_mday = (uInt)(uDate&0x1f) ;
502     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
503     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
504
505     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
506     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
507     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
508 }
509
510 /*
511   Get Info about the current file in the zipfile, with internal only info
512 */
513 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
514                                                   unz_file_info *pfile_info,
515                                                   unz_file_info_internal 
516                                                   *pfile_info_internal,
517                                                   char *szFileName,
518                                                                                                   uLong fileNameBufferSize,
519                                                   void *extraField,
520                                                                                                   uLong extraFieldBufferSize,
521                                                   char *szComment,
522                                                                                                   uLong commentBufferSize));
523
524 local int unzlocal_GetCurrentFileInfoInternal (file,
525                                               pfile_info,
526                                               pfile_info_internal,
527                                               szFileName, fileNameBufferSize,
528                                               extraField, extraFieldBufferSize,
529                                               szComment,  commentBufferSize)
530         unzFile file;
531         unz_file_info *pfile_info;
532         unz_file_info_internal *pfile_info_internal;
533         char *szFileName;
534         uLong fileNameBufferSize;
535         void *extraField;
536         uLong extraFieldBufferSize;
537         char *szComment;
538         uLong commentBufferSize;
539 {
540         unz_s* s;
541         unz_file_info file_info;
542         unz_file_info_internal file_info_internal;
543         int err=UNZ_OK;
544         uLong uMagic;
545         long lSeek=0;
546
547         if (file==NULL)
548                 return UNZ_PARAMERROR;
549         s=(unz_s*)file;
550         if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
551                 err=UNZ_ERRNO;
552
553
554         /* we check the magic */
555         if (err==UNZ_OK)
556                 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
557                         err=UNZ_ERRNO;
558                 else if (uMagic!=0x02014b50)
559                         err=UNZ_BADZIPFILE;
560
561         if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
562                 err=UNZ_ERRNO;
563
564         if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
565                 err=UNZ_ERRNO;
566
567         if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
568                 err=UNZ_ERRNO;
569
570         if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
571                 err=UNZ_ERRNO;
572
573         if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
574                 err=UNZ_ERRNO;
575
576     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
577
578         if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
579                 err=UNZ_ERRNO;
580
581         if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
582                 err=UNZ_ERRNO;
583
584         if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
585                 err=UNZ_ERRNO;
586
587         if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
588                 err=UNZ_ERRNO;
589
590         if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
591                 err=UNZ_ERRNO;
592
593         if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
594                 err=UNZ_ERRNO;
595
596         if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
597                 err=UNZ_ERRNO;
598
599         if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
600                 err=UNZ_ERRNO;
601
602         if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
603                 err=UNZ_ERRNO;
604
605         if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
606                 err=UNZ_ERRNO;
607
608         lSeek+=file_info.size_filename;
609         if ((err==UNZ_OK) && (szFileName!=NULL))
610         {
611                 uLong uSizeRead ;
612                 if (file_info.size_filename<fileNameBufferSize)
613                 {
614                         *(szFileName+file_info.size_filename)='\0';
615                         uSizeRead = file_info.size_filename;
616                 }
617                 else
618                         uSizeRead = fileNameBufferSize;
619
620                 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
621                         if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
622                                 err=UNZ_ERRNO;
623                 lSeek -= uSizeRead;
624         }
625
626         
627         if ((err==UNZ_OK) && (extraField!=NULL))
628         {
629                 uLong uSizeRead ;
630                 if (file_info.size_file_extra<extraFieldBufferSize)
631                         uSizeRead = file_info.size_file_extra;
632                 else
633                         uSizeRead = extraFieldBufferSize;
634
635                 if (lSeek!=0)
636                         if (fseek(s->file,lSeek,SEEK_CUR)==0)
637                                 lSeek=0;
638                         else
639                                 err=UNZ_ERRNO;
640                 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
641                         if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
642                                 err=UNZ_ERRNO;
643                 lSeek += file_info.size_file_extra - uSizeRead;
644         }
645         else
646                 lSeek+=file_info.size_file_extra; 
647
648         
649         if ((err==UNZ_OK) && (szComment!=NULL))
650         {
651                 uLong uSizeRead ;
652                 if (file_info.size_file_comment<commentBufferSize)
653                 {
654                         *(szComment+file_info.size_file_comment)='\0';
655                         uSizeRead = file_info.size_file_comment;
656                 }
657                 else
658                         uSizeRead = commentBufferSize;
659
660                 if (lSeek!=0)
661                         if (fseek(s->file,lSeek,SEEK_CUR)==0)
662                                 lSeek=0;
663                         else
664                                 err=UNZ_ERRNO;
665                 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
666                         if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
667                                 err=UNZ_ERRNO;
668                 lSeek+=file_info.size_file_comment - uSizeRead;
669         }
670         else
671                 lSeek+=file_info.size_file_comment;
672
673         if ((err==UNZ_OK) && (pfile_info!=NULL))
674                 *pfile_info=file_info;
675
676         if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
677                 *pfile_info_internal=file_info_internal;
678
679         return err;
680 }
681
682
683
684 /*
685   Write info about the ZipFile in the *pglobal_info structure.
686   No preparation of the structure is needed
687   return UNZ_OK if there is no problem.
688 */
689 extern int ZEXPORT unzGetCurrentFileInfo (file,
690                                                   pfile_info,
691                                                   szFileName, fileNameBufferSize,
692                                                   extraField, extraFieldBufferSize,
693                                                   szComment,  commentBufferSize)
694         unzFile file;
695         unz_file_info *pfile_info;
696         char *szFileName;
697         uLong fileNameBufferSize;
698         void *extraField;
699         uLong extraFieldBufferSize;
700         char *szComment;
701         uLong commentBufferSize;
702 {
703         return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
704                                                                                                 szFileName,fileNameBufferSize,
705                                                                                                 extraField,extraFieldBufferSize,
706                                                                                                 szComment,commentBufferSize);
707 }
708
709 /*
710   Set the current file of the zipfile to the first file.
711   return UNZ_OK if there is no problem
712 */
713 extern int ZEXPORT unzGoToFirstFile (file)
714         unzFile file;
715 {
716         int err=UNZ_OK;
717         unz_s* s;
718         if (file==NULL)
719                 return UNZ_PARAMERROR;
720         s=(unz_s*)file;
721         s->pos_in_central_dir=s->offset_central_dir;
722         s->num_file=0;
723         err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
724                                                                                          &s->cur_file_info_internal,
725                                                                                          NULL,0,NULL,0,NULL,0);
726         s->current_file_ok = (err == UNZ_OK);
727         return err;
728 }
729
730
731
732 /*
733   Set the current file of the zipfile to the next file.
734   return UNZ_OK if there is no problem
735   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
736 */
737 extern int ZEXPORT unzGoToNextFile (file)
738         unzFile file;
739 {
740         unz_s* s;       
741         int err;
742
743         if (file==NULL)
744                 return UNZ_PARAMERROR;
745         s=(unz_s*)file;
746         if (!s->current_file_ok)
747                 return UNZ_END_OF_LIST_OF_FILE;
748         if (s->num_file+1==s->gi.number_entry)
749                 return UNZ_END_OF_LIST_OF_FILE;
750
751         s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
752                         s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
753         s->num_file++;
754         err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
755                                                                                            &s->cur_file_info_internal,
756                                                                                            NULL,0,NULL,0,NULL,0);
757         s->current_file_ok = (err == UNZ_OK);
758         return err;
759 }
760
761
762 void cacao_create_directoryList(unzFile file)
763 {
764         unz_s* s=(unz_s*)file;
765         char *c;
766         int i;
767         unz_file_info tmp;
768         char filename[200];
769         if (unzGoToFirstFile(file)!=UNZ_OK) {
770                 s->cacao_dir_list=0;
771                 return;
772         }
773         i=0;
774         cacao_entry_s* ent=s->cacao_dir_list=(cacao_entry_s*)ALLOC(sizeof(cacao_entry_s));
775         ent->next=0;
776         ent->pos=s->pos_in_central_dir;
777
778         if (unzGetCurrentFileInfo (file,
779                                                   &tmp,
780                                                   filename, 200,
781                                                   0, 0,
782                                                   0,  0) !=UNZ_OK) {
783         
784                 panic("Error in ZIP archive");
785         }
786
787
788
789         ent->name=utf_new_char(filename);
790         while (unzGoToNextFile(file)==UNZ_OK) {
791                 i++;
792                 ent->next=(cacao_entry_s*)ALLOC(sizeof(cacao_entry_s));
793                 ent=ent->next;
794                 ent->next=0;
795                 ent->pos=s->pos_in_central_dir;
796
797                 if (unzGetCurrentFileInfo (file,
798                                                   &tmp,
799                                                   filename, 200,
800                                                   0, 0,
801                                                   0,  0) !=UNZ_OK) {
802         
803                         panic("Error in ZIP archive");
804                 }
805                 c=strstr(filename,".class");
806                 if (c) *c='\0';
807                 ent->name=utf_new_char(filename);
808         };
809         printf("Archive contains %d files\n",i);
810 }
811
812
813 /*
814   Try locate the file szFileName in the zipfile.
815   For the iCaseSensitivity signification, see unzipStringFileNameCompare
816
817   return value :
818   UNZ_OK if the file is found. It becomes the current file.
819   UNZ_END_OF_LIST_OF_FILE if the file is not found
820 */
821 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
822         unzFile file;
823         const char *szFileName;
824         int iCaseSensitivity;
825 {
826         unz_s* s;       
827         int err;
828
829         
830         uLong num_fileSaved;
831         uLong pos_in_central_dirSaved;
832
833         printf("Starting lookup\n");
834         fflush(stdout);
835
836         if (file==NULL)
837                 return UNZ_PARAMERROR;
838
839     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
840         return UNZ_PARAMERROR;
841
842         s=(unz_s*)file;
843         if (!s->current_file_ok)
844                 return UNZ_END_OF_LIST_OF_FILE;
845
846         num_fileSaved = s->num_file;
847         pos_in_central_dirSaved = s->pos_in_central_dir;
848
849         err = unzGoToFirstFile(file);
850
851         while (err == UNZ_OK)
852         {
853                 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
854                 unzGetCurrentFileInfo(file,NULL,
855                                                                 szCurrentFileName,sizeof(szCurrentFileName)-1,
856                                                                 NULL,0,NULL,0);
857                 if (unzStringFileNameCompare(szCurrentFileName,
858                                                                                 szFileName,iCaseSensitivity)==0) {
859                 printf("class found in zip directory\n");
860                 fflush(stdout);
861
862                         return UNZ_OK;
863                 }
864                 err = unzGoToNextFile(file);
865         }
866
867         s->num_file = num_fileSaved ;
868         s->pos_in_central_dir = pos_in_central_dirSaved ;
869         return err;
870 }
871
872 int cacao_locate(unzFile file,utf* filename) {
873         unz_s* s=(unz_s*)file;
874         cacao_entry_s *ent;
875         for (ent=s->cacao_dir_list;ent;ent=ent->next) {
876 /*              printf("searching: ");utf_display(filename);
877                 printf(" current: ");utf_display(ent->name);
878                 printf("\n");*/
879                 if (ent->name==filename) {
880                         s->pos_in_central_dir=ent->pos;
881                         return  unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
882                                                                                            &s->cur_file_info_internal,
883                                                                                            NULL,0,NULL,0,NULL,0);
884                 }
885         }
886 }
887
888 /*
889   Read the local header of the current zipfile
890   Check the coherency of the local header and info in the end of central
891         directory about this file
892   store in *piSizeVar the size of extra info in local header
893         (filename and size of extra field data)
894 */
895 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
896                                                                                                         poffset_local_extrafield,
897                                                                                                         psize_local_extrafield)
898         unz_s* s;
899         uInt* piSizeVar;
900         uLong *poffset_local_extrafield;
901         uInt  *psize_local_extrafield;
902 {
903         uLong uMagic,uData,uFlags;
904         uLong size_filename;
905         uLong size_extra_field;
906         int err=UNZ_OK;
907
908         *piSizeVar = 0;
909         *poffset_local_extrafield = 0;
910         *psize_local_extrafield = 0;
911
912         if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
913                                                                 s->byte_before_the_zipfile,SEEK_SET)!=0)
914                 return UNZ_ERRNO;
915
916
917         if (err==UNZ_OK)
918                 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
919                         err=UNZ_ERRNO;
920                 else if (uMagic!=0x04034b50)
921                         err=UNZ_BADZIPFILE;
922
923         if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
924                 err=UNZ_ERRNO;
925 /*
926         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
927                 err=UNZ_BADZIPFILE;
928 */
929         if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
930                 err=UNZ_ERRNO;
931
932         if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
933                 err=UNZ_ERRNO;
934         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
935                 err=UNZ_BADZIPFILE;
936
937     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
938                          (s->cur_file_info.compression_method!=Z_DEFLATED))
939         err=UNZ_BADZIPFILE;
940
941         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
942                 err=UNZ_ERRNO;
943
944         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
945                 err=UNZ_ERRNO;
946         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
947                                       ((uFlags & 8)==0))
948                 err=UNZ_BADZIPFILE;
949
950         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
951                 err=UNZ_ERRNO;
952         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
953                                                           ((uFlags & 8)==0))
954                 err=UNZ_BADZIPFILE;
955
956         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
957                 err=UNZ_ERRNO;
958         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && 
959                                                           ((uFlags & 8)==0))
960                 err=UNZ_BADZIPFILE;
961
962
963         if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
964                 err=UNZ_ERRNO;
965         else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
966                 err=UNZ_BADZIPFILE;
967
968         *piSizeVar += (uInt)size_filename;
969
970         if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
971                 err=UNZ_ERRNO;
972         *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
973                                                                         SIZEZIPLOCALHEADER + size_filename;
974         *psize_local_extrafield = (uInt)size_extra_field;
975
976         *piSizeVar += (uInt)size_extra_field;
977
978         return err;
979 }
980                                                                                                 
981 /*
982   Open for reading data the current file in the zipfile.
983   If there is no error and the file is opened, the return value is UNZ_OK.
984 */
985 extern int ZEXPORT unzOpenCurrentFile (file)
986         unzFile file;
987 {
988         int err=UNZ_OK;
989         int Store;
990         uInt iSizeVar;
991         unz_s* s;
992         file_in_zip_read_info_s* pfile_in_zip_read_info;
993         uLong offset_local_extrafield;  /* offset of the local extra field */
994         uInt  size_local_extrafield;    /* size of the local extra field */
995
996         if (file==NULL)
997                 return UNZ_PARAMERROR;
998         s=(unz_s*)file;
999         if (!s->current_file_ok)
1000                 return UNZ_PARAMERROR;
1001
1002     if (s->pfile_in_zip_read != NULL)
1003         unzCloseCurrentFile(file);
1004
1005         if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1006                                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1007                 return UNZ_BADZIPFILE;
1008
1009         pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1010                                                                             ALLOC(sizeof(file_in_zip_read_info_s));
1011         if (pfile_in_zip_read_info==NULL)
1012                 return UNZ_INTERNALERROR;
1013
1014         pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1015         pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1016         pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1017         pfile_in_zip_read_info->pos_local_extrafield=0;
1018
1019         if (pfile_in_zip_read_info->read_buffer==NULL)
1020         {
1021                 TRYFREE(pfile_in_zip_read_info);
1022                 return UNZ_INTERNALERROR;
1023         }
1024
1025         pfile_in_zip_read_info->stream_initialised=0;
1026         
1027         if ((s->cur_file_info.compression_method!=0) &&
1028         (s->cur_file_info.compression_method!=Z_DEFLATED))
1029                 err=UNZ_BADZIPFILE;
1030         Store = s->cur_file_info.compression_method==0;
1031
1032         pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1033         pfile_in_zip_read_info->crc32=0;
1034         pfile_in_zip_read_info->compression_method =
1035             s->cur_file_info.compression_method;
1036         pfile_in_zip_read_info->file=s->file;
1037         pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1038
1039     pfile_in_zip_read_info->stream.total_out = 0;
1040
1041         if (!Store)
1042         {
1043           pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1044           pfile_in_zip_read_info->stream.zfree = (free_func)0;
1045           pfile_in_zip_read_info->stream.opaque = (voidpf)0; 
1046       
1047           err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1048           if (err == Z_OK)
1049             pfile_in_zip_read_info->stream_initialised=1;
1050         /* windowBits is passed < 0 to tell that there is no zlib header.
1051          * Note that in this case inflate *requires* an extra "dummy" byte
1052          * after the compressed stream in order to complete decompression and
1053          * return Z_STREAM_END. 
1054          * In unzip, i don't wait absolutely Z_STREAM_END because I known the 
1055          * size of both compressed and uncompressed data
1056          */
1057         }
1058         pfile_in_zip_read_info->rest_read_compressed = 
1059             s->cur_file_info.compressed_size ;
1060         pfile_in_zip_read_info->rest_read_uncompressed = 
1061             s->cur_file_info.uncompressed_size ;
1062
1063         
1064         pfile_in_zip_read_info->pos_in_zipfile = 
1065             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + 
1066                           iSizeVar;
1067         
1068         pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1069
1070
1071         s->pfile_in_zip_read = pfile_in_zip_read_info;
1072
1073     return UNZ_OK;
1074 }
1075
1076
1077 /*
1078   Read bytes from the current file.
1079   buf contain buffer where data must be copied
1080   len the size of buf.
1081
1082   return the number of byte copied if somes bytes are copied
1083   return 0 if the end of file was reached
1084   return <0 with error code if there is an error
1085     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1086 */
1087 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
1088         unzFile file;
1089         voidp buf;
1090         unsigned len;
1091 {
1092         int err=UNZ_OK;
1093         uInt iRead = 0;
1094         unz_s* s;
1095         file_in_zip_read_info_s* pfile_in_zip_read_info;
1096         if (file==NULL)
1097                 return UNZ_PARAMERROR;
1098         s=(unz_s*)file;
1099     pfile_in_zip_read_info=s->pfile_in_zip_read;
1100
1101         if (pfile_in_zip_read_info==NULL)
1102                 return UNZ_PARAMERROR;
1103
1104
1105         if ((pfile_in_zip_read_info->read_buffer == NULL))
1106                 return UNZ_END_OF_LIST_OF_FILE;
1107         if (len==0)
1108                 return 0;
1109
1110         pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1111
1112         pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1113         
1114         if (len>pfile_in_zip_read_info->rest_read_uncompressed)
1115                 pfile_in_zip_read_info->stream.avail_out = 
1116                   (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1117
1118         while (pfile_in_zip_read_info->stream.avail_out>0)
1119         {
1120                 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1121             (pfile_in_zip_read_info->rest_read_compressed>0))
1122                 {
1123                         uInt uReadThis = UNZ_BUFSIZE;
1124                         if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1125                                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1126                         if (uReadThis == 0)
1127                                 return UNZ_EOF;
1128                         if (fseek(pfile_in_zip_read_info->file,
1129                       pfile_in_zip_read_info->pos_in_zipfile + 
1130                          pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
1131                                 return UNZ_ERRNO;
1132                         if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
1133                          pfile_in_zip_read_info->file)!=1)
1134                                 return UNZ_ERRNO;
1135                         pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1136
1137                         pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1138                         
1139                         pfile_in_zip_read_info->stream.next_in = 
1140                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1141                         pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1142                 }
1143
1144                 if (pfile_in_zip_read_info->compression_method==0)
1145                 {
1146                         uInt uDoCopy,i ;
1147                         if (pfile_in_zip_read_info->stream.avail_out < 
1148                             pfile_in_zip_read_info->stream.avail_in)
1149                                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1150                         else
1151                                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1152                                 
1153                         for (i=0;i<uDoCopy;i++)
1154                                 *(pfile_in_zip_read_info->stream.next_out+i) =
1155                         *(pfile_in_zip_read_info->stream.next_in+i);
1156                                         
1157                         pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1158                                                                 pfile_in_zip_read_info->stream.next_out,
1159                                                                 uDoCopy);
1160                         pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1161                         pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1162                         pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1163                         pfile_in_zip_read_info->stream.next_out += uDoCopy;
1164                         pfile_in_zip_read_info->stream.next_in += uDoCopy;
1165             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1166                         iRead += uDoCopy;
1167                 }
1168                 else
1169                 {
1170                         uLong uTotalOutBefore,uTotalOutAfter;
1171                         const Bytef *bufBefore;
1172                         uLong uOutThis;
1173                         int flush=Z_SYNC_FLUSH;
1174
1175                         uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1176                         bufBefore = pfile_in_zip_read_info->stream.next_out;
1177
1178                         /*
1179                         if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1180                                  pfile_in_zip_read_info->stream.avail_out) &&
1181                                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1182                                 flush = Z_FINISH;
1183                         */
1184                         err=inflate(&pfile_in_zip_read_info->stream,flush);
1185
1186                         uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1187                         uOutThis = uTotalOutAfter-uTotalOutBefore;
1188                         
1189                         pfile_in_zip_read_info->crc32 = 
1190                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1191                         (uInt)(uOutThis));
1192
1193                         pfile_in_zip_read_info->rest_read_uncompressed -=
1194                 uOutThis;
1195
1196                         iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1197             
1198                         if (err==Z_STREAM_END)
1199                                 return (iRead==0) ? UNZ_EOF : iRead;
1200                         if (err!=Z_OK) 
1201                                 break;
1202                 }
1203         }
1204
1205         if (err==Z_OK)
1206                 return iRead;
1207         return err;
1208 }
1209
1210
1211 /*
1212   Give the current position in uncompressed data
1213 */
1214 extern z_off_t ZEXPORT unztell (file)
1215         unzFile file;
1216 {
1217         unz_s* s;
1218         file_in_zip_read_info_s* pfile_in_zip_read_info;
1219         if (file==NULL)
1220                 return UNZ_PARAMERROR;
1221         s=(unz_s*)file;
1222     pfile_in_zip_read_info=s->pfile_in_zip_read;
1223
1224         if (pfile_in_zip_read_info==NULL)
1225                 return UNZ_PARAMERROR;
1226
1227         return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1228 }
1229
1230
1231 /*
1232   return 1 if the end of file was reached, 0 elsewhere 
1233 */
1234 extern int ZEXPORT unzeof (file)
1235         unzFile file;
1236 {
1237         unz_s* s;
1238         file_in_zip_read_info_s* pfile_in_zip_read_info;
1239         if (file==NULL)
1240                 return UNZ_PARAMERROR;
1241         s=(unz_s*)file;
1242     pfile_in_zip_read_info=s->pfile_in_zip_read;
1243
1244         if (pfile_in_zip_read_info==NULL)
1245                 return UNZ_PARAMERROR;
1246         
1247         if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1248                 return 1;
1249         else
1250                 return 0;
1251 }
1252
1253
1254
1255 /*
1256   Read extra field from the current file (opened by unzOpenCurrentFile)
1257   This is the local-header version of the extra field (sometimes, there is
1258     more info in the local-header version than in the central-header)
1259
1260   if buf==NULL, it return the size of the local extra field that can be read
1261
1262   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1263         buf.
1264   the return value is the number of bytes copied in buf, or (if <0) 
1265         the error code
1266 */
1267 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1268         unzFile file;
1269         voidp buf;
1270         unsigned len;
1271 {
1272         unz_s* s;
1273         file_in_zip_read_info_s* pfile_in_zip_read_info;
1274         uInt read_now;
1275         uLong size_to_read;
1276
1277         if (file==NULL)
1278                 return UNZ_PARAMERROR;
1279         s=(unz_s*)file;
1280     pfile_in_zip_read_info=s->pfile_in_zip_read;
1281
1282         if (pfile_in_zip_read_info==NULL)
1283                 return UNZ_PARAMERROR;
1284
1285         size_to_read = (pfile_in_zip_read_info->size_local_extrafield - 
1286                                 pfile_in_zip_read_info->pos_local_extrafield);
1287
1288         if (buf==NULL)
1289                 return (int)size_to_read;
1290         
1291         if (len>size_to_read)
1292                 read_now = (uInt)size_to_read;
1293         else
1294                 read_now = (uInt)len ;
1295
1296         if (read_now==0)
1297                 return 0;
1298         
1299         if (fseek(pfile_in_zip_read_info->file,
1300               pfile_in_zip_read_info->offset_local_extrafield + 
1301                           pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
1302                 return UNZ_ERRNO;
1303
1304         if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
1305                 return UNZ_ERRNO;
1306
1307         return (int)read_now;
1308 }
1309
1310 /*
1311   Close the file in zip opened with unzipOpenCurrentFile
1312   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1313 */
1314 extern int ZEXPORT unzCloseCurrentFile (file)
1315         unzFile file;
1316 {
1317         int err=UNZ_OK;
1318
1319         unz_s* s;
1320         file_in_zip_read_info_s* pfile_in_zip_read_info;
1321         if (file==NULL)
1322                 return UNZ_PARAMERROR;
1323         s=(unz_s*)file;
1324     pfile_in_zip_read_info=s->pfile_in_zip_read;
1325
1326         if (pfile_in_zip_read_info==NULL)
1327                 return UNZ_PARAMERROR;
1328
1329
1330         if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1331         {
1332                 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1333                         err=UNZ_CRCERROR;
1334         }
1335
1336
1337         TRYFREE(pfile_in_zip_read_info->read_buffer);
1338         pfile_in_zip_read_info->read_buffer = NULL;
1339         if (pfile_in_zip_read_info->stream_initialised)
1340                 inflateEnd(&pfile_in_zip_read_info->stream);
1341
1342         pfile_in_zip_read_info->stream_initialised = 0;
1343         TRYFREE(pfile_in_zip_read_info);
1344
1345     s->pfile_in_zip_read=NULL;
1346
1347         return err;
1348 }
1349
1350
1351 /*
1352   Get the global comment string of the ZipFile, in the szComment buffer.
1353   uSizeBuf is the size of the szComment buffer.
1354   return the number of byte copied or an error code <0
1355 */
1356 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1357         unzFile file;
1358         char *szComment;
1359         uLong uSizeBuf;
1360 {
1361         int err=UNZ_OK;
1362         unz_s* s;
1363         uLong uReadThis ;
1364         if (file==NULL)
1365                 return UNZ_PARAMERROR;
1366         s=(unz_s*)file;
1367
1368         uReadThis = uSizeBuf;
1369         if (uReadThis>s->gi.size_comment)
1370                 uReadThis = s->gi.size_comment;
1371
1372         if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
1373                 return UNZ_ERRNO;
1374
1375         if (uReadThis>0)
1376     {
1377       *szComment='\0';
1378           if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
1379                 return UNZ_ERRNO;
1380     }
1381
1382         if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1383                 *(szComment+s->gi.size_comment)='\0';
1384         return (int)uReadThis;
1385 }
1386
1387 #endif