source: psi/trunk/src/tools/zip/minizip/unzip.c

Last change on this file was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

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