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