DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Unzip.cpp (33696B)


      1 #include "../idlib/precompiled.h"
      2 #pragma hdrstop
      3 
      4 #include "Unzip.h"
      5 
      6 /* unzip.h -- IO for uncompress .zip files using zlib 
      7    Version 0.15 beta, Mar 19th, 1998,
      8 
      9    Copyright (C) 1998 Gilles Vollant
     10 
     11    This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
     12      WinZip, InfoZip tools and compatible.
     13    Encryption and multi volume ZipFile (span) are not supported.
     14    Old compressions used by old PKZip 1.x are not supported
     15 
     16    THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
     17    CAN CHANGE IN FUTURE VERSION !!
     18    I WAIT FEEDBACK at mail info@winimage.com
     19    Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
     20 
     21    Condition of use and distribution are the same than zlib :
     22 
     23   This software is provided 'as-is', without any express or implied
     24   warranty.  In no event will the authors be held liable for any damages
     25   arising from the use of this software.
     26 
     27   Permission is granted to anyone to use this software for any purpose,
     28   including commercial applications, and to alter it and redistribute it
     29   freely, subject to the following restrictions:
     30 
     31   1. The origin of this software must not be misrepresented; you must not
     32      claim that you wrote the original software. If you use this software
     33      in a product, an acknowledgment in the product documentation would be
     34      appreciated but is not required.
     35   2. Altered source versions must be plainly marked as such, and must not be
     36      misrepresented as being the original software.
     37   3. This notice may not be removed or altered from any source distribution.
     38 
     39 
     40 */
     41 /* for more info about .ZIP format, see 
     42       ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
     43    PkWare has also a specification at :
     44       ftp://ftp.pkware.com/probdesc.zip */
     45 
     46 
     47 #if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
     48                       !defined(CASESENSITIVITYDEFAULT_NO)
     49 #define CASESENSITIVITYDEFAULT_NO
     50 #endif
     51 
     52 
     53 #ifndef UNZ_BUFSIZE
     54 #define UNZ_BUFSIZE (65536)
     55 #endif
     56 
     57 #ifndef UNZ_MAXFILENAMEINZIP
     58 #define UNZ_MAXFILENAMEINZIP (256)
     59 #endif
     60 
     61 #ifndef ALLOC
     62 # define ALLOC(size) (Mem_Alloc(size, TAG_IDFILE))
     63 #endif
     64 #ifndef TRYFREE
     65 # define TRYFREE(p) {if (p) Mem_Free(p);}
     66 #endif
     67 
     68 #define SIZECENTRALDIRITEM (0x2e)
     69 #define SIZEZIPLOCALHEADER (0x1e)
     70 
     71 
     72 idCVar zip_numSeeks( "zip_numSeeks", "0", CVAR_INTEGER, "" );
     73 idCVar zip_skippedSeeks( "zip_skippedSeeks", "0", CVAR_INTEGER, "" );
     74 idCVar zip_seeksForward( "zip_seeksForward", "0", CVAR_INTEGER, "" );
     75 idCVar zip_seeksBackward( "zip_seeksBackward", "0", CVAR_INTEGER, "" );
     76 idCVar zip_avgSeekDistance( "zip_avgSeekDistance", "0", CVAR_INTEGER, "" );
     77 
     78 /* ===========================================================================
     79      Read a byte from a gz_stream; update next_in and avail_in. Return EOF
     80    for end of file.
     81    IN assertion: the stream s has been sucessfully opened for reading.
     82 */
     83 
     84 /*
     85 static int unzlocal_getByte(FILE *fin,int *pi)
     86 {
     87     unsigned char c;
     88 	int err = fread(&c, 1, 1, fin);
     89     if (err==1)
     90     {
     91         *pi = (int)c;
     92         return UNZ_OK;
     93     }
     94     else
     95     {
     96         if (ferror(fin)) 
     97             return UNZ_ERRNO;
     98         else
     99             return UNZ_EOF;
    100     }
    101 }
    102 */
    103 
    104 
    105 /* ===========================================================================
    106    Reads a long in LSB order from the given gz_stream. Sets 
    107 */
    108 static int unzlocal_getShort (idFile * fin, uLong *pX)
    109 {
    110 	byte s[2];
    111 	if ( fin->Read( s, 2 ) != 2 ) {
    112 		*pX = 0;
    113 		return UNZ_EOF;
    114 	}
    115 	*pX = ( s[1] << 8 ) | s[0];
    116 	return UNZ_OK;
    117 }
    118 
    119 static int unzlocal_getLong (idFile * fin, uLong *pX)
    120 {
    121 	byte s[4];
    122 	if ( fin->Read( s, 4 ) != 4 ) {
    123 		*pX = 0;
    124 		return UNZ_EOF;
    125 	}
    126 	*pX = ( s[3] << 24 ) | ( s[2] << 16 ) | ( s[1] << 8 ) | s[0];
    127 	return UNZ_OK;
    128 }
    129 
    130 
    131 /* My own strcmpi / strcasecmp */
    132 static int strcmpcasenosensitive_internal (const char* fileName1,const char* fileName2)
    133 {
    134 	for (;;)
    135 	{
    136 		char c1=*(fileName1++);
    137 		char c2=*(fileName2++);
    138 		if ((c1>='a') && (c1<='z'))
    139 			c1 -= 0x20;
    140 		if ((c2>='a') && (c2<='z'))
    141 			c2 -= 0x20;
    142 		if (c1=='\0')
    143 			return ((c2=='\0') ? 0 : -1);
    144 		if (c2=='\0')
    145 			return 1;
    146 		if (c1<c2)
    147 			return -1;
    148 		if (c1>c2)
    149 			return 1;
    150 	}
    151 }
    152 
    153 
    154 #ifdef  CASESENSITIVITYDEFAULT_NO
    155 #define CASESENSITIVITYDEFAULTVALUE 2
    156 #else
    157 #define CASESENSITIVITYDEFAULTVALUE 1
    158 #endif
    159 
    160 #ifndef STRCMPCASENOSENTIVEFUNCTION
    161 #define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
    162 #endif
    163 
    164 /* 
    165    Compare two filename (fileName1,fileName2).
    166    If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
    167    If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
    168                                                                 or strcasecmp)
    169    If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
    170         (like 1 on Unix, 2 on Windows)
    171 
    172 */
    173 extern int unzStringFileNameCompare (const char* fileName1,const char* fileName2,int iCaseSensitivity)
    174 {
    175 	if (iCaseSensitivity==0)
    176 		iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
    177 
    178 	if (iCaseSensitivity==1)
    179 		return strcmp(fileName1,fileName2);
    180 
    181 	return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
    182 } 
    183 
    184 #define BUFREADCOMMENT (0x400)
    185 
    186 /*
    187   Locate the Central directory of a zipfile (at the end, just before
    188     the global comment)
    189 */
    190 static uLong unzlocal_SearchCentralDir(idFile * fin)
    191 {
    192 	unsigned char* buf;
    193 	uLong uSizeFile;
    194 	uLong uBackRead;
    195 	uLong uMaxBack=0xffff; /* maximum size of global comment */
    196 	uLong uPosFound=0;
    197 	
    198 	if ( fin->Seek( 0, FS_SEEK_END ) != 0 )
    199 		return 0;
    200 
    201 	uSizeFile = fin->Tell();
    202 	
    203 	if (uMaxBack>uSizeFile)
    204 		uMaxBack = uSizeFile;
    205 
    206 	buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
    207 	if (buf==NULL)
    208 		return 0;
    209 
    210 	uBackRead = 4;
    211 	while (uBackRead<uMaxBack)
    212 	{
    213 		uLong uReadSize,uReadPos ;
    214 		int i;
    215 		if (uBackRead+BUFREADCOMMENT>uMaxBack) 
    216 			uBackRead = uMaxBack;
    217 		else
    218 			uBackRead+=BUFREADCOMMENT;
    219 		uReadPos = uSizeFile-uBackRead ;
    220 		
    221 		uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 
    222                      (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
    223 
    224 		if ( fin->Seek( uReadPos, FS_SEEK_SET ) != 0 )
    225 			break;
    226 
    227 		if ( fin->Read( buf, uReadSize ) != (int)uReadSize ) 
    228 			break;
    229 
    230                 for (i=(int)uReadSize-3; (i--)>0;)
    231 			if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && 
    232 				((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
    233 			{
    234 				uPosFound = uReadPos+i;
    235 				break;
    236 			}
    237 
    238 		if (uPosFound!=0)
    239 			break;
    240 	}
    241 	TRYFREE(buf);
    242 	return uPosFound;
    243 }
    244 
    245 extern unzFile unzReOpen (const char* path, unzFile file)
    246 {
    247 	unz_s *s;
    248 	idFile_Cached * fin;
    249 
    250 	fin = fileSystem->OpenExplicitPakFile( path );
    251 	if (fin==NULL)
    252 		return NULL;
    253 
    254 	s=(unz_s*)ALLOC(sizeof(unz_s));
    255 	memcpy(s, (unz_s*)file, sizeof(unz_s));
    256 
    257 	s->file = fin;
    258     s->pfile_in_zip_read = NULL;
    259 
    260 	return (unzFile)s;	
    261 }
    262 
    263 /*
    264   Open a Zip file. path contain the full pathname (by example,
    265      on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
    266 	 "zlib/zlib109.zip".
    267 	 If the zipfile cannot be opened (file don't exist or in not valid), the
    268 	   return value is NULL.
    269      Else, the return value is a unzFile Handle, usable with other function
    270 	   of this unzip package.
    271 */
    272 extern unzFile unzOpen (const char* path)
    273 {
    274 	unz_s us;
    275 	unz_s *s;
    276 	uLong central_pos,uL;
    277 	idFile_Cached * fin ;
    278 
    279 	uLong number_disk;          /* number of the current dist, used for 
    280 								   spaning ZIP, unsupported, always 0*/
    281 	uLong number_disk_with_CD;  /* number the the disk with central dir, used
    282 								   for spaning ZIP, unsupported, always 0*/
    283 	uLong number_entry_CD;      /* total number of entries in
    284 	                               the central dir 
    285 	                               (same than number_entry on nospan) */
    286 
    287 	int err=UNZ_OK;
    288 
    289 	fin = fileSystem->OpenExplicitPakFile( path );
    290 	if (fin==NULL)
    291 		return NULL;
    292 
    293 	central_pos = unzlocal_SearchCentralDir(fin);
    294 	if (central_pos==0)
    295 		err=UNZ_ERRNO;
    296 
    297 	if ( fin->Seek( central_pos, FS_SEEK_SET ) != 0 )
    298 		err = UNZ_ERRNO;
    299 
    300 	/* the signature, already checked */
    301 	if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
    302 		err=UNZ_ERRNO;
    303 
    304 	/* number of this disk */
    305 	if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
    306 		err=UNZ_ERRNO;
    307 
    308 	/* number of the disk with the start of the central directory */
    309 	if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
    310 		err=UNZ_ERRNO;
    311 
    312 	/* total number of entries in the central dir on this disk */
    313 	if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
    314 		err=UNZ_ERRNO;
    315 
    316 	/* total number of entries in the central dir */
    317 	if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
    318 		err=UNZ_ERRNO;
    319 
    320 	if ((number_entry_CD!=us.gi.number_entry) ||
    321 		(number_disk_with_CD!=0) ||
    322 		(number_disk!=0))
    323 		err=UNZ_BADZIPFILE;
    324 
    325 	/* size of the central directory */
    326 	if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
    327 		err=UNZ_ERRNO;
    328 
    329 	/* offset of start of central directory with respect to the 
    330 	      starting disk number */
    331 	if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
    332 		err=UNZ_ERRNO;
    333 
    334 	/* zipfile comment length */
    335 	if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
    336 		err=UNZ_ERRNO;
    337 
    338 	if ((central_pos<us.offset_central_dir+us.size_central_dir) && 
    339 		(err==UNZ_OK))
    340 		err=UNZ_BADZIPFILE;
    341 
    342 	if (err!=UNZ_OK)
    343 	{
    344 		fileSystem->CloseFile( fin );
    345 		return NULL;
    346 	}
    347 
    348 	us.file=fin;
    349 	us.byte_before_the_zipfile = central_pos -
    350 		                    (us.offset_central_dir+us.size_central_dir);
    351 	us.central_pos = central_pos;
    352     us.pfile_in_zip_read = NULL;
    353 	
    354 	us.file->CacheData( us.offset_central_dir, us.size_central_dir );
    355 
    356 	s=(unz_s*)ALLOC(sizeof(unz_s));
    357 	*s=us;
    358 
    359 //	unzGoToFirstFile((unzFile)s);	
    360 	return (unzFile)s;	
    361 }
    362 
    363 
    364 /*
    365   Close a ZipFile opened with unzipOpen.
    366   If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
    367     these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
    368   return UNZ_OK if there is no problem. */
    369 extern int unzClose (unzFile file)
    370 {
    371 	unz_s* s;
    372 	if (file==NULL)
    373 		return UNZ_PARAMERROR;
    374 	s=(unz_s*)file;
    375 
    376     if (s->pfile_in_zip_read!=NULL)
    377         unzCloseCurrentFile(file);
    378 
    379 	fileSystem->CloseFile( s->file );
    380 	TRYFREE(s);
    381 	return UNZ_OK;
    382 }
    383 
    384 
    385 /*
    386   Write info about the ZipFile in the *pglobal_info structure.
    387   No preparation of the structure is needed
    388   return UNZ_OK if there is no problem. */
    389 extern int unzGetGlobalInfo (unzFile file,unz_global_info *pglobal_info)
    390 {
    391 	unz_s* s;
    392 	if (file==NULL)
    393 		return UNZ_PARAMERROR;
    394 	s=(unz_s*)file;
    395 	*pglobal_info=s->gi;
    396 	return UNZ_OK;
    397 }
    398 
    399 
    400 /*
    401    Translate date/time from Dos format to tm_unz (readable more easilty)
    402 */
    403 static void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm)
    404 {
    405     uLong uDate;
    406     uDate = (uLong)(ulDosDate>>16);
    407     ptm->tm_mday = (uInt)(uDate&0x1f) ;
    408     ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
    409     ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
    410 
    411     ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
    412     ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
    413     ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
    414 }
    415 
    416 
    417 /*
    418   Get Info about the current file in the zipfile, with internal only info
    419 */
    420 static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
    421                                                   unz_file_info *pfile_info,
    422                                                   unz_file_info_internal 
    423                                                   *pfile_info_internal,
    424                                                   char *szFileName,
    425 												  uLong fileNameBufferSize,
    426                                                   void *extraField,
    427 												  uLong extraFieldBufferSize,
    428                                                   char *szComment,
    429 												  uLong commentBufferSize)
    430 {
    431 	unz_s* s;
    432 	unz_file_info file_info;
    433 	unz_file_info_internal file_info_internal;
    434 	int err=UNZ_OK;
    435 	uLong uMagic;
    436 	long lSeek=0;
    437 
    438 	if (file==NULL)
    439 		return UNZ_PARAMERROR;
    440 	s=(unz_s*)file;
    441 
    442 	int tellpos = s->file->Tell() - s->pos_in_central_dir + s->byte_before_the_zipfile;
    443 	if ( tellpos != 0 ) {
    444 		if ( s->file->Seek( s->pos_in_central_dir + s->byte_before_the_zipfile, FS_SEEK_SET ) != 0 ) {
    445 			err = UNZ_ERRNO;
    446 		}
    447 		if ( tellpos < 0 ) {
    448 			zip_seeksForward.SetInteger( zip_seeksForward.GetInteger() + 1 );
    449 		} else {
    450 			zip_seeksBackward.SetInteger( zip_seeksBackward.GetInteger() + 1 );
    451 		}
    452 
    453 		static long zip_totalSeekSize = 0;
    454 		if ( zip_numSeeks.GetInteger() == 0 ) {
    455 			zip_totalSeekSize = 0;
    456 		}
    457 		zip_totalSeekSize += abs( tellpos );
    458 
    459 		zip_numSeeks.SetInteger( zip_numSeeks.GetInteger() + 1 );
    460 		zip_avgSeekDistance.SetInteger( zip_totalSeekSize / zip_numSeeks.GetInteger() );
    461 	} else {
    462 		zip_skippedSeeks.SetInteger( zip_skippedSeeks.GetInteger() + 1 );
    463 	}
    464 
    465 
    466 	/* we check the magic */
    467 	if (err==UNZ_OK)
    468 		if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
    469 			err=UNZ_ERRNO;
    470 		else if (uMagic!=0x02014b50)
    471 			err=UNZ_BADZIPFILE;
    472 
    473 	if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
    474 		err=UNZ_ERRNO;
    475 
    476 	if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
    477 		err=UNZ_ERRNO;
    478 
    479 	if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
    480 		err=UNZ_ERRNO;
    481 
    482 	if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
    483 		err=UNZ_ERRNO;
    484 
    485 	if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
    486 		err=UNZ_ERRNO;
    487 
    488     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
    489 
    490 	if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
    491 		err=UNZ_ERRNO;
    492 
    493 	if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
    494 		err=UNZ_ERRNO;
    495 
    496 	if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
    497 		err=UNZ_ERRNO;
    498 
    499 	if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
    500 		err=UNZ_ERRNO;
    501 
    502 	if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
    503 		err=UNZ_ERRNO;
    504 
    505 	if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
    506 		err=UNZ_ERRNO;
    507 
    508 	if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
    509 		err=UNZ_ERRNO;
    510 
    511 	if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
    512 		err=UNZ_ERRNO;
    513 
    514 	if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
    515 		err=UNZ_ERRNO;
    516 
    517 	if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
    518 		err=UNZ_ERRNO;
    519 
    520 	lSeek+=file_info.size_filename;
    521 	if ((err==UNZ_OK) && (szFileName!=NULL))
    522 	{
    523 		uLong uSizeRead ;
    524 		if (file_info.size_filename<fileNameBufferSize)
    525 		{
    526 			*(szFileName+file_info.size_filename)='\0';
    527 			uSizeRead = file_info.size_filename;
    528 		}
    529 		else
    530 			uSizeRead = fileNameBufferSize;
    531 
    532 		if ((file_info.size_filename>0) && (fileNameBufferSize>0))
    533 			if ( s->file->Read( szFileName, uSizeRead ) != (int)uSizeRead )
    534 				err=UNZ_ERRNO;
    535 		lSeek -= uSizeRead;
    536 	}
    537 
    538 	
    539 	if ((err==UNZ_OK) && (extraField!=NULL))
    540 	{
    541 		uLong uSizeRead ;
    542 		if (file_info.size_file_extra<extraFieldBufferSize)
    543 			uSizeRead = file_info.size_file_extra;
    544 		else
    545 			uSizeRead = extraFieldBufferSize;
    546 
    547 		if (lSeek!=0)
    548 			if ( s->file->Seek( lSeek, FS_SEEK_CUR ) == 0 )
    549 				lSeek=0;
    550 			else
    551 				err=UNZ_ERRNO;
    552 		if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
    553 			if ( s->file->Read( extraField, uSizeRead ) != (int)uSizeRead )
    554 				err=UNZ_ERRNO;
    555 		lSeek += file_info.size_file_extra - uSizeRead;
    556 	}
    557 	else
    558 		lSeek+=file_info.size_file_extra; 
    559 
    560 	
    561 	if ((err==UNZ_OK) && (szComment!=NULL))
    562 	{
    563 		uLong uSizeRead ;
    564 		if (file_info.size_file_comment<commentBufferSize)
    565 		{
    566 			*(szComment+file_info.size_file_comment)='\0';
    567 			uSizeRead = file_info.size_file_comment;
    568 		}
    569 		else
    570 			uSizeRead = commentBufferSize;
    571 
    572 		if (lSeek!=0)
    573 			if ( s->file->Seek( lSeek, FS_SEEK_CUR ) == 0 )
    574 				lSeek=0;
    575 			else
    576 				err=UNZ_ERRNO;
    577 		if ((file_info.size_file_comment>0) && (commentBufferSize>0))
    578 			if ( s->file->Read( szComment, uSizeRead ) != (int)uSizeRead )
    579 				err=UNZ_ERRNO;
    580 		lSeek+=file_info.size_file_comment - uSizeRead;
    581 	}
    582 	else
    583 		lSeek+=file_info.size_file_comment;
    584 
    585 	if ((err==UNZ_OK) && (pfile_info!=NULL))
    586 		*pfile_info=file_info;
    587 
    588 	if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
    589 		*pfile_info_internal=file_info_internal;
    590 
    591 	return err;
    592 }
    593 
    594 /*
    595   Write info about the ZipFile in the *pglobal_info structure.
    596   No preparation of the structure is needed
    597   return UNZ_OK if there is no problem.
    598 */
    599 extern int unzGetCurrentFileInfo (	unzFile file, unz_file_info *pfile_info,
    600 									char *szFileName, uLong fileNameBufferSize,
    601 									void *extraField, uLong extraFieldBufferSize,
    602 									char *szComment, uLong commentBufferSize)
    603 {
    604 	return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
    605 												szFileName,fileNameBufferSize,
    606 												extraField,extraFieldBufferSize,
    607 												szComment,commentBufferSize);
    608 }
    609 
    610 /*
    611   Set the current file of the zipfile to the first file.
    612   return UNZ_OK if there is no problem
    613 */
    614 extern int unzGoToFirstFile (unzFile file)
    615 {
    616 	int err=UNZ_OK;
    617 	unz_s* s;
    618 	if (file==NULL)
    619 		return UNZ_PARAMERROR;
    620 	s=(unz_s*)file;
    621 	s->pos_in_central_dir=s->offset_central_dir;
    622 	s->num_file=0;
    623 	err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
    624 											 &s->cur_file_info_internal,
    625 											 NULL,0,NULL,0,NULL,0);
    626 	s->current_file_ok = (err == UNZ_OK);
    627 	return err;
    628 }
    629 
    630 /*
    631   Set the current file of the zipfile to the next file.
    632   return UNZ_OK if there is no problem
    633   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
    634 */
    635 extern int unzGoToNextFile (unzFile file)
    636 {
    637 	unz_s* s;	
    638 	int err;
    639 
    640 	if (file==NULL)
    641 		return UNZ_PARAMERROR;
    642 	s=(unz_s*)file;
    643 	if (!s->current_file_ok)
    644 		return UNZ_END_OF_LIST_OF_FILE;
    645 	if (s->num_file+1==s->gi.number_entry)
    646 		return UNZ_END_OF_LIST_OF_FILE;
    647 
    648 	s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
    649 			s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
    650 	s->num_file++;
    651 	err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
    652 											   &s->cur_file_info_internal,
    653 											   NULL,0,NULL,0,NULL,0);
    654 	s->current_file_ok = (err == UNZ_OK);
    655 	return err;
    656 }
    657 
    658 /*
    659   Get the position of the info of the current file in the zip.
    660   return UNZ_OK if there is no problem
    661 */
    662 extern int unzGetCurrentFileInfoPosition (unzFile file, unsigned long *pos )
    663 {
    664 	unz_s* s;	
    665 
    666 	if (file==NULL)
    667 		return UNZ_PARAMERROR;
    668 	s=(unz_s*)file;
    669 
    670 	*pos = s->pos_in_central_dir;
    671 	return UNZ_OK;
    672 }
    673 
    674 /*
    675   Set the position of the info of the current file in the zip.
    676   return UNZ_OK if there is no problem
    677 */
    678 extern int unzSetCurrentFileInfoPosition (unzFile file, unsigned long pos )
    679 {
    680 	unz_s* s;	
    681 	int err;
    682 
    683 	if (file==NULL)
    684 		return UNZ_PARAMERROR;
    685 	s=(unz_s*)file;
    686 
    687 	s->pos_in_central_dir = pos;
    688 	err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
    689 											   &s->cur_file_info_internal,
    690 											   NULL,0,NULL,0,NULL,0);
    691 	s->current_file_ok = (err == UNZ_OK);
    692 	return UNZ_OK;
    693 }
    694 
    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 */
    703 extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
    704 {
    705 	unz_s* s;	
    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 
    716     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
    717         return UNZ_PARAMERROR;
    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 
    746 /*
    747   Read the static header of the current zipfile
    748   Check the coherency of the static header and info in the end of central
    749         directory about this file
    750   store in *piSizeVar the size of extra info in static header
    751         (filename and size of extra field data)
    752 */
    753 static int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s, uInt* piSizeVar,
    754 													uLong *poffset_local_extrafield,
    755 													uInt *psize_local_extrafield)
    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 ( s->file->Seek( s->cur_file_info_internal.offset_curfile + s->byte_before_the_zipfile, FS_SEEK_SET ) != 0 )
    767 		return UNZ_ERRNO;
    768 
    769 
    770 	if (err==UNZ_OK)
    771 		if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
    772 			err=UNZ_ERRNO;
    773 		else if (uMagic!=0x04034b50)
    774 			err=UNZ_BADZIPFILE;
    775 
    776 	if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
    777 		err=UNZ_ERRNO;
    778 /*
    779 	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
    780 		err=UNZ_BADZIPFILE;
    781 */
    782 	if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
    783 		err=UNZ_ERRNO;
    784 
    785 	if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
    786 		err=UNZ_ERRNO;
    787 	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
    788 		err=UNZ_BADZIPFILE;
    789 
    790     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
    791                          (s->cur_file_info.compression_method!=Z_DEFLATED))
    792         err=UNZ_BADZIPFILE;
    793 
    794 	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
    795 		err=UNZ_ERRNO;
    796 
    797 	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
    798 		err=UNZ_ERRNO;
    799 	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
    800 		                      ((uFlags & 8)==0))
    801 		err=UNZ_BADZIPFILE;
    802 
    803 	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
    804 		err=UNZ_ERRNO;
    805 	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
    806 							  ((uFlags & 8)==0))
    807 		err=UNZ_BADZIPFILE;
    808 
    809 	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
    810 		err=UNZ_ERRNO;
    811 	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && 
    812 							  ((uFlags & 8)==0))
    813 		err=UNZ_BADZIPFILE;
    814 
    815 
    816 	if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
    817 		err=UNZ_ERRNO;
    818 	else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
    819 		err=UNZ_BADZIPFILE;
    820 
    821 	*piSizeVar += (uInt)size_filename;
    822 
    823 	if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
    824 		err=UNZ_ERRNO;
    825 	*poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
    826 									SIZEZIPLOCALHEADER + size_filename;
    827 	*psize_local_extrafield = (uInt)size_extra_field;
    828 
    829 	*piSizeVar += (uInt)size_extra_field;
    830 
    831 	return err;
    832 }
    833 												
    834 /*
    835   Open for reading data the current file in the zipfile.
    836   If there is no error and the file is opened, the return value is UNZ_OK.
    837 */
    838 extern int unzOpenCurrentFile (unzFile file)
    839 {
    840 	int err=UNZ_OK;
    841 	int Store;
    842 	uInt iSizeVar;
    843 	unz_s* s;
    844 	file_in_zip_read_info_s* pfile_in_zip_read_info;
    845 	uLong offset_local_extrafield;  /* offset of the static extra field */
    846 	uInt  size_local_extrafield;    /* size of the static extra field */
    847 
    848 	if (file==NULL)
    849 		return UNZ_PARAMERROR;
    850 	s=(unz_s*)file;
    851 	if (!s->current_file_ok)
    852 		return UNZ_PARAMERROR;
    853 
    854     if (s->pfile_in_zip_read != NULL)
    855         unzCloseCurrentFile(file);
    856 
    857 	if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
    858 				&offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
    859 		return UNZ_BADZIPFILE;
    860 
    861 	pfile_in_zip_read_info = (file_in_zip_read_info_s*)
    862 									    ALLOC(sizeof(file_in_zip_read_info_s));
    863 	if (pfile_in_zip_read_info==NULL)
    864 		return UNZ_INTERNALERROR;
    865 
    866 	pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
    867 	pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
    868 	pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
    869 	pfile_in_zip_read_info->pos_local_extrafield=0;
    870 
    871 	if (pfile_in_zip_read_info->read_buffer==NULL)
    872 	{
    873 		TRYFREE(pfile_in_zip_read_info);
    874 		return UNZ_INTERNALERROR;
    875 	}
    876 
    877 	pfile_in_zip_read_info->stream_initialised=0;
    878 	
    879 	if ((s->cur_file_info.compression_method!=0) &&
    880         (s->cur_file_info.compression_method!=Z_DEFLATED))
    881 		err=UNZ_BADZIPFILE;
    882 	Store = s->cur_file_info.compression_method==0;
    883 
    884 	pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
    885 	pfile_in_zip_read_info->crc32=0;
    886 	pfile_in_zip_read_info->compression_method =
    887             s->cur_file_info.compression_method;
    888 	pfile_in_zip_read_info->file=s->file;
    889 	pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
    890 
    891     pfile_in_zip_read_info->stream.total_out = 0;
    892 
    893 	if (!Store)
    894 	{
    895 	  pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
    896 	  pfile_in_zip_read_info->stream.zfree = (free_func)0;
    897 	  pfile_in_zip_read_info->stream.opaque = (voidp)0; 
    898       
    899 	  err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
    900 	  if (err == Z_OK)
    901 	    pfile_in_zip_read_info->stream_initialised=1;
    902         /* windowBits is passed < 0 to tell that there is no zlib header.
    903          * Note that in this case inflate *requires* an extra "dummy" byte
    904          * after the compressed stream in order to complete decompression and
    905          * return Z_STREAM_END. 
    906          * In unzip, i don't wait absolutely Z_STREAM_END because I known the 
    907          * size of both compressed and uncompressed data
    908          */
    909 	}
    910 	pfile_in_zip_read_info->rest_read_compressed = 
    911             s->cur_file_info.compressed_size ;
    912 	pfile_in_zip_read_info->rest_read_uncompressed = 
    913             s->cur_file_info.uncompressed_size ;
    914 
    915 	
    916 	pfile_in_zip_read_info->pos_in_zipfile = 
    917             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + 
    918 			  iSizeVar;
    919 	
    920 	pfile_in_zip_read_info->stream.avail_in = (uInt)0;
    921 
    922 
    923 	s->pfile_in_zip_read = pfile_in_zip_read_info;
    924     return UNZ_OK;
    925 }
    926 
    927 
    928 /*
    929   Read bytes from the current file.
    930   buf contain buffer where data must be copied
    931   len the size of buf.
    932 
    933   return the number of byte copied if somes bytes are copied
    934   return 0 if the end of file was reached
    935   return <0 with error code if there is an error
    936     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
    937 */
    938 extern int unzReadCurrentFile  (unzFile file, void *buf, unsigned len)
    939 {
    940 	int err=UNZ_OK;
    941 	uInt iRead = 0;
    942 	unz_s* s;
    943 	file_in_zip_read_info_s* pfile_in_zip_read_info;
    944 	if (file==NULL)
    945 		return UNZ_PARAMERROR;
    946 	s=(unz_s*)file;
    947     pfile_in_zip_read_info=s->pfile_in_zip_read;
    948 
    949 	if (pfile_in_zip_read_info==NULL)
    950 		return UNZ_PARAMERROR;
    951 
    952 
    953 	if ((pfile_in_zip_read_info->read_buffer == NULL))
    954 		return UNZ_END_OF_LIST_OF_FILE;
    955 	if (len==0)
    956 		return 0;
    957 
    958 	pfile_in_zip_read_info->stream.next_out = (Byte*)buf;
    959 
    960 	pfile_in_zip_read_info->stream.avail_out = (uInt)len;
    961 	
    962 	if (len>pfile_in_zip_read_info->rest_read_uncompressed)
    963 		pfile_in_zip_read_info->stream.avail_out = 
    964 		  (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
    965 
    966 	while (pfile_in_zip_read_info->stream.avail_out>0)
    967 	{
    968 		if ((pfile_in_zip_read_info->stream.avail_in==0) &&
    969             (pfile_in_zip_read_info->rest_read_compressed>0))
    970 		{
    971 			uInt uReadThis = UNZ_BUFSIZE;
    972 			if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
    973 				uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
    974 			if (uReadThis == 0)
    975 				return UNZ_EOF;
    976 			if (s->cur_file_info.compressed_size == pfile_in_zip_read_info->rest_read_compressed)
    977 				if ( pfile_in_zip_read_info->file->Seek( pfile_in_zip_read_info->pos_in_zipfile + pfile_in_zip_read_info->byte_before_the_zipfile, FS_SEEK_SET ) != 0 )
    978 					return UNZ_ERRNO;
    979 			if ( pfile_in_zip_read_info->file->Read( pfile_in_zip_read_info->read_buffer, uReadThis ) != (int)uReadThis )
    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 = 
    986                 (Byte*)pfile_in_zip_read_info->read_buffer;
    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 < 
    994                             pfile_in_zip_read_info->stream.avail_in)
    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) =
   1001                         *(pfile_in_zip_read_info->stream.next_in+i);
   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;
   1011             pfile_in_zip_read_info->stream.total_out += uDoCopy;
   1012 			iRead += uDoCopy;
   1013 		}
   1014 		else
   1015 		{
   1016 			uLong uTotalOutBefore,uTotalOutAfter;
   1017 			const Byte *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 = 
   1036                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
   1037                         (uInt)(uOutThis));
   1038 
   1039 			pfile_in_zip_read_info->rest_read_uncompressed -=
   1040                 uOutThis;
   1041 
   1042 			iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
   1043             
   1044 			if (err==Z_STREAM_END)
   1045 				return (iRead==0) ? UNZ_EOF : iRead;
   1046 			if (err!=Z_OK) 
   1047 				break;
   1048 		}
   1049 	}
   1050 
   1051 	if (err==Z_OK)
   1052 		return iRead;
   1053 	return err;
   1054 }
   1055 
   1056 
   1057 /*
   1058   Give the current position in uncompressed data
   1059 */
   1060 extern long unztell (unzFile file)
   1061 {
   1062 	unz_s* s;
   1063 	file_in_zip_read_info_s* pfile_in_zip_read_info;
   1064 	if (file==NULL)
   1065 		return UNZ_PARAMERROR;
   1066 	s=(unz_s*)file;
   1067     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1068 
   1069 	if (pfile_in_zip_read_info==NULL)
   1070 		return UNZ_PARAMERROR;
   1071 
   1072 	return (long)pfile_in_zip_read_info->stream.total_out;
   1073 }
   1074 
   1075 
   1076 /*
   1077   return 1 if the end of file was reached, 0 elsewhere 
   1078 */
   1079 extern int unzeof (unzFile file)
   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;
   1086     pfile_in_zip_read_info=s->pfile_in_zip_read;
   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 }
   1096 
   1097 
   1098 
   1099 /*
   1100   Read extra field from the current file (opened by unzOpenCurrentFile)
   1101   This is the static-header version of the extra field (sometimes, there is
   1102     more info in the static-header version than in the central-header)
   1103 
   1104   if buf==NULL, it return the size of the static extra field that can be read
   1105 
   1106   if buf!=NULL, len is the size of the buffer, the extra header is copied in
   1107 	buf.
   1108   the return value is the number of bytes copied in buf, or (if <0) 
   1109 	the error code
   1110 */
   1111 extern int unzGetLocalExtrafield (unzFile file,void *buf,unsigned len)
   1112 {
   1113 	unz_s* s;
   1114 	file_in_zip_read_info_s* pfile_in_zip_read_info;
   1115 	uInt read_now;
   1116 	uLong size_to_read;
   1117 
   1118 	if (file==NULL)
   1119 		return UNZ_PARAMERROR;
   1120 	s=(unz_s*)file;
   1121     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1122 
   1123 	if (pfile_in_zip_read_info==NULL)
   1124 		return UNZ_PARAMERROR;
   1125 
   1126 	size_to_read = (pfile_in_zip_read_info->size_local_extrafield - 
   1127 				pfile_in_zip_read_info->pos_local_extrafield);
   1128 
   1129 	if (buf==NULL)
   1130 		return (int)size_to_read;
   1131 	
   1132 	if (len>size_to_read)
   1133 		read_now = (uInt)size_to_read;
   1134 	else
   1135 		read_now = (uInt)len ;
   1136 
   1137 	if (read_now==0)
   1138 		return 0;
   1139 	
   1140 	if ( pfile_in_zip_read_info->file->Seek( pfile_in_zip_read_info->offset_local_extrafield + pfile_in_zip_read_info->pos_local_extrafield, FS_SEEK_SET ) != 0 )
   1141 		return UNZ_ERRNO;
   1142 
   1143 	if ( pfile_in_zip_read_info->file->Read( buf, size_to_read ) != (int)size_to_read )
   1144 		return UNZ_ERRNO;
   1145 
   1146 	return (int)read_now;
   1147 }
   1148 
   1149 /*
   1150   Close the file in zip opened with unzipOpenCurrentFile
   1151   Return UNZ_CRCERROR if all the file was read but the CRC is not good
   1152 */
   1153 extern int unzCloseCurrentFile (unzFile file)
   1154 {
   1155 	int err=UNZ_OK;
   1156 
   1157 	unz_s* s;
   1158 	file_in_zip_read_info_s* pfile_in_zip_read_info;
   1159 	if (file==NULL)
   1160 		return UNZ_PARAMERROR;
   1161 	s=(unz_s*)file;
   1162     pfile_in_zip_read_info=s->pfile_in_zip_read;
   1163 
   1164 	if (pfile_in_zip_read_info==NULL)
   1165 		return UNZ_PARAMERROR;
   1166 
   1167 
   1168 	if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
   1169 	{
   1170 		if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
   1171 			err=UNZ_CRCERROR;
   1172 	}
   1173 
   1174 
   1175 	TRYFREE(pfile_in_zip_read_info->read_buffer);
   1176 	pfile_in_zip_read_info->read_buffer = NULL;
   1177 	if (pfile_in_zip_read_info->stream_initialised)
   1178 		inflateEnd(&pfile_in_zip_read_info->stream);
   1179 
   1180 	pfile_in_zip_read_info->stream_initialised = 0;
   1181 	TRYFREE(pfile_in_zip_read_info);
   1182 
   1183     s->pfile_in_zip_read=NULL;
   1184 
   1185 	return err;
   1186 }
   1187 
   1188 
   1189 /*
   1190   Get the global comment string of the ZipFile, in the szComment buffer.
   1191   uSizeBuf is the size of the szComment buffer.
   1192   return the number of byte copied or an error code <0
   1193 */
   1194 extern int unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf)
   1195 {
   1196 	unz_s* s;
   1197 	uLong uReadThis ;
   1198 	if (file==NULL)
   1199 		return UNZ_PARAMERROR;
   1200 	s=(unz_s*)file;
   1201 
   1202 	uReadThis = uSizeBuf;
   1203 	if (uReadThis>s->gi.size_comment)
   1204 		uReadThis = s->gi.size_comment;
   1205 
   1206 	if ( s->file->Seek( s->central_pos + 22, FS_SEEK_SET ) == 0 )
   1207 		return UNZ_ERRNO;
   1208 
   1209 	if (uReadThis>0)
   1210     {
   1211 		if ( szComment == NULL ) {
   1212 			return (int)uReadThis;
   1213 		}
   1214       *szComment='\0';
   1215 	  if ( s->file->Read( szComment, uReadThis ) != (int)uReadThis )
   1216 		return UNZ_ERRNO;
   1217     }
   1218 
   1219 	if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
   1220 		*(szComment+s->gi.size_comment)='\0';
   1221 	return (int)uReadThis;
   1222 }