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