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