Skip to content

Latest commit

 

History

History
1410 lines (1108 loc) · 33.6 KB

physfs.c

File metadata and controls

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