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