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