remote.c: remove autotoolized conditional includes
[rofl0r-VisualBoyAdvance.git] / src / unzip.c
blob876691a5f56ddab4788f2ab6e5768f81cea1904c
1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 /* unzip.c -- IO on .zip files using zlib
20 Version 0.15 beta, Mar 19th, 1998,
22 Read unzip.h for more info
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "zlib.h"
30 #include "unzip.h"
32 #ifdef STDC
33 # include <stddef.h>
34 # include <string.h>
35 # include <stdlib.h>
36 #endif
37 #ifdef NO_ERRNO_H
38 extern int errno;
39 #else
40 # include <errno.h>
41 #endif
44 #ifndef local
45 # define local static
46 #endif
47 /* compile with -Dlocal if your debugger can't find static symbols */
51 #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
52 !defined(CASESENSITIVITYDEFAULT_NO)
53 #define CASESENSITIVITYDEFAULT_NO
54 #endif
57 #ifndef UNZ_BUFSIZE
58 #define UNZ_BUFSIZE (16384)
59 #endif
61 #ifndef UNZ_MAXFILENAMEINZIP
62 #define UNZ_MAXFILENAMEINZIP (256)
63 #endif
65 #ifndef ALLOC
66 # define ALLOC(size) (malloc(size))
67 #endif
68 #ifndef TRYFREE
69 # define TRYFREE(p) {if (p) free(p);}
70 #endif
72 #define SIZECENTRALDIRITEM (0x2e)
73 #define SIZEZIPLOCALHEADER (0x1e)
76 /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
78 #ifndef SEEK_CUR
79 #define SEEK_CUR 1
80 #endif
82 #ifndef SEEK_END
83 #define SEEK_END 2
84 #endif
86 #ifndef SEEK_SET
87 #define SEEK_SET 0
88 #endif
90 const char unz_copyright[] =
91 " unzip 0.15 Copyright 1998 Gilles Vollant ";
93 /* unz_file_info_interntal contain internal info about a file in zipfile*/
94 typedef struct unz_file_info_internal_s
96 uLong offset_curfile;/* relative offset of local header 4 bytes */
97 } unz_file_info_internal;
100 /* file_in_zip_read_info_s contain internal information about a file in zipfile,
101 when reading and decompress it */
102 typedef struct
104 char *read_buffer; /* internal buffer for compressed data */
105 z_stream stream; /* zLib stream structure for inflate */
107 uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
108 uLong stream_initialised; /* flag set if stream structure is initialised*/
110 uLong offset_local_extrafield;/* offset of the local extra field */
111 uInt size_local_extrafield;/* size of the local extra field */
112 uLong pos_local_extrafield; /* position in the local extra field in read*/
114 uLong crc32; /* crc32 of all data uncompressed */
115 uLong crc32_wait; /* crc32 we must obtain after decompress all */
116 uLong rest_read_compressed; /* number of byte to be decompressed */
117 uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
118 FILE* file; /* io structore of the zipfile */
119 uLong compression_method; /* compression method (0==store) */
120 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
121 } file_in_zip_read_info_s;
124 /* unz_s contain internal information about the zipfile
126 typedef struct
128 FILE* file; /* io structore of the zipfile */
129 unz_global_info gi; /* public global information */
130 uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
131 uLong num_file; /* number of the current file in the zipfile*/
132 uLong pos_in_central_dir; /* pos of the current file in the central dir*/
133 uLong current_file_ok; /* flag about the usability of the current file*/
134 uLong central_pos; /* position of the beginning of the central dir*/
136 uLong size_central_dir; /* size of the central directory */
137 uLong offset_central_dir; /* offset of start of central directory with
138 respect to the starting disk number */
140 unz_file_info cur_file_info; /* public info about the current file in zip*/
141 unz_file_info_internal cur_file_info_internal; /* private info about it*/
142 file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
143 file if we are decompressing it */
144 } unz_s;
147 /* ===========================================================================
148 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
149 for end of file.
150 IN assertion: the stream s has been sucessfully opened for reading.
154 local int unzlocal_getByte(FILE *fin,int *pi)
156 unsigned char c;
157 size_t err = fread(&c, 1, 1, fin);
158 if (err==1)
160 *pi = (int)c;
161 return UNZ_OK;
163 else
165 if (ferror(fin))
166 return UNZ_ERRNO;
167 else
168 return UNZ_EOF;
173 /* ===========================================================================
174 Reads a long in LSB order from the given gz_stream. Sets
176 local int unzlocal_getShort (FILE *fin,uLong *pX)
178 uLong x ;
179 int i;
180 int err;
182 err = unzlocal_getByte(fin,&i);
183 x = (uLong)i;
185 if (err==UNZ_OK)
186 err = unzlocal_getByte(fin,&i);
187 x += ((uLong)i)<<8;
189 if (err==UNZ_OK)
190 *pX = x;
191 else
192 *pX = 0;
193 return err;
196 local int unzlocal_getLong (FILE *fin,uLong *pX)
198 uLong x ;
199 int i;
200 int err;
202 err = unzlocal_getByte(fin,&i);
203 x = (uLong)i;
205 if (err==UNZ_OK)
206 err = unzlocal_getByte(fin,&i);
207 x += ((uLong)i)<<8;
209 if (err==UNZ_OK)
210 err = unzlocal_getByte(fin,&i);
211 x += ((uLong)i)<<16;
213 if (err==UNZ_OK)
214 err = unzlocal_getByte(fin,&i);
215 x += ((uLong)i)<<24;
217 if (err==UNZ_OK)
218 *pX = x;
219 else
220 *pX = 0;
221 return err;
225 /* My own strcmpi / strcasecmp */
226 local int strcmpcasenosensitive_internal (const char *fileName1,
227 const char *fileName2)
229 for (;;)
231 char c1=*(fileName1++);
232 char c2=*(fileName2++);
233 if ((c1>='a') && (c1<='z'))
234 c1 -= 0x20;
235 if ((c2>='a') && (c2<='z'))
236 c2 -= 0x20;
237 if (c1=='\0')
238 return ((c2=='\0') ? 0 : -1);
239 if (c2=='\0')
240 return 1;
241 if (c1<c2)
242 return -1;
243 if (c1>c2)
244 return 1;
249 #ifdef CASESENSITIVITYDEFAULT_NO
250 #define CASESENSITIVITYDEFAULTVALUE 2
251 #else
252 #define CASESENSITIVITYDEFAULTVALUE 1
253 #endif
255 #ifndef STRCMPCASENOSENTIVEFUNCTION
256 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
257 #endif
260 Compare two filename (fileName1,fileName2).
261 If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
262 If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
263 or strcasecmp)
264 If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
265 (like 1 on Unix, 2 on Windows)
268 extern int ZEXPORT unzStringFileNameCompare (const char *fileName1,
269 const char *fileName2,
270 int iCaseSensitivity)
272 if (iCaseSensitivity==0)
273 iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
275 if (iCaseSensitivity==1)
276 return strcmp(fileName1,fileName2);
278 return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
281 #define BUFREADCOMMENT (0x400)
284 Locate the Central directory of a zipfile (at the end, just before
285 the global comment)
287 local uLong unzlocal_SearchCentralDir(FILE *fin)
289 unsigned char* buf;
290 uLong uSizeFile;
291 uLong uBackRead;
292 uLong uMaxBack=0xffff; /* maximum size of global comment */
293 uLong uPosFound=0;
295 if (fseek(fin,0,SEEK_END) != 0)
296 return 0;
299 uSizeFile = ftell( fin );
301 if (uMaxBack>uSizeFile)
302 uMaxBack = uSizeFile;
304 buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
305 if (buf==NULL)
306 return 0;
308 uBackRead = 4;
309 while (uBackRead<uMaxBack)
311 uLong uReadSize,uReadPos ;
312 int i;
313 if (uBackRead+BUFREADCOMMENT>uMaxBack)
314 uBackRead = uMaxBack;
315 else
316 uBackRead+=BUFREADCOMMENT;
317 uReadPos = uSizeFile-uBackRead ;
319 uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
320 (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
321 if (fseek(fin,uReadPos,SEEK_SET)!=0)
322 break;
324 if (fread(buf,(uInt)uReadSize,1,fin)!=1)
325 break;
327 for (i=(int)uReadSize-3; (i--)>0;)
328 if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
329 ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
331 uPosFound = uReadPos+i;
332 break;
335 if (uPosFound!=0)
336 break;
338 TRYFREE(buf);
339 return uPosFound;
343 Open a Zip file. path contain the full pathname (by example,
344 on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
345 "zlib/zlib109.zip".
346 If the zipfile cannot be opened (file don't exist or in not valid), the
347 return value is NULL.
348 Else, the return value is a unzFile Handle, usable with other function
349 of this unzip package.
351 extern unzFile ZEXPORT unzOpen (const char *path)
353 unz_s us;
354 unz_s *s;
355 uLong central_pos,uL;
356 FILE * fin ;
358 uLong number_disk; /* number of the current dist, used for
359 spaning ZIP, unsupported, always 0*/
360 uLong number_disk_with_CD; /* number the the disk with central dir, used
361 for spaning ZIP, unsupported, always 0*/
362 uLong number_entry_CD; /* total number of entries in
363 the central dir
364 (same than number_entry on nospan) */
366 int err=UNZ_OK;
368 if (unz_copyright[0]!=' ')
369 return NULL;
371 fin=fopen(path,"rb");
372 if (fin==NULL)
373 return NULL;
375 central_pos = unzlocal_SearchCentralDir(fin);
376 if (central_pos==0)
377 err=UNZ_ERRNO;
379 if (fseek(fin,central_pos,SEEK_SET)!=0)
380 err=UNZ_ERRNO;
382 /* the signature, already checked */
383 if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
384 err=UNZ_ERRNO;
386 /* number of this disk */
387 if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
388 err=UNZ_ERRNO;
390 /* number of the disk with the start of the central directory */
391 if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
392 err=UNZ_ERRNO;
394 /* total number of entries in the central dir on this disk */
395 if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
396 err=UNZ_ERRNO;
398 /* total number of entries in the central dir */
399 if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
400 err=UNZ_ERRNO;
402 if ((number_entry_CD!=us.gi.number_entry) ||
403 (number_disk_with_CD!=0) ||
404 (number_disk!=0))
405 err=UNZ_BADZIPFILE;
407 /* size of the central directory */
408 if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
409 err=UNZ_ERRNO;
411 /* offset of start of central directory with respect to the
412 starting disk number */
413 if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
414 err=UNZ_ERRNO;
416 /* zipfile comment length */
417 if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
418 err=UNZ_ERRNO;
420 if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
421 (err==UNZ_OK))
422 err=UNZ_BADZIPFILE;
424 if (err!=UNZ_OK)
426 fclose(fin);
427 return NULL;
430 us.file=fin;
431 us.byte_before_the_zipfile = central_pos -
432 (us.offset_central_dir+us.size_central_dir);
433 us.central_pos = central_pos;
434 us.pfile_in_zip_read = NULL;
437 s=(unz_s*)ALLOC(sizeof(unz_s));
438 *s=us;
439 unzGoToFirstFile((unzFile)s);
440 return (unzFile)s;
445 Close a ZipFile opened with unzipOpen.
446 If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
447 these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
448 return UNZ_OK if there is no problem. */
449 extern int ZEXPORT unzClose (unzFile file)
451 unz_s* s;
452 if (file==NULL)
453 return UNZ_PARAMERROR;
454 s=(unz_s*)file;
456 if (s->pfile_in_zip_read!=NULL)
457 unzCloseCurrentFile(file);
459 fclose(s->file);
460 TRYFREE(s);
461 return UNZ_OK;
466 Write info about the ZipFile in the *pglobal_info structure.
467 No preparation of the structure is needed
468 return UNZ_OK if there is no problem. */
469 extern int ZEXPORT unzGetGlobalInfo (unzFile file,
470 unz_global_info *pglobal_info)
472 unz_s* s;
473 if (file==NULL)
474 return UNZ_PARAMERROR;
475 s=(unz_s*)file;
476 *pglobal_info=s->gi;
477 return UNZ_OK;
482 Translate date/time from Dos format to tm_unz (readable more easilty)
484 local void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz *ptm)
486 uLong uDate;
487 uDate = (uLong)(ulDosDate>>16);
488 ptm->tm_mday = (uInt)(uDate&0x1f) ;
489 ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
490 ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
492 ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
493 ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
494 ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
498 Get Info about the current file in the zipfile, with internal only info
500 local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
501 unz_file_info *pfile_info,
502 unz_file_info_internal
503 *pfile_info_internal,
504 char *szFileName,
505 uLong fileNameBufferSize,
506 void *extraField,
507 uLong extraFieldBufferSize,
508 char *szComment,
509 uLong commentBufferSize));
511 local int unzlocal_GetCurrentFileInfoInternal (unzFile file,
512 unz_file_info *pfile_info,
513 unz_file_info_internal *pfile_info_internal,
514 char *szFileName,
515 uLong fileNameBufferSize,
516 void *extraField,
517 uLong extraFieldBufferSize,
518 char *szComment,
519 uLong commentBufferSize)
521 unz_s* s;
522 unz_file_info file_info;
523 unz_file_info_internal file_info_internal;
524 int err=UNZ_OK;
525 uLong uMagic;
526 long lSeek=0;
528 if (file==NULL)
529 return UNZ_PARAMERROR;
530 s=(unz_s*)file;
531 if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
532 err=UNZ_ERRNO;
535 /* we check the magic */
536 if (err==UNZ_OK)
537 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
538 err=UNZ_ERRNO;
539 else if (uMagic!=0x02014b50)
540 err=UNZ_BADZIPFILE;
542 if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
543 err=UNZ_ERRNO;
545 if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
546 err=UNZ_ERRNO;
548 if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
549 err=UNZ_ERRNO;
551 if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
552 err=UNZ_ERRNO;
554 if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
555 err=UNZ_ERRNO;
557 unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
559 if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
560 err=UNZ_ERRNO;
562 if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
563 err=UNZ_ERRNO;
565 if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
566 err=UNZ_ERRNO;
568 if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
569 err=UNZ_ERRNO;
571 if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
572 err=UNZ_ERRNO;
574 if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
575 err=UNZ_ERRNO;
577 if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
578 err=UNZ_ERRNO;
580 if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
581 err=UNZ_ERRNO;
583 if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
584 err=UNZ_ERRNO;
586 if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
587 err=UNZ_ERRNO;
589 lSeek+=file_info.size_filename;
590 if ((err==UNZ_OK) && (szFileName!=NULL))
592 uLong uSizeRead ;
593 if (file_info.size_filename<fileNameBufferSize)
595 *(szFileName+file_info.size_filename)='\0';
596 uSizeRead = file_info.size_filename;
598 else
599 uSizeRead = fileNameBufferSize;
601 if ((file_info.size_filename>0) && (fileNameBufferSize>0))
602 if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
603 err=UNZ_ERRNO;
604 lSeek -= uSizeRead;
608 if ((err==UNZ_OK) && (extraField!=NULL))
610 uLong uSizeRead ;
611 if (file_info.size_file_extra<extraFieldBufferSize)
612 uSizeRead = file_info.size_file_extra;
613 else
614 uSizeRead = extraFieldBufferSize;
616 if (lSeek!=0)
617 if (fseek(s->file,lSeek,SEEK_CUR)==0)
618 lSeek=0;
619 else
620 err=UNZ_ERRNO;
621 if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
622 if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
623 err=UNZ_ERRNO;
624 lSeek += file_info.size_file_extra - uSizeRead;
626 else
627 lSeek+=file_info.size_file_extra;
630 if ((err==UNZ_OK) && (szComment!=NULL))
632 uLong uSizeRead ;
633 if (file_info.size_file_comment<commentBufferSize)
635 *(szComment+file_info.size_file_comment)='\0';
636 uSizeRead = file_info.size_file_comment;
638 else
639 uSizeRead = commentBufferSize;
641 if (lSeek!=0)
642 if (fseek(s->file,lSeek,SEEK_CUR)==0)
643 lSeek=0;
644 else
645 err=UNZ_ERRNO;
646 if ((file_info.size_file_comment>0) && (commentBufferSize>0))
647 if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
648 err=UNZ_ERRNO;
649 lSeek+=file_info.size_file_comment - uSizeRead;
651 else
652 lSeek+=file_info.size_file_comment;
654 if ((err==UNZ_OK) && (pfile_info!=NULL))
655 *pfile_info=file_info;
657 if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
658 *pfile_info_internal=file_info_internal;
660 return err;
666 Write info about the ZipFile in the *pglobal_info structure.
667 No preparation of the structure is needed
668 return UNZ_OK if there is no problem.
670 extern int ZEXPORT unzGetCurrentFileInfo (unzFile file,
671 unz_file_info *pfile_info,
672 char *szFileName,
673 uLong fileNameBufferSize,
674 void *extraField,
675 uLong extraFieldBufferSize,
676 char *szComment,
677 uLong commentBufferSize)
679 return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
680 szFileName,fileNameBufferSize,
681 extraField,extraFieldBufferSize,
682 szComment,commentBufferSize);
686 Set the current file of the zipfile to the first file.
687 return UNZ_OK if there is no problem
689 extern int ZEXPORT unzGoToFirstFile (unzFile file)
691 int err=UNZ_OK;
692 unz_s* s;
693 if (file==NULL)
694 return UNZ_PARAMERROR;
695 s=(unz_s*)file;
696 s->pos_in_central_dir=s->offset_central_dir;
697 s->num_file=0;
698 err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
699 &s->cur_file_info_internal,
700 NULL,0,NULL,0,NULL,0);
701 s->current_file_ok = (err == UNZ_OK);
702 return err;
707 Set the current file of the zipfile to the next file.
708 return UNZ_OK if there is no problem
709 return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
711 extern int ZEXPORT unzGoToNextFile (unzFile file)
713 unz_s* s;
714 int err;
716 if (file==NULL)
717 return UNZ_PARAMERROR;
718 s=(unz_s*)file;
719 if (!s->current_file_ok)
720 return UNZ_END_OF_LIST_OF_FILE;
721 if (s->num_file+1==s->gi.number_entry)
722 return UNZ_END_OF_LIST_OF_FILE;
724 s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
725 s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
726 s->num_file++;
727 err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
728 &s->cur_file_info_internal,
729 NULL,0,NULL,0,NULL,0);
730 s->current_file_ok = (err == UNZ_OK);
731 return err;
736 Try locate the file szFileName in the zipfile.
737 For the iCaseSensitivity signification, see unzipStringFileNameCompare
739 return value :
740 UNZ_OK if the file is found. It becomes the current file.
741 UNZ_END_OF_LIST_OF_FILE if the file is not found
743 extern int ZEXPORT unzLocateFile (unzFile file,
744 const char *szFileName,
745 int iCaseSensitivity)
747 unz_s* s;
748 int err;
751 uLong num_fileSaved;
752 uLong pos_in_central_dirSaved;
755 if (file==NULL)
756 return UNZ_PARAMERROR;
758 if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
759 return UNZ_PARAMERROR;
761 s=(unz_s*)file;
762 if (!s->current_file_ok)
763 return UNZ_END_OF_LIST_OF_FILE;
765 num_fileSaved = s->num_file;
766 pos_in_central_dirSaved = s->pos_in_central_dir;
768 err = unzGoToFirstFile(file);
770 while (err == UNZ_OK)
772 char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
773 unzGetCurrentFileInfo(file,NULL,
774 szCurrentFileName,sizeof(szCurrentFileName)-1,
775 NULL,0,NULL,0);
776 if (unzStringFileNameCompare(szCurrentFileName,
777 szFileName,iCaseSensitivity)==0)
778 return UNZ_OK;
779 err = unzGoToNextFile(file);
782 s->num_file = num_fileSaved ;
783 s->pos_in_central_dir = pos_in_central_dirSaved ;
784 return err;
789 Read the local header of the current zipfile
790 Check the coherency of the local header and info in the end of central
791 directory about this file
792 store in *piSizeVar the size of extra info in local header
793 (filename and size of extra field data)
795 local int unzlocal_CheckCurrentFileCoherencyHeader (unz_s *s,
796 uInt *piSizeVar,
797 uLong *poffset_local_extrafield,
798 uInt *psize_local_extrafield)
800 uLong uMagic,uData,uFlags;
801 uLong size_filename;
802 uLong size_extra_field;
803 int err=UNZ_OK;
805 *piSizeVar = 0;
806 *poffset_local_extrafield = 0;
807 *psize_local_extrafield = 0;
809 if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
810 s->byte_before_the_zipfile,SEEK_SET)!=0)
811 return UNZ_ERRNO;
814 if (err==UNZ_OK)
815 if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
816 err=UNZ_ERRNO;
817 else if (uMagic!=0x04034b50)
818 err=UNZ_BADZIPFILE;
820 if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
821 err=UNZ_ERRNO;
823 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
824 err=UNZ_BADZIPFILE;
826 if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
827 err=UNZ_ERRNO;
829 if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
830 err=UNZ_ERRNO;
831 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
832 err=UNZ_BADZIPFILE;
834 if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
835 (s->cur_file_info.compression_method!=Z_DEFLATED))
836 err=UNZ_BADZIPFILE;
838 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
839 err=UNZ_ERRNO;
841 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
842 err=UNZ_ERRNO;
843 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
844 ((uFlags & 8)==0))
845 err=UNZ_BADZIPFILE;
847 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
848 err=UNZ_ERRNO;
849 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
850 ((uFlags & 8)==0))
851 err=UNZ_BADZIPFILE;
853 if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
854 err=UNZ_ERRNO;
855 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
856 ((uFlags & 8)==0))
857 err=UNZ_BADZIPFILE;
860 if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
861 err=UNZ_ERRNO;
862 else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
863 err=UNZ_BADZIPFILE;
865 *piSizeVar += (uInt)size_filename;
867 if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
868 err=UNZ_ERRNO;
869 *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
870 SIZEZIPLOCALHEADER + size_filename;
871 *psize_local_extrafield = (uInt)size_extra_field;
873 *piSizeVar += (uInt)size_extra_field;
875 return err;
879 Open for reading data the current file in the zipfile.
880 If there is no error and the file is opened, the return value is UNZ_OK.
882 extern int ZEXPORT unzOpenCurrentFile (unzFile file)
884 int err=UNZ_OK;
885 int Store;
886 uInt iSizeVar;
887 unz_s* s;
888 file_in_zip_read_info_s* pfile_in_zip_read_info;
889 uLong offset_local_extrafield; /* offset of the local extra field */
890 uInt size_local_extrafield; /* size of the local extra field */
892 if (file==NULL)
893 return UNZ_PARAMERROR;
894 s=(unz_s*)file;
895 if (!s->current_file_ok)
896 return UNZ_PARAMERROR;
898 if (s->pfile_in_zip_read != NULL)
899 unzCloseCurrentFile(file);
901 if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
902 &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
903 return UNZ_BADZIPFILE;
905 pfile_in_zip_read_info = (file_in_zip_read_info_s*)
906 ALLOC(sizeof(file_in_zip_read_info_s));
907 if (pfile_in_zip_read_info==NULL)
908 return UNZ_INTERNALERROR;
910 pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
911 pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
912 pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
913 pfile_in_zip_read_info->pos_local_extrafield=0;
915 if (pfile_in_zip_read_info->read_buffer==NULL)
917 TRYFREE(pfile_in_zip_read_info);
918 return UNZ_INTERNALERROR;
921 pfile_in_zip_read_info->stream_initialised=0;
923 if ((s->cur_file_info.compression_method!=0) &&
924 (s->cur_file_info.compression_method!=Z_DEFLATED))
925 err=UNZ_BADZIPFILE;
926 Store = s->cur_file_info.compression_method==0;
928 pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
929 pfile_in_zip_read_info->crc32=0;
930 pfile_in_zip_read_info->compression_method =
931 s->cur_file_info.compression_method;
932 pfile_in_zip_read_info->file=s->file;
933 pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
935 pfile_in_zip_read_info->stream.total_out = 0;
937 if (!Store)
939 pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
940 pfile_in_zip_read_info->stream.zfree = (free_func)0;
941 pfile_in_zip_read_info->stream.opaque = (voidpf)0;
943 err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
944 if (err == Z_OK)
945 pfile_in_zip_read_info->stream_initialised=1;
946 /* windowBits is passed < 0 to tell that there is no zlib header.
947 * Note that in this case inflate *requires* an extra "dummy" byte
948 * after the compressed stream in order to complete decompression and
949 * return Z_STREAM_END.
950 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
951 * size of both compressed and uncompressed data
954 pfile_in_zip_read_info->rest_read_compressed =
955 s->cur_file_info.compressed_size ;
956 pfile_in_zip_read_info->rest_read_uncompressed =
957 s->cur_file_info.uncompressed_size ;
960 pfile_in_zip_read_info->pos_in_zipfile =
961 s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
962 iSizeVar;
964 pfile_in_zip_read_info->stream.avail_in = (uInt)0;
967 s->pfile_in_zip_read = pfile_in_zip_read_info;
968 return UNZ_OK;
973 Read bytes from the current file.
974 buf contain buffer where data must be copied
975 len the size of buf.
977 return the number of byte copied if somes bytes are copied
978 return 0 if the end of file was reached
979 return <0 with error code if there is an error
980 (UNZ_ERRNO for IO error, or zLib error for uncompress error)
982 extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len)
984 int err=UNZ_OK;
985 uInt iRead = 0;
986 unz_s* s;
987 file_in_zip_read_info_s* pfile_in_zip_read_info;
988 if (file==NULL)
989 return UNZ_PARAMERROR;
990 s=(unz_s*)file;
991 pfile_in_zip_read_info=s->pfile_in_zip_read;
993 if (pfile_in_zip_read_info==NULL)
994 return UNZ_PARAMERROR;
997 if ((pfile_in_zip_read_info->read_buffer == NULL))
998 return UNZ_END_OF_LIST_OF_FILE;
999 if (len==0)
1000 return 0;
1002 pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1004 pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1006 if (len>pfile_in_zip_read_info->rest_read_uncompressed)
1007 pfile_in_zip_read_info->stream.avail_out =
1008 (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1010 while (pfile_in_zip_read_info->stream.avail_out>0)
1012 if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1013 (pfile_in_zip_read_info->rest_read_compressed>0))
1015 uInt uReadThis = UNZ_BUFSIZE;
1016 if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1017 uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1018 if (uReadThis == 0)
1019 return UNZ_EOF;
1020 if (fseek(pfile_in_zip_read_info->file,
1021 pfile_in_zip_read_info->pos_in_zipfile +
1022 pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
1023 return UNZ_ERRNO;
1024 if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
1025 pfile_in_zip_read_info->file)!=1)
1026 return UNZ_ERRNO;
1027 pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1029 pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1031 pfile_in_zip_read_info->stream.next_in =
1032 (Bytef*)pfile_in_zip_read_info->read_buffer;
1033 pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1036 if (pfile_in_zip_read_info->compression_method==0)
1038 uInt uDoCopy,i ;
1039 if (pfile_in_zip_read_info->stream.avail_out <
1040 pfile_in_zip_read_info->stream.avail_in)
1041 uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1042 else
1043 uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1045 for (i=0;i<uDoCopy;i++)
1046 *(pfile_in_zip_read_info->stream.next_out+i) =
1047 *(pfile_in_zip_read_info->stream.next_in+i);
1049 pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1050 pfile_in_zip_read_info->stream.next_out,
1051 uDoCopy);
1052 pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1053 pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1054 pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1055 pfile_in_zip_read_info->stream.next_out += uDoCopy;
1056 pfile_in_zip_read_info->stream.next_in += uDoCopy;
1057 pfile_in_zip_read_info->stream.total_out += uDoCopy;
1058 iRead += uDoCopy;
1060 else
1062 uLong uTotalOutBefore,uTotalOutAfter;
1063 const Bytef *bufBefore;
1064 uLong uOutThis;
1065 int flush=Z_SYNC_FLUSH;
1067 uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1068 bufBefore = pfile_in_zip_read_info->stream.next_out;
1071 if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1072 pfile_in_zip_read_info->stream.avail_out) &&
1073 (pfile_in_zip_read_info->rest_read_compressed == 0))
1074 flush = Z_FINISH;
1076 err=inflate(&pfile_in_zip_read_info->stream,flush);
1078 uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1079 uOutThis = uTotalOutAfter-uTotalOutBefore;
1081 pfile_in_zip_read_info->crc32 =
1082 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1083 (uInt)(uOutThis));
1085 pfile_in_zip_read_info->rest_read_uncompressed -=
1086 uOutThis;
1088 iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1090 if (err==Z_STREAM_END)
1091 return (iRead==0) ? UNZ_EOF : iRead;
1092 if (err!=Z_OK)
1093 break;
1097 if (err==Z_OK)
1098 return iRead;
1099 return err;
1104 Give the current position in uncompressed data
1106 extern z_off_t ZEXPORT unztell (unzFile file)
1108 unz_s* s;
1109 file_in_zip_read_info_s* pfile_in_zip_read_info;
1110 if (file==NULL)
1111 return UNZ_PARAMERROR;
1112 s=(unz_s*)file;
1113 pfile_in_zip_read_info=s->pfile_in_zip_read;
1115 if (pfile_in_zip_read_info==NULL)
1116 return UNZ_PARAMERROR;
1118 return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1123 return 1 if the end of file was reached, 0 elsewhere
1125 extern int ZEXPORT unzeof (unzFile file)
1127 unz_s* s;
1128 file_in_zip_read_info_s* pfile_in_zip_read_info;
1129 if (file==NULL)
1130 return UNZ_PARAMERROR;
1131 s=(unz_s*)file;
1132 pfile_in_zip_read_info=s->pfile_in_zip_read;
1134 if (pfile_in_zip_read_info==NULL)
1135 return UNZ_PARAMERROR;
1137 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1138 return 1;
1139 else
1140 return 0;
1146 Read extra field from the current file (opened by unzOpenCurrentFile)
1147 This is the local-header version of the extra field (sometimes, there is
1148 more info in the local-header version than in the central-header)
1150 if buf==NULL, it return the size of the local extra field that can be read
1152 if buf!=NULL, len is the size of the buffer, the extra header is copied in
1153 buf.
1154 the return value is the number of bytes copied in buf, or (if <0)
1155 the error code
1157 extern int ZEXPORT unzGetLocalExtrafield (unzFile file,voidp buf,unsigned len)
1159 unz_s* s;
1160 file_in_zip_read_info_s* pfile_in_zip_read_info;
1161 uInt read_now;
1162 uLong size_to_read;
1164 if (file==NULL)
1165 return UNZ_PARAMERROR;
1166 s=(unz_s*)file;
1167 pfile_in_zip_read_info=s->pfile_in_zip_read;
1169 if (pfile_in_zip_read_info==NULL)
1170 return UNZ_PARAMERROR;
1172 size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1173 pfile_in_zip_read_info->pos_local_extrafield);
1175 if (buf==NULL)
1176 return (int)size_to_read;
1178 if (len>size_to_read)
1179 read_now = (uInt)size_to_read;
1180 else
1181 read_now = (uInt)len ;
1183 if (read_now==0)
1184 return 0;
1186 if (fseek(pfile_in_zip_read_info->file,
1187 pfile_in_zip_read_info->offset_local_extrafield +
1188 pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
1189 return UNZ_ERRNO;
1191 if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
1192 return UNZ_ERRNO;
1194 return (int)read_now;
1198 Close the file in zip opened with unzipOpenCurrentFile
1199 Return UNZ_CRCERROR if all the file was read but the CRC is not good
1201 extern int ZEXPORT unzCloseCurrentFile (unzFile file)
1203 int err=UNZ_OK;
1205 unz_s* s;
1206 file_in_zip_read_info_s* pfile_in_zip_read_info;
1207 if (file==NULL)
1208 return UNZ_PARAMERROR;
1209 s=(unz_s*)file;
1210 pfile_in_zip_read_info=s->pfile_in_zip_read;
1212 if (pfile_in_zip_read_info==NULL)
1213 return UNZ_PARAMERROR;
1216 if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1218 if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1219 err=UNZ_CRCERROR;
1223 TRYFREE(pfile_in_zip_read_info->read_buffer);
1224 pfile_in_zip_read_info->read_buffer = NULL;
1225 if (pfile_in_zip_read_info->stream_initialised)
1226 inflateEnd(&pfile_in_zip_read_info->stream);
1228 pfile_in_zip_read_info->stream_initialised = 0;
1229 TRYFREE(pfile_in_zip_read_info);
1231 s->pfile_in_zip_read=NULL;
1233 return err;
1238 Get the global comment string of the ZipFile, in the szComment buffer.
1239 uSizeBuf is the size of the szComment buffer.
1240 return the number of byte copied or an error code <0
1242 extern int ZEXPORT unzGetGlobalComment (unzFile file,
1243 char *szComment,
1244 uLong uSizeBuf)
1246 //int err=UNZ_OK;
1247 unz_s* s;
1248 uLong uReadThis ;
1249 if (file==NULL)
1250 return UNZ_PARAMERROR;
1251 s=(unz_s*)file;
1253 uReadThis = uSizeBuf;
1254 if (uReadThis>s->gi.size_comment)
1255 uReadThis = s->gi.size_comment;
1257 if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
1258 return UNZ_ERRNO;
1260 if (uReadThis>0)
1262 *szComment='\0';
1263 if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
1264 return UNZ_ERRNO;
1267 if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1268 *(szComment+s->gi.size_comment)='\0';
1269 return (int)uReadThis;