Skip to content

Latest commit

 

History

History
1548 lines (1218 loc) · 37.3 KB

physfs.c

File metadata and controls

1548 lines (1218 loc) · 37.3 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 26, 2002
Jul 26, 2002
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
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
231
232
233
static DirHandle *openDirectory(const char *d, int forWriting)
{
const DirFunctions **i;
Jul 26, 2002
Jul 26, 2002
234
const char *ext;
Jul 7, 2001
Jul 7, 2001
235
Jul 23, 2001
Jul 23, 2001
236
237
BAIL_IF_MACRO(!__PHYSFS_platformExists(d), ERR_NO_SUCH_FILE, NULL);
Jul 26, 2002
Jul 26, 2002
238
239
ext = find_filename_extension(d);
if (ext != NULL)
Jul 7, 2001
Jul 7, 2001
240
{
Jul 26, 2002
Jul 26, 2002
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
/* 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
270
271
272
273
274
275
__PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
return(NULL);
} /* openDirectory */
Apr 1, 2002
Apr 1, 2002
276
static PhysDirInfo *buildDirInfo(const char *newDir, int forWriting)
Jul 7, 2001
Jul 7, 2001
277
278
{
DirHandle *dirHandle = NULL;
Apr 1, 2002
Apr 1, 2002
279
PhysDirInfo *di = NULL;
Jul 7, 2001
Jul 7, 2001
280
281
282
283
284
285
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
286
di = (PhysDirInfo *) malloc(sizeof (PhysDirInfo));
Jul 7, 2001
Jul 7, 2001
287
if (di == NULL)
Mar 30, 2002
Mar 30, 2002
288
{
Jul 8, 2001
Jul 8, 2001
289
dirHandle->funcs->dirClose(dirHandle);
Mar 30, 2002
Mar 30, 2002
290
291
BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0);
} /* if */
Jul 7, 2001
Jul 7, 2001
292
293
294
295
296
di->dirName = (char *) malloc(strlen(newDir) + 1);
if (di->dirName == NULL)
{
free(di);
Jul 8, 2001
Jul 8, 2001
297
dirHandle->funcs->dirClose(dirHandle);
Mar 30, 2002
Mar 30, 2002
298
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
Jul 7, 2001
Jul 7, 2001
299
300
301
302
303
304
305
306
307
} /* if */
di->next = NULL;
di->dirHandle = dirHandle;
strcpy(di->dirName, newDir);
return(di);
} /* buildDirInfo */
Mar 30, 2002
Mar 30, 2002
308
/* MAKE SURE you've got the stateLock held before calling this! */
Apr 1, 2002
Apr 1, 2002
309
static int freeDirInfo(PhysDirInfo *di, FileHandleList *openList)
Jul 7, 2001
Jul 7, 2001
310
311
312
313
314
315
316
317
{
FileHandleList *i;
if (di == NULL)
return(1);
for (i = openList; i != NULL; i = i->next)
{
Jul 9, 2001
Jul 9, 2001
318
const DirHandle *h = ((FileHandle *) &(i->handle.opaque))->dirHandle;
Jul 7, 2001
Jul 7, 2001
319
320
BAIL_IF_MACRO(h == di->dirHandle, ERR_FILES_STILL_OPEN, 0);
} /* for */
Mar 30, 2002
Mar 30, 2002
321
Jul 8, 2001
Jul 8, 2001
322
di->dirHandle->funcs->dirClose(di->dirHandle);
Jul 7, 2001
Jul 7, 2001
323
324
325
326
327
328
329
free(di->dirName);
free(di);
return(1);
} /* freeDirInfo */
static char *calculateUserDir(void)
Jul 6, 2001
Jul 6, 2001
330
331
332
333
334
335
{
char *retval = NULL;
const char *str = NULL;
str = __PHYSFS_platformGetUserDir();
if (str != NULL)
Jul 7, 2001
Jul 7, 2001
336
retval = (char *) str;
Jul 6, 2001
Jul 6, 2001
337
338
339
340
341
342
else
{
const char *dirsep = PHYSFS_getDirSeparator();
const char *uname = __PHYSFS_platformGetUserName();
str = (uname != NULL) ? uname : "default";
Jul 7, 2001
Jul 7, 2001
343
retval = (char *) malloc(strlen(baseDir) + strlen(str) +
Apr 2, 2002
Apr 2, 2002
344
strlen(dirsep) + 6);
Jul 6, 2001
Jul 6, 2001
345
346
347
348
if (retval == NULL)
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
else
Apr 2, 2002
Apr 2, 2002
349
sprintf(retval, "%susers%s%s", baseDir, dirsep, str);
Jul 6, 2001
Jul 6, 2001
350
351
if (uname != NULL)
Jul 7, 2001
Jul 7, 2001
352
free((void *) uname);
Jul 6, 2001
Jul 6, 2001
353
354
355
356
357
358
} /* else */
return(retval);
} /* calculateUserDir */
Jul 8, 2001
Jul 8, 2001
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
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
380
381
static char *calculateBaseDir(const char *argv0)
{
Jul 8, 2001
Jul 8, 2001
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
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
407
size = (size_t) (ptr - argv0);
Jul 8, 2001
Jul 8, 2001
408
409
410
411
412
413
414
415
416
417
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
418
419
420
421
422
423
424
425
426
427
428
429
430
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
431
432
433
} /* calculateBaseDir */
Mar 30, 2002
Mar 30, 2002
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
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 */
458
459
int PHYSFS_init(const char *argv0)
{
Jul 16, 2001
Jul 16, 2001
460
461
char *ptr;
462
BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
Mar 24, 2002
Mar 24, 2002
463
BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0);
Mar 30, 2002
Mar 30, 2002
465
466
BAIL_IF_MACRO(!initializeMutexes(), NULL, 0);
Jul 6, 2001
Jul 6, 2001
467
baseDir = calculateBaseDir(argv0);
Jul 7, 2001
Jul 7, 2001
468
BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
Apr 6, 2002
Apr 6, 2002
469
Jul 16, 2001
Jul 16, 2001
470
471
472
473
474
ptr = __PHYSFS_platformRealPath(baseDir);
free(baseDir);
BAIL_IF_MACRO(ptr == NULL, NULL, 0);
baseDir = ptr;
Jul 8, 2001
Jul 8, 2001
475
BAIL_IF_MACRO(!appendDirSep(&baseDir), NULL, 0);
Jul 6, 2001
Jul 6, 2001
476
477
userDir = calculateUserDir();
Jul 16, 2001
Jul 16, 2001
478
479
480
481
482
483
484
if (userDir != NULL)
{
ptr = __PHYSFS_platformRealPath(userDir);
free(userDir);
userDir = ptr;
} /* if */
Jul 8, 2001
Jul 8, 2001
485
if ((userDir == NULL) || (!appendDirSep(&userDir)))
Jul 6, 2001
Jul 6, 2001
486
487
488
489
490
491
{
free(baseDir);
baseDir = NULL;
return(0);
} /* if */
492
initialized = 1;
Apr 4, 2002
Apr 4, 2002
493
494
495
/* This makes sure that the error subsystem is initialized. */
__PHYSFS_setError(PHYSFS_getLastError());
496
497
498
499
return(1);
} /* PHYSFS_init */
Mar 30, 2002
Mar 30, 2002
500
/* MAKE SURE you hold stateLock before calling this! */
Jul 7, 2001
Jul 7, 2001
501
static int closeFileHandleList(FileHandleList **list)
Jul 6, 2001
Jul 6, 2001
502
503
504
{
FileHandleList *i;
FileHandleList *next = NULL;
Jul 7, 2001
Jul 7, 2001
505
FileHandle *h;
Jul 6, 2001
Jul 6, 2001
506
507
508
509
for (i = *list; i != NULL; i = next)
{
next = i->next;
Jul 9, 2001
Jul 9, 2001
510
511
h = (FileHandle *) (i->handle.opaque);
if (!h->funcs->fileClose(h))
Jul 7, 2001
Jul 7, 2001
512
513
514
515
516
517
{
*list = i;
return(0);
} /* if */
free(i);
Jul 6, 2001
Jul 6, 2001
518
519
520
} /* for */
*list = NULL;
Jul 7, 2001
Jul 7, 2001
521
522
return(1);
} /* closeFileHandleList */
Jul 6, 2001
Jul 6, 2001
523
524
Mar 30, 2002
Mar 30, 2002
525
/* MAKE SURE you hold the stateLock before calling this! */
526
527
static void freeSearchPath(void)
{
Apr 1, 2002
Apr 1, 2002
528
529
PhysDirInfo *i;
PhysDirInfo *next = NULL;
Jul 6, 2001
Jul 6, 2001
531
532
closeFileHandleList(&openReadList);
533
534
535
536
if (searchPath != NULL)
{
for (i = searchPath; i != NULL; i = next)
{
Jul 9, 2001
Jul 9, 2001
537
next = i->next;
Jul 7, 2001
Jul 7, 2001
538
freeDirInfo(i, openReadList);
539
540
541
542
543
544
} /* for */
searchPath = NULL;
} /* if */
} /* freeSearchPath */
Jul 7, 2001
Jul 7, 2001
545
int PHYSFS_deinit(void)
546
547
{
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
Mar 24, 2002
Mar 24, 2002
548
BAIL_IF_MACRO(!__PHYSFS_platformDeinit(), NULL, 0);
Jul 6, 2001
Jul 6, 2001
550
closeFileHandleList(&openWriteList);
Jul 7, 2001
Jul 7, 2001
551
552
BAIL_IF_MACRO(!PHYSFS_setWriteDir(NULL), ERR_FILES_STILL_OPEN, 0);
553
554
555
freeSearchPath();
freeErrorMessages();
Jul 6, 2001
Jul 6, 2001
556
if (baseDir != NULL)
Jul 6, 2001
Jul 6, 2001
557
{
Jul 6, 2001
Jul 6, 2001
558
free(baseDir);
Jul 6, 2001
Jul 6, 2001
559
560
561
562
563
564
565
566
baseDir = NULL;
} /* if */
if (userDir != NULL)
{
free(userDir);
userDir = NULL;
} /* if */
Jul 6, 2001
Jul 6, 2001
567
568
allowSymLinks = 0;
569
initialized = 0;
Mar 30, 2002
Mar 30, 2002
570
571
572
573
574
__PHYSFS_platformDestroyMutex(errorLock);
__PHYSFS_platformDestroyMutex(stateLock);
errorLock = stateLock = NULL;
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
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
597
return(__PHYSFS_platformDirSeparator);
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
} /* 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
615
return(userDir); /* this is calculated in PHYSFS_init()... */
616
617
618
619
620
} /* PHYSFS_getUserDir */
const char *PHYSFS_getWriteDir(void)
{
Mar 30, 2002
Mar 30, 2002
621
622
623
624
625
626
const char *retval = NULL;
__PHYSFS_platformGrabMutex(stateLock);
if (writeDir != NULL)
retval = writeDir->dirName;
__PHYSFS_platformReleaseMutex(stateLock);
Jul 7, 2001
Jul 7, 2001
627
Mar 30, 2002
Mar 30, 2002
628
return(retval);
629
630
631
632
633
} /* PHYSFS_getWriteDir */
int PHYSFS_setWriteDir(const char *newDir)
{
Mar 30, 2002
Mar 30, 2002
634
635
636
637
int retval = 1;
__PHYSFS_platformGrabMutex(stateLock);
638
639
if (writeDir != NULL)
{
Mar 30, 2002
Mar 30, 2002
640
641
BAIL_IF_MACRO_MUTEX(!freeDirInfo(writeDir, openWriteList), NULL,
stateLock, 0);
642
643
644
writeDir = NULL;
} /* if */
Jul 6, 2001
Jul 6, 2001
645
646
if (newDir != NULL)
{
Jul 7, 2001
Jul 7, 2001
647
writeDir = buildDirInfo(newDir, 1);
Mar 30, 2002
Mar 30, 2002
648
retval = (writeDir != NULL);
Jul 6, 2001
Jul 6, 2001
649
} /* if */
Mar 30, 2002
Mar 30, 2002
651
652
653
__PHYSFS_platformReleaseMutex(stateLock);
return(retval);
654
655
656
657
658
} /* PHYSFS_setWriteDir */
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
{
Apr 1, 2002
Apr 1, 2002
659
660
661
PhysDirInfo *di;
PhysDirInfo *prev = NULL;
PhysDirInfo *i;
Jul 23, 2001
Jul 23, 2001
662
Mar 30, 2002
Mar 30, 2002
663
__PHYSFS_platformGrabMutex(stateLock);
Jul 23, 2001
Jul 23, 2001
664
Mar 30, 2002
Mar 30, 2002
665
666
667
668
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
669
prev = i;
Mar 30, 2002
Mar 30, 2002
670
} /* for */
Jul 23, 2001
Jul 23, 2001
671
672
di = buildDirInfo(newDir, 0);
Mar 30, 2002
Mar 30, 2002
673
BAIL_IF_MACRO_MUTEX(di == NULL, NULL, stateLock, 0);
674
675
676
if (appendToPath)
{
Jul 7, 2001
Jul 7, 2001
677
di->next = NULL;
678
if (prev == NULL)
Jul 7, 2001
Jul 7, 2001
679
searchPath = di;
680
else
Jul 7, 2001
Jul 7, 2001
681
prev->next = di;
Jul 8, 2001
Jul 8, 2001
682
683
684
685
686
} /* if */
else
{
di->next = searchPath;
searchPath = di;
687
688
} /* else */
Mar 30, 2002
Mar 30, 2002
689
__PHYSFS_platformReleaseMutex(stateLock);
690
691
692
693
694
695
return(1);
} /* PHYSFS_addToSearchPath */
int PHYSFS_removeFromSearchPath(const char *oldDir)
{
Apr 1, 2002
Apr 1, 2002
696
697
698
PhysDirInfo *i;
PhysDirInfo *prev = NULL;
PhysDirInfo *next = NULL;
699
700
701
BAIL_IF_MACRO(oldDir == NULL, ERR_INVALID_ARGUMENT, 0);
Mar 30, 2002
Mar 30, 2002
702
__PHYSFS_platformGrabMutex(stateLock);
703
704
705
706
for (i = searchPath; i != NULL; i = i->next)
{
if (strcmp(i->dirName, oldDir) == 0)
{
Jul 6, 2001
Jul 6, 2001
707
next = i->next;
Mar 30, 2002
Mar 30, 2002
708
709
BAIL_IF_MACRO_MUTEX(!freeDirInfo(i, openReadList), NULL,
stateLock, 0);
Jul 6, 2001
Jul 6, 2001
710
711
if (prev == NULL)
Jul 6, 2001
Jul 6, 2001
712
searchPath = next;
713
else
Jul 6, 2001
Jul 6, 2001
714
prev->next = next;
Jul 6, 2001
Jul 6, 2001
715
Mar 30, 2002
Mar 30, 2002
716
BAIL_MACRO_MUTEX(NULL, stateLock, 1);
717
718
719
720
} /* if */
prev = i;
} /* for */
Mar 30, 2002
Mar 30, 2002
721
BAIL_MACRO_MUTEX(ERR_NOT_IN_SEARCH_PATH, stateLock, 0);
722
723
724
725
726
727
728
} /* PHYSFS_removeFromSearchPath */
char **PHYSFS_getSearchPath(void)
{
int count = 1;
int x;
Apr 1, 2002
Apr 1, 2002
729
PhysDirInfo *i;
730
731
char **retval;
Mar 30, 2002
Mar 30, 2002
732
733
__PHYSFS_platformGrabMutex(stateLock);
734
735
736
737
for (i = searchPath; i != NULL; i = i->next)
count++;
retval = (char **) malloc(sizeof (char *) * count);
Mar 30, 2002
Mar 30, 2002
738
BAIL_IF_MACRO_MUTEX(!retval, ERR_OUT_OF_MEMORY, stateLock, NULL);
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
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
754
BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL);
755
756
757
758
759
} /* if */
strcpy(retval[x], i->dirName);
} /* for */
Mar 30, 2002
Mar 30, 2002
760
__PHYSFS_platformReleaseMutex(stateLock);
761
762
763
764
return(retval);
} /* PHYSFS_getSearchPath */
Sep 26, 2001
Sep 26, 2001
765
766
767
int PHYSFS_setSaneConfig(const char *organization, const char *appName,
const char *archiveExt, int includeCdRoms,
int archivesFirst)
Jul 6, 2001
Jul 6, 2001
769
770
771
772
773
const char *basedir = PHYSFS_getBaseDir();
const char *userdir = PHYSFS_getUserDir();
const char *dirsep = PHYSFS_getDirSeparator();
char *str;
Mar 30, 2002
Mar 30, 2002
774
775
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
Jul 6, 2001
Jul 6, 2001
776
/* set write dir... */
Sep 26, 2001
Sep 26, 2001
777
778
str = malloc(strlen(userdir) + (strlen(organization) * 2) +
(strlen(appName) * 2) + (strlen(dirsep) * 3) + 2);
Jul 6, 2001
Jul 6, 2001
779
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
Sep 26, 2001
Sep 26, 2001
780
sprintf(str, "%s.%s%s%s", userdir, organization, dirsep, appName);
Jul 16, 2001
Jul 16, 2001
781
782
783
if (!PHYSFS_setWriteDir(str))
{
Mar 15, 2002
Mar 15, 2002
784
785
int no_write = 0;
sprintf(str, ".%s/%s", organization, appName);
Sep 26, 2001
Sep 26, 2001
786
if ( (PHYSFS_setWriteDir(userdir)) &&
Mar 15, 2002
Mar 15, 2002
787
(PHYSFS_mkdir(str)) )
Sep 26, 2001
Sep 26, 2001
788
{
Mar 15, 2002
Mar 15, 2002
789
790
791
sprintf(str, "%s.%s%s%s", userdir, organization, dirsep, appName);
if (!PHYSFS_setWriteDir(str))
no_write = 1;
Sep 26, 2001
Sep 26, 2001
792
793
} /* if */
else
Jul 16, 2001
Jul 16, 2001
794
{
Mar 15, 2002
Mar 15, 2002
795
no_write = 1;
Sep 26, 2001
Sep 26, 2001
796
} /* else */
Mar 15, 2002
Mar 15, 2002
797
798
799
800
801
802
803
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
804
805
} /* if */
Sep 26, 2001
Sep 26, 2001
806
807
/* Put write dir first in search path... */
PHYSFS_addToSearchPath(str, 0);
Jul 6, 2001
Jul 6, 2001
808
809
free(str);
Sep 26, 2001
Sep 26, 2001
810
/* Put base path on search path... */
Jul 6, 2001
Jul 6, 2001
811
812
813
814
815
816
817
818
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
819
PHYSFS_addToSearchPath(*i, 1);
Sep 26, 2001
Sep 26, 2001
820
Jul 6, 2001
Jul 6, 2001
821
822
823
824
825
826
827
828
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
829
size_t extlen = strlen(archiveExt);
Jul 6, 2001
Jul 6, 2001
830
831
832
833
char *ext;
for (i = rc; *i != NULL; i++)
{
Sep 2, 2001
Sep 2, 2001
834
835
size_t l = strlen(*i);
if ((l > extlen) && ((*i)[l - extlen - 1] == '.'))
Jul 6, 2001
Jul 6, 2001
836
837
838
839
840
841
842
843
844
{
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
845
PHYSFS_addToSearchPath(str, archivesFirst == 0);
Jul 6, 2001
Jul 6, 2001
846
847
848
849
850
851
852
853
854
855
free(str);
} /* if */
} /* if */
} /* if */
} /* for */
PHYSFS_freeList(rc);
} /* if */
return(1);
856
857
858
} /* PHYSFS_setSaneConfig */
Jul 7, 2001
Jul 7, 2001
859
860
861
862
863
864
void PHYSFS_permitSymbolicLinks(int allow)
{
allowSymLinks = allow;
} /* PHYSFS_permitSymbolicLinks */
Jul 6, 2001
Jul 6, 2001
865
/* string manipulation in C makes my ass itch. */
Aug 23, 2001
Aug 23, 2001
866
867
868
char * __PHYSFS_convertToDependent(const char *prepend,
const char *dirName,
const char *append)
Jul 6, 2001
Jul 6, 2001
869
{
Mar 30, 2002
Mar 30, 2002
870
const char *dirsep = __PHYSFS_platformDirSeparator;
Sep 2, 2001
Sep 2, 2001
871
size_t sepsize = strlen(dirsep);
Jul 6, 2001
Jul 6, 2001
872
873
874
875
876
char *str;
char *i1;
char *i2;
size_t allocSize;
Jul 16, 2001
Jul 16, 2001
877
878
879
while (*dirName == '/')
dirName++;
Jul 7, 2001
Jul 7, 2001
880
allocSize = strlen(dirName) + 1;
Jul 6, 2001
Jul 6, 2001
881
882
883
884
885
886
887
888
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
889
890
str = (char *) dirName;
do
Jul 6, 2001
Jul 6, 2001
891
{
Jul 7, 2001
Jul 7, 2001
892
893
894
str = strchr(str, '/');
if (str != NULL)
{
Jul 6, 2001
Jul 6, 2001
895
allocSize += (sepsize - 1);
Jul 7, 2001
Jul 7, 2001
896
897
898
str++;
} /* if */
} while (str != NULL);
Jul 6, 2001
Jul 6, 2001
899
900
901
902
903
} /* if */
str = (char *) malloc(allocSize);
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, NULL);
Jul 8, 2001
Jul 8, 2001
904
905
906
if (prepend == NULL)
*str = '\0';
else
Jul 6, 2001
Jul 6, 2001
907
908
909
{
strcpy(str, prepend);
strcat(str, dirsep);
Jul 8, 2001
Jul 8, 2001
910
} /* else */
Jul 6, 2001
Jul 6, 2001
911
Jul 7, 2001
Jul 7, 2001
912
for (i1 = (char *) dirName, i2 = str + strlen(str); *i1; i1++, i2++)
Jul 6, 2001
Jul 6, 2001
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
{
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
933
} /* __PHYSFS_convertToDependent */
Jul 6, 2001
Jul 6, 2001
934
935
Jul 7, 2001
Jul 7, 2001
936
int __PHYSFS_verifySecurity(DirHandle *h, const char *fname)
Jul 7, 2001
Jul 7, 2001
938
939
940
int retval = 1;
char *start;
char *end;
Jul 6, 2001
Jul 6, 2001
941
942
char *str;
Jul 7, 2001
Jul 7, 2001
943
944
945
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
946
Jul 7, 2001
Jul 7, 2001
947
948
949
950
951
952
953
954
while (1)
{
end = strchr(start, '/');
if (end != NULL)
*end = '\0';
if ( (strcmp(start, ".") == 0) ||
(strcmp(start, "..") == 0) ||
Jul 8, 2001
Jul 8, 2001
955
(strchr(start, '\\') != NULL) ||
Jul 7, 2001
Jul 7, 2001
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
(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
976
977
free(str);
Jul 7, 2001
Jul 7, 2001
978
979
return(retval);
} /* __PHYSFS_verifySecurity */
Mar 30, 2002
Mar 30, 2002
982
int PHYSFS_mkdir(const char *dname)
Jul 7, 2001
Jul 7, 2001
984
DirHandle *h;
Jul 6, 2001
Jul 6, 2001
985
char *str;
Jul 7, 2001
Jul 7, 2001
986
987
988
char *start;
char *end;
int retval = 0;
Jul 6, 2001
Jul 6, 2001
989
Mar 30, 2002
Mar 30, 2002
990
991
992
BAIL_IF_MACRO(dname == NULL, ERR_INVALID_ARGUMENT, 0);
while (*dname == '/')
dname++;
Jul 16, 2001
Jul 16, 2001
993
Mar 30, 2002
Mar 30, 2002
994
995
__PHYSFS_platformGrabMutex(stateLock);
BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
Jul 7, 2001
Jul 7, 2001
996
h = writeDir->dirHandle;
Mar 30, 2002
Mar 30, 2002
997
998
999
1000
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);