Skip to content

Latest commit

 

History

History
1563 lines (1229 loc) · 37.6 KB

physfs.c

File metadata and controls

1563 lines (1229 loc) · 37.6 KB
 
1
2
3
4
5
6
7
8
9
10
/**
* PhysicsFS; a portable, flexible file i/o abstraction.
*
* Documentation is in physfs.h. It's verbose, honest. :)
*
* Please see the file LICENSE in the source's root directory.
*
* This file written by Ryan C. Gordon.
*/
May 10, 2002
May 10, 2002
11
12
13
14
#if HAVE_CONFIG_H
# include <config.h>
#endif
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Jul 16, 2001
Jul 16, 2001
18
19
#include <fcntl.h>
#include <errno.h>
20
21
22
#include <assert.h>
#include "physfs.h"
Jul 6, 2001
Jul 6, 2001
23
24
25
#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"
26
27
typedef struct __PHYSFS_ERRMSGTYPE__
{
Apr 3, 2002
Apr 3, 2002
28
PHYSFS_uint64 tid;
29
30
31
32
33
int errorAvailable;
char errorString[80];
struct __PHYSFS_ERRMSGTYPE__ *next;
} ErrMsg;
Jul 7, 2001
Jul 7, 2001
34
typedef struct __PHYSFS_DIRINFO__
35
36
{
char *dirName;
Jul 7, 2001
Jul 7, 2001
37
38
DirHandle *dirHandle;
struct __PHYSFS_DIRINFO__ *next;
Apr 1, 2002
Apr 1, 2002
39
} PhysDirInfo;
Jul 6, 2001
Jul 6, 2001
41
42
typedef struct __PHYSFS_FILEHANDLELIST__
{
Jul 9, 2001
Jul 9, 2001
43
PHYSFS_file handle;
Jul 6, 2001
Jul 6, 2001
44
45
struct __PHYSFS_FILEHANDLELIST__ *next;
} FileHandleList;
Jul 6, 2001
Jul 6, 2001
47
48
/* The various i/o drivers... */
Jul 6, 2001
Jul 6, 2001
49
50
#if (defined PHYSFS_SUPPORTS_ZIP)
Jul 6, 2001
Jul 6, 2001
51
52
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_ZIP;
extern const DirFunctions __PHYSFS_DirFunctions_ZIP;
Jul 6, 2001
Jul 6, 2001
53
#endif
Jul 8, 2001
Jul 8, 2001
55
56
57
58
59
#if (defined PHYSFS_SUPPORTS_GRP)
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_GRP;
extern const DirFunctions __PHYSFS_DirFunctions_GRP;
#endif
Aug 9, 2002
Aug 9, 2002
60
61
62
63
64
#if (defined PHYSFS_SUPPORTS_QPAK)
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_QPAK;
extern const DirFunctions __PHYSFS_DirFunctions_QPAK;
#endif
Jul 6, 2001
Jul 6, 2001
65
extern const DirFunctions __PHYSFS_DirFunctions_DIR;
Jul 6, 2001
Jul 6, 2001
66
Aug 9, 2002
Aug 9, 2002
67
68
// !!! FIXME: This is stored with dirFunctions now, too.
Jul 6, 2001
Jul 6, 2001
69
static const PHYSFS_ArchiveInfo *supported_types[] =
70
71
{
#if (defined PHYSFS_SUPPORTS_ZIP)
Jul 6, 2001
Jul 6, 2001
72
&__PHYSFS_ArchiveInfo_ZIP,
73
74
#endif
Jul 8, 2001
Jul 8, 2001
75
76
77
78
#if (defined PHYSFS_SUPPORTS_GRP)
&__PHYSFS_ArchiveInfo_GRP,
#endif
Aug 9, 2002
Aug 9, 2002
79
80
81
82
#if (defined PHYSFS_SUPPORTS_QPAK)
&__PHYSFS_ArchiveInfo_QPAK,
#endif
83
84
85
NULL
};
Jul 6, 2001
Jul 6, 2001
86
87
88
89
90
91
static const DirFunctions *dirFunctions[] =
{
#if (defined PHYSFS_SUPPORTS_ZIP)
&__PHYSFS_DirFunctions_ZIP,
#endif
Jul 8, 2001
Jul 8, 2001
92
93
94
95
#if (defined PHYSFS_SUPPORTS_GRP)
&__PHYSFS_DirFunctions_GRP,
#endif
Aug 9, 2002
Aug 9, 2002
96
97
98
99
#if (defined PHYSFS_SUPPORTS_QPAK)
&__PHYSFS_DirFunctions_QPAK,
#endif
Jul 6, 2001
Jul 6, 2001
100
101
102
&__PHYSFS_DirFunctions_DIR,
NULL
};
103
104
105
Jul 6, 2001
Jul 6, 2001
106
107
108
/* General PhysicsFS state ... */
static int initialized = 0;
static ErrMsg *errorMessages = NULL;
Apr 1, 2002
Apr 1, 2002
109
110
static PhysDirInfo *searchPath = NULL;
static PhysDirInfo *writeDir = NULL;
Jul 6, 2001
Jul 6, 2001
111
112
113
114
115
116
static FileHandleList *openWriteList = NULL;
static FileHandleList *openReadList = NULL;
static char *baseDir = NULL;
static char *userDir = NULL;
static int allowSymLinks = 0;
Mar 30, 2002
Mar 30, 2002
117
118
119
/* mutexes ... */
static void *errorLock = NULL; /* protects error message list. */
static void *stateLock = NULL; /* protects other PhysFS static state. */
Jul 6, 2001
Jul 6, 2001
120
121
122
123
/* functions ... */
124
125
126
static ErrMsg *findErrorForCurrentThread(void)
{
ErrMsg *i;
Apr 3, 2002
Apr 3, 2002
127
PHYSFS_uint64 tid;
Jun 8, 2002
Jun 8, 2002
129
if (errorLock != NULL)
Apr 8, 2002
Apr 8, 2002
130
131
__PHYSFS_platformGrabMutex(errorLock);
132
133
if (errorMessages != NULL)
{
Apr 3, 2002
Apr 3, 2002
134
tid = __PHYSFS_platformGetThreadID();
135
136
137
138
for (i = errorMessages; i != NULL; i = i->next)
{
if (i->tid == tid)
Mar 30, 2002
Mar 30, 2002
139
{
Jun 8, 2002
Jun 8, 2002
140
141
if (errorLock != NULL)
__PHYSFS_platformReleaseMutex(errorLock);
142
return(i);
Mar 30, 2002
Mar 30, 2002
143
} /* if */
144
145
} /* for */
} /* if */
Apr 8, 2002
Apr 8, 2002
146
Jun 8, 2002
Jun 8, 2002
147
if (errorLock != NULL)
Apr 8, 2002
Apr 8, 2002
148
__PHYSFS_platformReleaseMutex(errorLock);
149
150
151
152
153
return(NULL); /* no error available. */
} /* findErrorForCurrentThread */
Jul 6, 2001
Jul 6, 2001
154
void __PHYSFS_setError(const char *str)
Jul 7, 2001
Jul 7, 2001
156
157
158
159
160
161
ErrMsg *err;
if (str == NULL)
return;
err = findErrorForCurrentThread();
162
163
164
165
166
167
168
if (err == NULL)
{
err = (ErrMsg *) malloc(sizeof (ErrMsg));
if (err == NULL)
return; /* uhh...? */
Aug 1, 2001
Aug 1, 2001
169
memset((void *) err, '\0', sizeof (ErrMsg));
Apr 3, 2002
Apr 3, 2002
170
err->tid = __PHYSFS_platformGetThreadID();
Mar 30, 2002
Mar 30, 2002
171
Jun 8, 2002
Jun 8, 2002
172
173
174
if (errorLock != NULL)
__PHYSFS_platformGrabMutex(errorLock);
Jul 6, 2001
Jul 6, 2001
175
176
err->next = errorMessages;
errorMessages = err;
Jun 8, 2002
Jun 8, 2002
177
178
179
if (errorLock != NULL)
__PHYSFS_platformReleaseMutex(errorLock);
180
181
182
183
184
} /* if */
err->errorAvailable = 1;
strncpy(err->errorString, str, sizeof (err->errorString));
err->errorString[sizeof (err->errorString) - 1] = '\0';
Jul 6, 2001
Jul 6, 2001
185
} /* __PHYSFS_setError */
Mar 30, 2002
Mar 30, 2002
188
189
190
191
192
193
194
195
196
197
198
199
200
const char *PHYSFS_getLastError(void)
{
ErrMsg *err = findErrorForCurrentThread();
if ((err == NULL) || (!err->errorAvailable))
return(NULL);
err->errorAvailable = 0;
return(err->errorString);
} /* PHYSFS_getLastError */
/* MAKE SURE that errorLock is held before calling this! */
Jul 7, 2001
Jul 7, 2001
201
202
203
204
205
206
207
static void freeErrorMessages(void)
{
ErrMsg *i;
ErrMsg *next;
for (i = errorMessages; i != NULL; i = next)
{
Jul 9, 2001
Jul 9, 2001
208
next = i->next;
Jul 7, 2001
Jul 7, 2001
209
210
free(i);
} /* for */
Jun 8, 2002
Jun 8, 2002
211
212
errorMessages = NULL;
Jul 7, 2001
Jul 7, 2001
213
214
215
} /* freeErrorMessages */
216
217
218
219
220
221
222
223
224
225
226
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
static const char *find_filename_extension(const char *fname)
{
const char *retval = strchr(fname, '.');
const char *p = retval;
while (p != NULL)
{
p = strchr(p + 1, '.');
if (p != NULL)
retval = p;
} /* while */
if (retval != NULL)
retval++; /* skip '.' */
return(retval);
} /* find_filename_extension */
Jul 7, 2001
Jul 7, 2001
246
247
248
static DirHandle *openDirectory(const char *d, int forWriting)
{
const DirFunctions **i;
Jul 26, 2002
Jul 26, 2002
249
const char *ext;
Jul 7, 2001
Jul 7, 2001
250
Jul 23, 2001
Jul 23, 2001
251
252
BAIL_IF_MACRO(!__PHYSFS_platformExists(d), ERR_NO_SUCH_FILE, NULL);
Jul 26, 2002
Jul 26, 2002
253
254
ext = find_filename_extension(d);
if (ext != NULL)
Jul 7, 2001
Jul 7, 2001
255
{
Jul 26, 2002
Jul 26, 2002
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/* Look for archivers with matching file extensions first... */
for (i = dirFunctions; *i != NULL; i++)
{
if (__PHYSFS_platformStricmp(ext, (*i)->info->extension) == 0)
{
if ((*i)->isArchive(d, forWriting))
return( (*i)->openArchive(d, forWriting) );
} /* if */
} /* for */
/* failing an exact file extension match, try all the others... */
for (i = dirFunctions; *i != NULL; i++)
{
if (__PHYSFS_platformStricmp(ext, (*i)->info->extension) != 0)
{
if ((*i)->isArchive(d, forWriting))
return( (*i)->openArchive(d, forWriting) );
} /* if */
} /* for */
} /* if */
else /* no extension? Try them all. */
{
for (i = dirFunctions; *i != NULL; i++)
{
if ((*i)->isArchive(d, forWriting))
return( (*i)->openArchive(d, forWriting) );
} /* for */
} /* else */
Jul 7, 2001
Jul 7, 2001
285
286
287
288
289
290
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
return(NULL);
} /* openDirectory */
Apr 1, 2002
Apr 1, 2002
291
static PhysDirInfo *buildDirInfo(const char *newDir, int forWriting)
Jul 7, 2001
Jul 7, 2001
292
293
{
DirHandle *dirHandle = NULL;
Apr 1, 2002
Apr 1, 2002
294
PhysDirInfo *di = NULL;
Jul 7, 2001
Jul 7, 2001
295
296
297
298
299
300
BAIL_IF_MACRO(newDir == NULL, ERR_INVALID_ARGUMENT, 0);
dirHandle = openDirectory(newDir, forWriting);
BAIL_IF_MACRO(dirHandle == NULL, NULL, 0);
Apr 1, 2002
Apr 1, 2002
301
di = (PhysDirInfo *) malloc(sizeof (PhysDirInfo));
Jul 7, 2001
Jul 7, 2001
302
if (di == NULL)
Mar 30, 2002
Mar 30, 2002
303
{
Jul 8, 2001
Jul 8, 2001
304
dirHandle->funcs->dirClose(dirHandle);
Mar 30, 2002
Mar 30, 2002
305
306
BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0);
} /* if */
Jul 7, 2001
Jul 7, 2001
307
308
309
310
311
di->dirName = (char *) malloc(strlen(newDir) + 1);
if (di->dirName == NULL)
{
free(di);
Jul 8, 2001
Jul 8, 2001
312
dirHandle->funcs->dirClose(dirHandle);
Mar 30, 2002
Mar 30, 2002
313
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
Jul 7, 2001
Jul 7, 2001
314
315
316
317
318
319
320
321
322
} /* if */
di->next = NULL;
di->dirHandle = dirHandle;
strcpy(di->dirName, newDir);
return(di);
} /* buildDirInfo */
Mar 30, 2002
Mar 30, 2002
323
/* MAKE SURE you've got the stateLock held before calling this! */
Apr 1, 2002
Apr 1, 2002
324
static int freeDirInfo(PhysDirInfo *di, FileHandleList *openList)
Jul 7, 2001
Jul 7, 2001
325
326
327
328
329
330
331
332
{
FileHandleList *i;
if (di == NULL)
return(1);
for (i = openList; i != NULL; i = i->next)
{
Jul 9, 2001
Jul 9, 2001
333
const DirHandle *h = ((FileHandle *) &(i->handle.opaque))->dirHandle;
Jul 7, 2001
Jul 7, 2001
334
335
BAIL_IF_MACRO(h == di->dirHandle, ERR_FILES_STILL_OPEN, 0);
} /* for */
Mar 30, 2002
Mar 30, 2002
336
Jul 8, 2001
Jul 8, 2001
337
di->dirHandle->funcs->dirClose(di->dirHandle);
Jul 7, 2001
Jul 7, 2001
338
339
340
341
342
343
344
free(di->dirName);
free(di);
return(1);
} /* freeDirInfo */
static char *calculateUserDir(void)
Jul 6, 2001
Jul 6, 2001
345
346
347
348
349
350
{
char *retval = NULL;
const char *str = NULL;
str = __PHYSFS_platformGetUserDir();
if (str != NULL)
Jul 7, 2001
Jul 7, 2001
351
retval = (char *) str;
Jul 6, 2001
Jul 6, 2001
352
353
354
355
356
357
else
{
const char *dirsep = PHYSFS_getDirSeparator();
const char *uname = __PHYSFS_platformGetUserName();
str = (uname != NULL) ? uname : "default";
Jul 7, 2001
Jul 7, 2001
358
retval = (char *) malloc(strlen(baseDir) + strlen(str) +
Apr 2, 2002
Apr 2, 2002
359
strlen(dirsep) + 6);
Jul 6, 2001
Jul 6, 2001
360
361
362
363
if (retval == NULL)
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
else
Apr 2, 2002
Apr 2, 2002
364
sprintf(retval, "%susers%s%s", baseDir, dirsep, str);
Jul 6, 2001
Jul 6, 2001
365
366
if (uname != NULL)
Jul 7, 2001
Jul 7, 2001
367
free((void *) uname);
Jul 6, 2001
Jul 6, 2001
368
369
370
371
372
373
} /* else */
return(retval);
} /* calculateUserDir */
Jul 8, 2001
Jul 8, 2001
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
static int appendDirSep(char **dir)
{
const char *dirsep = PHYSFS_getDirSeparator();
char *ptr;
if (strcmp((*dir + strlen(*dir)) - strlen(dirsep), dirsep) == 0)
return(1);
ptr = realloc(*dir, strlen(*dir) + strlen(dirsep) + 1);
if (!ptr)
{
free(*dir);
return(0);
} /* if */
strcat(ptr, dirsep);
*dir = ptr;
return(1);
} /* appendDirSep */
Jul 7, 2001
Jul 7, 2001
395
396
static char *calculateBaseDir(const char *argv0)
{
Jul 8, 2001
Jul 8, 2001
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
const char *dirsep = PHYSFS_getDirSeparator();
char *retval;
char *ptr;
/*
* See if the platform driver wants to handle this for us...
*/
retval = __PHYSFS_platformCalcBaseDir(argv0);
if (retval != NULL)
return(retval);
/*
* Determine if there's a path on argv0. If there is, that's the base dir.
*/
ptr = strstr(argv0, dirsep);
if (ptr != NULL)
{
char *p = ptr;
size_t size;
while (p != NULL)
{
ptr = p;
p = strstr(p + 1, dirsep);
} /* while */
May 21, 2002
May 21, 2002
422
size = (size_t) (ptr - argv0);
Jul 8, 2001
Jul 8, 2001
423
424
425
426
427
428
429
430
431
432
retval = (char *) malloc(size + 1);
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
memcpy(retval, argv0, size);
retval[size] = '\0';
return(retval);
} /* if */
/*
* Last ditch effort: it's the current working directory. (*shrug*)
*/
Sep 14, 2001
Sep 14, 2001
433
434
435
436
437
438
439
440
441
442
443
444
445
retval = __PHYSFS_platformCurrentDir();
if(retval != NULL) {
return(retval);
}
/*
* Ok, current directory doesn't exist, use the root directory.
* Not a good alternative, but it only happens if the current
* directory was deleted from under the program.
*/
retval = (char *) malloc(strlen(dirsep) + 1);
strcpy(retval, dirsep);
return(retval);
Jul 7, 2001
Jul 7, 2001
446
447
448
} /* calculateBaseDir */
Mar 30, 2002
Mar 30, 2002
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
static int initializeMutexes(void)
{
errorLock = __PHYSFS_platformCreateMutex();
if (errorLock == NULL)
goto initializeMutexes_failed;
stateLock = __PHYSFS_platformCreateMutex();
if (stateLock == NULL)
goto initializeMutexes_failed;
return(1); /* success. */
initializeMutexes_failed:
if (errorLock != NULL)
__PHYSFS_platformDestroyMutex(errorLock);
if (stateLock != NULL)
__PHYSFS_platformDestroyMutex(stateLock);
errorLock = stateLock = NULL;
return(0); /* failed. */
} /* initializeMutexes */
473
474
int PHYSFS_init(const char *argv0)
{
Jul 16, 2001
Jul 16, 2001
475
476
char *ptr;
477
BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
Mar 24, 2002
Mar 24, 2002
478
BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0);
Mar 30, 2002
Mar 30, 2002
480
481
BAIL_IF_MACRO(!initializeMutexes(), NULL, 0);
Jul 6, 2001
Jul 6, 2001
482
baseDir = calculateBaseDir(argv0);
Jul 7, 2001
Jul 7, 2001
483
BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
Apr 6, 2002
Apr 6, 2002
484
Jul 16, 2001
Jul 16, 2001
485
486
487
488
489
ptr = __PHYSFS_platformRealPath(baseDir);
free(baseDir);
BAIL_IF_MACRO(ptr == NULL, NULL, 0);
baseDir = ptr;
Jul 8, 2001
Jul 8, 2001
490
BAIL_IF_MACRO(!appendDirSep(&baseDir), NULL, 0);
Jul 6, 2001
Jul 6, 2001
491
492
userDir = calculateUserDir();
Jul 16, 2001
Jul 16, 2001
493
494
495
496
497
498
499
if (userDir != NULL)
{
ptr = __PHYSFS_platformRealPath(userDir);
free(userDir);
userDir = ptr;
} /* if */
Jul 8, 2001
Jul 8, 2001
500
if ((userDir == NULL) || (!appendDirSep(&userDir)))
Jul 6, 2001
Jul 6, 2001
501
502
503
504
505
506
{
free(baseDir);
baseDir = NULL;
return(0);
} /* if */
507
initialized = 1;
Apr 4, 2002
Apr 4, 2002
508
509
510
/* This makes sure that the error subsystem is initialized. */
__PHYSFS_setError(PHYSFS_getLastError());
511
512
513
514
return(1);
} /* PHYSFS_init */
Mar 30, 2002
Mar 30, 2002
515
/* MAKE SURE you hold stateLock before calling this! */
Jul 7, 2001
Jul 7, 2001
516
static int closeFileHandleList(FileHandleList **list)
Jul 6, 2001
Jul 6, 2001
517
518
519
{
FileHandleList *i;
FileHandleList *next = NULL;
Jul 7, 2001
Jul 7, 2001
520
FileHandle *h;
Jul 6, 2001
Jul 6, 2001
521
522
523
524
for (i = *list; i != NULL; i = next)
{
next = i->next;
Jul 9, 2001
Jul 9, 2001
525
526
h = (FileHandle *) (i->handle.opaque);
if (!h->funcs->fileClose(h))
Jul 7, 2001
Jul 7, 2001
527
528
529
530
531
532
{
*list = i;
return(0);
} /* if */
free(i);
Jul 6, 2001
Jul 6, 2001
533
534
535
} /* for */
*list = NULL;
Jul 7, 2001
Jul 7, 2001
536
537
return(1);
} /* closeFileHandleList */
Jul 6, 2001
Jul 6, 2001
538
539
Mar 30, 2002
Mar 30, 2002
540
/* MAKE SURE you hold the stateLock before calling this! */
541
542
static void freeSearchPath(void)
{
Apr 1, 2002
Apr 1, 2002
543
544
PhysDirInfo *i;
PhysDirInfo *next = NULL;
Jul 6, 2001
Jul 6, 2001
546
547
closeFileHandleList(&openReadList);
548
549
550
551
if (searchPath != NULL)
{
for (i = searchPath; i != NULL; i = next)
{
Jul 9, 2001
Jul 9, 2001
552
next = i->next;
Jul 7, 2001
Jul 7, 2001
553
freeDirInfo(i, openReadList);
554
555
556
557
558
559
} /* for */
searchPath = NULL;
} /* if */
} /* freeSearchPath */
Jul 7, 2001
Jul 7, 2001
560
int PHYSFS_deinit(void)
561
562
{
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
Mar 24, 2002
Mar 24, 2002
563
BAIL_IF_MACRO(!__PHYSFS_platformDeinit(), NULL, 0);
Jul 6, 2001
Jul 6, 2001
565
closeFileHandleList(&openWriteList);
Jul 7, 2001
Jul 7, 2001
566
567
BAIL_IF_MACRO(!PHYSFS_setWriteDir(NULL), ERR_FILES_STILL_OPEN, 0);
568
569
570
freeSearchPath();
freeErrorMessages();
Jul 6, 2001
Jul 6, 2001
571
if (baseDir != NULL)
Jul 6, 2001
Jul 6, 2001
572
{
Jul 6, 2001
Jul 6, 2001
573
free(baseDir);
Jul 6, 2001
Jul 6, 2001
574
575
576
577
578
579
580
581
baseDir = NULL;
} /* if */
if (userDir != NULL)
{
free(userDir);
userDir = NULL;
} /* if */
Jul 6, 2001
Jul 6, 2001
582
583
allowSymLinks = 0;
584
initialized = 0;
Mar 30, 2002
Mar 30, 2002
585
586
587
588
589
__PHYSFS_platformDestroyMutex(errorLock);
__PHYSFS_platformDestroyMutex(stateLock);
errorLock = stateLock = NULL;
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
return(1);
} /* PHYSFS_deinit */
const PHYSFS_ArchiveInfo **PHYSFS_supportedArchiveTypes(void)
{
return(supported_types);
} /* PHYSFS_supportedArchiveTypes */
void PHYSFS_freeList(void *list)
{
void **i;
for (i = (void **) list; *i != NULL; i++)
free(*i);
free(list);
} /* PHYSFS_freeList */
const char *PHYSFS_getDirSeparator(void)
{
Jul 7, 2001
Jul 7, 2001
612
return(__PHYSFS_platformDirSeparator);
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
} /* PHYSFS_getDirSeparator */
char **PHYSFS_getCdRomDirs(void)
{
return(__PHYSFS_platformDetectAvailableCDs());
} /* PHYSFS_getCdRomDirs */
const char *PHYSFS_getBaseDir(void)
{
return(baseDir); /* this is calculated in PHYSFS_init()... */
} /* PHYSFS_getBaseDir */
const char *PHYSFS_getUserDir(void)
{
Jul 6, 2001
Jul 6, 2001
630
return(userDir); /* this is calculated in PHYSFS_init()... */
631
632
633
634
635
} /* PHYSFS_getUserDir */
const char *PHYSFS_getWriteDir(void)
{
Mar 30, 2002
Mar 30, 2002
636
637
638
639
640
641
const char *retval = NULL;
__PHYSFS_platformGrabMutex(stateLock);
if (writeDir != NULL)
retval = writeDir->dirName;
__PHYSFS_platformReleaseMutex(stateLock);
Jul 7, 2001
Jul 7, 2001
642
Mar 30, 2002
Mar 30, 2002
643
return(retval);
644
645
646
647
648
} /* PHYSFS_getWriteDir */
int PHYSFS_setWriteDir(const char *newDir)
{
Mar 30, 2002
Mar 30, 2002
649
650
651
652
int retval = 1;
__PHYSFS_platformGrabMutex(stateLock);
653
654
if (writeDir != NULL)
{
Mar 30, 2002
Mar 30, 2002
655
656
BAIL_IF_MACRO_MUTEX(!freeDirInfo(writeDir, openWriteList), NULL,
stateLock, 0);
657
658
659
writeDir = NULL;
} /* if */
Jul 6, 2001
Jul 6, 2001
660
661
if (newDir != NULL)
{
Jul 7, 2001
Jul 7, 2001
662
writeDir = buildDirInfo(newDir, 1);
Mar 30, 2002
Mar 30, 2002
663
retval = (writeDir != NULL);
Jul 6, 2001
Jul 6, 2001
664
} /* if */
Mar 30, 2002
Mar 30, 2002
666
667
668
__PHYSFS_platformReleaseMutex(stateLock);
return(retval);
669
670
671
672
673
} /* PHYSFS_setWriteDir */
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
{
Apr 1, 2002
Apr 1, 2002
674
675
676
PhysDirInfo *di;
PhysDirInfo *prev = NULL;
PhysDirInfo *i;
Jul 23, 2001
Jul 23, 2001
677
Mar 30, 2002
Mar 30, 2002
678
__PHYSFS_platformGrabMutex(stateLock);
Jul 23, 2001
Jul 23, 2001
679
Mar 30, 2002
Mar 30, 2002
680
681
682
683
for (i = searchPath; i != NULL; i = i->next)
{
/* already in search path? */
BAIL_IF_MACRO_MUTEX(strcmp(newDir, i->dirName)==0, NULL, stateLock, 1);
Jul 23, 2001
Jul 23, 2001
684
prev = i;
Mar 30, 2002
Mar 30, 2002
685
} /* for */
Jul 23, 2001
Jul 23, 2001
686
687
di = buildDirInfo(newDir, 0);
Mar 30, 2002
Mar 30, 2002
688
BAIL_IF_MACRO_MUTEX(di == NULL, NULL, stateLock, 0);
689
690
691
if (appendToPath)
{
Jul 7, 2001
Jul 7, 2001
692
di->next = NULL;
693
if (prev == NULL)
Jul 7, 2001
Jul 7, 2001
694
searchPath = di;
695
else
Jul 7, 2001
Jul 7, 2001
696
prev->next = di;
Jul 8, 2001
Jul 8, 2001
697
698
699
700
701
} /* if */
else
{
di->next = searchPath;
searchPath = di;
702
703
} /* else */
Mar 30, 2002
Mar 30, 2002
704
__PHYSFS_platformReleaseMutex(stateLock);
705
706
707
708
709
710
return(1);
} /* PHYSFS_addToSearchPath */
int PHYSFS_removeFromSearchPath(const char *oldDir)
{
Apr 1, 2002
Apr 1, 2002
711
712
713
PhysDirInfo *i;
PhysDirInfo *prev = NULL;
PhysDirInfo *next = NULL;
714
715
716
BAIL_IF_MACRO(oldDir == NULL, ERR_INVALID_ARGUMENT, 0);
Mar 30, 2002
Mar 30, 2002
717
__PHYSFS_platformGrabMutex(stateLock);
718
719
720
721
for (i = searchPath; i != NULL; i = i->next)
{
if (strcmp(i->dirName, oldDir) == 0)
{
Jul 6, 2001
Jul 6, 2001
722
next = i->next;
Mar 30, 2002
Mar 30, 2002
723
724
BAIL_IF_MACRO_MUTEX(!freeDirInfo(i, openReadList), NULL,
stateLock, 0);
Jul 6, 2001
Jul 6, 2001
725
726
if (prev == NULL)
Jul 6, 2001
Jul 6, 2001
727
searchPath = next;
728
else
Jul 6, 2001
Jul 6, 2001
729
prev->next = next;
Jul 6, 2001
Jul 6, 2001
730
Mar 30, 2002
Mar 30, 2002
731
BAIL_MACRO_MUTEX(NULL, stateLock, 1);
732
733
734
735
} /* if */
prev = i;
} /* for */
Mar 30, 2002
Mar 30, 2002
736
BAIL_MACRO_MUTEX(ERR_NOT_IN_SEARCH_PATH, stateLock, 0);
737
738
739
740
741
742
743
} /* PHYSFS_removeFromSearchPath */
char **PHYSFS_getSearchPath(void)
{
int count = 1;
int x;
Apr 1, 2002
Apr 1, 2002
744
PhysDirInfo *i;
745
746
char **retval;
Mar 30, 2002
Mar 30, 2002
747
748
__PHYSFS_platformGrabMutex(stateLock);
749
750
751
752
for (i = searchPath; i != NULL; i = i->next)
count++;
retval = (char **) malloc(sizeof (char *) * count);
Mar 30, 2002
Mar 30, 2002
753
BAIL_IF_MACRO_MUTEX(!retval, ERR_OUT_OF_MEMORY, stateLock, NULL);
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
count--;
retval[count] = NULL;
for (i = searchPath, x = 0; x < count; i = i->next, x++)
{
retval[x] = (char *) malloc(strlen(i->dirName) + 1);
if (retval[x] == NULL) /* this is friggin' ugly. */
{
while (x > 0)
{
x--;
free(retval[x]);
} /* while */
free(retval);
Mar 30, 2002
Mar 30, 2002
769
BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL);
770
771
772
773
774
} /* if */
strcpy(retval[x], i->dirName);
} /* for */
Mar 30, 2002
Mar 30, 2002
775
__PHYSFS_platformReleaseMutex(stateLock);
776
777
778
779
return(retval);
} /* PHYSFS_getSearchPath */
Sep 26, 2001
Sep 26, 2001
780
781
782
int PHYSFS_setSaneConfig(const char *organization, const char *appName,
const char *archiveExt, int includeCdRoms,
int archivesFirst)
Jul 6, 2001
Jul 6, 2001
784
785
786
787
788
const char *basedir = PHYSFS_getBaseDir();
const char *userdir = PHYSFS_getUserDir();
const char *dirsep = PHYSFS_getDirSeparator();
char *str;
Mar 30, 2002
Mar 30, 2002
789
790
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
Jul 6, 2001
Jul 6, 2001
791
/* set write dir... */
Sep 26, 2001
Sep 26, 2001
792
793
str = malloc(strlen(userdir) + (strlen(organization) * 2) +
(strlen(appName) * 2) + (strlen(dirsep) * 3) + 2);
Jul 6, 2001
Jul 6, 2001
794
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
Sep 26, 2001
Sep 26, 2001
795
sprintf(str, "%s.%s%s%s", userdir, organization, dirsep, appName);
Jul 16, 2001
Jul 16, 2001
796
797
798
if (!PHYSFS_setWriteDir(str))
{
Mar 15, 2002
Mar 15, 2002
799
800
int no_write = 0;
sprintf(str, ".%s/%s", organization, appName);
Sep 26, 2001
Sep 26, 2001
801
if ( (PHYSFS_setWriteDir(userdir)) &&
Mar 15, 2002
Mar 15, 2002
802
(PHYSFS_mkdir(str)) )
Sep 26, 2001
Sep 26, 2001
803
{
Mar 15, 2002
Mar 15, 2002
804
805
806
sprintf(str, "%s.%s%s%s", userdir, organization, dirsep, appName);
if (!PHYSFS_setWriteDir(str))
no_write = 1;
Sep 26, 2001
Sep 26, 2001
807
808
} /* if */
else
Jul 16, 2001
Jul 16, 2001
809
{
Mar 15, 2002
Mar 15, 2002
810
no_write = 1;
Sep 26, 2001
Sep 26, 2001
811
} /* else */
Mar 15, 2002
Mar 15, 2002
812
813
814
815
816
817
818
if (no_write)
{
PHYSFS_setWriteDir(NULL); /* just in case. */
free(str);
BAIL_MACRO(ERR_CANT_SET_WRITE_DIR, 0);
} /* if */
Jul 16, 2001
Jul 16, 2001
819
820
} /* if */
Sep 26, 2001
Sep 26, 2001
821
822
/* Put write dir first in search path... */
PHYSFS_addToSearchPath(str, 0);
Jul 6, 2001
Jul 6, 2001
823
824
free(str);
Sep 26, 2001
Sep 26, 2001
825
/* Put base path on search path... */
Jul 6, 2001
Jul 6, 2001
826
827
828
829
830
831
832
833
PHYSFS_addToSearchPath(basedir, 1);
/* handle CD-ROMs... */
if (includeCdRoms)
{
char **cds = PHYSFS_getCdRomDirs();
char **i;
for (i = cds; *i != NULL; i++)
Jul 7, 2001
Jul 7, 2001
834
PHYSFS_addToSearchPath(*i, 1);
Sep 26, 2001
Sep 26, 2001
835
Jul 6, 2001
Jul 6, 2001
836
837
838
839
840
841
PHYSFS_freeList(cds);
} /* if */
/* Root out archives, and add them to search path... */
if (archiveExt != NULL)
{
Jul 28, 2002
Jul 28, 2002
842
char **rc = PHYSFS_enumerateFiles("/");
Jul 6, 2001
Jul 6, 2001
843
char **i;
Sep 2, 2001
Sep 2, 2001
844
size_t extlen = strlen(archiveExt);
Jul 6, 2001
Jul 6, 2001
845
846
847
848
char *ext;
for (i = rc; *i != NULL; i++)
{
Sep 2, 2001
Sep 2, 2001
849
850
size_t l = strlen(*i);
if ((l > extlen) && ((*i)[l - extlen - 1] == '.'))
Jul 6, 2001
Jul 6, 2001
851
852
853
854
855
856
857
858
859
{
ext = (*i) + (l - extlen);
if (__PHYSFS_platformStricmp(ext, archiveExt) == 0)
{
const char *d = PHYSFS_getRealDir(*i);
str = malloc(strlen(d) + strlen(dirsep) + l + 1);
if (str != NULL)
{
sprintf(str, "%s%s%s", d, dirsep, *i);
Jul 7, 2001
Jul 7, 2001
860
PHYSFS_addToSearchPath(str, archivesFirst == 0);
Jul 6, 2001
Jul 6, 2001
861
862
863
864
865
866
867
868
869
870
free(str);
} /* if */
} /* if */
} /* if */
} /* for */
PHYSFS_freeList(rc);
} /* if */
return(1);
871
872
873
} /* PHYSFS_setSaneConfig */
Jul 7, 2001
Jul 7, 2001
874
875
876
877
878
879
void PHYSFS_permitSymbolicLinks(int allow)
{
allowSymLinks = allow;
} /* PHYSFS_permitSymbolicLinks */
Jul 6, 2001
Jul 6, 2001
880
/* string manipulation in C makes my ass itch. */
Aug 23, 2001
Aug 23, 2001
881
882
883
char * __PHYSFS_convertToDependent(const char *prepend,
const char *dirName,
const char *append)
Jul 6, 2001
Jul 6, 2001
884
{
Mar 30, 2002
Mar 30, 2002
885
const char *dirsep = __PHYSFS_platformDirSeparator;
Sep 2, 2001
Sep 2, 2001
886
size_t sepsize = strlen(dirsep);
Jul 6, 2001
Jul 6, 2001
887
888
889
890
891
char *str;
char *i1;
char *i2;
size_t allocSize;
Jul 16, 2001
Jul 16, 2001
892
893
894
while (*dirName == '/')
dirName++;
Jul 7, 2001
Jul 7, 2001
895
allocSize = strlen(dirName) + 1;
Jul 6, 2001
Jul 6, 2001
896
897
898
899
900
901
902
903
if (prepend != NULL)
allocSize += strlen(prepend) + sepsize;
if (append != NULL)
allocSize += strlen(append) + sepsize;
/* make sure there's enough space if the dir separator is bigger. */
if (sepsize > 1)
{
Jul 7, 2001
Jul 7, 2001
904
905
str = (char *) dirName;
do
Jul 6, 2001
Jul 6, 2001
906
{
Jul 7, 2001
Jul 7, 2001
907
908
909
str = strchr(str, '/');
if (str != NULL)
{
Jul 6, 2001
Jul 6, 2001
910
allocSize += (sepsize - 1);
Jul 7, 2001
Jul 7, 2001
911
912
913
str++;
} /* if */
} while (str != NULL);
Jul 6, 2001
Jul 6, 2001
914
915
916
917
918
} /* if */
str = (char *) malloc(allocSize);
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, NULL);
Jul 8, 2001
Jul 8, 2001
919
920
921
if (prepend == NULL)
*str = '\0';
else
Jul 6, 2001
Jul 6, 2001
922
923
924
{
strcpy(str, prepend);
strcat(str, dirsep);
Jul 8, 2001
Jul 8, 2001
925
} /* else */
Jul 6, 2001
Jul 6, 2001
926
Jul 7, 2001
Jul 7, 2001
927
for (i1 = (char *) dirName, i2 = str + strlen(str); *i1; i1++, i2++)
Jul 6, 2001
Jul 6, 2001
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
{
if (*i1 == '/')
{
strcpy(i2, dirsep);
i2 += sepsize;
} /* if */
else
{
*i2 = *i1;
} /* else */
} /* for */
*i2 = '\0';
if (append)
{
strcat(str, dirsep);
strcpy(str, append);
} /* if */
return(str);
Mar 24, 2002
Mar 24, 2002
948
} /* __PHYSFS_convertToDependent */
Jul 6, 2001
Jul 6, 2001
949
950
Jul 7, 2001
Jul 7, 2001
951
int __PHYSFS_verifySecurity(DirHandle *h, const char *fname)
Jul 7, 2001
Jul 7, 2001
953
954
955
int retval = 1;
char *start;
char *end;
Jul 6, 2001
Jul 6, 2001
956
957
char *str;
Jul 7, 2001
Jul 7, 2001
958
959
960
start = str = malloc(strlen(fname) + 1);
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
strcpy(str, fname);
Jul 6, 2001
Jul 6, 2001
961
Jul 7, 2001
Jul 7, 2001
962
963
964
965
966
967
968
969
while (1)
{
end = strchr(start, '/');
if (end != NULL)
*end = '\0';
if ( (strcmp(start, ".") == 0) ||
(strcmp(start, "..") == 0) ||
Jul 8, 2001
Jul 8, 2001
970
(strchr(start, '\\') != NULL) ||
Jul 7, 2001
Jul 7, 2001
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
(strchr(start, ':') != NULL) )
{
__PHYSFS_setError(ERR_INSECURE_FNAME);
retval = 0;
break;
} /* if */
if ((!allowSymLinks) && (h->funcs->isSymLink(h, str)))
{
__PHYSFS_setError(ERR_SYMLINK_DISALLOWED);
retval = 0;
break;
} /* if */
if (end == NULL)
break;
*end = '/';
start = end + 1;
} /* while */
Jul 6, 2001
Jul 6, 2001
991
992
free(str);
Jul 7, 2001
Jul 7, 2001
993
994
return(retval);
} /* __PHYSFS_verifySecurity */
Mar 30, 2002
Mar 30, 2002
997
int PHYSFS_mkdir(const char *dname)
Jul 7, 2001
Jul 7, 2001
999
DirHandle *h;
Jul 6, 2001
Jul 6, 2001
1000
char *str;