First shot at thread-safety.
This commit is contained in:
parent
5d2b8493f6
commit
39406cbacc
254
physfs.c
254
physfs.c
|
@ -85,7 +85,6 @@ static const DirFunctions *dirFunctions[] =
|
||||||
|
|
||||||
|
|
||||||
/* General PhysicsFS state ... */
|
/* General PhysicsFS state ... */
|
||||||
|
|
||||||
static int initialized = 0;
|
static int initialized = 0;
|
||||||
static ErrMsg *errorMessages = NULL;
|
static ErrMsg *errorMessages = NULL;
|
||||||
static DirInfo *searchPath = NULL;
|
static DirInfo *searchPath = NULL;
|
||||||
|
@ -96,6 +95,9 @@ static char *baseDir = NULL;
|
||||||
static char *userDir = NULL;
|
static char *userDir = NULL;
|
||||||
static int allowSymLinks = 0;
|
static int allowSymLinks = 0;
|
||||||
|
|
||||||
|
/* mutexes ... */
|
||||||
|
static void *errorLock = NULL; /* protects error message list. */
|
||||||
|
static void *stateLock = NULL; /* protects other PhysFS static state. */
|
||||||
|
|
||||||
|
|
||||||
/* functions ... */
|
/* functions ... */
|
||||||
|
@ -105,6 +107,7 @@ static ErrMsg *findErrorForCurrentThread(void)
|
||||||
ErrMsg *i;
|
ErrMsg *i;
|
||||||
int tid;
|
int tid;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(errorLock);
|
||||||
if (errorMessages != NULL)
|
if (errorMessages != NULL)
|
||||||
{
|
{
|
||||||
tid = __PHYSFS_platformGetThreadID();
|
tid = __PHYSFS_platformGetThreadID();
|
||||||
|
@ -112,9 +115,13 @@ static ErrMsg *findErrorForCurrentThread(void)
|
||||||
for (i = errorMessages; i != NULL; i = i->next)
|
for (i = errorMessages; i != NULL; i = i->next)
|
||||||
{
|
{
|
||||||
if (i->tid == tid)
|
if (i->tid == tid)
|
||||||
|
{
|
||||||
|
__PHYSFS_platformReleaseMutex(errorLock);
|
||||||
return(i);
|
return(i);
|
||||||
|
} /* if */
|
||||||
} /* for */
|
} /* for */
|
||||||
} /* if */
|
} /* if */
|
||||||
|
__PHYSFS_platformReleaseMutex(errorLock);
|
||||||
|
|
||||||
return(NULL); /* no error available. */
|
return(NULL); /* no error available. */
|
||||||
} /* findErrorForCurrentThread */
|
} /* findErrorForCurrentThread */
|
||||||
|
@ -137,8 +144,11 @@ void __PHYSFS_setError(const char *str)
|
||||||
|
|
||||||
memset((void *) err, '\0', sizeof (ErrMsg));
|
memset((void *) err, '\0', sizeof (ErrMsg));
|
||||||
err->tid = __PHYSFS_platformGetThreadID();
|
err->tid = __PHYSFS_platformGetThreadID();
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(errorLock);
|
||||||
err->next = errorMessages;
|
err->next = errorMessages;
|
||||||
errorMessages = err;
|
errorMessages = err;
|
||||||
|
__PHYSFS_platformReleaseMutex(errorLock);
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
err->errorAvailable = 1;
|
err->errorAvailable = 1;
|
||||||
|
@ -147,19 +157,6 @@ void __PHYSFS_setError(const char *str)
|
||||||
} /* __PHYSFS_setError */
|
} /* __PHYSFS_setError */
|
||||||
|
|
||||||
|
|
||||||
static void freeErrorMessages(void)
|
|
||||||
{
|
|
||||||
ErrMsg *i;
|
|
||||||
ErrMsg *next;
|
|
||||||
|
|
||||||
for (i = errorMessages; i != NULL; i = next)
|
|
||||||
{
|
|
||||||
next = i->next;
|
|
||||||
free(i);
|
|
||||||
} /* for */
|
|
||||||
} /* freeErrorMessages */
|
|
||||||
|
|
||||||
|
|
||||||
const char *PHYSFS_getLastError(void)
|
const char *PHYSFS_getLastError(void)
|
||||||
{
|
{
|
||||||
ErrMsg *err = findErrorForCurrentThread();
|
ErrMsg *err = findErrorForCurrentThread();
|
||||||
|
@ -172,6 +169,20 @@ const char *PHYSFS_getLastError(void)
|
||||||
} /* PHYSFS_getLastError */
|
} /* PHYSFS_getLastError */
|
||||||
|
|
||||||
|
|
||||||
|
/* MAKE SURE that errorLock is held before calling this! */
|
||||||
|
static void freeErrorMessages(void)
|
||||||
|
{
|
||||||
|
ErrMsg *i;
|
||||||
|
ErrMsg *next;
|
||||||
|
|
||||||
|
for (i = errorMessages; i != NULL; i = next)
|
||||||
|
{
|
||||||
|
next = i->next;
|
||||||
|
free(i);
|
||||||
|
} /* for */
|
||||||
|
} /* freeErrorMessages */
|
||||||
|
|
||||||
|
|
||||||
void PHYSFS_getLinkedVersion(PHYSFS_Version *ver)
|
void PHYSFS_getLinkedVersion(PHYSFS_Version *ver)
|
||||||
{
|
{
|
||||||
if (ver != NULL)
|
if (ver != NULL)
|
||||||
|
@ -212,16 +223,17 @@ static DirInfo *buildDirInfo(const char *newDir, int forWriting)
|
||||||
|
|
||||||
di = (DirInfo *) malloc(sizeof (DirInfo));
|
di = (DirInfo *) malloc(sizeof (DirInfo));
|
||||||
if (di == NULL)
|
if (di == NULL)
|
||||||
|
{
|
||||||
dirHandle->funcs->dirClose(dirHandle);
|
dirHandle->funcs->dirClose(dirHandle);
|
||||||
BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0);
|
BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
di->dirName = (char *) malloc(strlen(newDir) + 1);
|
di->dirName = (char *) malloc(strlen(newDir) + 1);
|
||||||
if (di->dirName == NULL)
|
if (di->dirName == NULL)
|
||||||
{
|
{
|
||||||
free(di);
|
free(di);
|
||||||
dirHandle->funcs->dirClose(dirHandle);
|
dirHandle->funcs->dirClose(dirHandle);
|
||||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
|
||||||
return(0);
|
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
di->next = NULL;
|
di->next = NULL;
|
||||||
|
@ -231,6 +243,7 @@ static DirInfo *buildDirInfo(const char *newDir, int forWriting)
|
||||||
} /* buildDirInfo */
|
} /* buildDirInfo */
|
||||||
|
|
||||||
|
|
||||||
|
/* MAKE SURE you've got the stateLock held before calling this! */
|
||||||
static int freeDirInfo(DirInfo *di, FileHandleList *openList)
|
static int freeDirInfo(DirInfo *di, FileHandleList *openList)
|
||||||
{
|
{
|
||||||
FileHandleList *i;
|
FileHandleList *i;
|
||||||
|
@ -243,7 +256,7 @@ static int freeDirInfo(DirInfo *di, FileHandleList *openList)
|
||||||
const DirHandle *h = ((FileHandle *) &(i->handle.opaque))->dirHandle;
|
const DirHandle *h = ((FileHandle *) &(i->handle.opaque))->dirHandle;
|
||||||
BAIL_IF_MACRO(h == di->dirHandle, ERR_FILES_STILL_OPEN, 0);
|
BAIL_IF_MACRO(h == di->dirHandle, ERR_FILES_STILL_OPEN, 0);
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
di->dirHandle->funcs->dirClose(di->dirHandle);
|
di->dirHandle->funcs->dirClose(di->dirHandle);
|
||||||
free(di->dirName);
|
free(di->dirName);
|
||||||
free(di);
|
free(di);
|
||||||
|
@ -356,6 +369,30 @@ static char *calculateBaseDir(const char *argv0)
|
||||||
} /* calculateBaseDir */
|
} /* calculateBaseDir */
|
||||||
|
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_init(const char *argv0)
|
int PHYSFS_init(const char *argv0)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
@ -364,6 +401,8 @@ int PHYSFS_init(const char *argv0)
|
||||||
BAIL_IF_MACRO(argv0 == NULL, ERR_INVALID_ARGUMENT, 0);
|
BAIL_IF_MACRO(argv0 == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0);
|
BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0);
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(!initializeMutexes(), NULL, 0);
|
||||||
|
|
||||||
baseDir = calculateBaseDir(argv0);
|
baseDir = calculateBaseDir(argv0);
|
||||||
BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
|
BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
|
||||||
ptr = __PHYSFS_platformRealPath(baseDir);
|
ptr = __PHYSFS_platformRealPath(baseDir);
|
||||||
|
@ -393,6 +432,7 @@ int PHYSFS_init(const char *argv0)
|
||||||
} /* PHYSFS_init */
|
} /* PHYSFS_init */
|
||||||
|
|
||||||
|
|
||||||
|
/* MAKE SURE you hold stateLock before calling this! */
|
||||||
static int closeFileHandleList(FileHandleList **list)
|
static int closeFileHandleList(FileHandleList **list)
|
||||||
{
|
{
|
||||||
FileHandleList *i;
|
FileHandleList *i;
|
||||||
|
@ -417,6 +457,7 @@ static int closeFileHandleList(FileHandleList **list)
|
||||||
} /* closeFileHandleList */
|
} /* closeFileHandleList */
|
||||||
|
|
||||||
|
|
||||||
|
/* MAKE SURE you hold the stateLock before calling this! */
|
||||||
static void freeSearchPath(void)
|
static void freeSearchPath(void)
|
||||||
{
|
{
|
||||||
DirInfo *i;
|
DirInfo *i;
|
||||||
|
@ -461,6 +502,11 @@ int PHYSFS_deinit(void)
|
||||||
|
|
||||||
allowSymLinks = 0;
|
allowSymLinks = 0;
|
||||||
initialized = 0;
|
initialized = 0;
|
||||||
|
|
||||||
|
__PHYSFS_platformDestroyMutex(errorLock);
|
||||||
|
__PHYSFS_platformDestroyMutex(stateLock);
|
||||||
|
|
||||||
|
errorLock = stateLock = NULL;
|
||||||
return(1);
|
return(1);
|
||||||
} /* PHYSFS_deinit */
|
} /* PHYSFS_deinit */
|
||||||
|
|
||||||
|
@ -507,49 +553,59 @@ const char *PHYSFS_getUserDir(void)
|
||||||
|
|
||||||
const char *PHYSFS_getWriteDir(void)
|
const char *PHYSFS_getWriteDir(void)
|
||||||
{
|
{
|
||||||
if (writeDir == NULL)
|
const char *retval = NULL;
|
||||||
return(NULL);
|
|
||||||
|
|
||||||
return(writeDir->dirName);
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
if (writeDir != NULL)
|
||||||
|
retval = writeDir->dirName;
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
|
||||||
|
return(retval);
|
||||||
} /* PHYSFS_getWriteDir */
|
} /* PHYSFS_getWriteDir */
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_setWriteDir(const char *newDir)
|
int PHYSFS_setWriteDir(const char *newDir)
|
||||||
{
|
{
|
||||||
|
int retval = 1;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
|
||||||
if (writeDir != NULL)
|
if (writeDir != NULL)
|
||||||
{
|
{
|
||||||
BAIL_IF_MACRO(!freeDirInfo(writeDir, openWriteList), NULL, 0);
|
BAIL_IF_MACRO_MUTEX(!freeDirInfo(writeDir, openWriteList), NULL,
|
||||||
|
stateLock, 0);
|
||||||
writeDir = NULL;
|
writeDir = NULL;
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
if (newDir != NULL)
|
if (newDir != NULL)
|
||||||
{
|
{
|
||||||
writeDir = buildDirInfo(newDir, 1);
|
writeDir = buildDirInfo(newDir, 1);
|
||||||
return(writeDir != NULL);
|
retval = (writeDir != NULL);
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
return(1);
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
|
||||||
|
return(retval);
|
||||||
} /* PHYSFS_setWriteDir */
|
} /* PHYSFS_setWriteDir */
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
||||||
{
|
{
|
||||||
DirInfo *di;
|
DirInfo *di;
|
||||||
DirInfo *i = searchPath;
|
|
||||||
DirInfo *prev = NULL;
|
DirInfo *prev = NULL;
|
||||||
|
DirInfo *i;
|
||||||
|
|
||||||
while (i != NULL)
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
|
||||||
|
for (i = searchPath; i != NULL; i = i->next)
|
||||||
{
|
{
|
||||||
if (strcmp(newDir, i->dirName) == 0) /* already in search path. */
|
/* already in search path? */
|
||||||
return(1);
|
BAIL_IF_MACRO_MUTEX(strcmp(newDir, i->dirName)==0, NULL, stateLock, 1);
|
||||||
|
|
||||||
prev = i;
|
prev = i;
|
||||||
i = i->next;
|
} /* for */
|
||||||
} /* while */
|
|
||||||
|
|
||||||
di = buildDirInfo(newDir, 0);
|
di = buildDirInfo(newDir, 0);
|
||||||
|
BAIL_IF_MACRO_MUTEX(di == NULL, NULL, stateLock, 0);
|
||||||
BAIL_IF_MACRO(di == NULL, NULL, 0);
|
|
||||||
|
|
||||||
if (appendToPath)
|
if (appendToPath)
|
||||||
{
|
{
|
||||||
|
@ -565,6 +621,7 @@ int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
||||||
searchPath = di;
|
searchPath = di;
|
||||||
} /* else */
|
} /* else */
|
||||||
|
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
return(1);
|
return(1);
|
||||||
} /* PHYSFS_addToSearchPath */
|
} /* PHYSFS_addToSearchPath */
|
||||||
|
|
||||||
|
@ -577,25 +634,26 @@ int PHYSFS_removeFromSearchPath(const char *oldDir)
|
||||||
|
|
||||||
BAIL_IF_MACRO(oldDir == NULL, ERR_INVALID_ARGUMENT, 0);
|
BAIL_IF_MACRO(oldDir == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
for (i = searchPath; i != NULL; i = i->next)
|
for (i = searchPath; i != NULL; i = i->next)
|
||||||
{
|
{
|
||||||
if (strcmp(i->dirName, oldDir) == 0)
|
if (strcmp(i->dirName, oldDir) == 0)
|
||||||
{
|
{
|
||||||
next = i->next;
|
next = i->next;
|
||||||
BAIL_IF_MACRO(!freeDirInfo(i, openReadList), NULL, 0);
|
BAIL_IF_MACRO_MUTEX(!freeDirInfo(i, openReadList), NULL,
|
||||||
|
stateLock, 0);
|
||||||
|
|
||||||
if (prev == NULL)
|
if (prev == NULL)
|
||||||
searchPath = next;
|
searchPath = next;
|
||||||
else
|
else
|
||||||
prev->next = next;
|
prev->next = next;
|
||||||
|
|
||||||
return(1);
|
BAIL_MACRO_MUTEX(NULL, stateLock, 1);
|
||||||
} /* if */
|
} /* if */
|
||||||
prev = i;
|
prev = i;
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
__PHYSFS_setError(ERR_NOT_IN_SEARCH_PATH);
|
BAIL_MACRO_MUTEX(ERR_NOT_IN_SEARCH_PATH, stateLock, 0);
|
||||||
return(0);
|
|
||||||
} /* PHYSFS_removeFromSearchPath */
|
} /* PHYSFS_removeFromSearchPath */
|
||||||
|
|
||||||
|
|
||||||
|
@ -606,11 +664,13 @@ char **PHYSFS_getSearchPath(void)
|
||||||
DirInfo *i;
|
DirInfo *i;
|
||||||
char **retval;
|
char **retval;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
|
||||||
for (i = searchPath; i != NULL; i = i->next)
|
for (i = searchPath; i != NULL; i = i->next)
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
retval = (char **) malloc(sizeof (char *) * count);
|
retval = (char **) malloc(sizeof (char *) * count);
|
||||||
BAIL_IF_MACRO(!retval, ERR_OUT_OF_MEMORY, NULL);
|
BAIL_IF_MACRO_MUTEX(!retval, ERR_OUT_OF_MEMORY, stateLock, NULL);
|
||||||
count--;
|
count--;
|
||||||
retval[count] = NULL;
|
retval[count] = NULL;
|
||||||
|
|
||||||
|
@ -626,13 +686,13 @@ char **PHYSFS_getSearchPath(void)
|
||||||
} /* while */
|
} /* while */
|
||||||
|
|
||||||
free(retval);
|
free(retval);
|
||||||
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL);
|
||||||
return(NULL);
|
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
strcpy(retval[x], i->dirName);
|
strcpy(retval[x], i->dirName);
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* PHYSFS_getSearchPath */
|
} /* PHYSFS_getSearchPath */
|
||||||
|
|
||||||
|
@ -646,6 +706,8 @@ int PHYSFS_setSaneConfig(const char *organization, const char *appName,
|
||||||
const char *dirsep = PHYSFS_getDirSeparator();
|
const char *dirsep = PHYSFS_getDirSeparator();
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
||||||
|
|
||||||
/* set write dir... */
|
/* set write dir... */
|
||||||
str = malloc(strlen(userdir) + (strlen(organization) * 2) +
|
str = malloc(strlen(userdir) + (strlen(organization) * 2) +
|
||||||
(strlen(appName) * 2) + (strlen(dirsep) * 3) + 2);
|
(strlen(appName) * 2) + (strlen(dirsep) * 3) + 2);
|
||||||
|
@ -740,7 +802,7 @@ char * __PHYSFS_convertToDependent(const char *prepend,
|
||||||
const char *dirName,
|
const char *dirName,
|
||||||
const char *append)
|
const char *append)
|
||||||
{
|
{
|
||||||
const char *dirsep = PHYSFS_getDirSeparator();
|
const char *dirsep = __PHYSFS_platformDirSeparator;
|
||||||
size_t sepsize = strlen(dirsep);
|
size_t sepsize = strlen(dirsep);
|
||||||
char *str;
|
char *str;
|
||||||
char *i1;
|
char *i1;
|
||||||
|
@ -852,7 +914,7 @@ int __PHYSFS_verifySecurity(DirHandle *h, const char *fname)
|
||||||
} /* __PHYSFS_verifySecurity */
|
} /* __PHYSFS_verifySecurity */
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_mkdir(const char *dirName)
|
int PHYSFS_mkdir(const char *dname)
|
||||||
{
|
{
|
||||||
DirHandle *h;
|
DirHandle *h;
|
||||||
char *str;
|
char *str;
|
||||||
|
@ -860,19 +922,18 @@ int PHYSFS_mkdir(const char *dirName)
|
||||||
char *end;
|
char *end;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
|
BAIL_IF_MACRO(dname == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
|
while (*dname == '/')
|
||||||
|
dname++;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
|
||||||
h = writeDir->dirHandle;
|
h = writeDir->dirHandle;
|
||||||
|
BAIL_IF_MACRO_MUTEX(!h->funcs->mkdir, ERR_NOT_SUPPORTED, stateLock, 0);
|
||||||
while (*dirName == '/')
|
BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, dname), NULL, stateLock, 0);
|
||||||
dirName++;
|
start = str = malloc(strlen(dname) + 1);
|
||||||
|
BAIL_IF_MACRO_MUTEX(str == NULL, ERR_OUT_OF_MEMORY, stateLock, 0);
|
||||||
BAIL_IF_MACRO(h->funcs->mkdir == NULL, ERR_NOT_SUPPORTED, 0);
|
strcpy(str, dname);
|
||||||
BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, dirName), NULL, 0);
|
|
||||||
|
|
||||||
start = str = malloc(strlen(dirName) + 1);
|
|
||||||
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
||||||
strcpy(str, dirName);
|
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
@ -891,6 +952,8 @@ int PHYSFS_mkdir(const char *dirName)
|
||||||
start = end + 1;
|
start = end + 1;
|
||||||
} /* while */
|
} /* while */
|
||||||
|
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
|
||||||
free(str);
|
free(str);
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* PHYSFS_mkdir */
|
} /* PHYSFS_mkdir */
|
||||||
|
@ -898,16 +961,23 @@ int PHYSFS_mkdir(const char *dirName)
|
||||||
|
|
||||||
int PHYSFS_delete(const char *fname)
|
int PHYSFS_delete(const char *fname)
|
||||||
{
|
{
|
||||||
|
int retval;
|
||||||
DirHandle *h;
|
DirHandle *h;
|
||||||
BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
|
|
||||||
h = writeDir->dirHandle;
|
|
||||||
BAIL_IF_MACRO(h->funcs->remove == NULL, ERR_NOT_SUPPORTED, 0);
|
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
while (*fname == '/')
|
while (*fname == '/')
|
||||||
fname++;
|
fname++;
|
||||||
|
|
||||||
BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, 0);
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
return(h->funcs->remove(h, fname));
|
|
||||||
|
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);
|
||||||
} /* PHYSFS_delete */
|
} /* PHYSFS_delete */
|
||||||
|
|
||||||
|
|
||||||
|
@ -918,15 +988,20 @@ const char *PHYSFS_getRealDir(const char *filename)
|
||||||
while (*filename == '/')
|
while (*filename == '/')
|
||||||
filename++;
|
filename++;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
for (i = searchPath; i != NULL; i = i->next)
|
for (i = searchPath; i != NULL; i = i->next)
|
||||||
{
|
{
|
||||||
DirHandle *h = i->dirHandle;
|
DirHandle *h = i->dirHandle;
|
||||||
if (__PHYSFS_verifySecurity(h, filename))
|
if (__PHYSFS_verifySecurity(h, filename))
|
||||||
{
|
{
|
||||||
if (h->funcs->exists(h, filename))
|
if (h->funcs->exists(h, filename))
|
||||||
|
{
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
return(i->dirName);
|
return(i->dirName);
|
||||||
|
} /* if */
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* for */
|
} /* for */
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
|
||||||
return(NULL);
|
return(NULL);
|
||||||
} /* PHYSFS_getRealDir */
|
} /* PHYSFS_getRealDir */
|
||||||
|
@ -1029,9 +1104,11 @@ char **PHYSFS_enumerateFiles(const char *path)
|
||||||
LinkedStringList *finalList = NULL;
|
LinkedStringList *finalList = NULL;
|
||||||
int omitSymLinks = !allowSymLinks;
|
int omitSymLinks = !allowSymLinks;
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(path == NULL, ERR_INVALID_ARGUMENT, NULL);
|
||||||
while (*path == '/')
|
while (*path == '/')
|
||||||
path++;
|
path++;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
for (i = searchPath; i != NULL; i = i->next)
|
for (i = searchPath; i != NULL; i = i->next)
|
||||||
{
|
{
|
||||||
DirHandle *h = i->dirHandle;
|
DirHandle *h = i->dirHandle;
|
||||||
|
@ -1041,6 +1118,7 @@ char **PHYSFS_enumerateFiles(const char *path)
|
||||||
interpolateStringLists(&finalList, rc);
|
interpolateStringLists(&finalList, rc);
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* for */
|
} /* for */
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
|
||||||
retval = convertStringListToPhysFSList(finalList);
|
retval = convertStringListToPhysFSList(finalList);
|
||||||
return(retval);
|
return(retval);
|
||||||
|
@ -1049,6 +1127,7 @@ char **PHYSFS_enumerateFiles(const char *path)
|
||||||
|
|
||||||
int PHYSFS_exists(const char *fname)
|
int PHYSFS_exists(const char *fname)
|
||||||
{
|
{
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
while (*fname == '/')
|
while (*fname == '/')
|
||||||
fname++;
|
fname++;
|
||||||
|
|
||||||
|
@ -1060,21 +1139,28 @@ int PHYSFS_isDirectory(const char *fname)
|
||||||
{
|
{
|
||||||
DirInfo *i;
|
DirInfo *i;
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
while (*fname == '/')
|
while (*fname == '/')
|
||||||
fname++;
|
fname++;
|
||||||
|
|
||||||
if (*fname == '\0')
|
if (*fname == '\0')
|
||||||
return(1);
|
return(1);
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
for (i = searchPath; i != NULL; i = i->next)
|
for (i = searchPath; i != NULL; i = i->next)
|
||||||
{
|
{
|
||||||
DirHandle *h = i->dirHandle;
|
DirHandle *h = i->dirHandle;
|
||||||
if (__PHYSFS_verifySecurity(h, fname))
|
if (__PHYSFS_verifySecurity(h, fname))
|
||||||
{
|
{
|
||||||
if (h->funcs->exists(h, fname))
|
if (h->funcs->exists(h, fname))
|
||||||
return(h->funcs->isDirectory(h, fname));
|
{
|
||||||
|
int retval = h->funcs->isDirectory(h, fname);
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
return(retval);
|
||||||
|
} /* if */
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* for */
|
} /* for */
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
} /* PHYSFS_isDirectory */
|
} /* PHYSFS_isDirectory */
|
||||||
|
@ -1087,19 +1173,28 @@ int PHYSFS_isSymbolicLink(const char *fname)
|
||||||
if (!allowSymLinks)
|
if (!allowSymLinks)
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
while (*fname == '/')
|
while (*fname == '/')
|
||||||
fname++;
|
fname++;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
for (i = searchPath; i != NULL; i = i->next)
|
for (i = searchPath; i != NULL; i = i->next)
|
||||||
{
|
{
|
||||||
DirHandle *h = i->dirHandle;
|
DirHandle *h = i->dirHandle;
|
||||||
if (__PHYSFS_verifySecurity(h, fname))
|
if (__PHYSFS_verifySecurity(h, fname))
|
||||||
{
|
{
|
||||||
if (h->funcs->exists(h, fname))
|
if (h->funcs->exists(h, fname))
|
||||||
return(h->funcs->isSymLink(h, fname));
|
{
|
||||||
|
int retval = h->funcs->isSymLink(h, fname);
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
return(retval);
|
||||||
|
} /* if */
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
|
/* !!! FIXME: setError ERR_FILE_NOT_FOUND? */
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
} /* PHYSFS_isSymbolicLink */
|
} /* PHYSFS_isSymbolicLink */
|
||||||
|
|
||||||
|
@ -1108,19 +1203,24 @@ static PHYSFS_file *doOpenWrite(const char *fname, int appending)
|
||||||
{
|
{
|
||||||
PHYSFS_file *retval = NULL;
|
PHYSFS_file *retval = NULL;
|
||||||
FileHandle *rc = NULL;
|
FileHandle *rc = NULL;
|
||||||
DirHandle *h = (writeDir == NULL) ? NULL : writeDir->dirHandle;
|
DirHandle *h;
|
||||||
const DirFunctions *f = (h == NULL) ? NULL : h->funcs;
|
const DirFunctions *f;
|
||||||
FileHandleList *list;
|
FileHandleList *list;
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL);
|
||||||
while (*fname == '/')
|
while (*fname == '/')
|
||||||
fname++;
|
fname++;
|
||||||
|
|
||||||
BAIL_IF_MACRO(!h, ERR_NO_WRITE_DIR, NULL);
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, NULL);
|
h = (writeDir == NULL) ? NULL : writeDir->dirHandle;
|
||||||
|
BAIL_IF_MACRO_MUTEX(!h, ERR_NO_WRITE_DIR, stateLock, NULL);
|
||||||
|
BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, fname), NULL,
|
||||||
|
stateLock, NULL);
|
||||||
|
|
||||||
list = (FileHandleList *) malloc(sizeof (FileHandleList));
|
list = (FileHandleList *) malloc(sizeof (FileHandleList));
|
||||||
BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
|
BAIL_IF_MACRO_MUTEX(!list, ERR_OUT_OF_MEMORY, stateLock, NULL);
|
||||||
|
|
||||||
|
f = h->funcs;
|
||||||
rc = (appending) ? f->openAppend(h, fname) : f->openWrite(h, fname);
|
rc = (appending) ? f->openAppend(h, fname) : f->openWrite(h, fname);
|
||||||
if (rc == NULL)
|
if (rc == NULL)
|
||||||
free(list);
|
free(list);
|
||||||
|
@ -1132,6 +1232,7 @@ static PHYSFS_file *doOpenWrite(const char *fname, int appending)
|
||||||
retval = &(list->handle);
|
retval = &(list->handle);
|
||||||
} /* else */
|
} /* else */
|
||||||
|
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* doOpenWrite */
|
} /* doOpenWrite */
|
||||||
|
|
||||||
|
@ -1150,13 +1251,16 @@ PHYSFS_file *PHYSFS_openAppend(const char *filename)
|
||||||
|
|
||||||
PHYSFS_file *PHYSFS_openRead(const char *fname)
|
PHYSFS_file *PHYSFS_openRead(const char *fname)
|
||||||
{
|
{
|
||||||
|
PHYSFS_file *retval;
|
||||||
FileHandle *rc = NULL;
|
FileHandle *rc = NULL;
|
||||||
FileHandleList *list;
|
FileHandleList *list;
|
||||||
DirInfo *i;
|
DirInfo *i;
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL);
|
||||||
while (*fname == '/')
|
while (*fname == '/')
|
||||||
fname++;
|
fname++;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
for (i = searchPath; i != NULL; i = i->next)
|
for (i = searchPath; i != NULL; i = i->next)
|
||||||
{
|
{
|
||||||
DirHandle *h = i->dirHandle;
|
DirHandle *h = i->dirHandle;
|
||||||
|
@ -1168,16 +1272,17 @@ PHYSFS_file *PHYSFS_openRead(const char *fname)
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
if (rc == NULL)
|
BAIL_IF_MACRO_MUTEX(rc == NULL, NULL, stateLock, NULL);
|
||||||
return(NULL);
|
|
||||||
|
|
||||||
list = (FileHandleList *) malloc(sizeof (FileHandleList));
|
list = (FileHandleList *) malloc(sizeof (FileHandleList));
|
||||||
BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
|
BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
|
||||||
list->handle.opaque = (void *) rc;
|
list->handle.opaque = (void *) rc;
|
||||||
list->next = openReadList;
|
list->next = openReadList;
|
||||||
openReadList = list;
|
openReadList = list;
|
||||||
|
retval = &(list->handle);
|
||||||
|
|
||||||
return(&(list->handle));
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
return(retval);
|
||||||
} /* PHYSFS_openRead */
|
} /* PHYSFS_openRead */
|
||||||
|
|
||||||
|
|
||||||
|
@ -1215,19 +1320,20 @@ int PHYSFS_close(PHYSFS_file *handle)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
|
||||||
/* -1 == close failure. 0 == not found. 1 == success. */
|
/* -1 == close failure. 0 == not found. 1 == success. */
|
||||||
rc = closeHandleInOpenList(&openReadList, handle);
|
rc = closeHandleInOpenList(&openReadList, handle);
|
||||||
BAIL_IF_MACRO(rc == -1, NULL, 0);
|
BAIL_IF_MACRO_MUTEX(rc == -1, NULL, stateLock, 0);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
{
|
{
|
||||||
rc = closeHandleInOpenList(&openWriteList, handle);
|
rc = closeHandleInOpenList(&openWriteList, handle);
|
||||||
BAIL_IF_MACRO(rc == -1, NULL, 0);
|
BAIL_IF_MACRO_MUTEX(rc == -1, NULL, stateLock, 0);
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
if (!rc)
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
__PHYSFS_setError(ERR_NOT_A_HANDLE);
|
BAIL_IF_MACRO(!rc, ERR_NOT_A_HANDLE, 0);
|
||||||
|
return(1);
|
||||||
return(rc);
|
|
||||||
} /* PHYSFS_close */
|
} /* PHYSFS_close */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -304,6 +304,8 @@ int __PHYSFS_verifySecurity(DirHandle *h, const char *fname);
|
||||||
/* These get used all over for lessening code clutter. */
|
/* These get used all over for lessening code clutter. */
|
||||||
#define BAIL_MACRO(e, r) { __PHYSFS_setError(e); return r; }
|
#define BAIL_MACRO(e, r) { __PHYSFS_setError(e); return r; }
|
||||||
#define BAIL_IF_MACRO(c, e, r) if (c) { __PHYSFS_setError(e); return r; }
|
#define BAIL_IF_MACRO(c, e, r) if (c) { __PHYSFS_setError(e); return r; }
|
||||||
|
#define BAIL_MACRO_MUTEX(e, m, r) { __PHYSFS_setError(e); __PHYSFS_platformReleaseMutex(m); return r; }
|
||||||
|
#define BAIL_IF_MACRO_MUTEX(c, e, m, r) if (c) { __PHYSFS_setError(e); __PHYSFS_platformReleaseMutex(m); return r; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -633,6 +635,44 @@ int __PHYSFS_platformMkDir(const char *path);
|
||||||
int __PHYSFS_platformDelete(const char *path);
|
int __PHYSFS_platformDelete(const char *path);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a platform-specific mutex. This can be whatever datatype your
|
||||||
|
* platform uses for mutexes, but it is cast to a (void *) for abstractness.
|
||||||
|
*
|
||||||
|
* Return (NULL) if you couldn't create one. Systems without threads can
|
||||||
|
* return any arbitrary non-NULL value.
|
||||||
|
*/
|
||||||
|
void *__PHYSFS_platformCreateMutex(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroy a platform-specific mutex, and clean up any resources associated
|
||||||
|
* with it. (mutex) is a value previously returned by
|
||||||
|
* __PHYSFS_platformCreateMutex(). This can be a no-op on single-threaded
|
||||||
|
* platforms.
|
||||||
|
*/
|
||||||
|
void __PHYSFS_platformDestroyMutex(void *mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grab possession of a platform-specific mutex. Mutexes should be recursive;
|
||||||
|
* that is, the same thread should be able to call this function multiple
|
||||||
|
* times in a row without causing a deadlock. This function should block
|
||||||
|
* until a thread can gain possession of the mutex.
|
||||||
|
*
|
||||||
|
* Return non-zero if the mutex was grabbed, zero if there was an
|
||||||
|
* unrecoverable problem grabbing it (this should not be a matter of
|
||||||
|
* timing out! We're talking major system errors; block until the mutex
|
||||||
|
* is available otherwise.)
|
||||||
|
*/
|
||||||
|
int __PHYSFS_platformGrabMutex(void *mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Relinquish possession of the mutex when this method has been called
|
||||||
|
* once for each time that platformGrabMutex was called. Once possession has
|
||||||
|
* been released, the next thread in line to grab the mutex (if any) may
|
||||||
|
* proceed.
|
||||||
|
*/
|
||||||
|
void __PHYSFS_platformReleaseMutex(void *mutex);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -660,5 +660,40 @@ int __PHYSFS_platformDelete(const char *path)
|
||||||
return(1);
|
return(1);
|
||||||
} /* __PHYSFS_platformDelete */
|
} /* __PHYSFS_platformDelete */
|
||||||
|
|
||||||
|
|
||||||
|
void *__PHYSFS_platformCreateMutex(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
pthread_mutex_t *m = (pthread_mutex_t *) malloc(sizeof (pthread_mutex_t));
|
||||||
|
BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||||
|
rc = pthread_mutex_init(m, NULL);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
free(m);
|
||||||
|
BAIL_MACRO(strerror(rc), NULL);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
return((void *) m);
|
||||||
|
} /* __PHYSFS_platformCreateMutex */
|
||||||
|
|
||||||
|
|
||||||
|
void __PHYSFS_platformDestroyMutex(void *mutex)
|
||||||
|
{
|
||||||
|
pthread_mutex_destroy((pthread_mutex_t *) mutex);
|
||||||
|
free(mutex);
|
||||||
|
} /* __PHYSFS_platformDestroyMutex */
|
||||||
|
|
||||||
|
|
||||||
|
int __PHYSFS_platformGrabMutex(void *mutex)
|
||||||
|
{
|
||||||
|
return(pthread_mutex_lock((pthread_mutex_t *) mutex) == 0);
|
||||||
|
} /* __PHYSFS_platformGrabMutex */
|
||||||
|
|
||||||
|
|
||||||
|
void __PHYSFS_platformReleaseMutex(void *mutex)
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock((pthread_mutex_t *) mutex);
|
||||||
|
} /* __PHYSFS_platformReleaseMutex */
|
||||||
|
|
||||||
/* end of unix.c ... */
|
/* end of unix.c ... */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue