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