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