Merged bug fix by jowenn (nov 25)
[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   cacao_entry_s* ent;
765         unz_s* s=(unz_s*)file;
766         char *c;
767         int i;
768         unz_file_info tmp;
769         char filename[200];
770         if (unzGoToFirstFile(file)!=UNZ_OK) {
771                 s->cacao_dir_list=0;
772                 return;
773         }
774         i=0;
775         ent = s->cacao_dir_list = (cacao_entry_s *) ALLOC(sizeof(cacao_entry_s));
776         ent->next=0;
777         ent->pos=s->pos_in_central_dir;
778
779         if (unzGetCurrentFileInfo (file,
780                                                   &tmp,
781                                                   filename, 200,
782                                                   0, 0,
783                                                   0,  0) !=UNZ_OK) {
784         
785                 panic("Error in ZIP archive");
786         }
787
788
789
790         ent->name=utf_new_char(filename);
791         while (unzGoToNextFile(file)==UNZ_OK) {
792                 i++;
793                 ent->next=(cacao_entry_s*)ALLOC(sizeof(cacao_entry_s));
794                 ent=ent->next;
795                 ent->next=0;
796                 ent->pos=s->pos_in_central_dir;
797
798                 if (unzGetCurrentFileInfo (file,
799                                                   &tmp,
800                                                   filename, 200,
801                                                   0, 0,
802                                                   0,  0) !=UNZ_OK) {
803         
804                         panic("Error in ZIP archive");
805                 }
806                 c=strstr(filename,".class");
807                 if (c) *c='\0';
808                 ent->name=utf_new_char(filename);
809         };
810         printf("Archive contains %d files\n",i);
811 }
812
813
814 /*
815   Try locate the file szFileName in the zipfile.
816   For the iCaseSensitivity signification, see unzipStringFileNameCompare
817
818   return value :
819   UNZ_OK if the file is found. It becomes the current file.
820   UNZ_END_OF_LIST_OF_FILE if the file is not found
821 */
822 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
823         unzFile file;
824         const char *szFileName;
825         int iCaseSensitivity;
826 {
827         unz_s* s;       
828         int err;
829
830         
831         uLong num_fileSaved;
832         uLong pos_in_central_dirSaved;
833
834         printf("Starting lookup\n");
835         fflush(stdout);
836
837         if (file==NULL)
838                 return UNZ_PARAMERROR;
839
840     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
841         return UNZ_PARAMERROR;
842
843         s=(unz_s*)file;
844         if (!s->current_file_ok)
845                 return UNZ_END_OF_LIST_OF_FILE;
846
847         num_fileSaved = s->num_file;
848         pos_in_central_dirSaved = s->pos_in_central_dir;
849
850         err = unzGoToFirstFile(file);
851
852         while (err == UNZ_OK)
853         {
854                 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
855                 unzGetCurrentFileInfo(file,NULL,
856                                                                 szCurrentFileName,sizeof(szCurrentFileName)-1,
857                                                                 NULL,0,NULL,0);
858                 if (unzStringFileNameCompare(szCurrentFileName,
859                                                                                 szFileName,iCaseSensitivity)==0) {
860                 printf("class found in zip directory\n");
861                 fflush(stdout);
862
863                         return UNZ_OK;
864                 }
865                 err = unzGoToNextFile(file);
866         }
867
868         s->num_file = num_fileSaved ;
869         s->pos_in_central_dir = pos_in_central_dirSaved ;
870         return err;
871 }
872
873 int cacao_locate(unzFile file,utf* filename) {
874         unz_s* s=(unz_s*)file;
875         cacao_entry_s *ent;
876         for (ent=s->cacao_dir_list;ent;ent=ent->next) {
877 /*              printf("searching: ");utf_display(filename);
878                 printf(" current: ");utf_display(ent->name);
879                 printf("\n");*/
880                 if (ent->name==filename) {
881                         s->pos_in_central_dir=ent->pos;
882                         return  unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
883                                                                                            &s->cur_file_info_internal,
884                                                                                            NULL,0,NULL,0,NULL,0);
885                 }
886         }
887
888         return 0;
889 }
890
891 /*
892   Read the local header of the current zipfile
893   Check the coherency of the local header and info in the end of central
894         directory about this file
895   store in *piSizeVar the size of extra info in local header
896         (filename and size of extra field data)
897 */
898 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
899                                                                                                         poffset_local_extrafield,
900                                                                                                         psize_local_extrafield)
901         unz_s* s;
902         uInt* piSizeVar;
903         uLong *poffset_local_extrafield;
904         uInt  *psize_local_extrafield;
905 {
906         uLong uMagic,uData,uFlags;
907         uLong size_filename;
908         uLong size_extra_field;
909         int err=UNZ_OK;
910
911         *piSizeVar = 0;
912         *poffset_local_extrafield = 0;
913         *psize_local_extrafield = 0;
914
915         if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
916                                                                 s->byte_before_the_zipfile,SEEK_SET)!=0)
917                 return UNZ_ERRNO;
918
919
920         if (err==UNZ_OK)
921                 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
922                         err=UNZ_ERRNO;
923                 else if (uMagic!=0x04034b50)
924                         err=UNZ_BADZIPFILE;
925
926         if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
927                 err=UNZ_ERRNO;
928 /*
929         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
930                 err=UNZ_BADZIPFILE;
931 */
932         if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
933                 err=UNZ_ERRNO;
934
935         if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
936                 err=UNZ_ERRNO;
937         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
938                 err=UNZ_BADZIPFILE;
939
940     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
941                          (s->cur_file_info.compression_method!=Z_DEFLATED))
942         err=UNZ_BADZIPFILE;
943
944         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
945                 err=UNZ_ERRNO;
946
947         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
948                 err=UNZ_ERRNO;
949         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
950                                       ((uFlags & 8)==0))
951                 err=UNZ_BADZIPFILE;
952
953         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
954                 err=UNZ_ERRNO;
955         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
956                                                           ((uFlags & 8)==0))
957                 err=UNZ_BADZIPFILE;
958
959         if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
960                 err=UNZ_ERRNO;
961         else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && 
962                                                           ((uFlags & 8)==0))
963                 err=UNZ_BADZIPFILE;
964
965
966         if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
967                 err=UNZ_ERRNO;
968         else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
969                 err=UNZ_BADZIPFILE;
970
971         *piSizeVar += (uInt)size_filename;
972
973         if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
974                 err=UNZ_ERRNO;
975         *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
976                                                                         SIZEZIPLOCALHEADER + size_filename;
977         *psize_local_extrafield = (uInt)size_extra_field;
978
979         *piSizeVar += (uInt)size_extra_field;
980
981         return err;
982 }
983                                                                                                 
984 /*
985   Open for reading data the current file in the zipfile.
986   If there is no error and the file is opened, the return value is UNZ_OK.
987 */
988 extern int ZEXPORT unzOpenCurrentFile (file)
989         unzFile file;
990 {
991         int err=UNZ_OK;
992         int Store;
993         uInt iSizeVar;
994         unz_s* s;
995         file_in_zip_read_info_s* pfile_in_zip_read_info;
996         uLong offset_local_extrafield;  /* offset of the local extra field */
997         uInt  size_local_extrafield;    /* size of the local extra field */
998
999         if (file==NULL)
1000                 return UNZ_PARAMERROR;
1001         s=(unz_s*)file;
1002         if (!s->current_file_ok)
1003                 return UNZ_PARAMERROR;
1004
1005     if (s->pfile_in_zip_read != NULL)
1006         unzCloseCurrentFile(file);
1007
1008         if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
1009                                 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
1010                 return UNZ_BADZIPFILE;
1011
1012         pfile_in_zip_read_info = (file_in_zip_read_info_s*)
1013                                                                             ALLOC(sizeof(file_in_zip_read_info_s));
1014         if (pfile_in_zip_read_info==NULL)
1015                 return UNZ_INTERNALERROR;
1016
1017         pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
1018         pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1019         pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1020         pfile_in_zip_read_info->pos_local_extrafield=0;
1021
1022         if (pfile_in_zip_read_info->read_buffer==NULL)
1023         {
1024                 TRYFREE(pfile_in_zip_read_info);
1025                 return UNZ_INTERNALERROR;
1026         }
1027
1028         pfile_in_zip_read_info->stream_initialised=0;
1029         
1030         if ((s->cur_file_info.compression_method!=0) &&
1031         (s->cur_file_info.compression_method!=Z_DEFLATED))
1032                 err=UNZ_BADZIPFILE;
1033         Store = s->cur_file_info.compression_method==0;
1034
1035         pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
1036         pfile_in_zip_read_info->crc32=0;
1037         pfile_in_zip_read_info->compression_method =
1038             s->cur_file_info.compression_method;
1039         pfile_in_zip_read_info->file=s->file;
1040         pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
1041
1042     pfile_in_zip_read_info->stream.total_out = 0;
1043
1044         if (!Store)
1045         {
1046           pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1047           pfile_in_zip_read_info->stream.zfree = (free_func)0;
1048           pfile_in_zip_read_info->stream.opaque = (voidpf)0; 
1049       
1050           err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1051           if (err == Z_OK)
1052             pfile_in_zip_read_info->stream_initialised=1;
1053         /* windowBits is passed < 0 to tell that there is no zlib header.
1054          * Note that in this case inflate *requires* an extra "dummy" byte
1055          * after the compressed stream in order to complete decompression and
1056          * return Z_STREAM_END. 
1057          * In unzip, i don't wait absolutely Z_STREAM_END because I known the 
1058          * size of both compressed and uncompressed data
1059          */
1060         }
1061         pfile_in_zip_read_info->rest_read_compressed = 
1062             s->cur_file_info.compressed_size ;
1063         pfile_in_zip_read_info->rest_read_uncompressed = 
1064             s->cur_file_info.uncompressed_size ;
1065
1066         
1067         pfile_in_zip_read_info->pos_in_zipfile = 
1068             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + 
1069                           iSizeVar;
1070         
1071         pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1072
1073
1074         s->pfile_in_zip_read = pfile_in_zip_read_info;
1075
1076     return UNZ_OK;
1077 }
1078
1079
1080 /*
1081   Read bytes from the current file.
1082   buf contain buffer where data must be copied
1083   len the size of buf.
1084
1085   return the number of byte copied if somes bytes are copied
1086   return 0 if the end of file was reached
1087   return <0 with error code if there is an error
1088     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
1089 */
1090 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
1091         unzFile file;
1092         voidp buf;
1093         unsigned len;
1094 {
1095         int err=UNZ_OK;
1096         uInt iRead = 0;
1097         unz_s* s;
1098         file_in_zip_read_info_s* pfile_in_zip_read_info;
1099         if (file==NULL)
1100                 return UNZ_PARAMERROR;
1101         s=(unz_s*)file;
1102     pfile_in_zip_read_info=s->pfile_in_zip_read;
1103
1104         if (pfile_in_zip_read_info==NULL)
1105                 return UNZ_PARAMERROR;
1106
1107
1108         if ((pfile_in_zip_read_info->read_buffer == NULL))
1109                 return UNZ_END_OF_LIST_OF_FILE;
1110         if (len==0)
1111                 return 0;
1112
1113         pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1114
1115         pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1116         
1117         if (len>pfile_in_zip_read_info->rest_read_uncompressed)
1118                 pfile_in_zip_read_info->stream.avail_out = 
1119                   (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1120
1121         while (pfile_in_zip_read_info->stream.avail_out>0)
1122         {
1123                 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1124             (pfile_in_zip_read_info->rest_read_compressed>0))
1125                 {
1126                         uInt uReadThis = UNZ_BUFSIZE;
1127                         if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1128                                 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1129                         if (uReadThis == 0)
1130                                 return UNZ_EOF;
1131                         if (fseek(pfile_in_zip_read_info->file,
1132                       pfile_in_zip_read_info->pos_in_zipfile + 
1133                          pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
1134                                 return UNZ_ERRNO;
1135                         if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
1136                          pfile_in_zip_read_info->file)!=1)
1137                                 return UNZ_ERRNO;
1138                         pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1139
1140                         pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1141                         
1142                         pfile_in_zip_read_info->stream.next_in = 
1143                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1144                         pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1145                 }
1146
1147                 if (pfile_in_zip_read_info->compression_method==0)
1148                 {
1149                         uInt uDoCopy,i ;
1150                         if (pfile_in_zip_read_info->stream.avail_out < 
1151                             pfile_in_zip_read_info->stream.avail_in)
1152                                 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1153                         else
1154                                 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1155                                 
1156                         for (i=0;i<uDoCopy;i++)
1157                                 *(pfile_in_zip_read_info->stream.next_out+i) =
1158                         *(pfile_in_zip_read_info->stream.next_in+i);
1159                                         
1160                         pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1161                                                                 pfile_in_zip_read_info->stream.next_out,
1162                                                                 uDoCopy);
1163                         pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1164                         pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1165                         pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1166                         pfile_in_zip_read_info->stream.next_out += uDoCopy;
1167                         pfile_in_zip_read_info->stream.next_in += uDoCopy;
1168             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1169                         iRead += uDoCopy;
1170                 }
1171                 else
1172                 {
1173                         uLong uTotalOutBefore,uTotalOutAfter;
1174                         const Bytef *bufBefore;
1175                         uLong uOutThis;
1176                         int flush=Z_SYNC_FLUSH;
1177
1178                         uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1179                         bufBefore = pfile_in_zip_read_info->stream.next_out;
1180
1181                         /*
1182                         if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1183                                  pfile_in_zip_read_info->stream.avail_out) &&
1184                                 (pfile_in_zip_read_info->rest_read_compressed == 0))
1185                                 flush = Z_FINISH;
1186                         */
1187                         err=inflate(&pfile_in_zip_read_info->stream,flush);
1188
1189                         uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1190                         uOutThis = uTotalOutAfter-uTotalOutBefore;
1191                         
1192                         pfile_in_zip_read_info->crc32 = 
1193                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1194                         (uInt)(uOutThis));
1195
1196                         pfile_in_zip_read_info->rest_read_uncompressed -=
1197                 uOutThis;
1198
1199                         iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1200             
1201                         if (err==Z_STREAM_END)
1202                                 return (iRead==0) ? UNZ_EOF : iRead;
1203                         if (err!=Z_OK) 
1204                                 break;
1205                 }
1206         }
1207
1208         if (err==Z_OK)
1209                 return iRead;
1210         return err;
1211 }
1212
1213
1214 /*
1215   Give the current position in uncompressed data
1216 */
1217 extern z_off_t ZEXPORT unztell (file)
1218         unzFile file;
1219 {
1220         unz_s* s;
1221         file_in_zip_read_info_s* pfile_in_zip_read_info;
1222         if (file==NULL)
1223                 return UNZ_PARAMERROR;
1224         s=(unz_s*)file;
1225     pfile_in_zip_read_info=s->pfile_in_zip_read;
1226
1227         if (pfile_in_zip_read_info==NULL)
1228                 return UNZ_PARAMERROR;
1229
1230         return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1231 }
1232
1233
1234 /*
1235   return 1 if the end of file was reached, 0 elsewhere 
1236 */
1237 extern int ZEXPORT unzeof (file)
1238         unzFile file;
1239 {
1240         unz_s* s;
1241         file_in_zip_read_info_s* pfile_in_zip_read_info;
1242         if (file==NULL)
1243                 return UNZ_PARAMERROR;
1244         s=(unz_s*)file;
1245     pfile_in_zip_read_info=s->pfile_in_zip_read;
1246
1247         if (pfile_in_zip_read_info==NULL)
1248                 return UNZ_PARAMERROR;
1249         
1250         if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1251                 return 1;
1252         else
1253                 return 0;
1254 }
1255
1256
1257
1258 /*
1259   Read extra field from the current file (opened by unzOpenCurrentFile)
1260   This is the local-header version of the extra field (sometimes, there is
1261     more info in the local-header version than in the central-header)
1262
1263   if buf==NULL, it return the size of the local extra field that can be read
1264
1265   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1266         buf.
1267   the return value is the number of bytes copied in buf, or (if <0) 
1268         the error code
1269 */
1270 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1271         unzFile file;
1272         voidp buf;
1273         unsigned len;
1274 {
1275         unz_s* s;
1276         file_in_zip_read_info_s* pfile_in_zip_read_info;
1277         uInt read_now;
1278         uLong size_to_read;
1279
1280         if (file==NULL)
1281                 return UNZ_PARAMERROR;
1282         s=(unz_s*)file;
1283     pfile_in_zip_read_info=s->pfile_in_zip_read;
1284
1285         if (pfile_in_zip_read_info==NULL)
1286                 return UNZ_PARAMERROR;
1287
1288         size_to_read = (pfile_in_zip_read_info->size_local_extrafield - 
1289                                 pfile_in_zip_read_info->pos_local_extrafield);
1290
1291         if (buf==NULL)
1292                 return (int)size_to_read;
1293         
1294         if (len>size_to_read)
1295                 read_now = (uInt)size_to_read;
1296         else
1297                 read_now = (uInt)len ;
1298
1299         if (read_now==0)
1300                 return 0;
1301         
1302         if (fseek(pfile_in_zip_read_info->file,
1303               pfile_in_zip_read_info->offset_local_extrafield + 
1304                           pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
1305                 return UNZ_ERRNO;
1306
1307         if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
1308                 return UNZ_ERRNO;
1309
1310         return (int)read_now;
1311 }
1312
1313 /*
1314   Close the file in zip opened with unzipOpenCurrentFile
1315   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1316 */
1317 extern int ZEXPORT unzCloseCurrentFile (file)
1318         unzFile file;
1319 {
1320         int err=UNZ_OK;
1321
1322         unz_s* s;
1323         file_in_zip_read_info_s* pfile_in_zip_read_info;
1324         if (file==NULL)
1325                 return UNZ_PARAMERROR;
1326         s=(unz_s*)file;
1327     pfile_in_zip_read_info=s->pfile_in_zip_read;
1328
1329         if (pfile_in_zip_read_info==NULL)
1330                 return UNZ_PARAMERROR;
1331
1332
1333         if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1334         {
1335                 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1336                         err=UNZ_CRCERROR;
1337         }
1338
1339
1340         TRYFREE(pfile_in_zip_read_info->read_buffer);
1341         pfile_in_zip_read_info->read_buffer = NULL;
1342         if (pfile_in_zip_read_info->stream_initialised)
1343                 inflateEnd(&pfile_in_zip_read_info->stream);
1344
1345         pfile_in_zip_read_info->stream_initialised = 0;
1346         TRYFREE(pfile_in_zip_read_info);
1347
1348     s->pfile_in_zip_read=NULL;
1349
1350         return err;
1351 }
1352
1353
1354 /*
1355   Get the global comment string of the ZipFile, in the szComment buffer.
1356   uSizeBuf is the size of the szComment buffer.
1357   return the number of byte copied or an error code <0
1358 */
1359 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1360         unzFile file;
1361         char *szComment;
1362         uLong uSizeBuf;
1363 {
1364         int err=UNZ_OK;
1365         unz_s* s;
1366         uLong uReadThis ;
1367         if (file==NULL)
1368                 return UNZ_PARAMERROR;
1369         s=(unz_s*)file;
1370
1371         uReadThis = uSizeBuf;
1372         if (uReadThis>s->gi.size_comment)
1373                 uReadThis = s->gi.size_comment;
1374
1375         if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
1376                 return UNZ_ERRNO;
1377
1378         if (uReadThis>0)
1379     {
1380       *szComment='\0';
1381           if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
1382                 return UNZ_ERRNO;
1383     }
1384
1385         if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1386                 *(szComment+s->gi.size_comment)='\0';
1387         return (int)uReadThis;
1388 }
1389
1390 #endif