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