Skip to content

Latest commit

 

History

History
1696 lines (1370 loc) · 52.7 KB

physfs_archiver_zip.c

File metadata and controls

1696 lines (1370 loc) · 52.7 KB
 
Jul 7, 2001
Jul 7, 2001
1
2
3
/*
* ZIP support routines for PhysicsFS.
*
Mar 11, 2007
Mar 11, 2007
4
* Please see the file LICENSE.txt in the source's root directory.
Jul 7, 2001
Jul 7, 2001
5
*
Jul 13, 2002
Jul 13, 2002
6
7
* This file written by Ryan C. Gordon, with some peeking at "unzip.c"
* by Gilles Vollant.
Jul 7, 2001
Jul 7, 2001
8
9
*/
Mar 23, 2012
Mar 23, 2012
10
11
12
13
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
#if PHYSFS_SUPPORTS_ZIP
May 10, 2002
May 10, 2002
14
Jul 13, 2002
Jul 13, 2002
15
#include <errno.h>
Nov 22, 2002
Nov 22, 2002
16
#include <time.h>
Sep 6, 2010
Sep 6, 2010
17
Mar 10, 2012
Mar 10, 2012
18
19
#include "physfs_miniz.h"
Jul 13, 2002
Jul 13, 2002
20
/*
Mar 14, 2005
Mar 14, 2005
21
22
* A buffer of ZIP_READBUFSIZE is allocated for each compressed file opened,
* and is freed when you close the file; compressed data is read into
Jul 13, 2002
Jul 13, 2002
23
24
25
26
27
28
29
30
31
32
33
* this buffer, and then is decompressed into the buffer passed to
* PHYSFS_read().
*
* Uncompressed entries in a zipfile do not allocate this buffer; they just
* read data directly into the buffer passed to PHYSFS_read().
*
* Depending on your speed and memory requirements, you should tweak this
* value.
*/
#define ZIP_READBUFSIZE (16 * 1024)
Jul 23, 2002
Jul 23, 2002
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/*
* Entries are "unresolved" until they are first opened. At that time,
* local file headers parsed/validated, data offsets will be updated to look
* at the actual file data instead of the header, and symlinks will be
* followed and optimized. This means that we don't seek and read around the
* archive until forced to do so, and after the first time, we had to do
* less reading and parsing, which is very CD-ROM friendly.
*/
typedef enum
{
ZIP_UNRESOLVED_FILE,
ZIP_UNRESOLVED_SYMLINK,
ZIP_RESOLVING,
ZIP_RESOLVED,
Feb 25, 2016
Feb 25, 2016
49
ZIP_DIRECTORY,
Jul 23, 2002
Jul 23, 2002
50
ZIP_BROKEN_FILE,
Jan 31, 2003
Jan 31, 2003
51
ZIP_BROKEN_SYMLINK
Jul 23, 2002
Jul 23, 2002
52
53
54
} ZipResolveType;
Jul 13, 2002
Jul 13, 2002
55
56
57
/*
* One ZIPentry is kept for each file in an open ZIP archive.
*/
Jul 23, 2002
Jul 23, 2002
58
typedef struct _ZIPentry
Jul 15, 2001
Jul 15, 2001
59
{
Jul 15, 2017
Jul 15, 2017
60
__PHYSFS_DirTreeEntry tree; /* manages directory tree */
Jul 23, 2002
Jul 23, 2002
61
62
struct _ZIPentry *symlink; /* NULL or file we symlink to */
ZipResolveType resolved; /* Have we resolved file/symlink? */
Jun 1, 2012
Jun 1, 2012
63
PHYSFS_uint64 offset; /* offset of data in archive */
Jul 23, 2002
Jul 23, 2002
64
65
PHYSFS_uint16 version; /* version made by */
PHYSFS_uint16 version_needed; /* version needed to extract */
Sep 12, 2016
Sep 12, 2016
66
PHYSFS_uint16 general_bits; /* general purpose bits */
Jul 23, 2002
Jul 23, 2002
67
68
PHYSFS_uint16 compression_method; /* compression method */
PHYSFS_uint32 crc; /* crc-32 */
Jun 1, 2012
Jun 1, 2012
69
70
PHYSFS_uint64 compressed_size; /* compressed size */
PHYSFS_uint64 uncompressed_size; /* uncompressed size */
Jul 23, 2002
Jul 23, 2002
71
PHYSFS_sint64 last_mod_time; /* last file mod time */
Sep 12, 2016
Sep 12, 2016
72
PHYSFS_uint32 dos_mod_time; /* original MS-DOS style mod time */
Jul 28, 2001
Jul 28, 2001
73
74
} ZIPentry;
Jul 13, 2002
Jul 13, 2002
75
76
77
/*
* One ZIPinfo is kept for each open ZIP archive.
*/
Jul 28, 2001
Jul 28, 2001
78
79
typedef struct
{
Jul 15, 2017
Jul 15, 2017
80
__PHYSFS_DirTree tree; /* manages directory tree. */
Sep 12, 2016
Sep 12, 2016
81
82
83
PHYSFS_Io *io; /* the i/o interface for this archive. */
int zip64; /* non-zero if this is a Zip64 archive. */
int has_crypto; /* non-zero if any entry uses encryption. */
Jul 15, 2001
Jul 15, 2001
84
85
} ZIPinfo;
Jul 13, 2002
Jul 13, 2002
86
87
88
/*
* One ZIPfileinfo is kept for each open file in a ZIP archive.
*/
Jul 15, 2001
Jul 15, 2001
89
90
typedef struct
{
Jul 13, 2002
Jul 13, 2002
91
ZIPentry *entry; /* Info on file. */
Aug 30, 2010
Aug 30, 2010
92
PHYSFS_Io *io; /* physical file handle. */
Jul 13, 2002
Jul 13, 2002
93
94
95
PHYSFS_uint32 compressed_position; /* offset in compressed data. */
PHYSFS_uint32 uncompressed_position; /* tell() position. */
PHYSFS_uint8 *buffer; /* decompression buffer. */
Sep 12, 2016
Sep 12, 2016
96
97
PHYSFS_uint32 crypto_keys[3]; /* for "traditional" crypto. */
PHYSFS_uint32 initial_crypto_keys[3]; /* for "traditional" crypto. */
Jul 13, 2002
Jul 13, 2002
98
z_stream stream; /* zlib stream state. */
Jul 15, 2001
Jul 15, 2001
99
100
101
} ZIPfileinfo;
Jul 13, 2002
Jul 13, 2002
102
/* Magic numbers... */
Jun 1, 2012
Jun 1, 2012
103
104
105
106
107
108
#define ZIP_LOCAL_FILE_SIG 0x04034b50
#define ZIP_CENTRAL_DIR_SIG 0x02014b50
#define ZIP_END_OF_CENTRAL_DIR_SIG 0x06054b50
#define ZIP64_END_OF_CENTRAL_DIR_SIG 0x06064b50
#define ZIP64_END_OF_CENTRAL_DIRECTORY_LOCATOR_SIG 0x07064b50
#define ZIP64_EXTENDED_INFO_EXTRA_FIELD_SIG 0x0001
Jul 13, 2002
Jul 13, 2002
109
110
111
112
113
114
/* compression methods... */
#define COMPMETH_NONE 0
/* ...and others... */
Jul 15, 2002
Jul 15, 2002
115
116
117
#define UNIX_FILETYPE_MASK 0170000
#define UNIX_FILETYPE_SYMLINK 0120000
Sep 12, 2016
Sep 12, 2016
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#define ZIP_GENERAL_BITS_TRADITIONAL_CRYPTO (1 << 0)
#define ZIP_GENERAL_BITS_IGNORE_LOCAL_HEADER (1 << 3)
/* support for "traditional" PKWARE encryption. */
static int zip_entry_is_tradional_crypto(const ZIPentry *entry)
{
return (entry->general_bits & ZIP_GENERAL_BITS_TRADITIONAL_CRYPTO) != 0;
} /* zip_entry_is_traditional_crypto */
static int zip_entry_ignore_local_header(const ZIPentry *entry)
{
return (entry->general_bits & ZIP_GENERAL_BITS_IGNORE_LOCAL_HEADER) != 0;
} /* zip_entry_is_traditional_crypto */
static PHYSFS_uint32 zip_crypto_crc32(const PHYSFS_uint32 crc, const PHYSFS_uint8 val)
{
int i;
PHYSFS_uint32 xorval = (crc ^ ((PHYSFS_uint32) val)) & 0xFF;
for (i = 0; i < 8; i++)
xorval = ((xorval & 1) ? (0xEDB88320 ^ (xorval >> 1)) : (xorval >> 1));
return xorval ^ (crc >> 8);
} /* zip_crc32 */
static void zip_update_crypto_keys(PHYSFS_uint32 *keys, const PHYSFS_uint8 val)
{
keys[0] = zip_crypto_crc32(keys[0], val);
keys[1] = keys[1] + (keys[0] & 0x000000FF);
keys[1] = (keys[1] * 134775813) + 1;
keys[2] = zip_crypto_crc32(keys[2], (PHYSFS_uint8) ((keys[1] >> 24) & 0xFF));
} /* zip_update_crypto_keys */
static PHYSFS_uint8 zip_decrypt_byte(const PHYSFS_uint32 *keys)
{
const PHYSFS_uint16 tmp = keys[2] | 2;
return (PHYSFS_uint8) ((tmp * (tmp ^ 1)) >> 8);
} /* zip_decrypt_byte */
static PHYSFS_sint64 zip_read_decrypt(ZIPfileinfo *finfo, void *buf, PHYSFS_uint64 len)
{
PHYSFS_Io *io = finfo->io;
const PHYSFS_sint64 br = io->read(io, buf, len);
/* Decompression the new data if necessary. */
if (zip_entry_is_tradional_crypto(finfo->entry) && (br > 0))
{
PHYSFS_uint32 *keys = finfo->crypto_keys;
PHYSFS_uint8 *ptr = (PHYSFS_uint8 *) buf;
PHYSFS_sint64 i;
for (i = 0; i < br; i++, ptr++)
{
const PHYSFS_uint8 ch = *ptr ^ zip_decrypt_byte(keys);
zip_update_crypto_keys(keys, ch);
*ptr = ch;
} /* for */
} /* if */
return br;
} /* zip_read_decrypt */
static int zip_prep_crypto_keys(ZIPfileinfo *finfo, const PHYSFS_uint8 *crypto_header, const PHYSFS_uint8 *password)
{
/* It doesn't appear to be documented in PKWare's APPNOTE.TXT, but you
need to use a different byte in the header to verify the password
if general purpose bit 3 is set. Discovered this from Info-Zip.
That's what the (verifier) value is doing, below. */
PHYSFS_uint32 *keys = finfo->crypto_keys;
const ZIPentry *entry = finfo->entry;
const int usedate = zip_entry_ignore_local_header(entry);
const PHYSFS_uint8 verifier = (PHYSFS_uint8) ((usedate ? (entry->dos_mod_time >> 8) : (entry->crc >> 24)) & 0xFF);
PHYSFS_uint8 finalbyte = 0;
int i = 0;
/* initialize vector with defaults, then password, then header. */
keys[0] = 305419896;
keys[1] = 591751049;
keys[2] = 878082192;
while (*password)
zip_update_crypto_keys(keys, *(password++));
for (i = 0; i < 12; i++)
{
const PHYSFS_uint8 c = crypto_header[i] ^ zip_decrypt_byte(keys);
zip_update_crypto_keys(keys, c);
finalbyte = c;
} /* for */
/* you have a 1/256 chance of passing this test incorrectly. :/ */
if (finalbyte != verifier)
Jul 6, 2017
Jul 6, 2017
208
BAIL(PHYSFS_ERR_BAD_PASSWORD, 0);
Sep 12, 2016
Sep 12, 2016
209
210
211
212
213
214
/* save the initial vector for seeking purposes. Not secure!! */
memcpy(finfo->initial_crypto_keys, finfo->crypto_keys, 12);
return 1;
} /* zip_prep_crypto_keys */
Jul 15, 2002
Jul 15, 2002
215
Sep 23, 2004
Sep 23, 2004
216
217
218
219
220
/*
* Bridge physfs allocation functions to zlib's format...
*/
static voidpf zlibPhysfsAlloc(voidpf opaque, uInt items, uInt size)
{
Jan 28, 2010
Jan 28, 2010
221
return ((PHYSFS_Allocator *) opaque)->Malloc(items * size);
Sep 23, 2004
Sep 23, 2004
222
223
224
225
226
227
228
} /* zlibPhysfsAlloc */
/*
* Bridge physfs allocation functions to zlib's format...
*/
static void zlibPhysfsFree(voidpf opaque, voidpf address)
{
Mar 14, 2005
Mar 14, 2005
229
((PHYSFS_Allocator *) opaque)->Free(address);
Sep 23, 2004
Sep 23, 2004
230
231
232
233
234
235
236
237
238
239
240
} /* zlibPhysfsFree */
/*
* Construct a new z_stream to a sane state.
*/
static void initializeZStream(z_stream *pstr)
{
memset(pstr, '\0', sizeof (z_stream));
pstr->zalloc = zlibPhysfsAlloc;
pstr->zfree = zlibPhysfsFree;
Mar 14, 2005
Mar 14, 2005
241
pstr->opaque = &allocator;
Sep 23, 2004
Sep 23, 2004
242
243
244
} /* initializeZStream */
Mar 20, 2012
Mar 20, 2012
245
static PHYSFS_ErrorCode zlib_error_code(int rc)
Jul 13, 2002
Jul 13, 2002
246
247
248
{
switch (rc)
{
Mar 20, 2012
Mar 20, 2012
249
250
251
252
253
case Z_OK: return PHYSFS_ERR_OK; /* not an error. */
case Z_STREAM_END: return PHYSFS_ERR_OK; /* not an error. */
case Z_ERRNO: return PHYSFS_ERR_IO;
case Z_MEM_ERROR: return PHYSFS_ERR_OUT_OF_MEMORY;
default: return PHYSFS_ERR_CORRUPT;
Jul 13, 2002
Jul 13, 2002
254
} /* switch */
Jul 28, 2002
Jul 28, 2002
255
256
} /* zlib_error_string */
Jul 13, 2002
Jul 13, 2002
257
Jul 28, 2002
Jul 28, 2002
258
259
260
/*
* Wrap all zlib calls in this, so the physfs error state is set appropriately.
*/
Mar 20, 2012
Mar 20, 2012
261
static int zlib_err(const int rc)
Jul 28, 2002
Jul 28, 2002
262
{
Nov 30, 2012
Nov 30, 2012
263
PHYSFS_setErrorCode(zlib_error_code(rc));
Jan 28, 2010
Jan 28, 2010
264
return rc;
Jul 13, 2002
Jul 13, 2002
265
266
} /* zlib_err */
Jun 1, 2012
Jun 1, 2012
267
268
269
270
271
272
/*
* Read an unsigned 64-bit int and swap to native byte order.
*/
static int readui64(PHYSFS_Io *io, PHYSFS_uint64 *val)
{
PHYSFS_uint64 v;
Jul 6, 2017
Jul 6, 2017
273
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
Jun 1, 2012
Jun 1, 2012
274
275
276
277
*val = PHYSFS_swapULE64(v);
return 1;
} /* readui64 */
Jul 13, 2002
Jul 13, 2002
278
279
280
/*
* Read an unsigned 32-bit int and swap to native byte order.
*/
Aug 30, 2010
Aug 30, 2010
281
static int readui32(PHYSFS_Io *io, PHYSFS_uint32 *val)
Jul 13, 2002
Jul 13, 2002
282
283
{
PHYSFS_uint32 v;
Jul 6, 2017
Jul 6, 2017
284
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
Jul 13, 2002
Jul 13, 2002
285
*val = PHYSFS_swapULE32(v);
Jan 28, 2010
Jan 28, 2010
286
return 1;
Jul 13, 2002
Jul 13, 2002
287
288
289
290
291
292
} /* readui32 */
/*
* Read an unsigned 16-bit int and swap to native byte order.
*/
Aug 30, 2010
Aug 30, 2010
293
static int readui16(PHYSFS_Io *io, PHYSFS_uint16 *val)
Jul 13, 2002
Jul 13, 2002
294
295
{
PHYSFS_uint16 v;
Jul 6, 2017
Jul 6, 2017
296
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
Jul 13, 2002
Jul 13, 2002
297
*val = PHYSFS_swapULE16(v);
Jan 28, 2010
Jan 28, 2010
298
return 1;
Jul 13, 2002
Jul 13, 2002
299
300
301
} /* readui16 */
Aug 30, 2010
Aug 30, 2010
302
static PHYSFS_sint64 ZIP_read(PHYSFS_Io *_io, void *buf, PHYSFS_uint64 len)
Jul 8, 2001
Jul 8, 2001
303
{
Aug 30, 2010
Aug 30, 2010
304
ZIPfileinfo *finfo = (ZIPfileinfo *) _io->opaque;
Jul 13, 2002
Jul 13, 2002
305
306
ZIPentry *entry = finfo->entry;
PHYSFS_sint64 retval = 0;
Aug 21, 2010
Aug 21, 2010
307
PHYSFS_sint64 maxread = (PHYSFS_sint64) len;
Jul 13, 2002
Jul 13, 2002
308
309
310
311
PHYSFS_sint64 avail = entry->uncompressed_size -
finfo->uncompressed_position;
if (avail < maxread)
Aug 21, 2010
Aug 21, 2010
312
maxread = avail;
Jul 13, 2002
Jul 13, 2002
313
Jul 6, 2017
Jul 6, 2017
314
BAIL_IF_ERRPASS(maxread == 0, 0); /* quick rejection. */
Jul 13, 2002
Jul 13, 2002
315
Aug 21, 2010
Aug 21, 2010
316
if (entry->compression_method == COMPMETH_NONE)
Sep 12, 2016
Sep 12, 2016
317
retval = zip_read_decrypt(finfo, buf, maxread);
Jul 13, 2002
Jul 13, 2002
318
319
320
else
{
finfo->stream.next_out = buf;
Mar 10, 2012
Mar 10, 2012
321
finfo->stream.avail_out = (uInt) maxread;
Jul 13, 2002
Jul 13, 2002
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
while (retval < maxread)
{
PHYSFS_uint32 before = finfo->stream.total_out;
int rc;
if (finfo->stream.avail_in == 0)
{
PHYSFS_sint64 br;
br = entry->compressed_size - finfo->compressed_position;
if (br > 0)
{
if (br > ZIP_READBUFSIZE)
br = ZIP_READBUFSIZE;
Sep 12, 2016
Sep 12, 2016
338
br = zip_read_decrypt(finfo, finfo->buffer, (PHYSFS_uint64) br);
Jul 13, 2002
Jul 13, 2002
339
340
341
if (br <= 0)
break;
Mar 12, 2003
Mar 12, 2003
342
finfo->compressed_position += (PHYSFS_uint32) br;
Jul 13, 2002
Jul 13, 2002
343
finfo->stream.next_in = finfo->buffer;
Jul 13, 2017
Jul 13, 2017
344
finfo->stream.avail_in = (unsigned int) br;
Jul 13, 2002
Jul 13, 2002
345
346
} /* if */
} /* if */
Jul 23, 2001
Jul 23, 2001
347
Jul 13, 2002
Jul 13, 2002
348
349
rc = zlib_err(inflate(&finfo->stream, Z_SYNC_FLUSH));
retval += (finfo->stream.total_out - before);
Jul 23, 2001
Jul 23, 2001
350
Jul 13, 2002
Jul 13, 2002
351
352
353
354
355
356
if (rc != Z_OK)
break;
} /* while */
} /* else */
if (retval > 0)
Aug 21, 2010
Aug 21, 2010
357
finfo->uncompressed_position += (PHYSFS_uint32) retval;
Jul 13, 2002
Jul 13, 2002
358
Jan 28, 2010
Jan 28, 2010
359
return retval;
Jul 8, 2001
Jul 8, 2001
360
361
362
} /* ZIP_read */
Aug 30, 2010
Aug 30, 2010
363
static PHYSFS_sint64 ZIP_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len)
Aug 21, 2002
Aug 21, 2002
364
{
Jul 6, 2017
Jul 6, 2017
365
BAIL(PHYSFS_ERR_READ_ONLY, -1);
Aug 21, 2002
Aug 21, 2002
366
367
368
} /* ZIP_write */
Aug 30, 2010
Aug 30, 2010
369
static PHYSFS_sint64 ZIP_tell(PHYSFS_Io *io)
Jul 8, 2001
Jul 8, 2001
370
{
Aug 30, 2010
Aug 30, 2010
371
return ((ZIPfileinfo *) io->opaque)->uncompressed_position;
Jul 8, 2001
Jul 8, 2001
372
373
374
} /* ZIP_tell */
Aug 30, 2010
Aug 30, 2010
375
static int ZIP_seek(PHYSFS_Io *_io, PHYSFS_uint64 offset)
Jul 8, 2001
Jul 8, 2001
376
{
Aug 30, 2010
Aug 30, 2010
377
ZIPfileinfo *finfo = (ZIPfileinfo *) _io->opaque;
Jul 13, 2002
Jul 13, 2002
378
ZIPentry *entry = finfo->entry;
Aug 30, 2010
Aug 30, 2010
379
PHYSFS_Io *io = finfo->io;
Sep 12, 2016
Sep 12, 2016
380
const int encrypted = zip_entry_is_tradional_crypto(entry);
Jul 23, 2001
Jul 23, 2001
381
Jul 6, 2017
Jul 6, 2017
382
BAIL_IF(offset > entry->uncompressed_size, PHYSFS_ERR_PAST_EOF, 0);
Jul 23, 2001
Jul 23, 2001
383
Sep 12, 2016
Sep 12, 2016
384
if (!encrypted && (entry->compression_method == COMPMETH_NONE))
Jul 23, 2001
Jul 23, 2001
385
{
Sep 12, 2016
Sep 12, 2016
386
PHYSFS_sint64 newpos = offset + entry->offset;
Jul 6, 2017
Jul 6, 2017
387
BAIL_IF_ERRPASS(!io->seek(io, newpos), 0);
Mar 30, 2003
Mar 30, 2003
388
finfo->uncompressed_position = (PHYSFS_uint32) offset;
Jul 13, 2002
Jul 13, 2002
389
} /* if */
Jul 23, 2001
Jul 23, 2001
390
Jul 13, 2002
Jul 13, 2002
391
else
Jul 23, 2001
Jul 23, 2001
392
{
Jul 13, 2002
Jul 13, 2002
393
394
395
396
/*
* If seeking backwards, we need to redecode the file
* from the start and throw away the compressed bits until we hit
* the offset we need. If seeking forward, we still need to
Jul 23, 2002
Jul 23, 2002
397
* decode, but we don't rewind first.
Jul 13, 2002
Jul 13, 2002
398
399
400
401
402
*/
if (offset < finfo->uncompressed_position)
{
/* we do a copy so state is sane if inflateInit2() fails. */
z_stream str;
Sep 23, 2004
Sep 23, 2004
403
initializeZStream(&str);
Jul 13, 2002
Jul 13, 2002
404
if (zlib_err(inflateInit2(&str, -MAX_WBITS)) != Z_OK)
Jan 28, 2010
Jan 28, 2010
405
return 0;
Jul 13, 2002
Jul 13, 2002
406
Sep 12, 2016
Sep 12, 2016
407
if (!io->seek(io, entry->offset + (encrypted ? 12 : 0)))
Jan 28, 2010
Jan 28, 2010
408
return 0;
Jul 17, 2002
Jul 17, 2002
409
Jul 13, 2002
Jul 13, 2002
410
411
412
inflateEnd(&finfo->stream);
memcpy(&finfo->stream, &str, sizeof (z_stream));
finfo->uncompressed_position = finfo->compressed_position = 0;
Sep 12, 2016
Sep 12, 2016
413
414
415
if (encrypted)
memcpy(finfo->crypto_keys, finfo->initial_crypto_keys, 12);
Jul 13, 2002
Jul 13, 2002
416
417
418
419
420
} /* if */
while (finfo->uncompressed_position != offset)
{
PHYSFS_uint8 buf[512];
Mar 12, 2003
Mar 12, 2003
421
422
423
PHYSFS_uint32 maxread;
maxread = (PHYSFS_uint32) (offset - finfo->uncompressed_position);
Jul 13, 2002
Jul 13, 2002
424
425
426
if (maxread > sizeof (buf))
maxread = sizeof (buf);
Aug 30, 2010
Aug 30, 2010
427
if (ZIP_read(_io, buf, maxread) != maxread)
Jan 28, 2010
Jan 28, 2010
428
return 0;
Jul 13, 2002
Jul 13, 2002
429
430
431
} /* while */
} /* else */
Jan 28, 2010
Jan 28, 2010
432
return 1;
Jul 8, 2001
Jul 8, 2001
433
434
435
} /* ZIP_seek */
Aug 30, 2010
Aug 30, 2010
436
static PHYSFS_sint64 ZIP_length(PHYSFS_Io *io)
Jul 9, 2001
Jul 9, 2001
437
{
Aug 30, 2010
Aug 30, 2010
438
const ZIPfileinfo *finfo = (ZIPfileinfo *) io->opaque;
Jun 1, 2012
Jun 1, 2012
439
return (PHYSFS_sint64) finfo->entry->uncompressed_size;
Aug 30, 2010
Aug 30, 2010
440
} /* ZIP_length */
Jul 9, 2001
Jul 9, 2001
441
442
Aug 30, 2010
Aug 30, 2010
443
444
445
static PHYSFS_Io *zip_get_io(PHYSFS_Io *io, ZIPinfo *inf, ZIPentry *entry);
static PHYSFS_Io *ZIP_duplicate(PHYSFS_Io *io)
Jul 8, 2001
Jul 8, 2001
446
{
Aug 30, 2010
Aug 30, 2010
447
448
449
ZIPfileinfo *origfinfo = (ZIPfileinfo *) io->opaque;
PHYSFS_Io *retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
ZIPfileinfo *finfo = (ZIPfileinfo *) allocator.Malloc(sizeof (ZIPfileinfo));
Jul 6, 2017
Jul 6, 2017
450
451
GOTO_IF(!retval, PHYSFS_ERR_OUT_OF_MEMORY, failed);
GOTO_IF(!finfo, PHYSFS_ERR_OUT_OF_MEMORY, failed);
Aug 30, 2010
Aug 30, 2010
452
453
454
455
memset(finfo, '\0', sizeof (*finfo));
finfo->entry = origfinfo->entry;
finfo->io = zip_get_io(origfinfo->io, NULL, finfo->entry);
Jul 6, 2017
Jul 6, 2017
456
GOTO_IF_ERRPASS(!finfo->io, failed);
Aug 30, 2010
Aug 30, 2010
457
458
459
460
if (finfo->entry->compression_method != COMPMETH_NONE)
{
finfo->buffer = (PHYSFS_uint8 *) allocator.Malloc(ZIP_READBUFSIZE);
Jul 6, 2017
Jul 6, 2017
461
GOTO_IF(!finfo->buffer, PHYSFS_ERR_OUT_OF_MEMORY, failed);
Mar 24, 2012
Mar 24, 2012
462
463
if (zlib_err(inflateInit2(&finfo->stream, -MAX_WBITS)) != Z_OK)
goto failed;
Aug 30, 2010
Aug 30, 2010
464
465
466
467
468
469
} /* if */
memcpy(retval, io, sizeof (PHYSFS_Io));
retval->opaque = finfo;
return retval;
Mar 24, 2012
Mar 24, 2012
470
failed:
Aug 30, 2010
Aug 30, 2010
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
if (finfo != NULL)
{
if (finfo->io != NULL)
finfo->io->destroy(finfo->io);
if (finfo->buffer != NULL)
{
allocator.Free(finfo->buffer);
inflateEnd(&finfo->stream);
} /* if */
allocator.Free(finfo);
} /* if */
if (retval != NULL)
allocator.Free(retval);
return NULL;
} /* ZIP_duplicate */
static int ZIP_flush(PHYSFS_Io *io) { return 1; /* no write support. */ }
static void ZIP_destroy(PHYSFS_Io *io)
{
ZIPfileinfo *finfo = (ZIPfileinfo *) io->opaque;
finfo->io->destroy(finfo->io);
Jul 13, 2002
Jul 13, 2002
497
498
499
500
501
if (finfo->entry->compression_method != COMPMETH_NONE)
inflateEnd(&finfo->stream);
if (finfo->buffer != NULL)
Mar 14, 2005
Mar 14, 2005
502
allocator.Free(finfo->buffer);
Jul 13, 2002
Jul 13, 2002
503
Mar 14, 2005
Mar 14, 2005
504
allocator.Free(finfo);
Aug 30, 2010
Aug 30, 2010
505
506
507
508
509
510
allocator.Free(io);
} /* ZIP_destroy */
static const PHYSFS_Io ZIP_Io =
{
Mar 25, 2012
Mar 25, 2012
511
CURRENT_PHYSFS_IO_API_VERSION, NULL,
Aug 30, 2010
Aug 30, 2010
512
513
514
515
516
517
518
ZIP_read,
ZIP_write,
ZIP_seek,
ZIP_tell,
ZIP_length,
ZIP_duplicate,
ZIP_flush,
Mar 25, 2012
Mar 25, 2012
519
ZIP_destroy
Aug 30, 2010
Aug 30, 2010
520
521
};
Jul 8, 2001
Jul 8, 2001
522
523
Aug 30, 2010
Aug 30, 2010
524
static PHYSFS_sint64 zip_find_end_of_central_dir(PHYSFS_Io *io, PHYSFS_sint64 *len)
Jul 13, 2002
Jul 13, 2002
525
{
Jul 23, 2002
Jul 23, 2002
526
PHYSFS_uint8 buf[256];
Mar 25, 2010
Mar 25, 2010
527
PHYSFS_uint8 extra[4] = { 0, 0, 0, 0 };
Jul 27, 2002
Jul 27, 2002
528
PHYSFS_sint32 i = 0;
Jul 13, 2002
Jul 13, 2002
529
530
531
PHYSFS_sint64 filelen;
PHYSFS_sint64 filepos;
PHYSFS_sint32 maxread;
Jul 23, 2002
Jul 23, 2002
532
533
PHYSFS_sint32 totalread = 0;
int found = 0;
Jul 13, 2002
Jul 13, 2002
534
Aug 30, 2010
Aug 30, 2010
535
filelen = io->length(io);
Jul 6, 2017
Jul 6, 2017
536
BAIL_IF_ERRPASS(filelen == -1, -1);
Jul 13, 2002
Jul 13, 2002
537
538
539
540
541
542
543
544
545
/*
* Jump to the end of the file and start reading backwards.
* The last thing in the file is the zipfile comment, which is variable
* length, and the field that specifies its size is before it in the
* file (argh!)...this means that we need to scan backwards until we
* hit the end-of-central-dir signature. We can then sanity check that
* the comment was as big as it should be to make sure we're in the
* right place. The comment length field is 16 bits, so we can stop
Jul 23, 2002
Jul 23, 2002
546
547
* searching for that signature after a little more than 64k at most,
* and call it a corrupted zipfile.
Jul 13, 2002
Jul 13, 2002
548
549
550
551
552
553
554
555
556
557
*/
if (sizeof (buf) < filelen)
{
filepos = filelen - sizeof (buf);
maxread = sizeof (buf);
} /* if */
else
{
filepos = 0;
Mar 12, 2003
Mar 12, 2003
558
maxread = (PHYSFS_uint32) filelen;
Jul 13, 2002
Jul 13, 2002
559
560
} /* else */
Jul 23, 2002
Jul 23, 2002
561
while ((totalread < filelen) && (totalread < 65557))
Jul 13, 2002
Jul 13, 2002
562
{
Jul 6, 2017
Jul 6, 2017
563
BAIL_IF_ERRPASS(!io->seek(io, filepos), -1);
Jul 23, 2002
Jul 23, 2002
564
565
566
/* make sure we catch a signature between buffers. */
if (totalread != 0)
Jul 13, 2002
Jul 13, 2002
567
{
Mar 9, 2012
Mar 9, 2012
568
if (!__PHYSFS_readAll(io, buf, maxread - 4))
Jan 28, 2010
Jan 28, 2010
569
return -1;
May 3, 2009
May 3, 2009
570
memcpy(&buf[maxread - 4], &extra, sizeof (extra));
Jul 23, 2002
Jul 23, 2002
571
totalread += maxread - 4;
Jul 13, 2002
Jul 13, 2002
572
} /* if */
Jul 23, 2002
Jul 23, 2002
573
574
else
{
Mar 9, 2012
Mar 9, 2012
575
if (!__PHYSFS_readAll(io, buf, maxread))
Jan 28, 2010
Jan 28, 2010
576
return -1;
Jul 23, 2002
Jul 23, 2002
577
578
579
totalread += maxread;
} /* else */
May 3, 2009
May 3, 2009
580
memcpy(&extra, buf, sizeof (extra));
Jul 13, 2002
Jul 13, 2002
581
Jul 23, 2002
Jul 23, 2002
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
for (i = maxread - 4; i > 0; i--)
{
if ((buf[i + 0] == 0x50) &&
(buf[i + 1] == 0x4B) &&
(buf[i + 2] == 0x05) &&
(buf[i + 3] == 0x06) )
{
found = 1; /* that's the signature! */
break;
} /* if */
} /* for */
if (found)
break;
filepos -= (maxread - 4);
May 5, 2007
May 5, 2007
598
599
if (filepos < 0)
filepos = 0;
Jul 23, 2002
Jul 23, 2002
600
601
} /* while */
Jul 6, 2017
Jul 6, 2017
602
BAIL_IF(!found, PHYSFS_ERR_UNSUPPORTED, -1);
Jul 13, 2002
Jul 13, 2002
603
604
605
606
if (len != NULL)
*len = filelen;
Jan 28, 2010
Jan 28, 2010
607
return (filepos + i);
Jul 23, 2002
Jul 23, 2002
608
} /* zip_find_end_of_central_dir */
Jul 13, 2002
Jul 13, 2002
609
610
Aug 30, 2010
Aug 30, 2010
611
static int isZip(PHYSFS_Io *io)
Jul 8, 2001
Jul 8, 2001
612
{
Aug 30, 2010
Aug 30, 2010
613
PHYSFS_uint32 sig = 0;
Jul 31, 2002
Jul 31, 2002
614
int retval = 0;
Jul 13, 2002
Jul 13, 2002
615
616
617
618
619
/*
* The first thing in a zip file might be the signature of the
* first local file record, so it makes for a quick determination.
*/
Aug 30, 2010
Aug 30, 2010
620
if (readui32(io, &sig))
Jul 15, 2001
Jul 15, 2001
621
{
Jul 31, 2002
Jul 31, 2002
622
623
624
625
626
627
628
629
retval = (sig == ZIP_LOCAL_FILE_SIG);
if (!retval)
{
/*
* No sig...might be a ZIP with data at the start
* (a self-extracting executable, etc), so we'll have to do
* it the hard way...
*/
Aug 30, 2010
Aug 30, 2010
630
retval = (zip_find_end_of_central_dir(io, NULL) != -1);
Jul 31, 2002
Jul 31, 2002
631
} /* if */
Jul 15, 2001
Jul 15, 2001
632
633
} /* if */
Jan 28, 2010
Jan 28, 2010
634
return retval;
Aug 24, 2010
Aug 24, 2010
635
} /* isZip */
Jul 8, 2001
Jul 8, 2001
636
637
Jul 23, 2002
Jul 23, 2002
638
/* Convert paths from old, buggy DOS zippers... */
Jul 15, 2017
Jul 15, 2017
639
static void zip_convert_dos_path(const PHYSFS_uint16 entryversion, char *path)
Jul 23, 2002
Jul 23, 2002
640
{
Jul 15, 2017
Jul 15, 2017
641
const PHYSFS_uint8 hosttype = (PHYSFS_uint8) ((entryversion >> 8) & 0xFF);
Jul 23, 2002
Jul 23, 2002
642
643
644
645
646
647
648
649
650
651
if (hosttype == 0) /* FS_FAT_ */
{
while (*path)
{
if (*path == '\\')
*path = '/';
path++;
} /* while */
} /* if */
} /* zip_convert_dos_path */
Jul 13, 2002
Jul 13, 2002
652
653
Jul 23, 2002
Jul 23, 2002
654
static void zip_expand_symlink_path(char *path)
Jul 8, 2001
Jul 8, 2001
655
{
Jul 23, 2002
Jul 23, 2002
656
657
char *ptr = path;
char *prevptr = path;
Jul 15, 2001
Jul 15, 2001
658
Jul 23, 2002
Jul 23, 2002
659
while (1)
Jul 28, 2001
Jul 28, 2001
660
{
Jul 23, 2002
Jul 23, 2002
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
ptr = strchr(ptr, '/');
if (ptr == NULL)
break;
if (*(ptr + 1) == '.')
{
if (*(ptr + 2) == '/')
{
/* current dir in middle of string: ditch it. */
memmove(ptr, ptr + 2, strlen(ptr + 2) + 1);
} /* else if */
else if (*(ptr + 2) == '\0')
{
/* current dir at end of string: ditch it. */
*ptr = '\0';
} /* else if */
else if (*(ptr + 2) == '.')
{
if (*(ptr + 3) == '/')
{
/* parent dir in middle: move back one, if possible. */
memmove(prevptr, ptr + 4, strlen(ptr + 4) + 1);
ptr = prevptr;
while (prevptr != path)
{
prevptr--;
if (*prevptr == '/')
{
prevptr++;
break;
} /* if */
} /* while */
} /* if */
Jul 15, 2001
Jul 15, 2001
696
Jul 23, 2002
Jul 23, 2002
697
698
699
700
701
702
703
704
705
706
if (*(ptr + 3) == '\0')
{
/* parent dir at end: move back one, if possible. */
*prevptr = '\0';
} /* if */
} /* if */
} /* if */
else
{
prevptr = ptr;
Jun 1, 2011
Jun 1, 2011
707
ptr++;
Jul 23, 2002
Jul 23, 2002
708
709
710
} /* else */
} /* while */
} /* zip_expand_symlink_path */
Jul 15, 2001
Jul 15, 2001
711
Jul 15, 2017
Jul 15, 2017
712
713
714
715
716
static inline ZIPentry *zip_find_entry(ZIPinfo *info, const char *path)
{
return (ZIPentry *) __PHYSFS_DirTreeFind(&info->tree, path);
} /* zip_find_entry */
Sep 29, 2004
Sep 29, 2004
717
/* (forward reference: zip_follow_symlink and zip_resolve call each other.) */
Aug 30, 2010
Aug 30, 2010
718
static int zip_resolve(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry);
Jul 15, 2001
Jul 15, 2001
719
Mar 29, 2002
Mar 29, 2002
720
/*
Jul 23, 2002
Jul 23, 2002
721
722
723
* Look for the entry named by (path). If it exists, resolve it, and return
* a pointer to that entry. If it's another symlink, keep resolving until you
* hit a real file and then return a pointer to the final non-symlink entry.
Mar 24, 2012
Mar 24, 2012
724
* If there's a problem, return NULL.
Mar 29, 2002
Mar 29, 2002
725
*/
Aug 30, 2010
Aug 30, 2010
726
static ZIPentry *zip_follow_symlink(PHYSFS_Io *io, ZIPinfo *info, char *path)
Jul 28, 2001
Jul 28, 2001
727
{
Jul 23, 2002
Jul 23, 2002
728
729
730
ZIPentry *entry;
zip_expand_symlink_path(path);
Feb 25, 2016
Feb 25, 2016
731
entry = zip_find_entry(info, path);
Jul 23, 2002
Jul 23, 2002
732
733
if (entry != NULL)
{
Aug 30, 2010
Aug 30, 2010
734
if (!zip_resolve(io, info, entry)) /* recursive! */
Jul 23, 2002
Jul 23, 2002
735
736
737
738
739
740
741
742
entry = NULL;
else
{
if (entry->symlink != NULL)
entry = entry->symlink;
} /* else */
} /* if */
Jan 28, 2010
Jan 28, 2010
743
return entry;
Jul 23, 2002
Jul 23, 2002
744
} /* zip_follow_symlink */
Jul 8, 2001
Jul 8, 2001
745
746
Aug 30, 2010
Aug 30, 2010
747
static int zip_resolve_symlink(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry)
Jul 23, 2001
Jul 23, 2001
748
{
Jun 1, 2012
Jun 1, 2012
749
const PHYSFS_uint64 size = entry->uncompressed_size;
Mar 24, 2012
Mar 24, 2012
750
char *path = NULL;
Jul 13, 2002
Jul 13, 2002
751
752
int rc = 0;
Jul 23, 2002
Jul 23, 2002
753
754
755
756
757
758
/*
* We've already parsed the local file header of the symlink at this
* point. Now we need to read the actual link from the file data and
* follow it.
*/
Jul 6, 2017
Jul 6, 2017
759
BAIL_IF_ERRPASS(!io->seek(io, entry->offset), 0);
Jul 23, 2002
Jul 23, 2002
760
Mar 24, 2012
Mar 24, 2012
761
path = (char *) __PHYSFS_smallAlloc(size + 1);
Jul 6, 2017
Jul 6, 2017
762
BAIL_IF(!path, PHYSFS_ERR_OUT_OF_MEMORY, 0);
Jul 13, 2002
Jul 13, 2002
763
764
if (entry->compression_method == COMPMETH_NONE)
Mar 9, 2012
Mar 9, 2012
765
rc = __PHYSFS_readAll(io, path, size);
Jul 13, 2002
Jul 13, 2002
766
767
768
769
else /* symlink target path is compressed... */
{
z_stream stream;
Jun 1, 2012
Jun 1, 2012
770
const PHYSFS_uint64 complen = entry->compressed_size;
Mar 24, 2007
Mar 24, 2007
771
PHYSFS_uint8 *compressed = (PHYSFS_uint8*) __PHYSFS_smallAlloc(complen);
Jul 13, 2002
Jul 13, 2002
772
773
if (compressed != NULL)
{
Mar 9, 2012
Mar 9, 2012
774
if (__PHYSFS_readAll(io, compressed, complen))
Jul 13, 2002
Jul 13, 2002
775
{
Sep 23, 2004
Sep 23, 2004
776
initializeZStream(&stream);
Jul 13, 2002
Jul 13, 2002
777
stream.next_in = compressed;
Jul 13, 2017
Jul 13, 2017
778
stream.avail_in = (unsigned int) complen;
Jan 31, 2003
Jan 31, 2003
779
stream.next_out = (unsigned char *) path;
Jul 13, 2017
Jul 13, 2017
780
stream.avail_out = (unsigned int) size;
Jul 13, 2002
Jul 13, 2002
781
782
if (zlib_err(inflateInit2(&stream, -MAX_WBITS)) == Z_OK)
{
Jul 15, 2002
Jul 15, 2002
783
rc = zlib_err(inflate(&stream, Z_FINISH));
Jul 13, 2002
Jul 13, 2002
784
inflateEnd(&stream);
Jul 15, 2002
Jul 15, 2002
785
786
787
/* both are acceptable outcomes... */
rc = ((rc == Z_OK) || (rc == Z_STREAM_END));
Jul 13, 2002
Jul 13, 2002
788
789
} /* if */
} /* if */
Mar 24, 2007
Mar 24, 2007
790
__PHYSFS_smallFree(compressed);
Jul 13, 2002
Jul 13, 2002
791
792
} /* if */
} /* else */
Mar 29, 2002
Mar 29, 2002
793
Mar 24, 2012
Mar 24, 2012
794
if (rc)
Jul 23, 2002
Jul 23, 2002
795
796
{
path[entry->uncompressed_size] = '\0'; /* null-terminate it. */
Jul 15, 2017
Jul 15, 2017
797
zip_convert_dos_path(entry->version, path);
Aug 30, 2010
Aug 30, 2010
798
entry->symlink = zip_follow_symlink(io, info, path);
Jul 23, 2002
Jul 23, 2002
799
800
} /* else */
Mar 24, 2012
Mar 24, 2012
801
802
__PHYSFS_smallFree(path);
Jan 28, 2010
Jan 28, 2010
803
return (entry->symlink != NULL);
Jul 23, 2002
Jul 23, 2002
804
805
806
807
808
809
} /* zip_resolve_symlink */
/*
* Parse the local file header of an entry, and update entry->offset.
*/
Aug 30, 2010
Aug 30, 2010
810
static int zip_parse_local(PHYSFS_Io *io, ZIPentry *entry)
Jul 23, 2002
Jul 23, 2002
811
812
813
814
815
816
{
PHYSFS_uint32 ui32;
PHYSFS_uint16 ui16;
PHYSFS_uint16 fnamelen;
PHYSFS_uint16 extralen;
Mar 30, 2003
Mar 30, 2003
817
818
819
820
821
/*
* crc and (un)compressed_size are always zero if this is a "JAR"
* archive created with Sun's Java tools, apparently. We only
* consider this archive corrupted if those entries don't match and
* aren't zero. That seems to work well.
Jun 1, 2012
Jun 1, 2012
822
823
* We also ignore a mismatch if the value is 0xFFFFFFFF here, since it's
* possible that's a Zip64 thing.
Mar 30, 2003
Mar 30, 2003
824
825
*/
Sep 12, 2016
Sep 12, 2016
826
827
828
829
/* !!! FIXME: apparently these are zero if general purpose bit 3 is set,
!!! FIXME: which is probably true for Jar files, fwiw, but we don't
!!! FIXME: care about these values anyhow. */
Jul 6, 2017
Jul 6, 2017
830
831
832
833
834
835
836
837
838
839
840
841
842
843
BAIL_IF_ERRPASS(!io->seek(io, entry->offset), 0);
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
BAIL_IF(ui32 != ZIP_LOCAL_FILE_SIG, PHYSFS_ERR_CORRUPT, 0);
BAIL_IF_ERRPASS(!readui16(io, &ui16), 0);
BAIL_IF(ui16 != entry->version_needed, PHYSFS_ERR_CORRUPT, 0);
BAIL_IF_ERRPASS(!readui16(io, &ui16), 0); /* general bits. */
BAIL_IF_ERRPASS(!readui16(io, &ui16), 0);
BAIL_IF(ui16 != entry->compression_method, PHYSFS_ERR_CORRUPT, 0);
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0); /* date/time */
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
BAIL_IF(ui32 && (ui32 != entry->crc), PHYSFS_ERR_CORRUPT, 0);
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
BAIL_IF(ui32 && (ui32 != 0xFFFFFFFF) &&
Jun 1, 2012
Jun 1, 2012
844
845
(ui32 != entry->compressed_size), PHYSFS_ERR_CORRUPT, 0);
Jul 6, 2017
Jul 6, 2017
846
847
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
BAIL_IF(ui32 && (ui32 != 0xFFFFFFFF) &&
Jun 1, 2012
Jun 1, 2012
848
849
(ui32 != entry->uncompressed_size), PHYSFS_ERR_CORRUPT, 0);
Jul 6, 2017
Jul 6, 2017
850
851
BAIL_IF_ERRPASS(!readui16(io, &fnamelen), 0);
BAIL_IF_ERRPASS(!readui16(io, &extralen), 0);
Jul 23, 2002
Jul 23, 2002
852
853
entry->offset += fnamelen + extralen + 30;
Jan 28, 2010
Jan 28, 2010
854
return 1;
Jul 23, 2002
Jul 23, 2002
855
856
857
} /* zip_parse_local */
Aug 30, 2010
Aug 30, 2010
858
static int zip_resolve(PHYSFS_Io *io, ZIPinfo *info, ZIPentry *entry)
Jul 23, 2002
Jul 23, 2002
859
860
{
int retval = 1;
Feb 25, 2016
Feb 25, 2016
861
862
863
864
const ZipResolveType resolve_type = entry->resolved;
if (resolve_type == ZIP_DIRECTORY)
return 1; /* we're good. */
Jul 23, 2002
Jul 23, 2002
865
866
/* Don't bother if we've failed to resolve this entry before. */
Jul 6, 2017
Jul 6, 2017
867
868
BAIL_IF(resolve_type == ZIP_BROKEN_FILE, PHYSFS_ERR_CORRUPT, 0);
BAIL_IF(resolve_type == ZIP_BROKEN_SYMLINK, PHYSFS_ERR_CORRUPT, 0);
Jul 23, 2002
Jul 23, 2002
869
870
/* uhoh...infinite symlink loop! */
Jul 6, 2017
Jul 6, 2017
871
BAIL_IF(resolve_type == ZIP_RESOLVING, PHYSFS_ERR_SYMLINK_LOOP, 0);
Jul 23, 2002
Jul 23, 2002
872
873
874
875
876
877
878
879
880
881
882
883
/*
* We fix up the offset to point to the actual data on the
* first open, since we don't want to seek across the whole file on
* archive open (can be SLOW on large, CD-stored files), but we
* need to check the local file header...not just for corruption,
* but since it stores offset info the central directory does not.
*/
if (resolve_type != ZIP_RESOLVED)
{
entry->resolved = ZIP_RESOLVING;
Aug 30, 2010
Aug 30, 2010
884
retval = zip_parse_local(io, entry);
Jul 23, 2002
Jul 23, 2002
885
886
887
888
889
890
891
892
if (retval)
{
/*
* If it's a symlink, find the original file. This will cause
* resolution of other entries (other symlinks and, eventually,
* the real file) if all goes well.
*/
if (resolve_type == ZIP_UNRESOLVED_SYMLINK)
Aug 30, 2010
Aug 30, 2010
893
retval = zip_resolve_symlink(io, info, entry);
Jul 23, 2002
Jul 23, 2002
894
895
896
897
898
899
} /* if */
if (resolve_type == ZIP_UNRESOLVED_SYMLINK)
entry->resolved = ((retval) ? ZIP_RESOLVED : ZIP_BROKEN_SYMLINK);
else if (resolve_type == ZIP_UNRESOLVED_FILE)
entry->resolved = ((retval) ? ZIP_RESOLVED : ZIP_BROKEN_FILE);
Jul 13, 2002
Jul 13, 2002
900
} /* if */
Mar 29, 2002
Mar 29, 2002
901
Jan 28, 2010
Jan 28, 2010
902
return retval;
Jul 23, 2002
Jul 23, 2002
903
} /* zip_resolve */
Jul 23, 2001
Jul 23, 2001
904
905
Feb 25, 2016
Feb 25, 2016
906
907
908
909
910
911
912
913
static int zip_entry_is_symlink(const ZIPentry *entry)
{
return ((entry->resolved == ZIP_UNRESOLVED_SYMLINK) ||
(entry->resolved == ZIP_BROKEN_SYMLINK) ||
(entry->symlink));
} /* zip_entry_is_symlink */
Jul 23, 2002
Jul 23, 2002
914
static int zip_version_does_symlinks(PHYSFS_uint32 version)
Jul 23, 2001
Jul 23, 2001
915
916
{
int retval = 0;
Apr 3, 2002
Apr 3, 2002
917
PHYSFS_uint8 hosttype = (PHYSFS_uint8) ((version >> 8) & 0xFF);
Jul 23, 2001
Jul 23, 2001
918
919
920
switch (hosttype)
{
Jul 15, 2002
Jul 15, 2002
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
/*
* These are the platforms that can NOT build an archive with
* symlinks, according to the Info-ZIP project.
*/
case 0: /* FS_FAT_ */
case 1: /* AMIGA_ */
case 2: /* VMS_ */
case 4: /* VM_CSM_ */
case 6: /* FS_HPFS_ */
case 11: /* FS_NTFS_ */
case 14: /* FS_VFAT_ */
case 13: /* ACORN_ */
case 15: /* MVS_ */
case 18: /* THEOS_ */
break; /* do nothing. */
default: /* assume the rest to be unix-like. */
Jul 23, 2001
Jul 23, 2001
938
939
940
941
retval = 1;
break;
} /* switch */
Jan 28, 2010
Jan 28, 2010
942
return retval;
Jul 23, 2002
Jul 23, 2002
943
944
945
} /* zip_version_does_symlinks */
Jul 15, 2017
Jul 15, 2017
946
947
static inline int zip_has_symlink_attr(const ZIPentry *entry,
const PHYSFS_uint32 extern_attr)
Jul 23, 2001
Jul 23, 2001
948
{
Jul 15, 2002
Jul 15, 2002
949
PHYSFS_uint16 xattr = ((extern_attr >> 16) & 0xFFFF);
Jan 28, 2010
Jan 28, 2010
950
951
952
return ( (zip_version_does_symlinks(entry->version)) &&
(entry->uncompressed_size > 0) &&
((xattr & UNIX_FILETYPE_MASK) == UNIX_FILETYPE_SYMLINK) );
Jul 23, 2002
Jul 23, 2002
953
} /* zip_has_symlink_attr */
Jul 23, 2001
Jul 23, 2001
954
955
Jan 31, 2003
Jan 31, 2003
956
static PHYSFS_sint64 zip_dos_time_to_physfs_time(PHYSFS_uint32 dostime)
Jul 23, 2001
Jul 23, 2001
957
{
Jul 23, 2002
Jul 23, 2002
958
PHYSFS_uint32 dosdate;
Jul 13, 2002
Jul 13, 2002
959
960
struct tm unixtime;
memset(&unixtime, '\0', sizeof (unixtime));
Jul 28, 2001
Jul 28, 2001
961
Jul 23, 2002
Jul 23, 2002
962
963
dosdate = (PHYSFS_uint32) ((dostime >> 16) & 0xFFFF);
dostime &= 0xFFFF;
Jul 23, 2001
Jul 23, 2001
964
Jul 23, 2002
Jul 23, 2002
965
966
967
968
969
970
971
972
973
974
975
976
/* dissect date */
unixtime.tm_year = ((dosdate >> 9) & 0x7F) + 80;
unixtime.tm_mon = ((dosdate >> 5) & 0x0F) - 1;
unixtime.tm_mday = ((dosdate ) & 0x1F);
/* dissect time */
unixtime.tm_hour = ((dostime >> 11) & 0x1F);
unixtime.tm_min = ((dostime >> 5) & 0x3F);
unixtime.tm_sec = ((dostime << 1) & 0x3E);
/* let mktime calculate daylight savings time. */
unixtime.tm_isdst = -1;
Jul 28, 2001
Jul 28, 2001
977
Jan 28, 2010
Jan 28, 2010
978
return ((PHYSFS_sint64) mktime(&unixtime));
Jul 23, 2002
Jul 23, 2002
979
} /* zip_dos_time_to_physfs_time */
Jul 13, 2002
Jul 13, 2002
980
981
Jul 15, 2017
Jul 15, 2017
982
static ZIPentry *zip_load_entry(ZIPinfo *info, const int zip64,
Feb 25, 2016
Feb 25, 2016
983
const PHYSFS_uint64 ofs_fixup)
Jul 13, 2002
Jul 13, 2002
984
{
Jul 15, 2017
Jul 15, 2017
985
PHYSFS_Io *io = info->io;
Feb 25, 2016
Feb 25, 2016
986
987
ZIPentry entry;
ZIPentry *retval = NULL;
Jul 13, 2002
Jul 13, 2002
988
989
PHYSFS_uint16 fnamelen, extralen, commentlen;
PHYSFS_uint32 external_attr;
Jun 1, 2012
Jun 1, 2012
990
991
PHYSFS_uint32 starting_disk;
PHYSFS_uint64 offset;
Jul 13, 2002
Jul 13, 2002
992
993
994
PHYSFS_uint16 ui16;
PHYSFS_uint32 ui32;
PHYSFS_sint64 si64;
Jul 15, 2017
Jul 15, 2017
995
996
char *name = NULL;
int isdir = 0;
Feb 25, 2016
Feb 25, 2016
997
Jul 13, 2002
Jul 13, 2002
998
/* sanity check with central directory signature... */
Jul 15, 2017
Jul 15, 2017
999
BAIL_IF_ERRPASS(!readui32(io, &ui32), NULL);
Jul 6, 2017
Jul 6, 2017
1000
BAIL_IF(ui32 != ZIP_CENTRAL_DIR_SIG, PHYSFS_ERR_CORRUPT, NULL);