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