Develop and Download Open Source Software

Browse CVS Repository

Contents of /mame32jp/mame32jp/src/unzip.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Wed Apr 24 03:53:21 2002 UTC (21 years, 11 months ago) by zero
Branch: MAIN
CVS Tags: ver_0_60_1, ver0_59_13, ver0_59_14, ver0_60_2, ver0_60_3, ver0_60_4, ver0_60_5, HEAD
Changes since 1.4: +0 -0 lines
File MIME type: text/x-csrc
*** empty log message ***

1 #include "unzip.h"
2 #include "driver.h"
3
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include <assert.h>
8 #include <zlib.h>
9
10 /* public globals */
11 int gUnzipQuiet = 0; /* flag controls error messages */
12
13
14 #ifdef JAPANESE
15 #define ERROR_CORRUPT "このzipファイルは破損しているようです。チェックしてください。"
16 #define ERROR_FILESYSTEM "ファイルシステムが破損しているようです。チェックしてください。"
17 #define ERROR_UNSUPPORTED "この形式のzipファイルには対応していません。再圧縮してください。"
18 #else
19 #define ERROR_CORRUPT "The zipfile seems to be corrupt, please check it"
20 #define ERROR_FILESYSTEM "Your filesystem seems to be corrupt, please check it"
21 #define ERROR_UNSUPPORTED "The format of this zipfile is not supported, please recompress it"
22 #endif
23
24 #define INFLATE_INPUT_BUFFER_MAX 16384
25 #ifndef MIN
26 #define MIN(x,y) ((x)<(y)?(x):(y))
27 #endif
28
29 /* Print a error message */
30 void errormsg(const char* extmsg, const char* usermsg, const char* zipname) {
31 /* Output to the user with no internal detail */
32 if (!gUnzipQuiet)
33 #ifdef JAPANESE
34 printf("zipファイルのエラー %s\n%s\n", zipname, usermsg);
35 #else
36 printf("Error in zipfile %s\n%s\n", zipname, usermsg);
37 #endif
38 /* Output to log file with all informations */
39 logerror("Error in zipfile %s: %s\n", zipname, extmsg);
40 }
41
42 /* -------------------------------------------------------------------------
43 Unzip support
44 ------------------------------------------------------------------------- */
45
46 /* Use these to avoid structure padding and byte-ordering problems */
47 static UINT16 read_word (char *buf) {
48 unsigned char *ubuf = (unsigned char *) buf;
49
50 return ((UINT16)ubuf[1] << 8) | (UINT16)ubuf[0];
51 }
52
53 /* Use these to avoid structure padding and byte-ordering problems */
54 static UINT32 read_dword (char *buf) {
55 unsigned char *ubuf = (unsigned char *) buf;
56
57 return ((UINT32)ubuf[3] << 24) | ((UINT32)ubuf[2] << 16) | ((UINT32)ubuf[1] << 8) | (UINT32)ubuf[0];
58 }
59
60 /* Locate end-of-central-dir sig in buffer and return offset
61 out:
62 *offset offset of cent dir start in buffer
63 return:
64 ==0 not found
65 !=0 found, *offset valid
66 */
67 static int ecd_find_sig (char *buffer, int buflen, int *offset)
68 {
69 static char ecdsig[] = { 'P', 'K', 0x05, 0x06 };
70 int i;
71 for (i=buflen-22; i>=0; i--) {
72 if (memcmp(buffer+i, ecdsig, 4) == 0) {
73 *offset = i;
74 return 1;
75 }
76 }
77 return 0;
78 }
79
80 /* Read ecd data in zip structure
81 in:
82 zip->fp, zip->length zip file
83 out:
84 zip->ecd, zip->ecd_length ecd data
85 */
86 static int ecd_read(ZIP* zip) {
87 char* buf;
88 int buf_length = 1024; /* initial buffer length */
89
90 while (1) {
91 int offset;
92
93 if (buf_length > zip->length)
94 buf_length = zip->length;
95
96 if (fseek(zip->fp, zip->length - buf_length, SEEK_SET) != 0) {
97 return -1;
98 }
99
100 /* allocate buffer */
101 buf = (char*)malloc( buf_length );
102 if (!buf) {
103 return -1;
104 }
105
106 if (fread( buf, buf_length, 1, zip->fp ) != 1) {
107 free(buf);
108 return -1;
109 }
110
111 if (ecd_find_sig(buf, buf_length, &offset)) {
112 zip->ecd_length = buf_length - offset;
113
114 zip->ecd = (char*)malloc( zip->ecd_length );
115 if (!zip->ecd) {
116 free(buf);
117 return -1;
118 }
119
120 memcpy(zip->ecd, buf + offset, zip->ecd_length);
121
122 free(buf);
123 return 0;
124 }
125
126 free(buf);
127
128 if (buf_length < zip->length) {
129 /* double buffer */
130 buf_length = 2*buf_length;
131
132 logerror("Retry reading of zip ecd for %d bytes\n",buf_length);
133
134 } else {
135 return -1;
136 }
137 }
138 }
139
140 /* offsets in end of central directory structure */
141 #define ZIPESIG 0x00
142 #define ZIPEDSK 0x04
143 #define ZIPECEN 0x06
144 #define ZIPENUM 0x08
145 #define ZIPECENN 0x0a
146 #define ZIPECSZ 0x0c
147 #define ZIPEOFST 0x10
148 #define ZIPECOML 0x14
149 #define ZIPECOM 0x16
150
151 /* offsets in central directory entry structure */
152 #define ZIPCENSIG 0x0
153 #define ZIPCVER 0x4
154 #define ZIPCOS 0x5
155 #define ZIPCVXT 0x6
156 #define ZIPCEXOS 0x7
157 #define ZIPCFLG 0x8
158 #define ZIPCMTHD 0xa
159 #define ZIPCTIM 0xc
160 #define ZIPCDAT 0xe
161 #define ZIPCCRC 0x10
162 #define ZIPCSIZ 0x14
163 #define ZIPCUNC 0x18
164 #define ZIPCFNL 0x1c
165 #define ZIPCXTL 0x1e
166 #define ZIPCCML 0x20
167 #define ZIPDSK 0x22
168 #define ZIPINT 0x24
169 #define ZIPEXT 0x26
170 #define ZIPOFST 0x2a
171 #define ZIPCFN 0x2e
172
173 /* offsets in local file header structure */
174 #define ZIPLOCSIG 0x00
175 #define ZIPVER 0x04
176 #define ZIPGENFLG 0x06
177 #define ZIPMTHD 0x08
178 #define ZIPTIME 0x0a
179 #define ZIPDATE 0x0c
180 #define ZIPCRC 0x0e
181 #define ZIPSIZE 0x12
182 #define ZIPUNCMP 0x16
183 #define ZIPFNLN 0x1a
184 #define ZIPXTRALN 0x1c
185 #define ZIPNAME 0x1e
186
187 /* Opens a zip stream for reading
188 return:
189 !=0 success, zip stream
190 ==0 error
191 */
192 ZIP* openzip(const char* zipfile) {
193 /* allocate */
194 ZIP* zip = (ZIP*)malloc( sizeof(ZIP) );
195 if (!zip) {
196 return 0;
197 }
198
199 /* open */
200 zip->fp = fopen(zipfile, "rb");
201 if (!zip->fp) {
202 errormsg ("Opening for reading", ERROR_FILESYSTEM, zipfile);
203 free(zip);
204 return 0;
205 }
206
207 /* go to end */
208 if (fseek(zip->fp, 0L, SEEK_END) != 0) {
209 errormsg ("Seeking to end", ERROR_FILESYSTEM, zipfile);
210 fclose(zip->fp);
211 free(zip);
212 return 0;
213 }
214
215 /* get length */
216 zip->length = ftell(zip->fp);
217 if (zip->length < 0) {
218 errormsg ("Get file size", ERROR_FILESYSTEM, zipfile);
219 fclose(zip->fp);
220 free(zip);
221 return 0;
222 }
223 if (zip->length == 0) {
224 errormsg ("Empty file", ERROR_CORRUPT, zipfile);
225 fclose(zip->fp);
226 free(zip);
227 return 0;
228 }
229
230 /* read ecd data */
231 if (ecd_read(zip)!=0) {
232 errormsg ("Reading ECD (end of central directory)", ERROR_CORRUPT, zipfile);
233 fclose(zip->fp);
234 free(zip);
235 return 0;
236 }
237
238 /* compile ecd info */
239 zip->end_of_cent_dir_sig = read_dword (zip->ecd+ZIPESIG);
240 zip->number_of_this_disk = read_word (zip->ecd+ZIPEDSK);
241 zip->number_of_disk_start_cent_dir = read_word (zip->ecd+ZIPECEN);
242 zip->total_entries_cent_dir_this_disk = read_word (zip->ecd+ZIPENUM);
243 zip->total_entries_cent_dir = read_word (zip->ecd+ZIPECENN);
244 zip->size_of_cent_dir = read_dword (zip->ecd+ZIPECSZ);
245 zip->offset_to_start_of_cent_dir = read_dword (zip->ecd+ZIPEOFST);
246 zip->zipfile_comment_length = read_word (zip->ecd+ZIPECOML);
247 zip->zipfile_comment = zip->ecd+ZIPECOM;
248
249 /* verify that we can work with this zipfile (no disk spanning allowed) */
250 if ((zip->number_of_this_disk != zip->number_of_disk_start_cent_dir) ||
251 (zip->total_entries_cent_dir_this_disk != zip->total_entries_cent_dir) ||
252 (zip->total_entries_cent_dir < 1)) {
253 errormsg("Cannot span disks", ERROR_UNSUPPORTED, zipfile);
254 free(zip->ecd);
255 fclose(zip->fp);
256 free(zip);
257 return 0;
258 }
259
260 if (fseek(zip->fp, zip->offset_to_start_of_cent_dir, SEEK_SET)!=0) {
261 errormsg ("Seeking to central directory", ERROR_CORRUPT, zipfile);
262 free(zip->ecd);
263 fclose(zip->fp);
264 free(zip);
265 return 0;
266 }
267
268 /* read from start of central directory */
269 zip->cd = (char*)malloc( zip->size_of_cent_dir );
270 if (!zip->cd) {
271 free(zip->ecd);
272 fclose(zip->fp);
273 free(zip);
274 return 0;
275 }
276
277 if (fread(zip->cd, zip->size_of_cent_dir, 1, zip->fp)!=1) {
278 errormsg ("Reading central directory", ERROR_CORRUPT, zipfile);
279 free(zip->cd);
280 free(zip->ecd);
281 fclose(zip->fp);
282 free(zip);
283 return 0;
284 }
285
286 /* reset ent */
287 zip->ent.name = 0;
288
289 /* rewind */
290 zip->cd_pos = 0;
291
292 /* file name */
293 zip->zip = (char*)malloc(strlen(zipfile)+1);
294 if (!zip->zip) {
295 free(zip->cd);
296 free(zip->ecd);
297 fclose(zip->fp);
298 free(zip);
299 return 0;
300 }
301 strcpy(zip->zip, zipfile);
302
303 return zip;
304 }
305
306 /* Reads the current entry from a zip stream
307 in:
308 zip opened zip
309 return:
310 !=0 success
311 ==0 error
312 */
313 struct zipent* readzip(ZIP* zip) {
314
315 /* end of directory */
316 if (zip->cd_pos >= zip->size_of_cent_dir)
317 return 0;
318
319 /* compile zipent info */
320 zip->ent.cent_file_header_sig = read_dword (zip->cd+zip->cd_pos+ZIPCENSIG);
321 zip->ent.version_made_by = *(zip->cd+zip->cd_pos+ZIPCVER);
322 zip->ent.host_os = *(zip->cd+zip->cd_pos+ZIPCOS);
323 zip->ent.version_needed_to_extract = *(zip->cd+zip->cd_pos+ZIPCVXT);
324 zip->ent.os_needed_to_extract = *(zip->cd+zip->cd_pos+ZIPCEXOS);
325 zip->ent.general_purpose_bit_flag = read_word (zip->cd+zip->cd_pos+ZIPCFLG);
326 zip->ent.compression_method = read_word (zip->cd+zip->cd_pos+ZIPCMTHD);
327 zip->ent.last_mod_file_time = read_word (zip->cd+zip->cd_pos+ZIPCTIM);
328 zip->ent.last_mod_file_date = read_word (zip->cd+zip->cd_pos+ZIPCDAT);
329 zip->ent.crc32 = read_dword (zip->cd+zip->cd_pos+ZIPCCRC);
330 zip->ent.compressed_size = read_dword (zip->cd+zip->cd_pos+ZIPCSIZ);
331 zip->ent.uncompressed_size = read_dword (zip->cd+zip->cd_pos+ZIPCUNC);
332 zip->ent.filename_length = read_word (zip->cd+zip->cd_pos+ZIPCFNL);
333 zip->ent.extra_field_length = read_word (zip->cd+zip->cd_pos+ZIPCXTL);
334 zip->ent.file_comment_length = read_word (zip->cd+zip->cd_pos+ZIPCCML);
335 zip->ent.disk_number_start = read_word (zip->cd+zip->cd_pos+ZIPDSK);
336 zip->ent.internal_file_attrib = read_word (zip->cd+zip->cd_pos+ZIPINT);
337 zip->ent.external_file_attrib = read_dword (zip->cd+zip->cd_pos+ZIPEXT);
338 zip->ent.offset_lcl_hdr_frm_frst_disk = read_dword (zip->cd+zip->cd_pos+ZIPOFST);
339
340 /* check to see if filename length is illegally long (past the size of this directory
341 entry) */
342 if (zip->cd_pos + ZIPCFN + zip->ent.filename_length > zip->size_of_cent_dir)
343 {
344 errormsg("Invalid filename length in directory", ERROR_CORRUPT,zip->zip);
345 return 0;
346 }
347
348 /* copy filename */
349 free(zip->ent.name);
350 zip->ent.name = (char*)malloc(zip->ent.filename_length + 1);
351 memcpy(zip->ent.name, zip->cd+zip->cd_pos+ZIPCFN, zip->ent.filename_length);
352 zip->ent.name[zip->ent.filename_length] = 0;
353
354 /* skip to next entry in central dir */
355 zip->cd_pos += ZIPCFN + zip->ent.filename_length + zip->ent.extra_field_length + zip->ent.file_comment_length;
356
357 return &zip->ent;
358 }
359
360 /* Closes a zip stream */
361 void closezip(ZIP* zip) {
362 /* release all */
363 free(zip->ent.name);
364 free(zip->cd);
365 free(zip->ecd);
366 /* only if not suspended */
367 if (zip->fp)
368 fclose(zip->fp);
369 free(zip->zip);
370 free(zip);
371 }
372
373 /* Suspend access to a zip file (release file handler)
374 in:
375 zip opened zip
376 note:
377 A suspended zip is automatically reopened at first call of
378 readuncompressd() or readcompressed() functions
379 */
380 void suspendzip(ZIP* zip) {
381 if (zip->fp) {
382 fclose(zip->fp);
383 zip->fp = 0;
384 }
385 }
386
387 /* Revive a suspended zip file (reopen file handler)
388 in:
389 zip suspended zip
390 return:
391 zip success
392 ==0 error (zip must be closed with closezip)
393 */
394 static ZIP* revivezip(ZIP* zip) {
395 if (!zip->fp) {
396 zip->fp = fopen(zip->zip, "rb");
397 if (!zip->fp) {
398 return 0;
399 }
400 }
401 return zip;
402
403 }
404
405 /* Reset a zip stream to the first entry
406 in:
407 zip opened zip
408 note:
409 ZIP file must be opened and not suspended
410 */
411 void rewindzip(ZIP* zip) {
412 zip->cd_pos = 0;
413 }
414
415 /* Seek zip->fp to compressed data
416 return:
417 ==0 success
418 <0 error
419 */
420 int seekcompresszip(ZIP* zip, struct zipent* ent) {
421 char buf[ZIPNAME];
422 long offset;
423
424 if (!zip->fp) {
425 if (!revivezip(zip))
426 return -1;
427 }
428
429 if (fseek(zip->fp, ent->offset_lcl_hdr_frm_frst_disk, SEEK_SET)!=0) {
430 errormsg ("Seeking to header", ERROR_CORRUPT, zip->zip);
431 return -1;
432 }
433
434 if (fread(buf, ZIPNAME, 1, zip->fp)!=1) {
435 errormsg ("Reading header", ERROR_CORRUPT, zip->zip);
436 return -1;
437 }
438
439 {
440 UINT16 filename_length = read_word (buf+ZIPFNLN);
441 UINT16 extra_field_length = read_word (buf+ZIPXTRALN);
442
443 /* calculate offset to data and fseek() there */
444 offset = ent->offset_lcl_hdr_frm_frst_disk + ZIPNAME + filename_length + extra_field_length;
445
446 if (fseek(zip->fp, offset, SEEK_SET) != 0) {
447 errormsg ("Seeking to compressed data", ERROR_CORRUPT, zip->zip);
448 return -1;
449 }
450
451 }
452
453 return 0;
454 }
455
456 /* Inflate a file
457 in:
458 in_file stream to inflate
459 in_size size of the compressed data to read
460 out_size size of decompressed data
461 out:
462 out_data buffer for decompressed data
463 return:
464 ==0 ok
465
466 990525 rewritten for use with zlib MLR
467 */
468 static int inflate_file(FILE* in_file, unsigned in_size, unsigned char* out_data, unsigned out_size)
469 {
470 int err;
471 unsigned char* in_buffer;
472 z_stream d_stream; /* decompression stream */
473
474 d_stream.zalloc = 0;
475 d_stream.zfree = 0;
476 d_stream.opaque = 0;
477
478 d_stream.next_in = 0;
479 d_stream.avail_in = 0;
480 d_stream.next_out = out_data;
481 d_stream.avail_out = out_size;
482
483 err = inflateInit2(&d_stream, -MAX_WBITS);
484 /* windowBits is passed < 0 to tell that there is no zlib header.
485 * Note that in this case inflate *requires* an extra "dummy" byte
486 * after the compressed stream in order to complete decompression and
487 * return Z_STREAM_END.
488 */
489 if (err != Z_OK)
490 {
491 logerror("inflateInit error: %d\n", err);
492 return -1;
493 }
494
495 in_buffer = (unsigned char*)malloc(INFLATE_INPUT_BUFFER_MAX+1);
496 if (!in_buffer)
497 return -1;
498
499 for (;;)
500 {
501 if (in_size <= 0)
502 {
503 logerror("inflate error: compressed size too small\n");
504 free (in_buffer);
505 return -1;
506 }
507 d_stream.next_in = in_buffer;
508 d_stream.avail_in = fread (in_buffer, 1, MIN(in_size, INFLATE_INPUT_BUFFER_MAX), in_file);
509 in_size -= d_stream.avail_in;
510 if (in_size == 0)
511 d_stream.avail_in++; /* add dummy byte at end of compressed data */
512
513 err = inflate(&d_stream, Z_NO_FLUSH);
514 if (err == Z_STREAM_END)
515 break;
516 if (err != Z_OK)
517 {
518 logerror("inflate error: %d\n", err);
519 free (in_buffer);
520 return -1;
521 }
522 }
523
524 err = inflateEnd(&d_stream);
525 if (err != Z_OK)
526 {
527 logerror("inflateEnd error: %d\n", err);
528 free (in_buffer);
529 return -1;
530 }
531
532 free (in_buffer);
533
534 if ((d_stream.avail_out > 0) || (in_size > 0))
535 {
536 logerror("zip size mismatch. %i\n", in_size);
537 return -1;
538 }
539
540 return 0;
541 }
542
543 /* Read compressed data
544 out:
545 data compressed data read
546 return:
547 ==0 success
548 <0 error
549 */
550 int readcompresszip(ZIP* zip, struct zipent* ent, char* data) {
551 int err = seekcompresszip(zip,ent);
552 if (err!=0)
553 return err;
554
555 if (fread(data, ent->compressed_size, 1, zip->fp)!=1) {
556 errormsg ("Reading compressed data", ERROR_CORRUPT, zip->zip);
557 return -1;
558 }
559
560 return 0;
561 }
562
563 /* Read UNcompressed data
564 out:
565 data UNcompressed data
566 return:
567 ==0 success
568 <0 error
569 */
570 int readuncompresszip(ZIP* zip, struct zipent* ent, char* data) {
571 if (ent->compression_method == 0x0000) {
572 /* file is not compressed, simply stored */
573
574 /* check if size are equal */
575 if (ent->compressed_size != ent->uncompressed_size) {
576 errormsg("Wrong uncompressed size in store compression", ERROR_CORRUPT,zip->zip);
577 return -3;
578 }
579
580 return readcompresszip(zip,ent,data);
581 } else if (ent->compression_method == 0x0008) {
582 /* file is compressed using "Deflate" method */
583 if (ent->version_needed_to_extract > 0x14) {
584 errormsg("Version too new", ERROR_UNSUPPORTED,zip->zip);
585 return -2;
586 }
587
588 if (ent->os_needed_to_extract != 0x00) {
589 errormsg("OS not supported", ERROR_UNSUPPORTED,zip->zip);
590 return -2;
591 }
592
593 if (ent->disk_number_start != zip->number_of_this_disk) {
594 errormsg("Cannot span disks", ERROR_UNSUPPORTED,zip->zip);
595 return -2;
596 }
597
598 /* read compressed data */
599 if (seekcompresszip(zip,ent)!=0) {
600 return -1;
601 }
602
603 /* configure inflate */
604 if (inflate_file( zip->fp, ent->compressed_size, (unsigned char*)data, ent->uncompressed_size))
605 {
606 errormsg("Inflating compressed data", ERROR_CORRUPT, zip->zip);
607 return -3;
608 }
609
610 return 0;
611 } else {
612 errormsg("Compression method unsupported", ERROR_UNSUPPORTED, zip->zip);
613 return -2;
614 }
615 }
616
617 /* -------------------------------------------------------------------------
618 Zip cache support
619 ------------------------------------------------------------------------- */
620
621 /* Use the zip cache */
622 #define ZIP_CACHE
623
624 #ifdef ZIP_CACHE
625
626 /* ZIP cache entries */
627 #define ZIP_CACHE_MAX 5
628
629 /* ZIP cache buffer LRU ( Last Recently Used )
630 zip_cache_map[0] is the newer
631 zip_cache_map[ZIP_CACHE_MAX-1] is the older
632 */
633 static ZIP* zip_cache_map[ZIP_CACHE_MAX];
634
635 static ZIP* cache_openzip(const char* zipfile) {
636 ZIP* zip;
637 unsigned i;
638
639 /* search in the cache buffer */
640 for(i=0;i<ZIP_CACHE_MAX;++i) {
641 if (zip_cache_map[i] && strcmp(zip_cache_map[i]->zip,zipfile)==0) {
642 /* found */
643 unsigned j;
644
645 /*
646 logerror("Zip cache HIT for %s\n", zipfile);
647 */
648
649 /* reset the zip directory */
650 rewindzip( zip_cache_map[i] );
651
652 /* store */
653 zip = zip_cache_map[i];
654
655 /* shift */
656 for(j=i;j>0;--j)
657 zip_cache_map[j] = zip_cache_map[j-1];
658
659 /* set the first entry */
660 zip_cache_map[0] = zip;
661
662 return zip_cache_map[0];
663 }
664 }
665 /* not found */
666
667 /*
668 logerror("Zip cache FAIL for %s\n", zipfile);
669 */
670
671 /* open the zip */
672 zip = openzip( zipfile );
673 if (!zip)
674 return 0;
675
676 /* close the oldest entry */
677 if (zip_cache_map[ZIP_CACHE_MAX-1]) {
678 /* close last zip */
679 closezip(zip_cache_map[ZIP_CACHE_MAX-1]);
680 /* reset the entry */
681 zip_cache_map[ZIP_CACHE_MAX-1] = 0;
682 }
683
684 /* shift */
685 for(i=ZIP_CACHE_MAX-1;i>0;--i)
686 zip_cache_map[i] = zip_cache_map[i-1];
687
688 /* set the first entry */
689 zip_cache_map[0] = zip;
690
691 return zip_cache_map[0];
692 }
693
694 static void cache_closezip(ZIP* zip) {
695 unsigned i;
696
697 /* search in the cache buffer */
698 for(i=0;i<ZIP_CACHE_MAX;++i) {
699 if (zip_cache_map[i]==zip) {
700 /* close zip */
701 closezip(zip);
702
703 /* reset cache entry */
704 zip_cache_map[i] = 0;
705 return;
706
707 }
708 }
709 /* not found */
710
711 /* close zip */
712 closezip(zip);
713 }
714
715 /* CK980415 added to allow osd code to clear zip cache for auditing--each time
716 the user opens up an audit for a game we should reread the zip */
717 void unzip_cache_clear()
718 {
719 unsigned i;
720
721 /* search in the cache buffer for any zip info and clear it */
722 for(i=0;i<ZIP_CACHE_MAX;++i) {
723 if (zip_cache_map[i] != NULL) {
724 /* close zip */
725 closezip(zip_cache_map[i]);
726
727 /* reset cache entry */
728 zip_cache_map[i] = 0;
729 /* return; */
730
731 }
732 }
733 }
734
735 #define cache_suspendzip(a) suspendzip(a)
736
737 #else
738
739 #define cache_openzip(a) openzip(a)
740 #define cache_closezip(a) closezip(a)
741 #define cache_suspendzip(a) closezip(a)
742
743 #define unzip_cache_clear()
744
745 #endif
746
747 /* -------------------------------------------------------------------------
748 Backward MAME compatibility
749 ------------------------------------------------------------------------- */
750
751 /* Compare two filename
752 note:
753 don't check directory in zip and ignore case
754 */
755 static int equal_filename(const char* zipfile, const char* file) {
756 const char* s1 = file;
757 /* start comparison after last / */
758 const char* s2 = strrchr(zipfile,'/');
759 if (s2)
760 ++s2;
761 else
762 s2 = zipfile;
763 while (*s1 && toupper(*s1)==toupper(*s2)) {
764 ++s1;
765 ++s2;
766 }
767 return !*s1 && !*s2;
768 }
769
770 /* Pass the path to the zipfile and the name of the file within the zipfile.
771 buf will be set to point to the uncompressed image of that zipped file.
772 length will be set to the length of the uncompressed data. */
773 int /* error */ load_zipped_file (const char* zipfile, const char* filename, unsigned char** buf, unsigned int* length) {
774 ZIP* zip;
775 struct zipent* ent;
776
777 zip = cache_openzip(zipfile);
778 if (!zip)
779 return -1;
780
781 while (readzip(zip)) {
782 /* NS981003: support for "load by CRC" */
783 char crc[9];
784
785 ent = &(zip->ent);
786
787 sprintf(crc,"%08x",ent->crc32);
788 if (equal_filename(ent->name, filename) ||
789 (ent->crc32 && !strcmp(crc, filename)))
790 {
791 *length = ent->uncompressed_size;
792 *buf = (unsigned char*)malloc( *length );
793 if (!*buf) {
794 if (!gUnzipQuiet)
795 printf("load_zipped_file(): Unable to allocate %d bytes of RAM\n",*length);
796 cache_closezip(zip);
797 return -1;
798 }
799
800 if (readuncompresszip(zip, ent, (char*)*buf)!=0) {
801 free(*buf);
802 cache_closezip(zip);
803 return -1;
804 }
805
806 cache_suspendzip(zip);
807 return 0;
808 }
809 }
810
811 cache_suspendzip(zip);
812 return -1;
813 }
814
815 /* Pass the path to the zipfile and the name of the file within the zipfile.
816 sum will be set to the CRC-32 of that zipped file. */
817 /* The caller can preset sum to the expected checksum to enable "load by CRC" */
818 int /* error */ checksum_zipped_file (const char *zipfile, const char *filename, unsigned int *length, unsigned int *sum) {
819 ZIP* zip;
820 struct zipent* ent;
821
822 zip = cache_openzip(zipfile);
823 if (!zip)
824 return -1;
825
826 while (readzip(zip)) {
827 ent = &(zip->ent);
828
829 if (equal_filename(ent->name, filename))
830 {
831 *length = ent->uncompressed_size;
832 *sum = ent->crc32;
833 cache_suspendzip(zip);
834 return 0;
835 }
836 }
837
838 cache_suspendzip(zip);
839
840 /* NS981003: support for "load by CRC" */
841 zip = cache_openzip(zipfile);
842 if (!zip)
843 return -1;
844
845 while (readzip(zip)) {
846 ent = &(zip->ent);
847
848 if (*sum && ent->crc32 == *sum)
849 {
850 *length = ent->uncompressed_size;
851 *sum = ent->crc32;
852 cache_suspendzip(zip);
853 return 0;
854 }
855 }
856
857 cache_suspendzip(zip);
858 return -1;
859 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26