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)
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
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
58 #define UNZ_BUFSIZE (16384)
61 #ifndef UNZ_MAXFILENAMEINZIP
62 #define UNZ_MAXFILENAMEINZIP (256)
66 # define ALLOC(size) (malloc(size))
69 # define TRYFREE(p) {if (p) free(p);}
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.... */
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 */
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
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 */
147 /* ===========================================================================
148 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
150 IN assertion: the stream s has been sucessfully opened for reading.
154 local
int unzlocal_getByte(FILE *fin
,int *pi
)
157 size_t err
= fread(&c
, 1, 1, fin
);
173 /* ===========================================================================
174 Reads a long in LSB order from the given gz_stream. Sets
176 local
int unzlocal_getShort (FILE *fin
,uLong
*pX
)
182 err
= unzlocal_getByte(fin
,&i
);
186 err
= unzlocal_getByte(fin
,&i
);
196 local
int unzlocal_getLong (FILE *fin
,uLong
*pX
)
202 err
= unzlocal_getByte(fin
,&i
);
206 err
= unzlocal_getByte(fin
,&i
);
210 err
= unzlocal_getByte(fin
,&i
);
214 err
= unzlocal_getByte(fin
,&i
);
225 /* My own strcmpi / strcasecmp */
226 local
int strcmpcasenosensitive_internal (const char *fileName1
,
227 const char *fileName2
)
231 char c1
=*(fileName1
++);
232 char c2
=*(fileName2
++);
233 if ((c1
>='a') && (c1
<='z'))
235 if ((c2
>='a') && (c2
<='z'))
238 return ((c2
=='\0') ? 0 : -1);
249 #ifdef CASESENSITIVITYDEFAULT_NO
250 #define CASESENSITIVITYDEFAULTVALUE 2
252 #define CASESENSITIVITYDEFAULTVALUE 1
255 #ifndef STRCMPCASENOSENTIVEFUNCTION
256 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
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
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
287 local uLong
unzlocal_SearchCentralDir(FILE *fin
)
292 uLong uMaxBack
=0xffff; /* maximum size of global comment */
295 if (fseek(fin
,0,SEEK_END
) != 0)
299 uSizeFile
= ftell( fin
);
301 if (uMaxBack
>uSizeFile
)
302 uMaxBack
= uSizeFile
;
304 buf
= (unsigned char*)ALLOC(BUFREADCOMMENT
+4);
309 while (uBackRead
<uMaxBack
)
311 uLong uReadSize
,uReadPos
;
313 if (uBackRead
+BUFREADCOMMENT
>uMaxBack
)
314 uBackRead
= uMaxBack
;
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)
324 if (fread(buf
,(uInt
)uReadSize
,1,fin
)!=1)
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
;
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
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
)
355 uLong central_pos
,uL
;
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
364 (same than number_entry on nospan) */
368 if (unz_copyright
[0]!=' ')
371 fin
=fopen(path
,"rb");
375 central_pos
= unzlocal_SearchCentralDir(fin
);
379 if (fseek(fin
,central_pos
,SEEK_SET
)!=0)
382 /* the signature, already checked */
383 if (unzlocal_getLong(fin
,&uL
)!=UNZ_OK
)
386 /* number of this disk */
387 if (unzlocal_getShort(fin
,&number_disk
)!=UNZ_OK
)
390 /* number of the disk with the start of the central directory */
391 if (unzlocal_getShort(fin
,&number_disk_with_CD
)!=UNZ_OK
)
394 /* total number of entries in the central dir on this disk */
395 if (unzlocal_getShort(fin
,&us
.gi
.number_entry
)!=UNZ_OK
)
398 /* total number of entries in the central dir */
399 if (unzlocal_getShort(fin
,&number_entry_CD
)!=UNZ_OK
)
402 if ((number_entry_CD
!=us
.gi
.number_entry
) ||
403 (number_disk_with_CD
!=0) ||
407 /* size of the central directory */
408 if (unzlocal_getLong(fin
,&us
.size_central_dir
)!=UNZ_OK
)
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
)
416 /* zipfile comment length */
417 if (unzlocal_getShort(fin
,&us
.gi
.size_comment
)!=UNZ_OK
)
420 if ((central_pos
<us
.offset_central_dir
+us
.size_central_dir
) &&
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
));
439 unzGoToFirstFile((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
)
453 return UNZ_PARAMERROR
;
456 if (s
->pfile_in_zip_read
!=NULL
)
457 unzCloseCurrentFile(file
);
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
)
474 return UNZ_PARAMERROR
;
482 Translate date/time from Dos format to tm_unz (readable more easilty)
484 local
void unzlocal_DosDateToTmuDate (uLong ulDosDate
, tm_unz
*ptm
)
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
,
505 uLong fileNameBufferSize
,
507 uLong extraFieldBufferSize
,
509 uLong commentBufferSize
));
511 local
int unzlocal_GetCurrentFileInfoInternal (unzFile file
,
512 unz_file_info
*pfile_info
,
513 unz_file_info_internal
*pfile_info_internal
,
515 uLong fileNameBufferSize
,
517 uLong extraFieldBufferSize
,
519 uLong commentBufferSize
)
522 unz_file_info file_info
;
523 unz_file_info_internal file_info_internal
;
529 return UNZ_PARAMERROR
;
531 if (fseek(s
->file
,s
->pos_in_central_dir
+s
->byte_before_the_zipfile
,SEEK_SET
)!=0)
535 /* we check the magic */
537 if (unzlocal_getLong(s
->file
,&uMagic
) != UNZ_OK
)
539 else if (uMagic
!=0x02014b50)
542 if (unzlocal_getShort(s
->file
,&file_info
.version
) != UNZ_OK
)
545 if (unzlocal_getShort(s
->file
,&file_info
.version_needed
) != UNZ_OK
)
548 if (unzlocal_getShort(s
->file
,&file_info
.flag
) != UNZ_OK
)
551 if (unzlocal_getShort(s
->file
,&file_info
.compression_method
) != UNZ_OK
)
554 if (unzlocal_getLong(s
->file
,&file_info
.dosDate
) != UNZ_OK
)
557 unzlocal_DosDateToTmuDate(file_info
.dosDate
,&file_info
.tmu_date
);
559 if (unzlocal_getLong(s
->file
,&file_info
.crc
) != UNZ_OK
)
562 if (unzlocal_getLong(s
->file
,&file_info
.compressed_size
) != UNZ_OK
)
565 if (unzlocal_getLong(s
->file
,&file_info
.uncompressed_size
) != UNZ_OK
)
568 if (unzlocal_getShort(s
->file
,&file_info
.size_filename
) != UNZ_OK
)
571 if (unzlocal_getShort(s
->file
,&file_info
.size_file_extra
) != UNZ_OK
)
574 if (unzlocal_getShort(s
->file
,&file_info
.size_file_comment
) != UNZ_OK
)
577 if (unzlocal_getShort(s
->file
,&file_info
.disk_num_start
) != UNZ_OK
)
580 if (unzlocal_getShort(s
->file
,&file_info
.internal_fa
) != UNZ_OK
)
583 if (unzlocal_getLong(s
->file
,&file_info
.external_fa
) != UNZ_OK
)
586 if (unzlocal_getLong(s
->file
,&file_info_internal
.offset_curfile
) != UNZ_OK
)
589 lSeek
+=file_info
.size_filename
;
590 if ((err
==UNZ_OK
) && (szFileName
!=NULL
))
593 if (file_info
.size_filename
<fileNameBufferSize
)
595 *(szFileName
+file_info
.size_filename
)='\0';
596 uSizeRead
= file_info
.size_filename
;
599 uSizeRead
= fileNameBufferSize
;
601 if ((file_info
.size_filename
>0) && (fileNameBufferSize
>0))
602 if (fread(szFileName
,(uInt
)uSizeRead
,1,s
->file
)!=1)
608 if ((err
==UNZ_OK
) && (extraField
!=NULL
))
611 if (file_info
.size_file_extra
<extraFieldBufferSize
)
612 uSizeRead
= file_info
.size_file_extra
;
614 uSizeRead
= extraFieldBufferSize
;
617 if (fseek(s
->file
,lSeek
,SEEK_CUR
)==0)
621 if ((file_info
.size_file_extra
>0) && (extraFieldBufferSize
>0))
622 if (fread(extraField
,(uInt
)uSizeRead
,1,s
->file
)!=1)
624 lSeek
+= file_info
.size_file_extra
- uSizeRead
;
627 lSeek
+=file_info
.size_file_extra
;
630 if ((err
==UNZ_OK
) && (szComment
!=NULL
))
633 if (file_info
.size_file_comment
<commentBufferSize
)
635 *(szComment
+file_info
.size_file_comment
)='\0';
636 uSizeRead
= file_info
.size_file_comment
;
639 uSizeRead
= commentBufferSize
;
642 if (fseek(s
->file
,lSeek
,SEEK_CUR
)==0)
646 if ((file_info
.size_file_comment
>0) && (commentBufferSize
>0))
647 if (fread(szComment
,(uInt
)uSizeRead
,1,s
->file
)!=1)
649 lSeek
+=file_info
.size_file_comment
- uSizeRead
;
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
;
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
,
673 uLong fileNameBufferSize
,
675 uLong extraFieldBufferSize
,
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
)
694 return UNZ_PARAMERROR
;
696 s
->pos_in_central_dir
=s
->offset_central_dir
;
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
);
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
)
717 return UNZ_PARAMERROR
;
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
;
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
);
736 Try locate the file szFileName in the zipfile.
737 For the iCaseSensitivity signification, see unzipStringFileNameCompare
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
)
752 uLong pos_in_central_dirSaved
;
756 return UNZ_PARAMERROR
;
758 if (strlen(szFileName
)>=UNZ_MAXFILENAMEINZIP
)
759 return UNZ_PARAMERROR
;
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,
776 if (unzStringFileNameCompare(szCurrentFileName
,
777 szFileName
,iCaseSensitivity
)==0)
779 err
= unzGoToNextFile(file
);
782 s
->num_file
= num_fileSaved
;
783 s
->pos_in_central_dir
= pos_in_central_dirSaved
;
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
,
797 uLong
*poffset_local_extrafield
,
798 uInt
*psize_local_extrafield
)
800 uLong uMagic
,uData
,uFlags
;
802 uLong size_extra_field
;
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)
815 if (unzlocal_getLong(s
->file
,&uMagic
) != UNZ_OK
)
817 else if (uMagic
!=0x04034b50)
820 if (unzlocal_getShort(s
->file
,&uData
) != UNZ_OK
)
823 else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
826 if (unzlocal_getShort(s
->file
,&uFlags
) != UNZ_OK
)
829 if (unzlocal_getShort(s
->file
,&uData
) != UNZ_OK
)
831 else if ((err
==UNZ_OK
) && (uData
!=s
->cur_file_info
.compression_method
))
834 if ((err
==UNZ_OK
) && (s
->cur_file_info
.compression_method
!=0) &&
835 (s
->cur_file_info
.compression_method
!=Z_DEFLATED
))
838 if (unzlocal_getLong(s
->file
,&uData
) != UNZ_OK
) /* date/time */
841 if (unzlocal_getLong(s
->file
,&uData
) != UNZ_OK
) /* crc */
843 else if ((err
==UNZ_OK
) && (uData
!=s
->cur_file_info
.crc
) &&
847 if (unzlocal_getLong(s
->file
,&uData
) != UNZ_OK
) /* size compr */
849 else if ((err
==UNZ_OK
) && (uData
!=s
->cur_file_info
.compressed_size
) &&
853 if (unzlocal_getLong(s
->file
,&uData
) != UNZ_OK
) /* size uncompr */
855 else if ((err
==UNZ_OK
) && (uData
!=s
->cur_file_info
.uncompressed_size
) &&
860 if (unzlocal_getShort(s
->file
,&size_filename
) != UNZ_OK
)
862 else if ((err
==UNZ_OK
) && (size_filename
!=s
->cur_file_info
.size_filename
))
865 *piSizeVar
+= (uInt
)size_filename
;
867 if (unzlocal_getShort(s
->file
,&size_extra_field
) != UNZ_OK
)
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
;
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
)
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 */
893 return UNZ_PARAMERROR
;
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
))
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;
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
);
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
+
964 pfile_in_zip_read_info
->stream
.avail_in
= (uInt
)0;
967 s
->pfile_in_zip_read
= pfile_in_zip_read_info
;
973 Read bytes from the current file.
974 buf contain buffer where data must be copied
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
)
987 file_in_zip_read_info_s
* pfile_in_zip_read_info
;
989 return UNZ_PARAMERROR
;
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
;
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
;
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)
1024 if (fread(pfile_in_zip_read_info
->read_buffer
,uReadThis
,1,
1025 pfile_in_zip_read_info
->file
)!=1)
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)
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
;
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
,
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
;
1062 uLong uTotalOutBefore
,uTotalOutAfter
;
1063 const Bytef
*bufBefore
;
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))
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
,
1085 pfile_in_zip_read_info
->rest_read_uncompressed
-=
1088 iRead
+= (uInt
)(uTotalOutAfter
- uTotalOutBefore
);
1090 if (err
==Z_STREAM_END
)
1091 return (iRead
==0) ? UNZ_EOF
: iRead
;
1104 Give the current position in uncompressed data
1106 extern z_off_t ZEXPORT
unztell (unzFile file
)
1109 file_in_zip_read_info_s
* pfile_in_zip_read_info
;
1111 return UNZ_PARAMERROR
;
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
)
1128 file_in_zip_read_info_s
* pfile_in_zip_read_info
;
1130 return UNZ_PARAMERROR
;
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)
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
1154 the return value is the number of bytes copied in buf, or (if <0)
1157 extern int ZEXPORT
unzGetLocalExtrafield (unzFile file
,voidp buf
,unsigned len
)
1160 file_in_zip_read_info_s
* pfile_in_zip_read_info
;
1165 return UNZ_PARAMERROR
;
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
);
1176 return (int)size_to_read
;
1178 if (len
>size_to_read
)
1179 read_now
= (uInt
)size_to_read
;
1181 read_now
= (uInt
)len
;
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)
1191 if (fread(buf
,(uInt
)size_to_read
,1,pfile_in_zip_read_info
->file
)!=1)
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
)
1206 file_in_zip_read_info_s
* pfile_in_zip_read_info
;
1208 return UNZ_PARAMERROR
;
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
)
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
;
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
,
1250 return UNZ_PARAMERROR
;
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)
1263 if (fread(szComment
,(uInt
)uReadThis
,1,s
->file
)!=1)
1267 if ((szComment
!= NULL
) && (uSizeBuf
> s
->gi
.size_comment
))
1268 *(szComment
+s
->gi
.size_comment
)='\0';
1269 return (int)uReadThis
;