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