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 
unzlocal_getByte(fin,pi)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 */
unzlocal_getShort(fin,pX)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 
unzlocal_getLong(fin,pX)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 */
strcmpcasenosensitive_internal(fileName1,fileName2)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 */
unzlocal_SearchCentralDir(fin)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 */
unzlocal_DosDateToTmuDate(ulDosDate,ptm)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 
unzlocal_GetCurrentFileInfoInternal(file,pfile_info,pfile_info_internal,szFileName,fileNameBufferSize,extraField,extraFieldBufferSize,szComment,commentBufferSize)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 		if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
540 			err=UNZ_ERRNO;
541 		else if (uMagic!=0x02014b50)
542 			err=UNZ_BADZIPFILE;
543 	}
544 	if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
545 		err=UNZ_ERRNO;
546 
547 	if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
548 		err=UNZ_ERRNO;
549 
550 	if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
551 		err=UNZ_ERRNO;
552 
553 	if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
554 		err=UNZ_ERRNO;
555 
556 	if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
557 		err=UNZ_ERRNO;
558 
559     unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
560 
561 	if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
562 		err=UNZ_ERRNO;
563 
564 	if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
565 		err=UNZ_ERRNO;
566 
567 	if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
568 		err=UNZ_ERRNO;
569 
570 	if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
571 		err=UNZ_ERRNO;
572 
573 	if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
574 		err=UNZ_ERRNO;
575 
576 	if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
577 		err=UNZ_ERRNO;
578 
579 	if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
580 		err=UNZ_ERRNO;
581 
582 	if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
583 		err=UNZ_ERRNO;
584 
585 	if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
586 		err=UNZ_ERRNO;
587 
588 	if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
589 		err=UNZ_ERRNO;
590 
591 	lSeek+=file_info.size_filename;
592 	if ((err==UNZ_OK) && (szFileName!=NULL))
593 	{
594 		uLong uSizeRead ;
595 		if (file_info.size_filename<fileNameBufferSize)
596 		{
597 			*(szFileName+file_info.size_filename)='\0';
598 			uSizeRead = file_info.size_filename;
599 		}
600 		else
601 			uSizeRead = fileNameBufferSize;
602 
603 		if ((file_info.size_filename>0) && (fileNameBufferSize>0))
604 			if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
605 				err=UNZ_ERRNO;
606 		lSeek -= uSizeRead;
607 	}
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 			if (fseek(s->file,lSeek,SEEK_CUR)==0)
620 				lSeek=0;
621 			else
622 				err=UNZ_ERRNO;
623 		}
624 		if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
625 			if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
626 				err=UNZ_ERRNO;
627 		lSeek += file_info.size_file_extra - uSizeRead;
628 	}
629 	else
630 		lSeek+=file_info.size_file_extra;
631 
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 			if (fseek(s->file,lSeek,SEEK_CUR)==0)
646 				lSeek=0;
647 			else
648 				err=UNZ_ERRNO;
649 		}
650 		if ((file_info.size_file_comment>0) && (commentBufferSize>0))
651 			if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
652 				err=UNZ_ERRNO;
653 		lSeek+=file_info.size_file_comment - uSizeRead;
654 	}
655 	else
656 		lSeek+=file_info.size_file_comment;
657 
658 	if ((err==UNZ_OK) && (pfile_info!=NULL))
659 		*pfile_info=file_info;
660 
661 	if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
662 		*pfile_info_internal=file_info_internal;
663 
664 	return err;
665 }
666 
667 
668 
669 /*
670   Write info about the ZipFile in the *pglobal_info structure.
671   No preparation of the structure is needed
672   return UNZ_OK if there is no problem.
673 */
674 extern int ZEXPORT unzGetCurrentFileInfo (file,
675                                                   pfile_info,
676                                                   szFileName, fileNameBufferSize,
677                                                   extraField, extraFieldBufferSize,
678                                                   szComment,  commentBufferSize)
679 	unzFile file;
680 	unz_file_info *pfile_info;
681 	char *szFileName;
682 	uLong fileNameBufferSize;
683 	void *extraField;
684 	uLong extraFieldBufferSize;
685 	char *szComment;
686 	uLong commentBufferSize;
687 {
688 	return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
689 												szFileName,fileNameBufferSize,
690 												extraField,extraFieldBufferSize,
691 												szComment,commentBufferSize);
692 }
693 
694 /*
695   Set the current file of the zipfile to the first file.
696   return UNZ_OK if there is no problem
697 */
698 extern int ZEXPORT unzGoToFirstFile (file)
699 	unzFile file;
700 {
701 	int err=UNZ_OK;
702 	unz_s* s;
703 	if (file==NULL)
704 		return UNZ_PARAMERROR;
705 	s=(unz_s*)file;
706 	s->pos_in_central_dir=s->offset_central_dir;
707 	s->num_file=0;
708 	err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
709 											 &s->cur_file_info_internal,
710 											 NULL,0,NULL,0,NULL,0);
711 	s->current_file_ok = (err == UNZ_OK);
712 	return err;
713 }
714 
715 
716 /*
717   Set the current file of the zipfile to the next file.
718   return UNZ_OK if there is no problem
719   return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
720 */
721 extern int ZEXPORT unzGoToNextFile (file)
722 	unzFile file;
723 {
724 	unz_s* s;
725 	int err;
726 
727 	if (file==NULL)
728 		return UNZ_PARAMERROR;
729 	s=(unz_s*)file;
730 	if (!s->current_file_ok)
731 		return UNZ_END_OF_LIST_OF_FILE;
732 	if (s->num_file+1==s->gi.number_entry)
733 		return UNZ_END_OF_LIST_OF_FILE;
734 
735 	s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
736 			s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
737 	s->num_file++;
738 	err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
739 											   &s->cur_file_info_internal,
740 											   NULL,0,NULL,0,NULL,0);
741 	s->current_file_ok = (err == UNZ_OK);
742 	return err;
743 }
744 
745 
746 /*
747   Try locate the file szFileName in the zipfile.
748   For the iCaseSensitivity signification, see unzipStringFileNameCompare
749 
750   return value :
751   UNZ_OK if the file is found. It becomes the current file.
752   UNZ_END_OF_LIST_OF_FILE if the file is not found
753 */
754 extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
755 	unzFile file;
756 	const char *szFileName;
757 	int iCaseSensitivity;
758 {
759 	unz_s* s;
760 	int err;
761 
762 
763 	uLong num_fileSaved;
764 	uLong pos_in_central_dirSaved;
765 
766 
767 	if (file==NULL)
768 		return UNZ_PARAMERROR;
769 
770     if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
771         return UNZ_PARAMERROR;
772 
773 	s=(unz_s*)file;
774 	if (!s->current_file_ok)
775 		return UNZ_END_OF_LIST_OF_FILE;
776 
777 	num_fileSaved = s->num_file;
778 	pos_in_central_dirSaved = s->pos_in_central_dir;
779 
780 	err = unzGoToFirstFile(file);
781 
782 	while (err == UNZ_OK)
783 	{
784 		char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
785 		unzGetCurrentFileInfo(file,NULL,
786 								szCurrentFileName,sizeof(szCurrentFileName)-1,
787 								NULL,0,NULL,0);
788 		if (unzStringFileNameCompare(szCurrentFileName,
789 										szFileName,iCaseSensitivity)==0)
790 			return UNZ_OK;
791 		err = unzGoToNextFile(file);
792 	}
793 
794 	s->num_file = num_fileSaved ;
795 	s->pos_in_central_dir = pos_in_central_dirSaved ;
796 	return err;
797 }
798 
799 
800 /*
801   Read the local header of the current zipfile
802   Check the coherency of the local header and info in the end of central
803         directory about this file
804   store in *piSizeVar the size of extra info in local header
805         (filename and size of extra field data)
806 */
unzlocal_CheckCurrentFileCoherencyHeader(s,piSizeVar,poffset_local_extrafield,psize_local_extrafield)807 local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
808 													poffset_local_extrafield,
809 													psize_local_extrafield)
810 	unz_s* s;
811 	uInt* piSizeVar;
812 	uLong *poffset_local_extrafield;
813 	uInt  *psize_local_extrafield;
814 {
815 	uLong uMagic,uData,uFlags;
816 	uLong size_filename;
817 	uLong size_extra_field;
818 	int err=UNZ_OK;
819 
820 	*piSizeVar = 0;
821 	*poffset_local_extrafield = 0;
822 	*psize_local_extrafield = 0;
823 
824 	if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
825 								s->byte_before_the_zipfile,SEEK_SET)!=0)
826 		return UNZ_ERRNO;
827 
828 
829 	if (err==UNZ_OK) {
830 		if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
831 			err=UNZ_ERRNO;
832 		else if (uMagic!=0x04034b50)
833 			err=UNZ_BADZIPFILE;
834 	}
835 	if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
836 		err=UNZ_ERRNO;
837 /*
838 	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
839 		err=UNZ_BADZIPFILE;
840 */
841 	if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
842 		err=UNZ_ERRNO;
843 
844 	if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
845 		err=UNZ_ERRNO;
846 	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
847 		err=UNZ_BADZIPFILE;
848 
849     if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
850                          (s->cur_file_info.compression_method!=Z_DEFLATED))
851         err=UNZ_BADZIPFILE;
852 
853 	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
854 		err=UNZ_ERRNO;
855 
856 	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
857 		err=UNZ_ERRNO;
858 	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
859 		                      ((uFlags & 8)==0))
860 		err=UNZ_BADZIPFILE;
861 
862 	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
863 		err=UNZ_ERRNO;
864 	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
865 							  ((uFlags & 8)==0))
866 		err=UNZ_BADZIPFILE;
867 
868 	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
869 		err=UNZ_ERRNO;
870 	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
871 							  ((uFlags & 8)==0))
872 		err=UNZ_BADZIPFILE;
873 
874 
875 	if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
876 		err=UNZ_ERRNO;
877 	else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
878 		err=UNZ_BADZIPFILE;
879 
880 	*piSizeVar += (uInt)size_filename;
881 
882 	if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
883 		err=UNZ_ERRNO;
884 	*poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
885 									SIZEZIPLOCALHEADER + size_filename;
886 	*psize_local_extrafield = (uInt)size_extra_field;
887 
888 	*piSizeVar += (uInt)size_extra_field;
889 
890 	return err;
891 }
892 
893 /*
894   Open for reading data the current file in the zipfile.
895   If there is no error and the file is opened, the return value is UNZ_OK.
896 */
897 extern int ZEXPORT unzOpenCurrentFile (file)
898 	unzFile file;
899 {
900 	int err=UNZ_OK;
901 	int Store;
902 	uInt iSizeVar;
903 	unz_s* s;
904 	file_in_zip_read_info_s* pfile_in_zip_read_info;
905 	uLong offset_local_extrafield;  /* offset of the local extra field */
906 	uInt  size_local_extrafield;    /* size of the local extra field */
907 
908 	if (file==NULL)
909 		return UNZ_PARAMERROR;
910 	s=(unz_s*)file;
911 	if (!s->current_file_ok)
912 		return UNZ_PARAMERROR;
913 
914     if (s->pfile_in_zip_read != NULL)
915         unzCloseCurrentFile(file);
916 
917 	if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
918 				&offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
919 		return UNZ_BADZIPFILE;
920 
921 	pfile_in_zip_read_info = (file_in_zip_read_info_s*)
922 									    ALLOC(sizeof(file_in_zip_read_info_s));
923 	if (pfile_in_zip_read_info==NULL)
924 		return UNZ_INTERNALERROR;
925 
926 	pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
927 	pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
928 	pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
929 	pfile_in_zip_read_info->pos_local_extrafield=0;
930 
931 	if (pfile_in_zip_read_info->read_buffer==NULL)
932 	{
933 		TRYFREE(pfile_in_zip_read_info);
934 		return UNZ_INTERNALERROR;
935 	}
936 
937 	pfile_in_zip_read_info->stream_initialised=0;
938 
939 	if ((s->cur_file_info.compression_method!=0) &&
940         (s->cur_file_info.compression_method!=Z_DEFLATED))
941 		err=UNZ_BADZIPFILE;
942 	Store = s->cur_file_info.compression_method==0;
943 
944 	pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
945 	pfile_in_zip_read_info->crc32=0;
946 	pfile_in_zip_read_info->compression_method =
947             s->cur_file_info.compression_method;
948 	pfile_in_zip_read_info->file=s->file;
949 	pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
950 
951     pfile_in_zip_read_info->stream.total_out = 0;
952 
953 	if (!Store)
954 	{
955 	  pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
956 	  pfile_in_zip_read_info->stream.zfree = (free_func)0;
957 	  pfile_in_zip_read_info->stream.opaque = (voidpf)0;
958 
959 	  err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
960 	  if (err == Z_OK)
961 	    pfile_in_zip_read_info->stream_initialised=1;
962         /* windowBits is passed < 0 to tell that there is no zlib header.
963          * Note that in this case inflate *requires* an extra "dummy" byte
964          * after the compressed stream in order to complete decompression and
965          * return Z_STREAM_END.
966          * In unzip, i don't wait absolutely Z_STREAM_END because I known the
967          * size of both compressed and uncompressed data
968          */
969 	}
970 	pfile_in_zip_read_info->rest_read_compressed =
971             s->cur_file_info.compressed_size ;
972 	pfile_in_zip_read_info->rest_read_uncompressed =
973             s->cur_file_info.uncompressed_size ;
974 
975 
976 	pfile_in_zip_read_info->pos_in_zipfile =
977             s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
978 			  iSizeVar;
979 
980 	pfile_in_zip_read_info->stream.avail_in = (uInt)0;
981 
982 
983 	s->pfile_in_zip_read = pfile_in_zip_read_info;
984     return UNZ_OK;
985 }
986 
987 
988 /*
989   Read bytes from the current file.
990   buf contain buffer where data must be copied
991   len the size of buf.
992 
993   return the number of byte copied if somes bytes are copied
994   return 0 if the end of file was reached
995   return <0 with error code if there is an error
996     (UNZ_ERRNO for IO error, or zLib error for uncompress error)
997 */
998 extern int ZEXPORT unzReadCurrentFile  (file, buf, len)
999 	unzFile file;
1000 	voidp buf;
1001 	unsigned len;
1002 {
1003 	int err=UNZ_OK;
1004 	uInt iRead = 0;
1005 	unz_s* s;
1006 	file_in_zip_read_info_s* pfile_in_zip_read_info;
1007 	if (file==NULL)
1008 		return UNZ_PARAMERROR;
1009 	s=(unz_s*)file;
1010     pfile_in_zip_read_info=s->pfile_in_zip_read;
1011 
1012 	if (pfile_in_zip_read_info==NULL)
1013 		return UNZ_PARAMERROR;
1014 
1015 
1016 	if ((pfile_in_zip_read_info->read_buffer == NULL))
1017 		return UNZ_END_OF_LIST_OF_FILE;
1018 	if (len==0)
1019 		return 0;
1020 
1021 	pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
1022 
1023 	pfile_in_zip_read_info->stream.avail_out = (uInt)len;
1024 
1025 	if (len>pfile_in_zip_read_info->rest_read_uncompressed)
1026 		pfile_in_zip_read_info->stream.avail_out =
1027 		  (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
1028 
1029 	while (pfile_in_zip_read_info->stream.avail_out>0)
1030 	{
1031 		if ((pfile_in_zip_read_info->stream.avail_in==0) &&
1032             (pfile_in_zip_read_info->rest_read_compressed>0))
1033 		{
1034 			uInt uReadThis = UNZ_BUFSIZE;
1035 			if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
1036 				uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
1037 			if (uReadThis == 0)
1038 				return UNZ_EOF;
1039 			if (fseek(pfile_in_zip_read_info->file,
1040                       pfile_in_zip_read_info->pos_in_zipfile +
1041                          pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
1042 				return UNZ_ERRNO;
1043 			if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
1044                          pfile_in_zip_read_info->file)!=1)
1045 				return UNZ_ERRNO;
1046 			pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
1047 
1048 			pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
1049 
1050 			pfile_in_zip_read_info->stream.next_in =
1051                 (Bytef*)pfile_in_zip_read_info->read_buffer;
1052 			pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
1053 		}
1054 
1055 		if (pfile_in_zip_read_info->compression_method==0)
1056 		{
1057 			uInt uDoCopy,i ;
1058 			if (pfile_in_zip_read_info->stream.avail_out <
1059                             pfile_in_zip_read_info->stream.avail_in)
1060 				uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
1061 			else
1062 				uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
1063 
1064 			for (i=0;i<uDoCopy;i++)
1065 				*(pfile_in_zip_read_info->stream.next_out+i) =
1066                         *(pfile_in_zip_read_info->stream.next_in+i);
1067 
1068 			pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
1069 								pfile_in_zip_read_info->stream.next_out,
1070 								uDoCopy);
1071 			pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
1072 			pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
1073 			pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
1074 			pfile_in_zip_read_info->stream.next_out += uDoCopy;
1075 			pfile_in_zip_read_info->stream.next_in += uDoCopy;
1076             pfile_in_zip_read_info->stream.total_out += uDoCopy;
1077 			iRead += uDoCopy;
1078 		}
1079 		else
1080 		{
1081 			uLong uTotalOutBefore,uTotalOutAfter;
1082 			const Bytef *bufBefore;
1083 			uLong uOutThis;
1084 			int flush=Z_SYNC_FLUSH;
1085 
1086 			uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
1087 			bufBefore = pfile_in_zip_read_info->stream.next_out;
1088 
1089 			/*
1090 			if ((pfile_in_zip_read_info->rest_read_uncompressed ==
1091 			         pfile_in_zip_read_info->stream.avail_out) &&
1092 				(pfile_in_zip_read_info->rest_read_compressed == 0))
1093 				flush = Z_FINISH;
1094 			*/
1095 			err=inflate(&pfile_in_zip_read_info->stream,flush);
1096 
1097 			uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
1098 			uOutThis = uTotalOutAfter-uTotalOutBefore;
1099 
1100 			pfile_in_zip_read_info->crc32 =
1101                 crc32(pfile_in_zip_read_info->crc32,bufBefore,
1102                         (uInt)(uOutThis));
1103 
1104 			pfile_in_zip_read_info->rest_read_uncompressed -=
1105                 uOutThis;
1106 
1107 			iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
1108 
1109 			if (err==Z_STREAM_END)
1110 				return (iRead==0) ? UNZ_EOF : iRead;
1111 			if (err!=Z_OK)
1112 				break;
1113 		}
1114 	}
1115 
1116 	if (err==Z_OK)
1117 		return iRead;
1118 	return err;
1119 }
1120 
1121 
1122 /*
1123   Give the current position in uncompressed data
1124 */
1125 extern z_off_t ZEXPORT unztell (file)
1126 	unzFile file;
1127 {
1128 	unz_s* s;
1129 	file_in_zip_read_info_s* pfile_in_zip_read_info;
1130 	if (file==NULL)
1131 		return UNZ_PARAMERROR;
1132 	s=(unz_s*)file;
1133     pfile_in_zip_read_info=s->pfile_in_zip_read;
1134 
1135 	if (pfile_in_zip_read_info==NULL)
1136 		return UNZ_PARAMERROR;
1137 
1138 	return (z_off_t)pfile_in_zip_read_info->stream.total_out;
1139 }
1140 
1141 
1142 /*
1143   return 1 if the end of file was reached, 0 elsewhere
1144 */
1145 extern int ZEXPORT unzeof (file)
1146 	unzFile file;
1147 {
1148 	unz_s* s;
1149 	file_in_zip_read_info_s* pfile_in_zip_read_info;
1150 	if (file==NULL)
1151 		return UNZ_PARAMERROR;
1152 	s=(unz_s*)file;
1153     pfile_in_zip_read_info=s->pfile_in_zip_read;
1154 
1155 	if (pfile_in_zip_read_info==NULL)
1156 		return UNZ_PARAMERROR;
1157 
1158 	if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1159 		return 1;
1160 	else
1161 		return 0;
1162 }
1163 
1164 
1165 
1166 /*
1167   Read extra field from the current file (opened by unzOpenCurrentFile)
1168   This is the local-header version of the extra field (sometimes, there is
1169     more info in the local-header version than in the central-header)
1170 
1171   if buf==NULL, it return the size of the local extra field that can be read
1172 
1173   if buf!=NULL, len is the size of the buffer, the extra header is copied in
1174 	buf.
1175   the return value is the number of bytes copied in buf, or (if <0)
1176 	the error code
1177 */
1178 extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
1179 	unzFile file;
1180 	voidp buf;
1181 	unsigned len;
1182 {
1183 	unz_s* s;
1184 	file_in_zip_read_info_s* pfile_in_zip_read_info;
1185 	uInt read_now;
1186 	uLong size_to_read;
1187 
1188 	if (file==NULL)
1189 		return UNZ_PARAMERROR;
1190 	s=(unz_s*)file;
1191     pfile_in_zip_read_info=s->pfile_in_zip_read;
1192 
1193 	if (pfile_in_zip_read_info==NULL)
1194 		return UNZ_PARAMERROR;
1195 
1196 	size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
1197 				pfile_in_zip_read_info->pos_local_extrafield);
1198 
1199 	if (buf==NULL)
1200 		return (int)size_to_read;
1201 
1202 	if (len>size_to_read)
1203 		read_now = (uInt)size_to_read;
1204 	else
1205 		read_now = (uInt)len ;
1206 
1207 	if (read_now==0)
1208 		return 0;
1209 
1210 	if (fseek(pfile_in_zip_read_info->file,
1211               pfile_in_zip_read_info->offset_local_extrafield +
1212 			  pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
1213 		return UNZ_ERRNO;
1214 
1215 	if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
1216 		return UNZ_ERRNO;
1217 
1218 	return (int)read_now;
1219 }
1220 
1221 /*
1222   Close the file in zip opened with unzipOpenCurrentFile
1223   Return UNZ_CRCERROR if all the file was read but the CRC is not good
1224 */
1225 extern int ZEXPORT unzCloseCurrentFile (file)
1226 	unzFile file;
1227 {
1228 	int err=UNZ_OK;
1229 
1230 	unz_s* s;
1231 	file_in_zip_read_info_s* pfile_in_zip_read_info;
1232 	if (file==NULL)
1233 		return UNZ_PARAMERROR;
1234 	s=(unz_s*)file;
1235     pfile_in_zip_read_info=s->pfile_in_zip_read;
1236 
1237 	if (pfile_in_zip_read_info==NULL)
1238 		return UNZ_PARAMERROR;
1239 
1240 
1241 	if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
1242 	{
1243 		if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
1244 			err=UNZ_CRCERROR;
1245 	}
1246 
1247 
1248 	TRYFREE(pfile_in_zip_read_info->read_buffer);
1249 	pfile_in_zip_read_info->read_buffer = NULL;
1250 	if (pfile_in_zip_read_info->stream_initialised)
1251 		inflateEnd(&pfile_in_zip_read_info->stream);
1252 
1253 	pfile_in_zip_read_info->stream_initialised = 0;
1254 	TRYFREE(pfile_in_zip_read_info);
1255 
1256     s->pfile_in_zip_read=NULL;
1257 
1258 	return err;
1259 }
1260 
1261 
1262 /*
1263   Get the global comment string of the ZipFile, in the szComment buffer.
1264   uSizeBuf is the size of the szComment buffer.
1265   return the number of byte copied or an error code <0
1266 */
1267 extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
1268 	unzFile file;
1269 	char *szComment;
1270 	uLong uSizeBuf;
1271 {
1272 	int err=UNZ_OK;
1273 	unz_s* s;
1274 	uLong uReadThis ;
1275 	if (file==NULL)
1276 		return UNZ_PARAMERROR;
1277 	s=(unz_s*)file;
1278 
1279 	uReadThis = uSizeBuf;
1280 	if (uReadThis>s->gi.size_comment)
1281 		uReadThis = s->gi.size_comment;
1282 
1283 	if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
1284 		return UNZ_ERRNO;
1285 
1286 	if (uReadThis>0)
1287     {
1288       *szComment='\0';
1289 	  if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
1290 		return UNZ_ERRNO;
1291     }
1292 
1293 	if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
1294 		*(szComment+s->gi.size_comment)='\0';
1295 	return (int)uReadThis;
1296 }
1297