Skip to content

Latest commit

 

History

History
2468 lines (1974 loc) · 67 KB

physfs.c

File metadata and controls

2468 lines (1974 loc) · 67 KB
 
1
2
3
4
5
/**
* PhysicsFS; a portable, flexible file i/o abstraction.
*
* Documentation is in physfs.h. It's verbose, honest. :)
*
Mar 11, 2007
Mar 11, 2007
6
* Please see the file LICENSE.txt in the source's root directory.
7
8
9
10
*
* This file written by Ryan C. Gordon.
*/
Aug 21, 2010
Aug 21, 2010
11
12
/* !!! FIXME: ERR_PAST_EOF shouldn't trigger for reads. Just return zero. */
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "physfs.h"
Jul 6, 2001
Jul 6, 2001
18
19
20
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
Sep 26, 2004
Sep 26, 2004
21
22
23
typedef struct __PHYSFS_DIRHANDLE__
{
Sep 26, 2004
Sep 26, 2004
24
25
void *opaque; /* Instance data unique to the archiver. */
char *dirName; /* Path to archive in platform-dependent notation. */
Mar 13, 2005
Mar 13, 2005
26
char *mountPoint; /* Mountpoint in virtual file tree. */
Sep 26, 2004
Sep 26, 2004
27
28
const PHYSFS_Archiver *funcs; /* Ptr to archiver info for this handle. */
struct __PHYSFS_DIRHANDLE__ *next; /* linked list stuff. */
Sep 26, 2004
Sep 26, 2004
29
30
31
} DirHandle;
Sep 26, 2004
Sep 26, 2004
32
33
typedef struct __PHYSFS_FILEHANDLE__
{
Aug 30, 2010
Aug 30, 2010
34
PHYSFS_Io *io; /* Instance data unique to the archiver for this file. */
Sep 26, 2004
Sep 26, 2004
35
36
37
38
39
40
41
42
43
44
PHYSFS_uint8 forReading; /* Non-zero if reading, zero if write/append */
const DirHandle *dirHandle; /* Archiver instance that created this */
PHYSFS_uint8 *buffer; /* Buffer, if set (NULL otherwise). Don't touch! */
PHYSFS_uint32 bufsize; /* Bufsize, if set (0 otherwise). Don't touch! */
PHYSFS_uint32 buffill; /* Buffer fill size. Don't touch! */
PHYSFS_uint32 bufpos; /* Buffer position. Don't touch! */
struct __PHYSFS_FILEHANDLE__ *next; /* linked list stuff. */
} FileHandle;
45
46
typedef struct __PHYSFS_ERRMSGTYPE__
{
Sep 6, 2009
Sep 6, 2009
47
void *tid;
48
49
50
51
52
int errorAvailable;
char errorString[80];
struct __PHYSFS_ERRMSGTYPE__ *next;
} ErrMsg;
Jul 6, 2001
Jul 6, 2001
53
Mar 10, 2007
Mar 10, 2007
54
/* The various i/o drivers...some of these may not be compiled in. */
Sep 26, 2004
Sep 26, 2004
55
56
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_ZIP;
extern const PHYSFS_Archiver __PHYSFS_Archiver_ZIP;
Apr 11, 2006
Apr 11, 2006
57
58
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_LZMA;
extern const PHYSFS_Archiver __PHYSFS_Archiver_LZMA;
Sep 26, 2004
Sep 26, 2004
59
60
61
62
63
64
65
66
67
68
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_GRP;
extern const PHYSFS_Archiver __PHYSFS_Archiver_GRP;
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_QPAK;
extern const PHYSFS_Archiver __PHYSFS_Archiver_QPAK;
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_HOG;
extern const PHYSFS_Archiver __PHYSFS_Archiver_HOG;
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_MVL;
extern const PHYSFS_Archiver __PHYSFS_Archiver_MVL;
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_WAD;
extern const PHYSFS_Archiver __PHYSFS_Archiver_WAD;
Mar 10, 2007
Mar 10, 2007
69
extern const PHYSFS_Archiver __PHYSFS_Archiver_DIR;
Mar 17, 2010
Mar 17, 2010
70
71
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_ISO9660;
extern const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660;
Jul 6, 2001
Jul 6, 2001
72
Aug 9, 2002
Aug 9, 2002
73
Jul 6, 2001
Jul 6, 2001
74
static const PHYSFS_ArchiveInfo *supported_types[] =
75
76
{
#if (defined PHYSFS_SUPPORTS_ZIP)
Jul 6, 2001
Jul 6, 2001
77
&__PHYSFS_ArchiveInfo_ZIP,
78
#endif
Mar 9, 2007
Mar 9, 2007
79
#if (defined PHYSFS_SUPPORTS_7Z)
Apr 11, 2006
Apr 11, 2006
80
81
&__PHYSFS_ArchiveInfo_LZMA,
#endif
Jul 8, 2001
Jul 8, 2001
82
83
84
#if (defined PHYSFS_SUPPORTS_GRP)
&__PHYSFS_ArchiveInfo_GRP,
#endif
Jul 21, 2003
Jul 21, 2003
85
86
87
#if (defined PHYSFS_SUPPORTS_QPAK)
&__PHYSFS_ArchiveInfo_QPAK,
#endif
Mar 30, 2003
Mar 30, 2003
88
89
90
91
92
93
#if (defined PHYSFS_SUPPORTS_HOG)
&__PHYSFS_ArchiveInfo_HOG,
#endif
#if (defined PHYSFS_SUPPORTS_MVL)
&__PHYSFS_ArchiveInfo_MVL,
#endif
Dec 15, 2003
Dec 15, 2003
94
95
#if (defined PHYSFS_SUPPORTS_WAD)
&__PHYSFS_ArchiveInfo_WAD,
Apr 9, 2004
Apr 9, 2004
96
#endif
Mar 17, 2010
Mar 17, 2010
97
#if (defined PHYSFS_SUPPORTS_ISO9660)
Mar 17, 2010
Mar 17, 2010
98
&__PHYSFS_ArchiveInfo_ISO9660,
Mar 17, 2010
Mar 17, 2010
99
#endif
100
101
102
NULL
};
Sep 26, 2004
Sep 26, 2004
103
static const PHYSFS_Archiver *archivers[] =
Jul 6, 2001
Jul 6, 2001
104
105
{
#if (defined PHYSFS_SUPPORTS_ZIP)
Sep 26, 2004
Sep 26, 2004
106
&__PHYSFS_Archiver_ZIP,
Jul 6, 2001
Jul 6, 2001
107
#endif
Mar 9, 2007
Mar 9, 2007
108
#if (defined PHYSFS_SUPPORTS_7Z)
Apr 11, 2006
Apr 11, 2006
109
110
&__PHYSFS_Archiver_LZMA,
#endif
Jul 8, 2001
Jul 8, 2001
111
#if (defined PHYSFS_SUPPORTS_GRP)
Sep 26, 2004
Sep 26, 2004
112
&__PHYSFS_Archiver_GRP,
Jul 8, 2001
Jul 8, 2001
113
#endif
Jul 21, 2003
Jul 21, 2003
114
#if (defined PHYSFS_SUPPORTS_QPAK)
Sep 26, 2004
Sep 26, 2004
115
&__PHYSFS_Archiver_QPAK,
Jul 21, 2003
Jul 21, 2003
116
#endif
Mar 30, 2003
Mar 30, 2003
117
#if (defined PHYSFS_SUPPORTS_HOG)
Sep 26, 2004
Sep 26, 2004
118
&__PHYSFS_Archiver_HOG,
Mar 30, 2003
Mar 30, 2003
119
120
#endif
#if (defined PHYSFS_SUPPORTS_MVL)
Sep 26, 2004
Sep 26, 2004
121
&__PHYSFS_Archiver_MVL,
Mar 30, 2003
Mar 30, 2003
122
#endif
Dec 15, 2003
Dec 15, 2003
123
#if (defined PHYSFS_SUPPORTS_WAD)
Sep 26, 2004
Sep 26, 2004
124
&__PHYSFS_Archiver_WAD,
Apr 9, 2004
Apr 9, 2004
125
#endif
Mar 17, 2010
Mar 17, 2010
126
#if (defined PHYSFS_SUPPORTS_ISO9660)
Mar 17, 2010
Mar 17, 2010
127
&__PHYSFS_Archiver_ISO9660,
Mar 17, 2010
Mar 17, 2010
128
#endif
Jul 6, 2001
Jul 6, 2001
129
130
NULL
};
131
132
133
Jul 6, 2001
Jul 6, 2001
134
135
136
/* General PhysicsFS state ... */
static int initialized = 0;
static ErrMsg *errorMessages = NULL;
Sep 26, 2004
Sep 26, 2004
137
138
139
140
static DirHandle *searchPath = NULL;
static DirHandle *writeDir = NULL;
static FileHandle *openWriteList = NULL;
static FileHandle *openReadList = NULL;
Jul 6, 2001
Jul 6, 2001
141
142
143
144
static char *baseDir = NULL;
static char *userDir = NULL;
static int allowSymLinks = 0;
Mar 30, 2002
Mar 30, 2002
145
146
147
/* mutexes ... */
static void *errorLock = NULL; /* protects error message list. */
static void *stateLock = NULL; /* protects other PhysFS static state. */
Jul 6, 2001
Jul 6, 2001
148
Sep 23, 2004
Sep 23, 2004
149
150
/* allocator ... */
static int externalAllocator = 0;
Mar 14, 2005
Mar 14, 2005
151
PHYSFS_Allocator allocator;
Sep 23, 2004
Sep 23, 2004
152
Jul 6, 2001
Jul 6, 2001
153
Aug 30, 2010
Aug 30, 2010
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
208
209
210
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
256
257
258
259
260
261
262
263
264
265
266
267
268
269
/* PHYSFS_Io implementation for i/o to physical filesystem... */
/* !!! FIXME: maybe refcount the paths in a string pool? */
typedef struct __PHYSFS_NativeIoInfo
{
void *handle;
const char *path;
int mode; /* 'r', 'w', or 'a' */
} NativeIoInfo;
static PHYSFS_sint64 nativeIo_read(PHYSFS_Io *io, void *buf, PHYSFS_uint64 len)
{
NativeIoInfo *info = (NativeIoInfo *) io->opaque;
return __PHYSFS_platformRead(info->handle, buf, len);
} /* nativeIo_read */
static PHYSFS_sint64 nativeIo_write(PHYSFS_Io *io, const void *buffer,
PHYSFS_uint64 len)
{
NativeIoInfo *info = (NativeIoInfo *) io->opaque;
return __PHYSFS_platformWrite(info->handle, buffer, len);
} /* nativeIo_write */
static int nativeIo_seek(PHYSFS_Io *io, PHYSFS_uint64 offset)
{
NativeIoInfo *info = (NativeIoInfo *) io->opaque;
return __PHYSFS_platformSeek(info->handle, offset);
} /* nativeIo_seek */
static PHYSFS_sint64 nativeIo_tell(PHYSFS_Io *io)
{
NativeIoInfo *info = (NativeIoInfo *) io->opaque;
return __PHYSFS_platformTell(info->handle);
} /* nativeIo_tell */
static PHYSFS_sint64 nativeIo_length(PHYSFS_Io *io)
{
NativeIoInfo *info = (NativeIoInfo *) io->opaque;
return __PHYSFS_platformFileLength(info->handle);
} /* nativeIo_length */
static PHYSFS_Io *nativeIo_duplicate(PHYSFS_Io *io)
{
NativeIoInfo *info = (NativeIoInfo *) io->opaque;
return __PHYSFS_createNativeIo(info->path, info->mode);
} /* nativeIo_duplicate */
static int nativeIo_flush(PHYSFS_Io *io)
{
return __PHYSFS_platformFlush(io->opaque);
} /* nativeIo_flush */
static void nativeIo_destroy(PHYSFS_Io *io)
{
NativeIoInfo *info = (NativeIoInfo *) io->opaque;
__PHYSFS_platformClose(info->handle);
allocator.Free((void *) info->path);
allocator.Free(info);
allocator.Free(io);
} /* nativeIo_destroy */
static const PHYSFS_Io __PHYSFS_nativeIoInterface =
{
nativeIo_read,
nativeIo_write,
nativeIo_seek,
nativeIo_tell,
nativeIo_length,
nativeIo_duplicate,
nativeIo_flush,
nativeIo_destroy,
NULL
};
PHYSFS_Io *__PHYSFS_createNativeIo(const char *path, const int mode)
{
PHYSFS_Io *io = NULL;
NativeIoInfo *info = NULL;
void *handle = NULL;
char *pathdup = NULL;
assert((mode == 'r') || (mode == 'w') || (mode == 'a'));
io = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io));
GOTO_IF_MACRO(io == NULL, ERR_OUT_OF_MEMORY, createNativeIo_failed);
info = (NativeIoInfo *) allocator.Malloc(sizeof (NativeIoInfo));
GOTO_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, createNativeIo_failed);
pathdup = (char *) allocator.Malloc(strlen(path) + 1);
GOTO_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, createNativeIo_failed);
if (mode == 'r')
handle = __PHYSFS_platformOpenRead(path);
else if (mode == 'w')
handle = __PHYSFS_platformOpenWrite(path);
else if (mode == 'a')
handle = __PHYSFS_platformOpenAppend(path);
GOTO_IF_MACRO(handle == NULL, NULL, createNativeIo_failed);
strcpy(pathdup, path);
info->handle = handle;
info->path = pathdup;
info->mode = mode;
memcpy(io, &__PHYSFS_nativeIoInterface, sizeof (*io));
io->opaque = info;
return io;
createNativeIo_failed:
if (handle != NULL) __PHYSFS_platformClose(handle);
if (pathdup != NULL) allocator.Free(pathdup);
if (info != NULL) allocator.Free(info);
if (io != NULL) allocator.Free(io);
return NULL;
} /* __PHYSFS_createNativeIo */
Jul 6, 2001
Jul 6, 2001
270
271
/* functions ... */
Sep 29, 2004
Sep 29, 2004
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
typedef struct
{
char **list;
PHYSFS_uint32 size;
const char *errorstr;
} EnumStringListCallbackData;
static void enumStringListCallback(void *data, const char *str)
{
void *ptr;
char *newstr;
EnumStringListCallbackData *pecd = (EnumStringListCallbackData *) data;
if (pecd->errorstr)
return;
Mar 14, 2005
Mar 14, 2005
288
289
ptr = allocator.Realloc(pecd->list, (pecd->size + 2) * sizeof (char *));
newstr = (char *) allocator.Malloc(strlen(str) + 1);
Sep 29, 2004
Sep 29, 2004
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
if (ptr != NULL)
pecd->list = (char **) ptr;
if ((ptr == NULL) || (newstr == NULL))
{
pecd->errorstr = ERR_OUT_OF_MEMORY;
pecd->list[pecd->size] = NULL;
PHYSFS_freeList(pecd->list);
return;
} /* if */
strcpy(newstr, str);
pecd->list[pecd->size] = newstr;
pecd->size++;
} /* enumStringListCallback */
static char **doEnumStringList(void (*func)(PHYSFS_StringCallback, void *))
{
EnumStringListCallbackData ecd;
memset(&ecd, '\0', sizeof (ecd));
Mar 14, 2005
Mar 14, 2005
311
ecd.list = (char **) allocator.Malloc(sizeof (char *));
Sep 29, 2004
Sep 29, 2004
312
313
314
315
BAIL_IF_MACRO(ecd.list == NULL, ERR_OUT_OF_MEMORY, NULL);
func(enumStringListCallback, &ecd);
BAIL_IF_MACRO(ecd.errorstr != NULL, ecd.errorstr, NULL);
ecd.list[ecd.size] = NULL;
Jan 28, 2010
Jan 28, 2010
316
return ecd.list;
Sep 29, 2004
Sep 29, 2004
317
318
319
} /* doEnumStringList */
Jan 31, 2003
Jan 31, 2003
320
static void __PHYSFS_bubble_sort(void *a, PHYSFS_uint32 lo, PHYSFS_uint32 hi,
Aug 20, 2002
Aug 20, 2002
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
int (*cmpfn)(void *, PHYSFS_uint32, PHYSFS_uint32),
void (*swapfn)(void *, PHYSFS_uint32, PHYSFS_uint32))
{
PHYSFS_uint32 i;
int sorted;
do
{
sorted = 1;
for (i = lo; i < hi; i++)
{
if (cmpfn(a, i, i + 1) > 0)
{
swapfn(a, i, i + 1);
sorted = 0;
} /* if */
} /* for */
} while (!sorted);
} /* __PHYSFS_bubble_sort */
Jan 31, 2003
Jan 31, 2003
342
static void __PHYSFS_quick_sort(void *a, PHYSFS_uint32 lo, PHYSFS_uint32 hi,
Aug 20, 2002
Aug 20, 2002
343
344
345
346
347
348
349
int (*cmpfn)(void *, PHYSFS_uint32, PHYSFS_uint32),
void (*swapfn)(void *, PHYSFS_uint32, PHYSFS_uint32))
{
PHYSFS_uint32 i;
PHYSFS_uint32 j;
PHYSFS_uint32 v;
Jul 20, 2003
Jul 20, 2003
350
if ((hi - lo) <= PHYSFS_QUICKSORT_THRESHOLD)
Aug 20, 2002
Aug 20, 2002
351
352
__PHYSFS_bubble_sort(a, lo, hi, cmpfn, swapfn);
else
Jul 20, 2003
Jul 20, 2003
353
354
{
i = (hi + lo) / 2;
Aug 20, 2002
Aug 20, 2002
355
356
if (cmpfn(a, lo, i) > 0) swapfn(a, lo, i);
Jul 20, 2003
Jul 20, 2003
357
358
359
360
361
362
363
364
365
366
367
368
if (cmpfn(a, lo, hi) > 0) swapfn(a, lo, hi);
if (cmpfn(a, i, hi) > 0) swapfn(a, i, hi);
j = hi - 1;
swapfn(a, i, j);
i = lo;
v = j;
while (1)
{
while(cmpfn(a, ++i, v) < 0) { /* do nothing */ }
while(cmpfn(a, --j, v) > 0) { /* do nothing */ }
if (j < i)
Aug 20, 2002
Aug 20, 2002
369
break;
Jul 20, 2003
Jul 20, 2003
370
371
swapfn(a, i, j);
} /* while */
Feb 28, 2009
Feb 28, 2009
372
373
if (i != (hi-1))
swapfn(a, i, hi-1);
Jul 20, 2003
Jul 20, 2003
374
375
376
__PHYSFS_quick_sort(a, lo, j, cmpfn, swapfn);
__PHYSFS_quick_sort(a, i+1, hi, cmpfn, swapfn);
} /* else */
Aug 20, 2002
Aug 20, 2002
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
} /* __PHYSFS_quick_sort */
void __PHYSFS_sort(void *entries, PHYSFS_uint32 max,
int (*cmpfn)(void *, PHYSFS_uint32, PHYSFS_uint32),
void (*swapfn)(void *, PHYSFS_uint32, PHYSFS_uint32))
{
/*
* Quicksort w/ Bubblesort fallback algorithm inspired by code from here:
* http://www.cs.ubc.ca/spider/harrison/Java/sorting-demo.html
*/
__PHYSFS_quick_sort(entries, 0, max - 1, cmpfn, swapfn);
} /* __PHYSFS_sort */
392
393
394
static ErrMsg *findErrorForCurrentThread(void)
{
ErrMsg *i;
Sep 6, 2009
Sep 6, 2009
395
void *tid;
Jun 8, 2002
Jun 8, 2002
397
if (errorLock != NULL)
Apr 8, 2002
Apr 8, 2002
398
399
__PHYSFS_platformGrabMutex(errorLock);
400
401
if (errorMessages != NULL)
{
Apr 3, 2002
Apr 3, 2002
402
tid = __PHYSFS_platformGetThreadID();
403
404
405
406
for (i = errorMessages; i != NULL; i = i->next)
{
if (i->tid == tid)
Mar 30, 2002
Mar 30, 2002
407
{
Jun 8, 2002
Jun 8, 2002
408
409
if (errorLock != NULL)
__PHYSFS_platformReleaseMutex(errorLock);
Jan 28, 2010
Jan 28, 2010
410
return i;
Mar 30, 2002
Mar 30, 2002
411
} /* if */
412
413
} /* for */
} /* if */
Apr 8, 2002
Apr 8, 2002
414
Jun 8, 2002
Jun 8, 2002
415
if (errorLock != NULL)
Apr 8, 2002
Apr 8, 2002
416
__PHYSFS_platformReleaseMutex(errorLock);
Jan 28, 2010
Jan 28, 2010
418
return NULL; /* no error available. */
419
420
421
} /* findErrorForCurrentThread */
Jul 6, 2001
Jul 6, 2001
422
void __PHYSFS_setError(const char *str)
Jul 7, 2001
Jul 7, 2001
424
425
426
427
428
429
ErrMsg *err;
if (str == NULL)
return;
err = findErrorForCurrentThread();
430
431
432
if (err == NULL)
{
Mar 14, 2005
Mar 14, 2005
433
err = (ErrMsg *) allocator.Malloc(sizeof (ErrMsg));
434
435
436
if (err == NULL)
return; /* uhh...? */
Aug 1, 2001
Aug 1, 2001
437
memset((void *) err, '\0', sizeof (ErrMsg));
Apr 3, 2002
Apr 3, 2002
438
err->tid = __PHYSFS_platformGetThreadID();
Mar 30, 2002
Mar 30, 2002
439
Jun 8, 2002
Jun 8, 2002
440
441
442
if (errorLock != NULL)
__PHYSFS_platformGrabMutex(errorLock);
Jul 6, 2001
Jul 6, 2001
443
444
err->next = errorMessages;
errorMessages = err;
Jun 8, 2002
Jun 8, 2002
445
446
447
if (errorLock != NULL)
__PHYSFS_platformReleaseMutex(errorLock);
448
449
450
451
452
} /* if */
err->errorAvailable = 1;
strncpy(err->errorString, str, sizeof (err->errorString));
err->errorString[sizeof (err->errorString) - 1] = '\0';
Jul 6, 2001
Jul 6, 2001
453
} /* __PHYSFS_setError */
Mar 30, 2002
Mar 30, 2002
456
457
458
459
460
const char *PHYSFS_getLastError(void)
{
ErrMsg *err = findErrorForCurrentThread();
if ((err == NULL) || (!err->errorAvailable))
Jan 28, 2010
Jan 28, 2010
461
return NULL;
Mar 30, 2002
Mar 30, 2002
462
463
err->errorAvailable = 0;
Jan 28, 2010
Jan 28, 2010
464
return err->errorString;
Mar 30, 2002
Mar 30, 2002
465
466
467
468
} /* PHYSFS_getLastError */
/* MAKE SURE that errorLock is held before calling this! */
Jul 7, 2001
Jul 7, 2001
469
470
471
472
473
474
475
static void freeErrorMessages(void)
{
ErrMsg *i;
ErrMsg *next;
for (i = errorMessages; i != NULL; i = next)
{
Jul 9, 2001
Jul 9, 2001
476
next = i->next;
Mar 14, 2005
Mar 14, 2005
477
allocator.Free(i);
Jul 7, 2001
Jul 7, 2001
478
} /* for */
Jun 8, 2002
Jun 8, 2002
479
480
errorMessages = NULL;
Jul 7, 2001
Jul 7, 2001
481
482
483
} /* freeErrorMessages */
484
485
486
487
488
489
490
491
492
493
494
void PHYSFS_getLinkedVersion(PHYSFS_Version *ver)
{
if (ver != NULL)
{
ver->major = PHYSFS_VER_MAJOR;
ver->minor = PHYSFS_VER_MINOR;
ver->patch = PHYSFS_VER_PATCH;
} /* if */
} /* PHYSFS_getLinkedVersion */
Jul 26, 2002
Jul 26, 2002
495
496
static const char *find_filename_extension(const char *fname)
{
Aug 30, 2010
Aug 30, 2010
497
498
const char *retval = NULL;
if (fname != NULL)
Jul 26, 2002
Jul 26, 2002
499
{
Aug 30, 2010
Aug 30, 2010
500
501
retval = strchr(fname, '.');
const char *p = retval;
Jul 26, 2002
Jul 26, 2002
502
Aug 30, 2010
Aug 30, 2010
503
504
505
506
507
508
509
510
511
512
while (p != NULL)
{
p = strchr(p + 1, '.');
if (p != NULL)
retval = p;
} /* while */
if (retval != NULL)
retval++; /* skip '.' */
} /* if */
Jul 26, 2002
Jul 26, 2002
513
Jan 28, 2010
Jan 28, 2010
514
return retval;
Jul 26, 2002
Jul 26, 2002
515
516
517
} /* find_filename_extension */
Aug 30, 2010
Aug 30, 2010
518
static DirHandle *tryOpenDir(PHYSFS_Io *io, const PHYSFS_Archiver *funcs,
Sep 26, 2004
Sep 26, 2004
519
const char *d, int forWriting)
Sep 26, 2004
Sep 26, 2004
520
521
{
DirHandle *retval = NULL;
Aug 30, 2010
Aug 30, 2010
522
523
524
525
526
527
void *opaque = NULL;
if (io != NULL)
BAIL_IF_MACRO(!io->seek(io, 0), NULL, NULL);
opaque = funcs->openArchive(io, d, forWriting);
Aug 24, 2010
Aug 24, 2010
528
if (opaque != NULL)
Sep 26, 2004
Sep 26, 2004
529
{
Aug 24, 2010
Aug 24, 2010
530
531
532
533
retval = (DirHandle *) allocator.Malloc(sizeof (DirHandle));
if (retval == NULL)
funcs->dirClose(opaque);
else
Sep 26, 2004
Sep 26, 2004
534
{
Aug 24, 2010
Aug 24, 2010
535
536
537
538
539
memset(retval, '\0', sizeof (DirHandle));
retval->mountPoint = NULL;
retval->funcs = funcs;
retval->opaque = opaque;
} /* else */
Sep 26, 2004
Sep 26, 2004
540
541
} /* if */
Jan 28, 2010
Jan 28, 2010
542
return retval;
Sep 26, 2004
Sep 26, 2004
543
544
545
} /* tryOpenDir */
Aug 30, 2010
Aug 30, 2010
546
static DirHandle *openDirectory(PHYSFS_Io *io, const char *d, int forWriting)
Jul 7, 2001
Jul 7, 2001
547
{
Sep 26, 2004
Sep 26, 2004
548
DirHandle *retval = NULL;
Sep 26, 2004
Sep 26, 2004
549
const PHYSFS_Archiver **i;
Jul 26, 2002
Jul 26, 2002
550
const char *ext;
Jul 7, 2001
Jul 7, 2001
551
Aug 30, 2010
Aug 30, 2010
552
assert((io != NULL) || (d != NULL));
Jul 23, 2001
Jul 23, 2001
553
Aug 30, 2010
Aug 30, 2010
554
555
556
557
558
559
560
561
562
563
564
565
if (io == NULL)
{
BAIL_IF_MACRO(!__PHYSFS_platformExists(d), ERR_NO_SUCH_FILE, NULL);
/* DIR gets first shot (unlike the rest, it doesn't deal with files). */
retval = tryOpenDir(io, &__PHYSFS_Archiver_DIR, d, forWriting);
if (retval != NULL)
return retval;
io = __PHYSFS_createNativeIo(d, forWriting ? 'w' : 'r');
BAIL_IF_MACRO_MUTEX(io == NULL, NULL, stateLock, 0);
} /* if */
Aug 24, 2010
Aug 24, 2010
566
Jul 26, 2002
Jul 26, 2002
567
568
ext = find_filename_extension(d);
if (ext != NULL)
Jul 7, 2001
Jul 7, 2001
569
{
Jul 26, 2002
Jul 26, 2002
570
/* Look for archivers with matching file extensions first... */
Sep 26, 2004
Sep 26, 2004
571
for (i = archivers; (*i != NULL) && (retval == NULL); i++)
Jul 26, 2002
Jul 26, 2002
572
{
Mar 15, 2007
Mar 15, 2007
573
if (__PHYSFS_stricmpASCII(ext, (*i)->info->extension) == 0)
Aug 30, 2010
Aug 30, 2010
574
retval = tryOpenDir(io, *i, d, forWriting);
Jul 26, 2002
Jul 26, 2002
575
576
577
} /* for */
/* failing an exact file extension match, try all the others... */
Sep 26, 2004
Sep 26, 2004
578
for (i = archivers; (*i != NULL) && (retval == NULL); i++)
Jul 26, 2002
Jul 26, 2002
579
{
Mar 15, 2007
Mar 15, 2007
580
if (__PHYSFS_stricmpASCII(ext, (*i)->info->extension) != 0)
Aug 30, 2010
Aug 30, 2010
581
retval = tryOpenDir(io, *i, d, forWriting);
Jul 26, 2002
Jul 26, 2002
582
583
584
585
586
} /* for */
} /* if */
else /* no extension? Try them all. */
{
Sep 26, 2004
Sep 26, 2004
587
for (i = archivers; (*i != NULL) && (retval == NULL); i++)
Aug 30, 2010
Aug 30, 2010
588
retval = tryOpenDir(io, *i, d, forWriting);
Jul 26, 2002
Jul 26, 2002
589
} /* else */
Jul 7, 2001
Jul 7, 2001
590
Sep 26, 2004
Sep 26, 2004
591
BAIL_IF_MACRO(retval == NULL, ERR_UNSUPPORTED_ARCHIVE, NULL);
Jan 28, 2010
Jan 28, 2010
592
return retval;
Jul 7, 2001
Jul 7, 2001
593
594
595
} /* openDirectory */
Mar 13, 2005
Mar 13, 2005
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
/*
* Make a platform-independent path string sane. Doesn't actually check the
* file hierarchy, it just cleans up the string.
* (dst) must be a buffer at least as big as (src), as this is where the
* cleaned up string is deposited.
* If there are illegal bits in the path (".." entries, etc) then we
* return zero and (dst) is undefined. Non-zero if the path was sanitized.
*/
static int sanitizePlatformIndependentPath(const char *src, char *dst)
{
char *prev;
char ch;
while (*src == '/') /* skip initial '/' chars... */
src++;
prev = dst;
do
{
ch = *(src++);
if ((ch == ':') || (ch == '\\')) /* illegal chars in a physfs path. */
BAIL_MACRO(ERR_INSECURE_FNAME, 0);
if (ch == '/') /* path separator. */
{
*dst = '\0'; /* "." and ".." are illegal pathnames. */
if ((strcmp(prev, ".") == 0) || (strcmp(prev, "..") == 0))
BAIL_MACRO(ERR_INSECURE_FNAME, 0);
while (*src == '/') /* chop out doubles... */
src++;
if (*src == '\0') /* ends with a pathsep? */
break; /* we're done, don't add final pathsep to dst. */
prev = dst + 1;
} /* if */
*(dst++) = ch;
} while (ch != '\0');
Jan 28, 2010
Jan 28, 2010
638
return 1;
Mar 13, 2005
Mar 13, 2005
639
640
641
} /* sanitizePlatformIndependentPath */
Mar 14, 2005
Mar 14, 2005
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
/*
* Figure out if (fname) is part of (h)'s mountpoint. (fname) must be an
* output from sanitizePlatformIndependentPath(), so that it is in a known
* state.
*
* This only finds legitimate segments of a mountpoint. If the mountpoint is
* "/a/b/c" and (fname) is "/a/b/c", "/", or "/a/b/c/d", then the results are
* all zero. "/a/b" will succeed, though.
*/
static int partOfMountPoint(DirHandle *h, char *fname)
{
/* !!! FIXME: This code feels gross. */
int rc;
size_t len, mntpntlen;
if (h->mountPoint == NULL)
Jan 28, 2010
Jan 28, 2010
658
return 0;
Mar 14, 2005
Mar 14, 2005
659
else if (*fname == '\0')
Jan 28, 2010
Jan 28, 2010
660
return 1;
Mar 14, 2005
Mar 14, 2005
661
662
663
664
len = strlen(fname);
mntpntlen = strlen(h->mountPoint);
if (len > mntpntlen) /* can't be a subset of mountpoint. */
Jan 28, 2010
Jan 28, 2010
665
return 0;
Mar 14, 2005
Mar 14, 2005
666
667
668
/* if true, must be not a match or a complete match, but not a subset. */
if ((len + 1) == mntpntlen)
Jan 28, 2010
Jan 28, 2010
669
return 0;
Mar 14, 2005
Mar 14, 2005
670
671
672
rc = strncmp(fname, h->mountPoint, len); /* !!! FIXME: case insensitive? */
if (rc != 0)
Jan 28, 2010
Jan 28, 2010
673
return 0; /* not a match. */
Mar 14, 2005
Mar 14, 2005
674
675
/* make sure /a/b matches /a/b/ and not /a/bc ... */
Jan 28, 2010
Jan 28, 2010
676
return h->mountPoint[len] == '/';
Mar 14, 2005
Mar 14, 2005
677
678
679
} /* partOfMountPoint */
Aug 30, 2010
Aug 30, 2010
680
681
static DirHandle *createDirHandle(PHYSFS_Io *io, const char *newDir,
const char *mountPoint, int forWriting)
Jul 7, 2001
Jul 7, 2001
682
683
{
DirHandle *dirHandle = NULL;
Mar 24, 2007
Mar 24, 2007
684
char *tmpmntpnt = NULL;
Mar 13, 2005
Mar 13, 2005
685
686
687
if (mountPoint != NULL)
{
Mar 24, 2007
Mar 24, 2007
688
689
690
691
const size_t len = strlen(mountPoint) + 1;
tmpmntpnt = (char *) __PHYSFS_smallAlloc(len);
GOTO_IF_MACRO(!tmpmntpnt, ERR_OUT_OF_MEMORY, badDirHandle);
if (!sanitizePlatformIndependentPath(mountPoint, tmpmntpnt))
Mar 13, 2005
Mar 13, 2005
692
goto badDirHandle;
Mar 24, 2007
Mar 24, 2007
693
mountPoint = tmpmntpnt; /* sanitized version. */
Mar 13, 2005
Mar 13, 2005
694
} /* if */
Jul 7, 2001
Jul 7, 2001
695
Aug 30, 2010
Aug 30, 2010
696
dirHandle = openDirectory(io, newDir, forWriting);
Mar 13, 2005
Mar 13, 2005
697
GOTO_IF_MACRO(!dirHandle, NULL, badDirHandle);
Jul 7, 2001
Jul 7, 2001
698
Aug 30, 2010
Aug 30, 2010
699
700
701
702
703
704
705
706
if (newDir == NULL)
dirHandle->dirName = NULL;
else
{
dirHandle->dirName = (char *) allocator.Malloc(strlen(newDir) + 1);
GOTO_IF_MACRO(!dirHandle->dirName, ERR_OUT_OF_MEMORY, badDirHandle);
strcpy(dirHandle->dirName, newDir);
} /* else */
Mar 13, 2005
Mar 13, 2005
707
708
709
if ((mountPoint != NULL) && (*mountPoint != '\0'))
{
Mar 14, 2005
Mar 14, 2005
710
dirHandle->mountPoint = (char *)allocator.Malloc(strlen(mountPoint)+2);
Mar 13, 2005
Mar 13, 2005
711
712
713
714
715
GOTO_IF_MACRO(!dirHandle->mountPoint, ERR_OUT_OF_MEMORY, badDirHandle);
strcpy(dirHandle->mountPoint, mountPoint);
strcat(dirHandle->mountPoint, "/");
} /* if */
Mar 24, 2007
Mar 24, 2007
716
__PHYSFS_smallFree(tmpmntpnt);
Jan 28, 2010
Jan 28, 2010
717
return dirHandle;
Mar 13, 2005
Mar 13, 2005
718
719
720
badDirHandle:
if (dirHandle != NULL)
Mar 30, 2002
Mar 30, 2002
721
{
Sep 26, 2004
Sep 26, 2004
722
dirHandle->funcs->dirClose(dirHandle->opaque);
Mar 14, 2005
Mar 14, 2005
723
724
725
allocator.Free(dirHandle->dirName);
allocator.Free(dirHandle->mountPoint);
allocator.Free(dirHandle);
Mar 30, 2002
Mar 30, 2002
726
} /* if */
Jul 7, 2001
Jul 7, 2001
727
Mar 24, 2007
Mar 24, 2007
728
__PHYSFS_smallFree(tmpmntpnt);
Jan 28, 2010
Jan 28, 2010
729
return NULL;
Sep 26, 2004
Sep 26, 2004
730
} /* createDirHandle */
Jul 7, 2001
Jul 7, 2001
731
732
Mar 30, 2002
Mar 30, 2002
733
/* MAKE SURE you've got the stateLock held before calling this! */
Sep 26, 2004
Sep 26, 2004
734
static int freeDirHandle(DirHandle *dh, FileHandle *openList)
Jul 7, 2001
Jul 7, 2001
735
{
Sep 26, 2004
Sep 26, 2004
736
FileHandle *i;
Jul 7, 2001
Jul 7, 2001
737
Sep 26, 2004
Sep 26, 2004
738
if (dh == NULL)
Jan 28, 2010
Jan 28, 2010
739
return 1;
Jul 7, 2001
Jul 7, 2001
740
741
for (i = openList; i != NULL; i = i->next)
Sep 26, 2004
Sep 26, 2004
742
BAIL_IF_MACRO(i->dirHandle == dh, ERR_FILES_STILL_OPEN, 0);
Apr 11, 2006
Apr 11, 2006
743
Sep 26, 2004
Sep 26, 2004
744
dh->funcs->dirClose(dh->opaque);
Mar 14, 2005
Mar 14, 2005
745
746
747
allocator.Free(dh->dirName);
allocator.Free(dh->mountPoint);
allocator.Free(dh);
Jan 28, 2010
Jan 28, 2010
748
return 1;
Sep 26, 2004
Sep 26, 2004
749
} /* freeDirHandle */
Jul 7, 2001
Jul 7, 2001
750
751
752
static char *calculateUserDir(void)
Jul 6, 2001
Jul 6, 2001
753
{
Mar 21, 2010
Mar 21, 2010
754
755
756
757
758
759
760
761
char *retval = __PHYSFS_platformGetUserDir();
if (retval != NULL)
{
/* make sure it really exists and is normalized. */
char *ptr = __PHYSFS_platformRealPath(retval);
allocator.Free(retval);
retval = ptr;
} /* if */
Jul 6, 2001
Jul 6, 2001
762
Mar 21, 2010
Mar 21, 2010
763
if (retval == NULL)
Jul 6, 2001
Jul 6, 2001
764
765
766
{
const char *dirsep = PHYSFS_getDirSeparator();
const char *uname = __PHYSFS_platformGetUserName();
Mar 21, 2010
Mar 21, 2010
767
const char *str = (uname != NULL) ? uname : "default";
Jul 6, 2001
Jul 6, 2001
768
Mar 14, 2005
Mar 14, 2005
769
770
retval = (char *) allocator.Malloc(strlen(baseDir) + strlen(str) +
strlen(dirsep) + 6);
Jul 6, 2001
Jul 6, 2001
771
772
773
774
if (retval == NULL)
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
else
Apr 2, 2002
Apr 2, 2002
775
sprintf(retval, "%susers%s%s", baseDir, dirsep, str);
Jul 6, 2001
Jul 6, 2001
776
Mar 24, 2007
Mar 24, 2007
777
allocator.Free((void *) uname);
Jul 6, 2001
Jul 6, 2001
778
779
} /* else */
Jan 28, 2010
Jan 28, 2010
780
return retval;
Jul 6, 2001
Jul 6, 2001
781
782
783
} /* calculateUserDir */
Jul 8, 2001
Jul 8, 2001
784
785
786
787
788
789
static int appendDirSep(char **dir)
{
const char *dirsep = PHYSFS_getDirSeparator();
char *ptr;
if (strcmp((*dir + strlen(*dir)) - strlen(dirsep), dirsep) == 0)
Jan 28, 2010
Jan 28, 2010
790
return 1;
Jul 8, 2001
Jul 8, 2001
791
Mar 14, 2005
Mar 14, 2005
792
ptr = (char *) allocator.Realloc(*dir, strlen(*dir) + strlen(dirsep) + 1);
Jul 8, 2001
Jul 8, 2001
793
794
if (!ptr)
{
Mar 14, 2005
Mar 14, 2005
795
allocator.Free(*dir);
Jan 28, 2010
Jan 28, 2010
796
return 0;
Jul 8, 2001
Jul 8, 2001
797
798
799
800
} /* if */
strcat(ptr, dirsep);
*dir = ptr;
Jan 28, 2010
Jan 28, 2010
801
return 1;
Jul 8, 2001
Jul 8, 2001
802
803
804
} /* appendDirSep */
Jul 7, 2001
Jul 7, 2001
805
806
static char *calculateBaseDir(const char *argv0)
{
Mar 21, 2007
Mar 21, 2007
807
808
809
char *retval = NULL;
const char *dirsep = NULL;
char *ptr = NULL;
Jul 8, 2001
Jul 8, 2001
810
Mar 21, 2007
Mar 21, 2007
811
/* Give the platform layer first shot at this. */
Jul 8, 2001
Jul 8, 2001
812
813
retval = __PHYSFS_platformCalcBaseDir(argv0);
if (retval != NULL)
Jan 28, 2010
Jan 28, 2010
814
return retval;
Jul 8, 2001
Jul 8, 2001
815
Mar 21, 2007
Mar 21, 2007
816
817
/* We need argv0 to go on. */
BAIL_IF_MACRO(argv0 == NULL, ERR_ARGV0_IS_NULL, NULL);
Mar 19, 2007
Mar 19, 2007
818
Mar 21, 2007
Mar 21, 2007
819
820
821
822
dirsep = PHYSFS_getDirSeparator();
if (strlen(dirsep) == 1) /* fast path. */
ptr = strrchr(argv0, *dirsep);
else
Jul 8, 2001
Jul 8, 2001
823
{
Mar 21, 2007
Mar 21, 2007
824
825
ptr = strstr(argv0, dirsep);
if (ptr != NULL)
Jul 8, 2001
Jul 8, 2001
826
{
Mar 21, 2007
Mar 21, 2007
827
828
829
830
831
832
833
834
char *p = ptr;
while (p != NULL)
{
ptr = p;
p = strstr(p + 1, dirsep);
} /* while */
} /* if */
} /* else */
Jul 8, 2001
Jul 8, 2001
835
Mar 21, 2007
Mar 21, 2007
836
837
838
if (ptr != NULL)
{
size_t size = (size_t) (ptr - argv0);
Mar 14, 2005
Mar 14, 2005
839
retval = (char *) allocator.Malloc(size + 1);
Jul 8, 2001
Jul 8, 2001
840
841
842
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
memcpy(retval, argv0, size);
retval[size] = '\0';
Jan 28, 2010
Jan 28, 2010
843
return retval;
Jul 8, 2001
Jul 8, 2001
844
845
} /* if */
Mar 21, 2007
Mar 21, 2007
846
847
/* argv0 wasn't helpful. */
BAIL_MACRO(ERR_INVALID_ARGUMENT, NULL);
Jul 7, 2001
Jul 7, 2001
848
849
850
} /* calculateBaseDir */
Mar 30, 2002
Mar 30, 2002
851
852
853
854
855
856
857
858
859
860
static int initializeMutexes(void)
{
errorLock = __PHYSFS_platformCreateMutex();
if (errorLock == NULL)
goto initializeMutexes_failed;
stateLock = __PHYSFS_platformCreateMutex();
if (stateLock == NULL)
goto initializeMutexes_failed;
Jan 28, 2010
Jan 28, 2010
861
return 1; /* success. */
Mar 30, 2002
Mar 30, 2002
862
863
864
865
866
867
868
869
870
initializeMutexes_failed:
if (errorLock != NULL)
__PHYSFS_platformDestroyMutex(errorLock);
if (stateLock != NULL)
__PHYSFS_platformDestroyMutex(stateLock);
errorLock = stateLock = NULL;
Jan 28, 2010
Jan 28, 2010
871
return 0; /* failed. */
Mar 30, 2002
Mar 30, 2002
872
873
874
} /* initializeMutexes */
Sep 23, 2004
Sep 23, 2004
875
876
static void setDefaultAllocator(void);
877
878
int PHYSFS_init(const char *argv0)
{
Jul 16, 2001
Jul 16, 2001
879
880
char *ptr;
881
BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
Sep 23, 2004
Sep 23, 2004
882
883
884
885
if (!externalAllocator)
setDefaultAllocator();
Sep 9, 2005
Sep 9, 2005
886
887
if (allocator.Init != NULL)
BAIL_IF_MACRO(!allocator.Init(), NULL, 0);
Sep 26, 2004
Sep 26, 2004
888
Mar 24, 2002
Mar 24, 2002
889
BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0);
Mar 30, 2002
Mar 30, 2002
891
892
BAIL_IF_MACRO(!initializeMutexes(), NULL, 0);
Jul 6, 2001
Jul 6, 2001
893
baseDir = calculateBaseDir(argv0);
Jul 7, 2001
Jul 7, 2001
894
BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
Apr 6, 2002
Apr 6, 2002
895
Mar 21, 2007
Mar 21, 2007
896
/* !!! FIXME: only call this if we got this from argv0 (unreliable). */
Jul 16, 2001
Jul 16, 2001
897
ptr = __PHYSFS_platformRealPath(baseDir);
Mar 14, 2005
Mar 14, 2005
898
allocator.Free(baseDir);
Jul 16, 2001
Jul 16, 2001
899
900
901
BAIL_IF_MACRO(ptr == NULL, NULL, 0);
baseDir = ptr;
Jul 8, 2001
Jul 8, 2001
902
BAIL_IF_MACRO(!appendDirSep(&baseDir), NULL, 0);
Jul 6, 2001
Jul 6, 2001
903
904
userDir = calculateUserDir();
Jul 8, 2001
Jul 8, 2001
905
if ((userDir == NULL) || (!appendDirSep(&userDir)))
Jul 6, 2001
Jul 6, 2001
906
{
Mar 14, 2005
Mar 14, 2005
907
allocator.Free(baseDir);
Jul 6, 2001
Jul 6, 2001
908
baseDir = NULL;
Jan 28, 2010
Jan 28, 2010
909
return 0;
Jul 6, 2001
Jul 6, 2001
910
911
} /* if */
912
initialized = 1;
Apr 4, 2002
Apr 4, 2002
913
914
915
/* This makes sure that the error subsystem is initialized. */
__PHYSFS_setError(PHYSFS_getLastError());
Aug 20, 2002
Aug 20, 2002
916
Jan 28, 2010
Jan 28, 2010
917
return 1;
918
919
920
} /* PHYSFS_init */
Mar 30, 2002
Mar 30, 2002
921
/* MAKE SURE you hold stateLock before calling this! */
Sep 26, 2004
Sep 26, 2004
922
static int closeFileHandleList(FileHandle **list)
Jul 6, 2001
Jul 6, 2001
923
{
Sep 26, 2004
Sep 26, 2004
924
925
FileHandle *i;
FileHandle *next = NULL;
Jul 6, 2001
Jul 6, 2001
926
927
928
for (i = *list; i != NULL; i = next)
{
Aug 30, 2010
Aug 30, 2010
929
PHYSFS_Io *io = i->io;
Jul 6, 2001
Jul 6, 2001
930
next = i->next;
Aug 30, 2010
Aug 30, 2010
931
932
if (!io->flush(io))
Jul 7, 2001
Jul 7, 2001
933
934
{
*list = i;
Jan 28, 2010
Jan 28, 2010
935
return 0;
Jul 7, 2001
Jul 7, 2001
936
937
} /* if */
Aug 30, 2010
Aug 30, 2010
938
io->destroy(io);
Mar 14, 2005
Mar 14, 2005
939
allocator.Free(i);
Jul 6, 2001
Jul 6, 2001
940
941
942
} /* for */
*list = NULL;
Jan 28, 2010
Jan 28, 2010
943
return 1;
Jul 7, 2001
Jul 7, 2001
944
} /* closeFileHandleList */
Jul 6, 2001
Jul 6, 2001
945
946
Mar 30, 2002
Mar 30, 2002
947
/* MAKE SURE you hold the stateLock before calling this! */
948
949
static void freeSearchPath(void)
{
Sep 26, 2004
Sep 26, 2004
950
951
DirHandle *i;
DirHandle *next = NULL;
Jul 6, 2001
Jul 6, 2001
953
954
closeFileHandleList(&openReadList);
955
956
957
958
if (searchPath != NULL)
{
for (i = searchPath; i != NULL; i = next)
{
Jul 9, 2001
Jul 9, 2001
959
next = i->next;
Sep 26, 2004
Sep 26, 2004
960
freeDirHandle(i, openReadList);
961
962
963
964
965
966
} /* for */
searchPath = NULL;
} /* if */
} /* freeSearchPath */
Jul 7, 2001
Jul 7, 2001
967
int PHYSFS_deinit(void)
968
969
{
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
Mar 24, 2002
Mar 24, 2002
970
BAIL_IF_MACRO(!__PHYSFS_platformDeinit(), NULL, 0);
Jul 6, 2001
Jul 6, 2001
972
closeFileHandleList(&openWriteList);
Jul 7, 2001
Jul 7, 2001
973
974
BAIL_IF_MACRO(!PHYSFS_setWriteDir(NULL), ERR_FILES_STILL_OPEN, 0);
975
976
977
freeSearchPath();
freeErrorMessages();
Jul 6, 2001
Jul 6, 2001
978
if (baseDir != NULL)
Jul 6, 2001
Jul 6, 2001
979
{
Mar 14, 2005
Mar 14, 2005
980
allocator.Free(baseDir);
Jul 6, 2001
Jul 6, 2001
981
982
983
984
985
baseDir = NULL;
} /* if */
if (userDir != NULL)
{
Mar 14, 2005
Mar 14, 2005
986
allocator.Free(userDir);
Jul 6, 2001
Jul 6, 2001
987
988
userDir = NULL;
} /* if */
Jul 6, 2001
Jul 6, 2001
989
990
allowSymLinks = 0;
991
initialized = 0;
Mar 30, 2002
Mar 30, 2002
992
993
994
995
__PHYSFS_platformDestroyMutex(errorLock);
__PHYSFS_platformDestroyMutex(stateLock);
Sep 9, 2005
Sep 9, 2005
996
997
if (allocator.Deinit != NULL)
allocator.Deinit();
Sep 26, 2004
Sep 26, 2004
998
Mar 30, 2002
Mar 30, 2002
999
errorLock = stateLock = NULL;
Jan 28, 2010
Jan 28, 2010
1000
return 1;