annotate src/common/unzip.cpp @ 613:e1dcad3ce967

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