Skip to content

Latest commit

 

History

History
621 lines (492 loc) · 16.7 KB

archiver_qpak.c

File metadata and controls

621 lines (492 loc) · 16.7 KB
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
* QPAK support routines for PhysicsFS.
*
* This archiver handles the archive format utilized by Quake 1 and 2.
* Quake3-based games use the PkZip/Info-Zip format (which our zip.c
* archiver handles).
*
* ========================================================================
*
* This format info (in more detail) comes from:
* http://debian.fmi.uni-sofia.bg/~sergei/cgsr/docs/pak.txt
*
* Quake PAK Format
*
* Header
* (4 bytes) signature = 'PACK'
* (4 bytes) directory offset
* (4 bytes) directory length
*
* Directory
* (56 bytes) file name
* (4 bytes) file position
* (4 bytes) file length
*
* ========================================================================
*
Mar 11, 2007
Mar 11, 2007
27
* Please see the file LICENSE.txt in the source's root directory.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
*
* This file written by Ryan C. Gordon.
*/
#if (defined PHYSFS_SUPPORTS_QPAK)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "physfs.h"
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
Nov 9, 2003
Nov 9, 2003
42
#if 1 /* Make this case insensitive? */
Mar 15, 2007
Mar 15, 2007
43
44
#define QPAK_strcmp(x, y) __PHYSFS_stricmpASCII(x, y)
#define QPAK_strncmp(x, y, z) __PHYSFS_strnicmpASCII(x, y, z)
Nov 9, 2003
Nov 9, 2003
45
46
47
48
49
50
#else
#define QPAK_strcmp(x, y) strcmp(x, y)
#define QPAK_strncmp(x, y, z) strncmp(x, y, z)
#endif
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
typedef struct
{
char name[56];
PHYSFS_uint32 startPos;
PHYSFS_uint32 size;
} QPAKentry;
typedef struct
{
char *filename;
PHYSFS_sint64 last_mod_time;
PHYSFS_uint32 entryCount;
QPAKentry *entries;
} QPAKinfo;
typedef struct
{
void *handle;
QPAKentry *entry;
PHYSFS_uint32 curPos;
} QPAKfileinfo;
/* Magic numbers... */
Mar 13, 2005
Mar 13, 2005
74
#define QPAK_SIG 0x4b434150 /* "PACK" in ASCII. */
75
76
Sep 26, 2004
Sep 26, 2004
77
static void QPAK_dirClose(dvoid *opaque)
78
{
Sep 26, 2004
Sep 26, 2004
79
QPAKinfo *info = ((QPAKinfo *) opaque);
Mar 14, 2005
Mar 14, 2005
80
81
82
allocator.Free(info->filename);
allocator.Free(info->entries);
allocator.Free(info);
83
84
85
} /* QPAK_dirClose */
Aug 21, 2010
Aug 21, 2010
86
static PHYSFS_sint64 QPAK_read(fvoid *opaque, void *buffer, PHYSFS_uint64 len)
87
{
Sep 26, 2004
Sep 26, 2004
88
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
Aug 21, 2010
Aug 21, 2010
89
90
const QPAKentry *entry = finfo->entry;
const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos);
91
92
PHYSFS_sint64 rc;
Aug 21, 2010
Aug 21, 2010
93
94
if (bytesLeft < len)
len = bytesLeft;
95
Aug 21, 2010
Aug 21, 2010
96
rc = __PHYSFS_platformRead(finfo->handle, buffer, len);
97
if (rc > 0)
Aug 21, 2010
Aug 21, 2010
98
finfo->curPos += (PHYSFS_uint32) rc;
99
Jan 28, 2010
Jan 28, 2010
100
return rc;
101
102
103
} /* QPAK_read */
Aug 21, 2010
Aug 21, 2010
104
static PHYSFS_sint64 QPAK_write(fvoid *f, const void *buf, PHYSFS_uint64 len)
105
106
107
108
109
{
BAIL_MACRO(ERR_NOT_SUPPORTED, -1);
} /* QPAK_write */
Sep 26, 2004
Sep 26, 2004
110
static int QPAK_eof(fvoid *opaque)
111
{
Sep 26, 2004
Sep 26, 2004
112
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
113
QPAKentry *entry = finfo->entry;
Jan 28, 2010
Jan 28, 2010
114
return (finfo->curPos >= entry->size);
115
116
117
} /* QPAK_eof */
Sep 26, 2004
Sep 26, 2004
118
static PHYSFS_sint64 QPAK_tell(fvoid *opaque)
119
{
Jan 28, 2010
Jan 28, 2010
120
return ((QPAKfileinfo *) opaque)->curPos;
121
122
123
} /* QPAK_tell */
Sep 26, 2004
Sep 26, 2004
124
static int QPAK_seek(fvoid *opaque, PHYSFS_uint64 offset)
125
{
Sep 26, 2004
Sep 26, 2004
126
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
127
128
129
130
131
132
133
134
135
QPAKentry *entry = finfo->entry;
int rc;
BAIL_IF_MACRO(offset < 0, ERR_INVALID_ARGUMENT, 0);
BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0);
rc = __PHYSFS_platformSeek(finfo->handle, entry->startPos + offset);
if (rc)
finfo->curPos = (PHYSFS_uint32) offset;
Jan 28, 2010
Jan 28, 2010
136
return rc;
137
138
139
} /* QPAK_seek */
Sep 26, 2004
Sep 26, 2004
140
static PHYSFS_sint64 QPAK_fileLength(fvoid *opaque)
141
{
Sep 26, 2004
Sep 26, 2004
142
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
Jan 28, 2010
Jan 28, 2010
143
return ((PHYSFS_sint64) finfo->entry->size);
144
145
146
} /* QPAK_fileLength */
Sep 26, 2004
Sep 26, 2004
147
static int QPAK_fileClose(fvoid *opaque)
148
{
Sep 26, 2004
Sep 26, 2004
149
QPAKfileinfo *finfo = (QPAKfileinfo *) opaque;
150
BAIL_IF_MACRO(!__PHYSFS_platformClose(finfo->handle), NULL, 0);
Mar 14, 2005
Mar 14, 2005
151
allocator.Free(finfo);
Jan 28, 2010
Jan 28, 2010
152
return 1;
153
154
155
} /* QPAK_fileClose */
Aug 21, 2010
Aug 21, 2010
156
157
158
159
160
static inline int readAll(void *fh, void *buf, const PHYSFS_uint64 len)
{
return (__PHYSFS_platformRead(fh, buf, len) == len);
} /* readAll */
161
162
163
164
165
166
167
168
169
170
171
static int qpak_open(const char *filename, int forWriting,
void **fh, PHYSFS_uint32 *count)
{
PHYSFS_uint32 buf;
*fh = NULL;
BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0);
*fh = __PHYSFS_platformOpenRead(filename);
BAIL_IF_MACRO(*fh == NULL, NULL, 0);
Aug 21, 2010
Aug 21, 2010
172
if (!readAll(*fh, &buf, sizeof (PHYSFS_uint32)))
173
174
175
goto openQpak_failed;
buf = PHYSFS_swapULE32(buf);
Mar 13, 2005
Mar 13, 2005
176
GOTO_IF_MACRO(buf != QPAK_SIG, ERR_UNSUPPORTED_ARCHIVE, openQpak_failed);
177
Aug 21, 2010
Aug 21, 2010
178
if (!readAll(*fh, &buf, sizeof (PHYSFS_uint32)))
179
180
181
182
goto openQpak_failed;
buf = PHYSFS_swapULE32(buf); /* directory table offset. */
Aug 21, 2010
Aug 21, 2010
183
if (!readAll(*fh, count, sizeof (PHYSFS_uint32)))
184
185
186
187
goto openQpak_failed;
*count = PHYSFS_swapULE32(*count);
Mar 13, 2005
Mar 13, 2005
188
189
/* corrupted archive? */
GOTO_IF_MACRO((*count % 64) != 0, ERR_CORRUPTED, openQpak_failed);
190
191
192
193
194
if (!__PHYSFS_platformSeek(*fh, buf))
goto openQpak_failed;
*count /= 64;
Jan 28, 2010
Jan 28, 2010
195
return 1;
196
197
198
199
200
201
202
openQpak_failed:
if (*fh != NULL)
__PHYSFS_platformClose(*fh);
*count = -1;
*fh = NULL;
Jan 28, 2010
Jan 28, 2010
203
return 0;
204
205
206
207
208
} /* qpak_open */
static int qpak_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
Feb 20, 2008
Feb 20, 2008
209
210
211
if (one != two)
{
const QPAKentry *a = (const QPAKentry *) _a;
Jan 28, 2010
Jan 28, 2010
212
return QPAK_strcmp(a[one].name, a[two].name);
Feb 20, 2008
Feb 20, 2008
213
214
215
} /* if */
return 0;
216
217
218
219
220
} /* qpak_entry_cmp */
static void qpak_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
Feb 20, 2008
Feb 20, 2008
221
222
223
224
225
226
227
228
229
if (one != two)
{
QPAKentry tmp;
QPAKentry *first = &(((QPAKentry *) _a)[one]);
QPAKentry *second = &(((QPAKentry *) _a)[two]);
memcpy(&tmp, first, sizeof (QPAKentry));
memcpy(first, second, sizeof (QPAKentry));
memcpy(second, &tmp, sizeof (QPAKentry));
} /* if */
230
231
232
233
234
235
236
237
238
239
240
} /* qpak_entry_swap */
static int qpak_load_entries(const char *name, int forWriting, QPAKinfo *info)
{
void *fh = NULL;
PHYSFS_uint32 fileCount;
QPAKentry *entry;
BAIL_IF_MACRO(!qpak_open(name, forWriting, &fh, &fileCount), NULL, 0);
info->entryCount = fileCount;
Mar 14, 2005
Mar 14, 2005
241
info->entries = (QPAKentry*) allocator.Malloc(sizeof(QPAKentry)*fileCount);
242
243
244
245
246
247
248
249
if (info->entries == NULL)
{
__PHYSFS_platformClose(fh);
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
} /* if */
for (entry = info->entries; fileCount > 0; fileCount--, entry++)
{
Aug 21, 2010
Aug 21, 2010
250
251
252
if ( (!readAll(fh, &entry->name, sizeof (entry->name))) ||
(!readAll(fh, &entry->startPos, sizeof (entry->startPos))) ||
(!readAll(fh, &entry->size, sizeof(entry->size))) )
253
254
{
__PHYSFS_platformClose(fh);
Jan 28, 2010
Jan 28, 2010
255
return 0;
256
257
258
} /* if */
entry->size = PHYSFS_swapULE32(entry->size);
Aug 21, 2010
Aug 21, 2010
259
entry->startPos = PHYSFS_swapULE32(entry->startPos);
260
261
262
263
264
265
} /* for */
__PHYSFS_platformClose(fh);
__PHYSFS_sort(info->entries, info->entryCount,
qpak_entry_cmp, qpak_entry_swap);
Jan 28, 2010
Jan 28, 2010
266
return 1;
267
268
269
} /* qpak_load_entries */
Sep 26, 2004
Sep 26, 2004
270
static void *QPAK_openArchive(const char *name, int forWriting)
271
{
Mar 14, 2005
Mar 14, 2005
272
QPAKinfo *info = (QPAKinfo *) allocator.Malloc(sizeof (QPAKinfo));
273
274
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
Sep 26, 2004
Sep 26, 2004
275
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
276
277
memset(info, '\0', sizeof (QPAKinfo));
Mar 14, 2005
Mar 14, 2005
278
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
279
280
281
282
283
284
285
286
287
288
289
if (info->filename == NULL)
{
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
goto QPAK_openArchive_failed;
} /* if */
if (!qpak_load_entries(name, forWriting, info))
goto QPAK_openArchive_failed;
strcpy(info->filename, name);
info->last_mod_time = modtime;
Jan 28, 2010
Jan 28, 2010
290
return info;
291
292
QPAK_openArchive_failed:
Sep 26, 2004
Sep 26, 2004
293
if (info != NULL)
294
{
Sep 26, 2004
Sep 26, 2004
295
if (info->filename != NULL)
Mar 14, 2005
Mar 14, 2005
296
allocator.Free(info->filename);
Sep 26, 2004
Sep 26, 2004
297
if (info->entries != NULL)
Mar 14, 2005
Mar 14, 2005
298
299
allocator.Free(info->entries);
allocator.Free(info);
300
301
} /* if */
Jan 28, 2010
Jan 28, 2010
302
return NULL;
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
} /* QPAK_openArchive */
static PHYSFS_sint32 qpak_find_start_of_dir(QPAKinfo *info, const char *path,
int stop_on_first_find)
{
PHYSFS_sint32 lo = 0;
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
PHYSFS_sint32 middle;
PHYSFS_uint32 dlen = strlen(path);
PHYSFS_sint32 retval = -1;
const char *name;
int rc;
if (*path == '\0') /* root dir? */
Jan 28, 2010
Jan 28, 2010
318
return 0;
319
320
321
322
323
324
325
326
if ((dlen > 0) && (path[dlen - 1] == '/')) /* ignore trailing slash. */
dlen--;
while (lo <= hi)
{
middle = lo + ((hi - lo) / 2);
name = info->entries[middle].name;
Nov 9, 2003
Nov 9, 2003
327
rc = QPAK_strncmp(path, name, dlen);
328
329
330
331
332
333
334
335
336
337
if (rc == 0)
{
char ch = name[dlen];
if (ch < '/') /* make sure this isn't just a substr match. */
rc = -1;
else if (ch > '/')
rc = 1;
else
{
if (stop_on_first_find) /* Just checking dir's existance? */
Jan 28, 2010
Jan 28, 2010
338
return middle;
339
340
if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
Jan 28, 2010
Jan 28, 2010
341
return (middle + 1);
342
343
344
345
346
347
348
349
350
351
352
353
354
/* there might be more entries earlier in the list. */
retval = middle;
hi = middle - 1;
} /* else */
} /* if */
if (rc > 0)
lo = middle + 1;
else
hi = middle - 1;
} /* while */
Jan 28, 2010
Jan 28, 2010
355
return retval;
356
357
358
} /* qpak_find_start_of_dir */
Sep 29, 2004
Sep 29, 2004
359
360
361
362
/*
* Moved to seperate function so we can use alloca then immediately throw
* away the allocated stack space...
*/
Sep 18, 2005
Sep 18, 2005
363
364
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
const char *odir, const char *str, PHYSFS_sint32 ln)
Sep 29, 2004
Sep 29, 2004
365
{
Mar 24, 2007
Mar 24, 2007
366
char *newstr = __PHYSFS_smallAlloc(ln + 1);
Sep 29, 2004
Sep 29, 2004
367
368
369
370
371
if (newstr == NULL)
return;
memcpy(newstr, str, ln);
newstr[ln] = '\0';
Sep 18, 2005
Sep 18, 2005
372
cb(callbackdata, odir, newstr);
Mar 24, 2007
Mar 24, 2007
373
__PHYSFS_smallFree(newstr);
Sep 29, 2004
Sep 29, 2004
374
375
376
377
} /* doEnumCallback */
static void QPAK_enumerateFiles(dvoid *opaque, const char *dname,
Sep 18, 2005
Sep 18, 2005
378
379
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
380
{
Sep 26, 2004
Sep 26, 2004
381
QPAKinfo *info = ((QPAKinfo *) opaque);
382
383
PHYSFS_sint32 dlen, dlen_inc, max, i;
Sep 29, 2004
Sep 29, 2004
384
385
386
i = qpak_find_start_of_dir(info, dname, 0);
if (i == -1) /* no such directory. */
return;
387
Sep 29, 2004
Sep 29, 2004
388
389
dlen = strlen(dname);
if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
390
391
392
393
394
395
396
397
398
399
dlen--;
dlen_inc = ((dlen > 0) ? 1 : 0) + dlen;
max = (PHYSFS_sint32) info->entryCount;
while (i < max)
{
char *add;
char *ptr;
PHYSFS_sint32 ln;
char *e = info->entries[i].name;
Sep 29, 2004
Sep 29, 2004
400
if ((dlen) && ((QPAK_strncmp(e, dname, dlen)) || (e[dlen] != '/')))
401
402
403
404
405
break; /* past end of this dir; we're done. */
add = e + dlen_inc;
ptr = strchr(add, '/');
ln = (PHYSFS_sint32) ((ptr) ? ptr-add : strlen(add));
Sep 18, 2005
Sep 18, 2005
406
doEnumCallback(cb, callbackdata, origdir, add, ln);
407
408
409
410
411
412
ln += dlen_inc; /* point past entry to children... */
/* increment counter and skip children of subdirs... */
while ((++i < max) && (ptr != NULL))
{
char *e_new = info->entries[i].name;
Nov 9, 2003
Nov 9, 2003
413
if ((QPAK_strncmp(e, e_new, ln) != 0) || (e_new[ln] != '/'))
414
415
416
417
418
419
420
421
422
423
424
break;
} /* while */
} /* while */
} /* QPAK_enumerateFiles */
/*
* This will find the QPAKentry associated with a path in platform-independent
* notation. Directories don't have QPAKentries associated with them, but
* (*isDir) will be set to non-zero if a dir was hit.
*/
Feb 15, 2010
Feb 15, 2010
425
426
static QPAKentry *qpak_find_entry(const QPAKinfo *info, const char *path,
int *isDir)
427
428
429
430
431
432
433
434
435
436
437
438
439
{
QPAKentry *a = info->entries;
PHYSFS_sint32 pathlen = strlen(path);
PHYSFS_sint32 lo = 0;
PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1);
PHYSFS_sint32 middle;
const char *thispath = NULL;
int rc;
while (lo <= hi)
{
middle = lo + ((hi - lo) / 2);
thispath = a[middle].name;
Nov 9, 2003
Nov 9, 2003
440
rc = QPAK_strncmp(path, thispath, pathlen);
441
442
443
444
445
446
447
448
449
450
451
452
453
if (rc > 0)
lo = middle + 1;
else if (rc < 0)
hi = middle - 1;
else /* substring match...might be dir or entry or nothing. */
{
if (isDir != NULL)
{
*isDir = (thispath[pathlen] == '/');
if (*isDir)
Jan 28, 2010
Jan 28, 2010
454
return NULL;
455
456
457
} /* if */
if (thispath[pathlen] == '\0') /* found entry? */
Jan 28, 2010
Jan 28, 2010
458
return &a[middle];
459
460
461
462
463
464
465
466
467
468
469
470
else
hi = middle - 1; /* adjust search params, try again. */
} /* if */
} /* while */
if (isDir != NULL)
*isDir = 0;
BAIL_MACRO(ERR_NO_SUCH_FILE, NULL);
} /* qpak_find_entry */
Sep 26, 2004
Sep 26, 2004
471
static int QPAK_exists(dvoid *opaque, const char *name)
472
473
{
int isDir;
Sep 26, 2004
Sep 26, 2004
474
QPAKinfo *info = (QPAKinfo *) opaque;
475
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
Jan 28, 2010
Jan 28, 2010
476
return ((entry != NULL) || (isDir));
477
478
479
} /* QPAK_exists */
Sep 26, 2004
Sep 26, 2004
480
static int QPAK_isDirectory(dvoid *opaque, const char *name, int *fileExists)
481
{
Sep 26, 2004
Sep 26, 2004
482
QPAKinfo *info = (QPAKinfo *) opaque;
483
484
485
486
487
int isDir;
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
*fileExists = ((isDir) || (entry != NULL));
if (isDir)
Jan 28, 2010
Jan 28, 2010
488
return 1; /* definitely a dir. */
489
490
491
492
493
BAIL_MACRO(ERR_NO_SUCH_FILE, 0);
} /* QPAK_isDirectory */
Sep 26, 2004
Sep 26, 2004
494
static int QPAK_isSymLink(dvoid *opaque, const char *name, int *fileExists)
495
{
Sep 26, 2004
Sep 26, 2004
496
*fileExists = QPAK_exists(opaque, name);
Jan 28, 2010
Jan 28, 2010
497
return 0; /* never symlinks in a quake pak. */
498
499
500
} /* QPAK_isSymLink */
Sep 26, 2004
Sep 26, 2004
501
static fvoid *QPAK_openRead(dvoid *opaque, const char *fnm, int *fileExists)
502
{
Sep 26, 2004
Sep 26, 2004
503
QPAKinfo *info = ((QPAKinfo *) opaque);
504
505
506
507
508
509
510
511
512
QPAKfileinfo *finfo;
QPAKentry *entry;
int isDir;
entry = qpak_find_entry(info, fnm, &isDir);
*fileExists = ((entry != NULL) || (isDir));
BAIL_IF_MACRO(isDir, ERR_NOT_A_FILE, NULL);
BAIL_IF_MACRO(entry == NULL, ERR_NO_SUCH_FILE, NULL);
Mar 14, 2005
Mar 14, 2005
513
finfo = (QPAKfileinfo *) allocator.Malloc(sizeof (QPAKfileinfo));
Sep 26, 2004
Sep 26, 2004
514
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
515
516
517
518
519
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
if ( (finfo->handle == NULL) ||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
{
Mar 14, 2005
Mar 14, 2005
520
allocator.Free(finfo);
Jan 28, 2010
Jan 28, 2010
521
return NULL;
522
523
524
525
} /* if */
finfo->curPos = 0;
finfo->entry = entry;
Jan 28, 2010
Jan 28, 2010
526
return finfo;
527
528
529
} /* QPAK_openRead */
Sep 26, 2004
Sep 26, 2004
530
static fvoid *QPAK_openWrite(dvoid *opaque, const char *name)
531
532
533
534
535
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* QPAK_openWrite */
Sep 26, 2004
Sep 26, 2004
536
static fvoid *QPAK_openAppend(dvoid *opaque, const char *name)
537
538
539
540
541
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* QPAK_openAppend */
Sep 26, 2004
Sep 26, 2004
542
static int QPAK_remove(dvoid *opaque, const char *name)
543
544
545
546
547
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* QPAK_remove */
Sep 26, 2004
Sep 26, 2004
548
static int QPAK_mkdir(dvoid *opaque, const char *name)
549
550
551
552
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* QPAK_mkdir */
Sep 29, 2004
Sep 29, 2004
553
Aug 22, 2010
Aug 22, 2010
554
static int QPAK_stat(dvoid *opaque, const char *filename, int *exists,
Feb 15, 2010
Feb 15, 2010
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
PHYSFS_Stat *stat)
{
int isDir = 0;
const QPAKinfo *info = (const QPAKinfo *) opaque;
const QPAKentry *entry = qpak_find_entry(info, filename, &isDir);
*exists = ((isDir) || (entry != NULL));
if (!exists)
return 0;
if (isDir)
{
stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
stat->filesize = 0;
} /* if */
else
{
stat->filetype = PHYSFS_FILETYPE_REGULAR;
stat->filesize = entry->size;
} /* else */
stat->modtime = info->last_mod_time;
stat->createtime = info->last_mod_time;
stat->accesstime = 0;
stat->readonly = 1;
Aug 21, 2010
Aug 21, 2010
581
return 1;
Feb 15, 2010
Feb 15, 2010
582
583
584
} /* QPAK_stat */
Sep 29, 2004
Sep 29, 2004
585
586
587
588
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_QPAK =
{
"PAK",
QPAK_ARCHIVE_DESCRIPTION,
Jan 1, 2006
Jan 1, 2006
589
"Ryan C. Gordon <icculus@icculus.org>",
Sep 29, 2004
Sep 29, 2004
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
"http://icculus.org/physfs/",
};
const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
{
&__PHYSFS_ArchiveInfo_QPAK,
QPAK_openArchive, /* openArchive() method */
QPAK_enumerateFiles, /* enumerateFiles() method */
QPAK_exists, /* exists() method */
QPAK_isDirectory, /* isDirectory() method */
QPAK_isSymLink, /* isSymLink() method */
QPAK_openRead, /* openRead() method */
QPAK_openWrite, /* openWrite() method */
QPAK_openAppend, /* openAppend() method */
QPAK_remove, /* remove() method */
QPAK_mkdir, /* mkdir() method */
QPAK_dirClose, /* dirClose() method */
Aug 22, 2010
Aug 22, 2010
608
QPAK_stat, /* stat() method */
Sep 29, 2004
Sep 29, 2004
609
610
611
612
613
614
QPAK_read, /* read() method */
QPAK_write, /* write() method */
QPAK_eof, /* eof() method */
QPAK_tell, /* tell() method */
QPAK_seek, /* seek() method */
QPAK_fileLength, /* fileLength() method */
Aug 22, 2010
Aug 22, 2010
615
QPAK_fileClose /* fileClose() method */
Sep 29, 2004
Sep 29, 2004
616
617
};
618
619
620
#endif /* defined PHYSFS_SUPPORTS_QPAK */
/* end of qpak.c ... */