Skip to content

Latest commit

 

History

History
679 lines (544 loc) · 18.4 KB

zip.c

File metadata and controls

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