Skip to content

Latest commit

 

History

History
1465 lines (1152 loc) · 35.1 KB

physfs.c

File metadata and controls

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