Skip to content

Latest commit

 

History

History
653 lines (516 loc) · 17.6 KB

archiver_qpak.c

File metadata and controls

653 lines (516 loc) · 17.6 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
209
210
211
212
213
214
215
} /* qpak_open */
static int QPAK_isArchive(const char *filename, int forWriting)
{
void *fh;
PHYSFS_uint32 fileCount;
int retval = qpak_open(filename, forWriting, &fh, &fileCount);
if (fh != NULL)
__PHYSFS_platformClose(fh);
Jan 28, 2010
Jan 28, 2010
216
return retval;
217
218
219
220
221
} /* QPAK_isArchive */
static int qpak_entry_cmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
Feb 20, 2008
Feb 20, 2008
222
223
224
if (one != two)
{
const QPAKentry *a = (const QPAKentry *) _a;
Jan 28, 2010
Jan 28, 2010
225
return QPAK_strcmp(a[one].name, a[two].name);
Feb 20, 2008
Feb 20, 2008
226
227
228
} /* if */
return 0;
229
230
231
232
233
} /* qpak_entry_cmp */
static void qpak_entry_swap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two)
{
Feb 20, 2008
Feb 20, 2008
234
235
236
237
238
239
240
241
242
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 */
243
244
245
246
247
248
249
250
251
252
253
} /* 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
254
info->entries = (QPAKentry*) allocator.Malloc(sizeof(QPAKentry)*fileCount);
255
256
257
258
259
260
261
262
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
263
264
265
if ( (!readAll(fh, &entry->name, sizeof (entry->name))) ||
(!readAll(fh, &entry->startPos, sizeof (entry->startPos))) ||
(!readAll(fh, &entry->size, sizeof(entry->size))) )
266
267
{
__PHYSFS_platformClose(fh);
Jan 28, 2010
Jan 28, 2010
268
return 0;
269
270
271
} /* if */
entry->size = PHYSFS_swapULE32(entry->size);
Aug 21, 2010
Aug 21, 2010
272
entry->startPos = PHYSFS_swapULE32(entry->startPos);
273
274
275
276
277
278
} /* for */
__PHYSFS_platformClose(fh);
__PHYSFS_sort(info->entries, info->entryCount,
qpak_entry_cmp, qpak_entry_swap);
Jan 28, 2010
Jan 28, 2010
279
return 1;
280
281
282
} /* qpak_load_entries */
Sep 26, 2004
Sep 26, 2004
283
static void *QPAK_openArchive(const char *name, int forWriting)
284
{
Mar 14, 2005
Mar 14, 2005
285
QPAKinfo *info = (QPAKinfo *) allocator.Malloc(sizeof (QPAKinfo));
286
287
PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name);
Sep 26, 2004
Sep 26, 2004
288
BAIL_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, NULL);
289
290
memset(info, '\0', sizeof (QPAKinfo));
Mar 14, 2005
Mar 14, 2005
291
info->filename = (char *) allocator.Malloc(strlen(name) + 1);
292
293
294
295
296
297
298
299
300
301
302
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
303
return info;
304
305
QPAK_openArchive_failed:
Sep 26, 2004
Sep 26, 2004
306
if (info != NULL)
307
{
Sep 26, 2004
Sep 26, 2004
308
if (info->filename != NULL)
Mar 14, 2005
Mar 14, 2005
309
allocator.Free(info->filename);
Sep 26, 2004
Sep 26, 2004
310
if (info->entries != NULL)
Mar 14, 2005
Mar 14, 2005
311
312
allocator.Free(info->entries);
allocator.Free(info);
313
314
} /* if */
Jan 28, 2010
Jan 28, 2010
315
return NULL;
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
} /* 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
331
return 0;
332
333
334
335
336
337
338
339
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
340
rc = QPAK_strncmp(path, name, dlen);
341
342
343
344
345
346
347
348
349
350
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
351
return middle;
352
353
if (name[dlen + 1] == '\0') /* Skip initial dir entry. */
Jan 28, 2010
Jan 28, 2010
354
return (middle + 1);
355
356
357
358
359
360
361
362
363
364
365
366
367
/* 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
368
return retval;
369
370
371
} /* qpak_find_start_of_dir */
Sep 29, 2004
Sep 29, 2004
372
373
374
375
/*
* Moved to seperate function so we can use alloca then immediately throw
* away the allocated stack space...
*/
Sep 18, 2005
Sep 18, 2005
376
377
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
const char *odir, const char *str, PHYSFS_sint32 ln)
Sep 29, 2004
Sep 29, 2004
378
{
Mar 24, 2007
Mar 24, 2007
379
char *newstr = __PHYSFS_smallAlloc(ln + 1);
Sep 29, 2004
Sep 29, 2004
380
381
382
383
384
if (newstr == NULL)
return;
memcpy(newstr, str, ln);
newstr[ln] = '\0';
Sep 18, 2005
Sep 18, 2005
385
cb(callbackdata, odir, newstr);
Mar 24, 2007
Mar 24, 2007
386
__PHYSFS_smallFree(newstr);
Sep 29, 2004
Sep 29, 2004
387
388
389
390
} /* doEnumCallback */
static void QPAK_enumerateFiles(dvoid *opaque, const char *dname,
Sep 18, 2005
Sep 18, 2005
391
392
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
393
{
Sep 26, 2004
Sep 26, 2004
394
QPAKinfo *info = ((QPAKinfo *) opaque);
395
396
PHYSFS_sint32 dlen, dlen_inc, max, i;
Sep 29, 2004
Sep 29, 2004
397
398
399
i = qpak_find_start_of_dir(info, dname, 0);
if (i == -1) /* no such directory. */
return;
400
Sep 29, 2004
Sep 29, 2004
401
402
dlen = strlen(dname);
if ((dlen > 0) && (dname[dlen - 1] == '/')) /* ignore trailing slash. */
403
404
405
406
407
408
409
410
411
412
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
413
if ((dlen) && ((QPAK_strncmp(e, dname, dlen)) || (e[dlen] != '/')))
414
415
416
417
418
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
419
doEnumCallback(cb, callbackdata, origdir, add, ln);
420
421
422
423
424
425
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
426
if ((QPAK_strncmp(e, e_new, ln) != 0) || (e_new[ln] != '/'))
427
428
429
430
431
432
433
434
435
436
437
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
438
439
static QPAKentry *qpak_find_entry(const QPAKinfo *info, const char *path,
int *isDir)
440
441
442
443
444
445
446
447
448
449
450
451
452
{
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
453
rc = QPAK_strncmp(path, thispath, pathlen);
454
455
456
457
458
459
460
461
462
463
464
465
466
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
467
return NULL;
468
469
470
} /* if */
if (thispath[pathlen] == '\0') /* found entry? */
Jan 28, 2010
Jan 28, 2010
471
return &a[middle];
472
473
474
475
476
477
478
479
480
481
482
483
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
484
static int QPAK_exists(dvoid *opaque, const char *name)
485
486
{
int isDir;
Sep 26, 2004
Sep 26, 2004
487
QPAKinfo *info = (QPAKinfo *) opaque;
488
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
Jan 28, 2010
Jan 28, 2010
489
return ((entry != NULL) || (isDir));
490
491
492
} /* QPAK_exists */
Sep 26, 2004
Sep 26, 2004
493
static int QPAK_isDirectory(dvoid *opaque, const char *name, int *fileExists)
494
{
Sep 26, 2004
Sep 26, 2004
495
QPAKinfo *info = (QPAKinfo *) opaque;
496
497
498
499
500
int isDir;
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
*fileExists = ((isDir) || (entry != NULL));
if (isDir)
Jan 28, 2010
Jan 28, 2010
501
return 1; /* definitely a dir. */
502
503
504
505
506
BAIL_MACRO(ERR_NO_SUCH_FILE, 0);
} /* QPAK_isDirectory */
Sep 26, 2004
Sep 26, 2004
507
static int QPAK_isSymLink(dvoid *opaque, const char *name, int *fileExists)
508
{
Sep 26, 2004
Sep 26, 2004
509
*fileExists = QPAK_exists(opaque, name);
Jan 28, 2010
Jan 28, 2010
510
return 0; /* never symlinks in a quake pak. */
511
512
513
} /* QPAK_isSymLink */
Sep 26, 2004
Sep 26, 2004
514
static PHYSFS_sint64 QPAK_getLastModTime(dvoid *opaque,
515
516
517
518
const char *name,
int *fileExists)
{
int isDir;
Sep 26, 2004
Sep 26, 2004
519
QPAKinfo *info = ((QPAKinfo *) opaque);
520
521
522
523
524
525
526
PHYSFS_sint64 retval = -1;
QPAKentry *entry = qpak_find_entry(info, name, &isDir);
*fileExists = ((isDir) || (entry != NULL));
if (*fileExists) /* use time of QPAK itself in the physical filesystem. */
retval = info->last_mod_time;
Jan 28, 2010
Jan 28, 2010
527
return retval;
528
529
530
} /* QPAK_getLastModTime */
Sep 26, 2004
Sep 26, 2004
531
static fvoid *QPAK_openRead(dvoid *opaque, const char *fnm, int *fileExists)
532
{
Sep 26, 2004
Sep 26, 2004
533
QPAKinfo *info = ((QPAKinfo *) opaque);
534
535
536
537
538
539
540
541
542
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
543
finfo = (QPAKfileinfo *) allocator.Malloc(sizeof (QPAKfileinfo));
Sep 26, 2004
Sep 26, 2004
544
BAIL_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, NULL);
545
546
547
548
549
finfo->handle = __PHYSFS_platformOpenRead(info->filename);
if ( (finfo->handle == NULL) ||
(!__PHYSFS_platformSeek(finfo->handle, entry->startPos)) )
{
Mar 14, 2005
Mar 14, 2005
550
allocator.Free(finfo);
Jan 28, 2010
Jan 28, 2010
551
return NULL;
552
553
554
555
} /* if */
finfo->curPos = 0;
finfo->entry = entry;
Jan 28, 2010
Jan 28, 2010
556
return finfo;
557
558
559
} /* QPAK_openRead */
Sep 26, 2004
Sep 26, 2004
560
static fvoid *QPAK_openWrite(dvoid *opaque, const char *name)
561
562
563
564
565
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* QPAK_openWrite */
Sep 26, 2004
Sep 26, 2004
566
static fvoid *QPAK_openAppend(dvoid *opaque, const char *name)
567
568
569
570
571
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
} /* QPAK_openAppend */
Sep 26, 2004
Sep 26, 2004
572
static int QPAK_remove(dvoid *opaque, const char *name)
573
574
575
576
577
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* QPAK_remove */
Sep 26, 2004
Sep 26, 2004
578
static int QPAK_mkdir(dvoid *opaque, const char *name)
579
580
581
582
{
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
} /* QPAK_mkdir */
Sep 29, 2004
Sep 29, 2004
583
Aug 22, 2010
Aug 22, 2010
584
static int QPAK_stat(dvoid *opaque, const char *filename, int *exists,
Feb 15, 2010
Feb 15, 2010
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
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
611
return 1;
Feb 15, 2010
Feb 15, 2010
612
613
614
} /* QPAK_stat */
Sep 29, 2004
Sep 29, 2004
615
616
617
618
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_QPAK =
{
"PAK",
QPAK_ARCHIVE_DESCRIPTION,
Jan 1, 2006
Jan 1, 2006
619
"Ryan C. Gordon <icculus@icculus.org>",
Sep 29, 2004
Sep 29, 2004
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
"http://icculus.org/physfs/",
};
const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
{
&__PHYSFS_ArchiveInfo_QPAK,
QPAK_isArchive, /* isArchive() method */
QPAK_openArchive, /* openArchive() method */
QPAK_enumerateFiles, /* enumerateFiles() method */
QPAK_exists, /* exists() method */
QPAK_isDirectory, /* isDirectory() method */
QPAK_isSymLink, /* isSymLink() method */
QPAK_getLastModTime, /* getLastModTime() 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
640
QPAK_stat, /* stat() method */
Sep 29, 2004
Sep 29, 2004
641
642
643
644
645
646
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
647
QPAK_fileClose /* fileClose() method */
Sep 29, 2004
Sep 29, 2004
648
649
};
650
651
652
#endif /* defined PHYSFS_SUPPORTS_QPAK */
/* end of qpak.c ... */