Skip to content

Latest commit

 

History

History
664 lines (528 loc) · 16.9 KB

zip.c

File metadata and controls

664 lines (528 loc) · 16.9 KB
 
Jul 7, 2001
Jul 7, 2001
1
2
3
4
5
6
7
8
/*
* ZIP support routines for PhysicsFS.
*
* Please see the file LICENSE in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
Jul 23, 2001
Jul 23, 2001
9
10
11
12
13
14
15
16
17
18
/*
* !!! FIXME: overall design bugs.
*
* Make unz_file_info.version into two fields of unsigned char. That's what
* they are in the zipfile; heavens knows why unzip.c casts it...this causes
* a byte ordering headache for me in entry_is_symlink().
*
* Maybe add a seekToStartOfCurrentFile() in unzip.c if complete seek
* semantics are impossible.
*/
Jul 23, 2001
Jul 23, 2001
19
Jul 7, 2001
Jul 7, 2001
20
21
#include <stdio.h>
#include <stdlib.h>
Jul 15, 2001
Jul 15, 2001
22
#include <string.h>
Jul 23, 2001
Jul 23, 2001
23
#include <errno.h>
Jul 8, 2001
Jul 8, 2001
24
#include "physfs.h"
Jul 15, 2001
Jul 15, 2001
25
26
#include "unzip.h"
Jul 7, 2001
Jul 7, 2001
27
28
29
30
31
32
33
34
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
#if (!defined PHYSFS_SUPPORTS_ZIP)
#error PHYSFS_SUPPORTS_ZIP must be defined.
#endif
Jul 23, 2001
Jul 23, 2001
35
#define MAXZIPENTRYSIZE 256
Jul 15, 2001
Jul 15, 2001
36
37
38
typedef struct
{
Jul 28, 2001
Jul 28, 2001
39
40
41
42
43
44
45
char *name;
unz_file_info info;
char *symlink;
} ZIPentry;
typedef struct
{
Jul 23, 2001
Jul 23, 2001
46
char *archiveName;
Jul 28, 2001
Jul 28, 2001
47
48
unz_global_info global;
ZIPentry *entries;
Jul 15, 2001
Jul 15, 2001
49
50
51
52
} ZIPinfo;
typedef struct
{
Jul 23, 2001
Jul 23, 2001
53
unzFile handle;
Jul 15, 2001
Jul 15, 2001
54
55
56
} ZIPfileinfo;
Jul 8, 2001
Jul 8, 2001
57
extern const DirFunctions __PHYSFS_DirFunctions_ZIP;
Jul 8, 2001
Jul 8, 2001
58
static const FileFunctions __PHYSFS_FileFunctions_ZIP;
Jul 8, 2001
Jul 8, 2001
59
60
Jul 28, 2001
Jul 28, 2001
61
62
63
64
/* Number of symlinks to follow before we assume it's a recursive link... */
#define SYMLINK_RECURSE_COUNT 20
Jul 8, 2001
Jul 8, 2001
65
66
67
static int ZIP_read(FileHandle *handle, void *buffer,
unsigned int objSize, unsigned int objCount)
{
Jul 23, 2001
Jul 23, 2001
68
69
70
71
72
73
74
75
76
77
78
79
unzFile fh = ((ZIPfileinfo *) (handle->opaque))->handle;
int bytes = objSize * objCount;
int rc = unzReadCurrentFile(fh, buffer, bytes);
if (rc < bytes)
__PHYSFS_setError(ERR_PAST_EOF);
else if (rc == UNZ_ERRNO)
__PHYSFS_setError(ERR_IO_ERROR);
else if (rc < 0)
__PHYSFS_setError(ERR_COMPRESSION);
return(rc / objSize);
Jul 8, 2001
Jul 8, 2001
80
81
82
83
84
} /* ZIP_read */
static int ZIP_eof(FileHandle *handle)
{
Jul 23, 2001
Jul 23, 2001
85
return(unzeof(((ZIPfileinfo *) (handle->opaque))->handle));
Jul 8, 2001
Jul 8, 2001
86
87
88
89
90
} /* ZIP_eof */
static int ZIP_tell(FileHandle *handle)
{
Jul 23, 2001
Jul 23, 2001
91
return(unztell(((ZIPfileinfo *) (handle->opaque))->handle));
Jul 8, 2001
Jul 8, 2001
92
93
94
} /* ZIP_tell */
Jul 23, 2001
Jul 23, 2001
95
96
97
static int ZIP_fileLength(FileHandle *handle);
Jul 8, 2001
Jul 8, 2001
98
99
static int ZIP_seek(FileHandle *handle, int offset)
{
Jul 23, 2001
Jul 23, 2001
100
101
/* this blows. */
unzFile fh = ((ZIPfileinfo *) (handle->opaque))->handle;
Jul 23, 2001
Jul 23, 2001
102
char *buf = NULL;
Jul 23, 2001
Jul 23, 2001
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
int bufsize = 4096 * 2;
BAIL_IF_MACRO(unztell(fh) == offset, NULL, 1);
BAIL_IF_MACRO(ZIP_fileLength(handle) <= offset, ERR_PAST_EOF, 0);
/* reset to the start of the zipfile. */
unzCloseCurrentFile(fh);
BAIL_IF_MACRO(unzOpenCurrentFile(fh) != UNZ_OK, ERR_IO_ERROR, 0);
while ((buf == NULL) && (bufsize >= 512))
{
bufsize >>= 1; /* divides by two. */
buf = (char *) malloc(bufsize);
} /* while */
BAIL_IF_MACRO(buf == NULL, ERR_OUT_OF_MEMORY, 0);
while (offset > 0)
{
int chunk = (offset > bufsize) ? bufsize : offset;
int rc = unzReadCurrentFile(fh, buf, chunk);
BAIL_IF_MACRO(rc == 0, ERR_IO_ERROR, 0); /* shouldn't happen. */
BAIL_IF_MACRO(rc == UNZ_ERRNO, ERR_IO_ERROR, 0);
BAIL_IF_MACRO(rc < 0, ERR_COMPRESSION, 0);
offset -= rc;
} /* while */
free(buf);
return(offset == 0);
Jul 8, 2001
Jul 8, 2001
131
132
133
} /* ZIP_seek */
Jul 9, 2001
Jul 9, 2001
134
135
static int ZIP_fileLength(FileHandle *handle)
{
Jul 23, 2001
Jul 23, 2001
136
137
138
139
140
ZIPfileinfo *finfo = (ZIPfileinfo *) (handle->opaque);
unz_file_info info;
unzGetCurrentFileInfo(finfo->handle, &info, NULL, 0, NULL, 0, NULL, 0);
return(info.uncompressed_size);
Jul 9, 2001
Jul 9, 2001
141
142
143
} /* ZIP_fileLength */
Jul 8, 2001
Jul 8, 2001
144
145
static int ZIP_fileClose(FileHandle *handle)
{
Jul 23, 2001
Jul 23, 2001
146
147
148
149
150
ZIPfileinfo *finfo = (ZIPfileinfo *) (handle->opaque);
unzClose(finfo->handle);
free(finfo);
free(handle);
return(1);
Jul 8, 2001
Jul 8, 2001
151
152
153
154
155
} /* ZIP_fileClose */
static int ZIP_isArchive(const char *filename, int forWriting)
{
Jul 15, 2001
Jul 15, 2001
156
int retval = 0;
Jul 23, 2001
Jul 23, 2001
157
unzFile unz = unzOpen(filename);
Jul 15, 2001
Jul 15, 2001
158
159
160
161
162
163
164
165
166
167
unz_global_info global;
if (unz != NULL)
{
if (unzGetGlobalInfo(unz, &global) == UNZ_OK)
retval = 1;
unzClose(unz);
} /* if */
return(retval);
Jul 8, 2001
Jul 8, 2001
168
169
170
} /* ZIP_isArchive */
Jul 28, 2001
Jul 28, 2001
171
static void freeEntries(ZIPinfo *info, int count, const char *errmsg)
Jul 8, 2001
Jul 8, 2001
172
{
Jul 28, 2001
Jul 28, 2001
173
int i;
Jul 15, 2001
Jul 15, 2001
174
Jul 28, 2001
Jul 28, 2001
175
176
177
178
179
180
for (i = 0; i < count; i++)
{
free(info->entries[i].name);
if (info->entries[i].symlink != NULL)
free(info->entries[i].symlink);
} /* for */
Jul 15, 2001
Jul 15, 2001
181
Jul 28, 2001
Jul 28, 2001
182
free(info->entries);
Jul 15, 2001
Jul 15, 2001
183
Jul 28, 2001
Jul 28, 2001
184
185
186
if (errmsg != NULL)
__PHYSFS_setError(errmsg);
} /* freeEntries */
Jul 15, 2001
Jul 15, 2001
187
188
Jul 28, 2001
Jul 28, 2001
189
190
191
192
static char *ZIP_realpath(unzFile fh, unz_file_info *info)
{
char *retval = NULL;
int size;
Jul 15, 2001
Jul 15, 2001
193
Jul 28, 2001
Jul 28, 2001
194
195
196
197
198
BAIL_IF_MACRO(unzOpenCurrentFile(fh) != UNZ_OK, ERR_IO_ERROR, NULL);
size = info->uncompressed_size;
retval = (char *) malloc(size + 1);
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
if (unzReadCurrentFile(fh, retval, size) != size)
Jul 23, 2001
Jul 23, 2001
199
200
{
free(retval);
Jul 28, 2001
Jul 28, 2001
201
202
__PHYSFS_setError(ERR_IO_ERROR);
retval = NULL;
Jul 23, 2001
Jul 23, 2001
203
} /* if */
Jul 28, 2001
Jul 28, 2001
204
205
retval[size] = '\0';
unzCloseCurrentFile(fh);
Jul 15, 2001
Jul 15, 2001
206
207
return(retval);
Jul 28, 2001
Jul 28, 2001
208
} /* ZIP_realpath */
Jul 8, 2001
Jul 8, 2001
209
210
Jul 23, 2001
Jul 23, 2001
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/* "uLong" is defined by zlib and/or unzip.h ... */
typedef union
{
unsigned char uchar4[4];
uLong ul;
} uchar4_uLong;
static int version_does_symlinks(uLong version)
{
int retval = 0;
unsigned char hosttype;
uchar4_uLong converter;
converter.ul = version;
hosttype = converter.uchar4[1]; /* !!! BYTE ORDERING ALERT! */
/*
* These are the platforms that can build an archive with symlinks,
* according to the Info-ZIP project.
*/
switch (hosttype)
{
case 3: /* Unix */
case 16: /* BeOS */
case 5: /* Atari */
retval = 1;
break;
} /* switch */
return(retval);
} /* version_does_symlinks */
static int entry_is_symlink(unz_file_info *info)
{
return (
(version_does_symlinks(info->version)) &&
(info->uncompressed_size > 0) &&
(info->external_fa & 0x0120000) /* symlink flag. */
);
} /* entry_is_symlink */
Jul 28, 2001
Jul 28, 2001
256
static int loadZipEntries(ZIPinfo *info, unzFile unz)
Jul 23, 2001
Jul 23, 2001
257
{
Jul 28, 2001
Jul 28, 2001
258
259
260
261
262
int i, max;
BAIL_IF_MACRO(unzGetGlobalInfo(unz, &(info->global)) != UNZ_OK,
ERR_IO_ERROR, 0);
BAIL_IF_MACRO(unzGoToFirstFile(unz) != UNZ_OK, ERR_IO_ERROR, 0);
Jul 23, 2001
Jul 23, 2001
263
Jul 28, 2001
Jul 28, 2001
264
265
266
267
268
max = info->global.number_entry;
info->entries = (ZIPentry *) malloc(sizeof (ZIPentry) * max);
BAIL_IF_MACRO(info->entries == NULL, ERR_OUT_OF_MEMORY, 0);
for (i = 0; i < max; i++)
Jul 23, 2001
Jul 23, 2001
269
{
Jul 28, 2001
Jul 28, 2001
270
271
unz_file_info *d = &((info->entries[i]).info);
if (unzGetCurrentFileInfo(unz, d, NULL, 0, NULL, 0, NULL, 0) != UNZ_OK)
Jul 23, 2001
Jul 23, 2001
272
{
Jul 28, 2001
Jul 28, 2001
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
freeEntries(info, i, ERR_IO_ERROR);
return(0);
} /* if */
(info->entries[i]).name = (char *) malloc(d->size_filename + 1);
if ((info->entries[i]).name == NULL)
{
freeEntries(info, i, ERR_OUT_OF_MEMORY);
return(0);
} /* if */
info->entries[i].symlink = NULL;
if (unzGetCurrentFileInfo(unz, NULL, (info->entries[i]).name,
d->size_filename + 1, NULL, 0,
NULL, 0) != UNZ_OK)
{
freeEntries(info, i + 1, ERR_IO_ERROR);
return(0);
} /* if */
if (entry_is_symlink(d))
{
info->entries[i].symlink = ZIP_realpath(unz, d);
if (info->entries[i].symlink == NULL)
{
freeEntries(info, i + 1, NULL);
return(0);
} /* if */
Jul 23, 2001
Jul 23, 2001
302
} /* if */
Jul 28, 2001
Jul 28, 2001
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
if ((unzGoToNextFile(unz) != UNZ_OK) && (i + 1 < max))
{
freeEntries(info, i + 1, ERR_IO_ERROR);
return(0);
} /* if */
} /* for */
return(1);
} /* loadZipEntries */
static DirHandle *ZIP_openArchive(const char *name, int forWriting)
{
unzFile unz = NULL;
DirHandle *retval = NULL;
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, NULL);
retval = malloc(sizeof (DirHandle));
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
unz = unzOpen(name);
if (unz == NULL)
{
free(retval);
BAIL_IF_MACRO(1, ERR_UNSUPPORTED_ARCHIVE, NULL);
} /* if */
retval->opaque = malloc(sizeof (ZIPinfo));
if (retval->opaque == NULL)
{
free(retval);
unzClose(unz);
BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
} /* if */
((ZIPinfo *) (retval->opaque))->archiveName = malloc(strlen(name) + 1);
if ( (((ZIPinfo *) (retval->opaque))->archiveName == NULL) ||
(!loadZipEntries( (ZIPinfo *) (retval->opaque), unz)) )
{
if (((ZIPinfo *) (retval->opaque))->archiveName != NULL)
free(((ZIPinfo *) (retval->opaque))->archiveName);
free(retval->opaque);
free(retval);
unzClose(unz);
BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
Jul 23, 2001
Jul 23, 2001
350
351
} /* if */
Jul 28, 2001
Jul 28, 2001
352
353
354
355
unzClose(unz);
strcpy(((ZIPinfo *) (retval->opaque))->archiveName, name);
retval->funcs = &__PHYSFS_DirFunctions_ZIP;
Jul 23, 2001
Jul 23, 2001
356
return(retval);
Jul 28, 2001
Jul 28, 2001
357
} /* ZIP_openArchive */
Jul 23, 2001
Jul 23, 2001
358
359
360
/* !!! This is seriously ugly. */
Jul 16, 2001
Jul 16, 2001
361
362
363
static LinkedStringList *ZIP_enumerateFiles(DirHandle *h,
const char *dirname,
int omitSymLinks)
Jul 8, 2001
Jul 8, 2001
364
{
Jul 15, 2001
Jul 15, 2001
365
366
ZIPinfo *zi = (ZIPinfo *) (h->opaque);
int i;
Jul 23, 2001
Jul 23, 2001
367
int dlen;
Jul 15, 2001
Jul 15, 2001
368
369
370
371
LinkedStringList *retval = NULL;
LinkedStringList *l = NULL;
LinkedStringList *prev = NULL;
char *d;
Jul 28, 2001
Jul 28, 2001
372
373
ZIPentry *entry;
char buf[MAXZIPENTRYSIZE];
Jul 15, 2001
Jul 15, 2001
374
Jul 23, 2001
Jul 23, 2001
375
376
377
dlen = strlen(dirname);
d = malloc(dlen + 1);
BAIL_IF_MACRO(d == NULL, ERR_OUT_OF_MEMORY, NULL);
Jul 15, 2001
Jul 15, 2001
378
strcpy(d, dirname);
Jul 23, 2001
Jul 23, 2001
379
380
381
382
383
if ((dlen > 0) && (d[dlen - 1] == '/')) /* no trailing slash. */
{
dlen--;
d[dlen] = '\0';
} /* if */
Jul 15, 2001
Jul 15, 2001
384
Jul 28, 2001
Jul 28, 2001
385
for (i = 0, entry = zi->entries; i < zi->global.number_entry; i++, entry++)
Jul 15, 2001
Jul 15, 2001
386
387
{
char *ptr;
Jul 23, 2001
Jul 23, 2001
388
389
390
char *add_file;
int this_dlen;
Jul 28, 2001
Jul 28, 2001
391
if ((omitSymLinks) && (entry->symlink != NULL))
Jul 23, 2001
Jul 23, 2001
392
393
continue;
Jul 28, 2001
Jul 28, 2001
394
395
396
397
398
399
this_dlen = strlen(entry->name);
if (this_dlen + 1 > MAXZIPENTRYSIZE)
continue; /* ugh. */
strcpy(buf, entry->name);
Jul 23, 2001
Jul 23, 2001
400
if ((this_dlen > 0) && (buf[this_dlen - 1] == '/')) /* no trailing slash. */
Jul 15, 2001
Jul 15, 2001
401
{
Jul 23, 2001
Jul 23, 2001
402
403
404
405
406
407
408
409
410
this_dlen--;
buf[this_dlen] = '\0';
} /* if */
if (this_dlen <= dlen) /* not in this dir. */
continue;
if (*d == '\0')
add_file = buf;
Jul 15, 2001
Jul 15, 2001
411
412
else
{
Jul 23, 2001
Jul 23, 2001
413
414
415
416
if (buf[dlen] != '/') /* can't be in same directory? */
continue;
buf[dlen] = '\0';
Jul 23, 2001
Jul 23, 2001
417
if (__PHYSFS_platformStricmp(d, buf) != 0) /* not same directory? */
Jul 23, 2001
Jul 23, 2001
418
419
420
continue;
add_file = buf + dlen + 1;
Jul 15, 2001
Jul 15, 2001
421
422
} /* else */
Jul 23, 2001
Jul 23, 2001
423
424
425
426
427
428
429
430
/* handle subdirectories... */
ptr = strchr(add_file, '/');
if (ptr != NULL)
{
LinkedStringList *j;
*ptr = '\0';
for (j = retval; j != NULL; j = j->next)
{
Jul 23, 2001
Jul 23, 2001
431
if (__PHYSFS_platformStricmp(j->str, ptr) == 0)
Jul 23, 2001
Jul 23, 2001
432
433
434
435
436
437
438
break;
} /* for */
if (j != NULL)
continue;
} /* if */
Jul 15, 2001
Jul 15, 2001
439
l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
Jul 16, 2001
Jul 16, 2001
440
if (l == NULL)
Jul 15, 2001
Jul 15, 2001
441
442
break;
Jul 23, 2001
Jul 23, 2001
443
l->str = (char *) malloc(strlen(add_file) + 1);
Jul 15, 2001
Jul 15, 2001
444
445
446
447
448
449
if (l->str == NULL)
{
free(l);
break;
} /* if */
Jul 23, 2001
Jul 23, 2001
450
strcpy(l->str, add_file);
Jul 16, 2001
Jul 16, 2001
451
Jul 15, 2001
Jul 15, 2001
452
453
454
455
456
457
458
459
460
461
462
if (retval == NULL)
retval = l;
else
prev->next = l;
prev = l;
l->next = NULL;
} /* for */
free(d);
return(retval);
Jul 8, 2001
Jul 8, 2001
463
464
465
} /* ZIP_enumerateFiles */
Jul 23, 2001
Jul 23, 2001
466
467
468
469
470
471
472
473
/* !!! This is seriously ugly. */
static int ZIP_exists_symcheck(DirHandle *h, const char *name, int follow)
{
char buf[MAXZIPENTRYSIZE];
ZIPinfo *zi = (ZIPinfo *) (h->opaque);
int dlen;
char *d;
int i;
Jul 28, 2001
Jul 28, 2001
474
ZIPentry *entry;
Jul 23, 2001
Jul 23, 2001
475
476
477
dlen = strlen(name);
d = malloc(dlen + 1);
Jul 28, 2001
Jul 28, 2001
478
BAIL_IF_MACRO(d == NULL, ERR_OUT_OF_MEMORY, -1);
Jul 23, 2001
Jul 23, 2001
479
480
481
482
483
484
485
strcpy(d, name);
if ((dlen > 0) && (d[dlen - 1] == '/')) /* no trailing slash. */
{
dlen--;
d[dlen] = '\0';
} /* if */
Jul 28, 2001
Jul 28, 2001
486
for (i = 0, entry = zi->entries; i < zi->global.number_entry; i++, entry++)
Jul 23, 2001
Jul 23, 2001
487
{
Jul 28, 2001
Jul 28, 2001
488
489
490
491
492
int this_dlen = strlen(entry->name);
if (this_dlen + 1 > MAXZIPENTRYSIZE)
continue; /* ugh. */
strcpy(buf, entry->name);
Jul 23, 2001
Jul 23, 2001
493
494
495
496
497
498
499
500
501
if ((this_dlen > 0) && (buf[this_dlen - 1] == '/')) /* no trailing slash. */
{
this_dlen--;
buf[this_dlen] = '\0';
} /* if */
if ( ((buf[dlen] == '/') || (buf[dlen] == '\0')) &&
(strncmp(d, buf, dlen) == 0) )
{
Jul 28, 2001
Jul 28, 2001
502
int retval = i;
Jul 23, 2001
Jul 23, 2001
503
504
505
free(d);
if (follow) /* follow symlinks? */
{
Jul 28, 2001
Jul 28, 2001
506
507
if (entry->symlink != NULL)
retval = ZIP_exists_symcheck(h, entry->symlink, follow-1);
Jul 23, 2001
Jul 23, 2001
508
509
510
511
512
513
} /* if */
return(retval);
} /* if */
} /* for */
free(d);
Jul 28, 2001
Jul 28, 2001
514
return(-1);
Jul 23, 2001
Jul 23, 2001
515
516
517
} /* ZIP_exists_symcheck */
Jul 8, 2001
Jul 8, 2001
518
static int ZIP_exists(DirHandle *h, const char *name)
Jul 8, 2001
Jul 8, 2001
519
{
Jul 28, 2001
Jul 28, 2001
520
521
int retval = ZIP_exists_symcheck(h, name, SYMLINK_RECURSE_COUNT);
int is_sym;
Jul 23, 2001
Jul 23, 2001
522
Jul 28, 2001
Jul 28, 2001
523
524
if (retval == -1)
return(0);
Jul 23, 2001
Jul 23, 2001
525
Jul 28, 2001
Jul 28, 2001
526
527
528
/* if it's a symlink, then we ran into a possible symlink loop. */
is_sym = ( ((ZIPinfo *)(h->opaque))->entries[retval].symlink != NULL );
BAIL_IF_MACRO(is_sym, ERR_TOO_MANY_SYMLINKS, 0);
Jul 23, 2001
Jul 23, 2001
529
Jul 28, 2001
Jul 28, 2001
530
return(1);
Jul 8, 2001
Jul 8, 2001
531
532
533
} /* ZIP_exists */
Jul 8, 2001
Jul 8, 2001
534
static int ZIP_isDirectory(DirHandle *h, const char *name)
Jul 8, 2001
Jul 8, 2001
535
{
Jul 28, 2001
Jul 28, 2001
536
537
538
int dlen;
int is_sym;
int retval = ZIP_exists_symcheck(h, name, SYMLINK_RECURSE_COUNT);
Jul 23, 2001
Jul 23, 2001
539
Jul 28, 2001
Jul 28, 2001
540
541
542
543
544
545
if (retval == -1)
return(0);
/* if it's a symlink, then we ran into a possible symlink loop. */
is_sym = ( ((ZIPinfo *)(h->opaque))->entries[retval].symlink != NULL );
BAIL_IF_MACRO(is_sym, ERR_TOO_MANY_SYMLINKS, 0);
Jul 23, 2001
Jul 23, 2001
546
Jul 28, 2001
Jul 28, 2001
547
548
549
dlen = strlen(name);
/* !!! yikes. Better way to check? */
retval = (((ZIPinfo *)(h->opaque))->entries[retval].name[dlen] == '/');
Jul 23, 2001
Jul 23, 2001
550
return(retval);
Jul 8, 2001
Jul 8, 2001
551
552
553
} /* ZIP_isDirectory */
Jul 8, 2001
Jul 8, 2001
554
static int ZIP_isSymLink(DirHandle *h, const char *name)
Jul 8, 2001
Jul 8, 2001
555
{
Jul 28, 2001
Jul 28, 2001
556
int retval = ZIP_exists_symcheck(h, name, 0);
Jul 28, 2001
Jul 28, 2001
557
558
if (retval == -1)
return(0);
Jul 23, 2001
Jul 23, 2001
559
Jul 28, 2001
Jul 28, 2001
560
retval = ( ((ZIPinfo *)(h->opaque))->entries[retval].symlink != NULL );
Jul 23, 2001
Jul 23, 2001
561
return(retval);
Jul 8, 2001
Jul 8, 2001
562
563
564
} /* ZIP_isSymLink */
Jul 8, 2001
Jul 8, 2001
565
static FileHandle *ZIP_openRead(DirHandle *h, const char *filename)
Jul 8, 2001
Jul 8, 2001
566
{
Jul 23, 2001
Jul 23, 2001
567
FileHandle *retval = NULL;
Jul 28, 2001
Jul 28, 2001
568
ZIPinfo *zi = ((ZIPinfo *) (h->opaque));
Jul 23, 2001
Jul 23, 2001
569
ZIPfileinfo *finfo = NULL;
Jul 28, 2001
Jul 28, 2001
570
int pos = ZIP_exists_symcheck(h, filename, SYMLINK_RECURSE_COUNT);
Jul 23, 2001
Jul 23, 2001
571
unzFile f;
Jul 23, 2001
Jul 23, 2001
572
Jul 28, 2001
Jul 28, 2001
573
BAIL_IF_MACRO(pos == -1, ERR_NO_SUCH_FILE, NULL);
Jul 23, 2001
Jul 23, 2001
574
Jul 28, 2001
Jul 28, 2001
575
f = unzOpen(zi->archiveName);
Jul 23, 2001
Jul 23, 2001
576
577
BAIL_IF_MACRO(f == NULL, ERR_IO_ERROR, NULL);
Jul 28, 2001
Jul 28, 2001
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
if (unzGoToFirstFile(f) != UNZ_OK)
{
unzClose(f);
BAIL_IF_MACRO(1, ERR_IO_ERROR, NULL);
} /* if */
for (; pos > 0; pos--)
{
if (unzGoToNextFile(f) != UNZ_OK)
{
unzClose(f);
BAIL_IF_MACRO(1, ERR_IO_ERROR, NULL);
} /* if */
} /* for */
if ( (unzOpenCurrentFile(f) != UNZ_OK) ||
Jul 23, 2001
Jul 23, 2001
594
( (finfo = (ZIPfileinfo *) malloc(sizeof (ZIPfileinfo))) == NULL ) )
Jul 23, 2001
Jul 23, 2001
595
596
597
598
599
{
unzClose(f);
BAIL_IF_MACRO(1, ERR_IO_ERROR, NULL);
} /* if */
Jul 23, 2001
Jul 23, 2001
600
601
602
603
604
605
606
607
608
if ( (!(retval = (FileHandle *) malloc(sizeof (FileHandle)))) ||
(!(retval->opaque = (ZIPfileinfo *) malloc(sizeof (ZIPfileinfo)))) )
{
if (retval)
free(retval);
unzClose(f);
BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
} /* if */
Jul 23, 2001
Jul 23, 2001
609
finfo->handle = f;
Jul 23, 2001
Jul 23, 2001
610
retval->opaque = (void *) finfo;
Jul 23, 2001
Jul 23, 2001
611
retval->funcs = &__PHYSFS_FileFunctions_ZIP;
Jul 23, 2001
Jul 23, 2001
612
613
retval->dirHandle = h;
return(retval);
Jul 8, 2001
Jul 8, 2001
614
615
616
} /* ZIP_openRead */
Jul 8, 2001
Jul 8, 2001
617
static void ZIP_dirClose(DirHandle *h)
Jul 8, 2001
Jul 8, 2001
618
{
Jul 28, 2001
Jul 28, 2001
619
620
621
622
ZIPinfo *zi = (ZIPinfo *) (h->opaque);
freeEntries(zi, zi->global.number_entry, NULL);
free(zi->archiveName);
free(zi);
Jul 23, 2001
Jul 23, 2001
623
free(h);
Jul 8, 2001
Jul 8, 2001
624
625
} /* ZIP_dirClose */
Jul 7, 2001
Jul 7, 2001
626
Jul 8, 2001
Jul 8, 2001
627
static const FileFunctions __PHYSFS_FileFunctions_ZIP =
Jul 7, 2001
Jul 7, 2001
628
{
Jul 9, 2001
Jul 9, 2001
629
630
631
632
633
634
635
ZIP_read, /* read() method */
NULL, /* write() method */
ZIP_eof, /* eof() method */
ZIP_tell, /* tell() method */
ZIP_seek, /* seek() method */
ZIP_fileLength, /* fileLength() method */
ZIP_fileClose /* fileClose() method */
Jul 7, 2001
Jul 7, 2001
636
637
638
639
640
};
const DirFunctions __PHYSFS_DirFunctions_ZIP =
{
Jul 8, 2001
Jul 8, 2001
641
642
643
644
645
646
647
648
649
650
651
ZIP_isArchive, /* isArchive() method */
ZIP_openArchive, /* openArchive() method */
ZIP_enumerateFiles, /* enumerateFiles() method */
ZIP_exists, /* exists() method */
ZIP_isDirectory, /* isDirectory() method */
ZIP_isSymLink, /* isSymLink() method */
ZIP_openRead, /* openRead() method */
NULL, /* openWrite() method */
NULL, /* openAppend() method */
NULL, /* remove() method */
NULL, /* mkdir() method */
Jul 8, 2001
Jul 8, 2001
652
ZIP_dirClose /* dirClose() method */
Jul 7, 2001
Jul 7, 2001
653
654
};
Jul 8, 2001
Jul 8, 2001
655
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_ZIP =
Jul 7, 2001
Jul 7, 2001
656
657
{
"ZIP",
Jul 9, 2001
Jul 9, 2001
658
"PkZip/WinZip/Info-Zip compatible",
Aug 7, 2001
Aug 7, 2001
659
660
"Ryan C. Gordon (icculus@clutteredmind.org)",
"http://www.icculus.org/physfs/",
Jul 7, 2001
Jul 7, 2001
661
662
663
};
/* end of zip.c ... */