|
|
@@ -25,16 +25,16 @@ typedef struct __PHYSFS_ERRMSGTYPE__
|
|
|
struct __PHYSFS_ERRMSGTYPE__ *next;
|
|
|
} ErrMsg;
|
|
|
|
|
|
-typedef struct __PHYSFS_SEARCHDIRINFO__
|
|
|
+typedef struct __PHYSFS_DIRINFO__
|
|
|
{
|
|
|
char *dirName;
|
|
|
- DirReader *reader;
|
|
|
- struct __PHYSFS_SEARCHDIRINFO__ *next;
|
|
|
-} SearchDirInfo;
|
|
|
+ DirHandle *dirHandle;
|
|
|
+ struct __PHYSFS_DIRINFO__ *next;
|
|
|
+} DirInfo;
|
|
|
|
|
|
typedef struct __PHYSFS_FILEHANDLELIST__
|
|
|
{
|
|
|
- FileHandle *handle;
|
|
|
+ PHYSFS_file *handle;
|
|
|
struct __PHYSFS_FILEHANDLELIST__ *next;
|
|
|
} FileHandleList;
|
|
|
|
|
|
@@ -73,12 +73,12 @@ static const DirFunctions *dirFunctions[] =
|
|
|
|
|
|
static int initialized = 0;
|
|
|
static ErrMsg *errorMessages = NULL;
|
|
|
-static SearchDirInfo *searchPath = NULL;
|
|
|
+static DirInfo *searchPath = NULL;
|
|
|
+static DirInfo *writeDir = NULL;
|
|
|
static FileHandleList *openWriteList = NULL;
|
|
|
static FileHandleList *openReadList = NULL;
|
|
|
static char *baseDir = NULL;
|
|
|
static char *userDir = NULL;
|
|
|
-static char *writeDir = NULL;
|
|
|
static int allowSymLinks = 0;
|
|
|
|
|
|
|
|
|
@@ -107,7 +107,12 @@ static ErrMsg *findErrorForCurrentThread(void)
|
|
|
|
|
|
void __PHYSFS_setError(const char *str)
|
|
|
{
|
|
|
- ErrMsg *err = findErrorForCurrentThread();
|
|
|
+ ErrMsg *err;
|
|
|
+
|
|
|
+ if (str == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ err = findErrorForCurrentThread();
|
|
|
|
|
|
if (err == NULL)
|
|
|
{
|
|
|
@@ -126,6 +131,19 @@ void __PHYSFS_setError(const char *str)
|
|
|
} /* __PHYSFS_setError */
|
|
|
|
|
|
|
|
|
+static void freeErrorMessages(void)
|
|
|
+{
|
|
|
+ ErrMsg *i;
|
|
|
+ ErrMsg *next;
|
|
|
+
|
|
|
+ for (i = errorMessages; i != NULL; i = next)
|
|
|
+ {
|
|
|
+ next = i;
|
|
|
+ free(i);
|
|
|
+ } /* for */
|
|
|
+} /* freeErrorMessages */
|
|
|
+
|
|
|
+
|
|
|
const char *PHYSFS_getLastError(void)
|
|
|
{
|
|
|
ErrMsg *err = findErrorForCurrentThread();
|
|
|
@@ -149,22 +167,88 @@ void PHYSFS_getLinkedVersion(PHYSFS_Version *ver)
|
|
|
} /* PHYSFS_getLinkedVersion */
|
|
|
|
|
|
|
|
|
-static const char *calculateUserDir(void)
|
|
|
+static DirHandle *openDirectory(const char *d, int forWriting)
|
|
|
+{
|
|
|
+ const DirFunctions **i;
|
|
|
+
|
|
|
+ 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 */
|
|
|
+
|
|
|
+
|
|
|
+static DirInfo *buildDirInfo(const char *newDir, int forWriting)
|
|
|
+{
|
|
|
+ DirHandle *dirHandle = NULL;
|
|
|
+ DirInfo *di = NULL;
|
|
|
+
|
|
|
+ BAIL_IF_MACRO(newDir == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
+
|
|
|
+ dirHandle = openDirectory(newDir, forWriting);
|
|
|
+ BAIL_IF_MACRO(dirHandle == NULL, NULL, 0);
|
|
|
+
|
|
|
+ di = (DirInfo *) malloc(sizeof (DirInfo));
|
|
|
+ if (di == NULL)
|
|
|
+ dirHandle->funcs->close(dirHandle);
|
|
|
+ BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
|
+
|
|
|
+ di->dirName = (char *) malloc(strlen(newDir) + 1);
|
|
|
+ if (di->dirName == NULL)
|
|
|
+ {
|
|
|
+ free(di);
|
|
|
+ dirHandle->funcs->close(dirHandle);
|
|
|
+ __PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
|
|
+ return(0);
|
|
|
+ } /* if */
|
|
|
+
|
|
|
+ di->next = NULL;
|
|
|
+ di->dirHandle = dirHandle;
|
|
|
+ strcpy(di->dirName, newDir);
|
|
|
+ return(di);
|
|
|
+} /* buildDirInfo */
|
|
|
+
|
|
|
+
|
|
|
+static int freeDirInfo(DirInfo *di, FileHandleList *openList)
|
|
|
+{
|
|
|
+ FileHandleList *i;
|
|
|
+
|
|
|
+ if (di == NULL)
|
|
|
+ return(1);
|
|
|
+
|
|
|
+ for (i = openList; i != NULL; i = i->next)
|
|
|
+ {
|
|
|
+ const DirHandle *h = ((FileHandle *) i->handle->opaque)->dirHandle;
|
|
|
+ BAIL_IF_MACRO(h == di->dirHandle, ERR_FILES_STILL_OPEN, 0);
|
|
|
+ } /* for */
|
|
|
+
|
|
|
+ di->dirHandle->funcs->close(di->dirHandle);
|
|
|
+ free(di->dirName);
|
|
|
+ free(di);
|
|
|
+ return(1);
|
|
|
+} /* freeDirInfo */
|
|
|
+
|
|
|
+
|
|
|
+static char *calculateUserDir(void)
|
|
|
{
|
|
|
char *retval = NULL;
|
|
|
const char *str = NULL;
|
|
|
|
|
|
str = __PHYSFS_platformGetUserDir();
|
|
|
if (str != NULL)
|
|
|
- retval = str;
|
|
|
+ retval = (char *) str;
|
|
|
else
|
|
|
{
|
|
|
const char *dirsep = PHYSFS_getDirSeparator();
|
|
|
const char *uname = __PHYSFS_platformGetUserName();
|
|
|
|
|
|
str = (uname != NULL) ? uname : "default";
|
|
|
- retval = malloc(strlen(baseDir) + strlen(str) +
|
|
|
- (strlen(dirsep) * 2) + 6);
|
|
|
+ retval = (char *) malloc(strlen(baseDir) + strlen(str) +
|
|
|
+ (strlen(dirsep) * 2) + 6);
|
|
|
|
|
|
if (retval == NULL)
|
|
|
__PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
|
|
@@ -172,21 +256,26 @@ static const char *calculateUserDir(void)
|
|
|
sprintf(retval, "%s%susers%s%s", baseDir, dirsep, dirsep, str);
|
|
|
|
|
|
if (uname != NULL)
|
|
|
- free(uname);
|
|
|
+ free((void *) uname);
|
|
|
} /* else */
|
|
|
|
|
|
return(retval);
|
|
|
} /* calculateUserDir */
|
|
|
|
|
|
|
|
|
+static char *calculateBaseDir(const char *argv0)
|
|
|
+{
|
|
|
+assert(0); return(NULL);
|
|
|
+} /* calculateBaseDir */
|
|
|
+
|
|
|
+
|
|
|
int PHYSFS_init(const char *argv0)
|
|
|
{
|
|
|
BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
|
|
|
BAIL_IF_MACRO(argv0 == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
|
|
|
baseDir = calculateBaseDir(argv0);
|
|
|
- if (baseDir == NULL)
|
|
|
- return(0);
|
|
|
+ BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
|
|
|
|
|
|
userDir = calculateUserDir();
|
|
|
if (userDir == NULL)
|
|
|
@@ -201,42 +290,35 @@ int PHYSFS_init(const char *argv0)
|
|
|
} /* PHYSFS_init */
|
|
|
|
|
|
|
|
|
-static void freeSearchDir(SearchDirInfo *sdi)
|
|
|
-{
|
|
|
- FileHandleList *i;
|
|
|
-
|
|
|
- assert(sdi != NULL);
|
|
|
- for (i = openReadList; i != NULL; i = i->next)
|
|
|
- {
|
|
|
- BAIL_IF_MACRO(i->handle->dirReader == sdi->reader,
|
|
|
- ERR_FILES_OPEN_READ, 0);
|
|
|
- } /* for */
|
|
|
-
|
|
|
- sdi->reader->close(sdi->reader);
|
|
|
- free(sdi->dirName);
|
|
|
- free(sdi);
|
|
|
-} /* freeSearchDir */
|
|
|
-
|
|
|
-
|
|
|
-static void closeFileHandleList(FileHandleList **list)
|
|
|
+static int closeFileHandleList(FileHandleList **list)
|
|
|
{
|
|
|
FileHandleList *i;
|
|
|
FileHandleList *next = NULL;
|
|
|
+ FileHandle *h;
|
|
|
|
|
|
for (i = *list; i != NULL; i = next)
|
|
|
{
|
|
|
next = i->next;
|
|
|
- i->handle->close(i->handle);
|
|
|
+ h = (FileHandle *) (i->handle->opaque);
|
|
|
+ if (!h->funcs->close(i->handle->opaque))
|
|
|
+ {
|
|
|
+ *list = i;
|
|
|
+ return(0);
|
|
|
+ } /* if */
|
|
|
+
|
|
|
+ free(i->handle);
|
|
|
+ free(i);
|
|
|
} /* for */
|
|
|
|
|
|
*list = NULL;
|
|
|
-} /* closeAllFiles */
|
|
|
+ return(1);
|
|
|
+} /* closeFileHandleList */
|
|
|
|
|
|
|
|
|
static void freeSearchPath(void)
|
|
|
{
|
|
|
- SearchDirInfo *i;
|
|
|
- SearchDirInfo *next = NULL;
|
|
|
+ DirInfo *i;
|
|
|
+ DirInfo *next = NULL;
|
|
|
|
|
|
closeFileHandleList(&openReadList);
|
|
|
|
|
|
@@ -245,19 +327,20 @@ static void freeSearchPath(void)
|
|
|
for (i = searchPath; i != NULL; i = next)
|
|
|
{
|
|
|
next = i;
|
|
|
- freeSearchDir(i);
|
|
|
+ freeDirInfo(i, openReadList);
|
|
|
} /* for */
|
|
|
searchPath = NULL;
|
|
|
} /* if */
|
|
|
} /* freeSearchPath */
|
|
|
|
|
|
|
|
|
-void PHYSFS_deinit(void)
|
|
|
+int PHYSFS_deinit(void)
|
|
|
{
|
|
|
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
|
|
|
|
|
closeFileHandleList(&openWriteList);
|
|
|
- PHYSFS_setWriteDir(NULL);
|
|
|
+ BAIL_IF_MACRO(!PHYSFS_setWriteDir(NULL), ERR_FILES_STILL_OPEN, 0);
|
|
|
+
|
|
|
freeSearchPath();
|
|
|
freeErrorMessages();
|
|
|
|
|
|
@@ -297,7 +380,7 @@ void PHYSFS_freeList(void *list)
|
|
|
|
|
|
const char *PHYSFS_getDirSeparator(void)
|
|
|
{
|
|
|
- return(__PHYSFS_pathSeparator);
|
|
|
+ return(__PHYSFS_platformDirSeparator);
|
|
|
} /* PHYSFS_getDirSeparator */
|
|
|
|
|
|
|
|
|
@@ -321,96 +404,55 @@ const char *PHYSFS_getUserDir(void)
|
|
|
|
|
|
const char *PHYSFS_getWriteDir(void)
|
|
|
{
|
|
|
- return(writeDir);
|
|
|
+ if (writeDir == NULL)
|
|
|
+ return(NULL);
|
|
|
+
|
|
|
+ return(writeDir->dirName);
|
|
|
} /* PHYSFS_getWriteDir */
|
|
|
|
|
|
|
|
|
int PHYSFS_setWriteDir(const char *newDir)
|
|
|
{
|
|
|
- BAIL_IF_MACRO(openWriteList != NULL, ERR_FILES_OPEN_WRITE, 0);
|
|
|
-
|
|
|
if (writeDir != NULL)
|
|
|
{
|
|
|
- free(writeDir);
|
|
|
+ BAIL_IF_MACRO(!freeDirInfo(writeDir, openWriteList), NULL, 0);
|
|
|
writeDir = NULL;
|
|
|
} /* if */
|
|
|
|
|
|
if (newDir != NULL)
|
|
|
{
|
|
|
- BAIL_IF_MACRO(!createDirs_dependent(newDir), ERR_NO_DIR_CREATE, 0);
|
|
|
-
|
|
|
- writeDir = malloc(strlen(newDir) + 1);
|
|
|
- BAIL_IF_MACRO(writeDir == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
|
-
|
|
|
- strcpy(writeDir, newDir);
|
|
|
+ writeDir = buildDirInfo(newDir, 1);
|
|
|
+ return(writeDir != NULL);
|
|
|
} /* if */
|
|
|
|
|
|
return(1);
|
|
|
} /* PHYSFS_setWriteDir */
|
|
|
|
|
|
|
|
|
-static DirReader *getDirReader(const char *d)
|
|
|
-{
|
|
|
- DirFunctions **i;
|
|
|
-
|
|
|
- for (i = dirFunctions; *i != NULL; i++)
|
|
|
- {
|
|
|
- if ((*i)->isArchive(d))
|
|
|
- return( (*i)->openArchive(d) );
|
|
|
- } /* for */
|
|
|
-
|
|
|
- __PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE);
|
|
|
- return(NULL);
|
|
|
-} /* getDirReader */
|
|
|
-
|
|
|
-
|
|
|
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
|
|
{
|
|
|
- char *str = NULL;
|
|
|
- SearchDirInfo *sdi = NULL;
|
|
|
- DirReader *dirReader = NULL;
|
|
|
-
|
|
|
- BAIL_IF_MACRO(newDir == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
-
|
|
|
- reader = getDirReader(newDir); /* This sets the error message. */
|
|
|
- if (reader == NULL)
|
|
|
- return(0);
|
|
|
-
|
|
|
- sdi = (SearchDirInfo *) malloc(sizeof (SearchDirInfo));
|
|
|
- if (sdi == NULL)
|
|
|
- reader->close(reader);
|
|
|
- BAIL_IF_MACRO(sdi == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
|
+ DirInfo *di = buildDirInfo(newDir, 0);
|
|
|
|
|
|
- sdi->dirName = (char *) malloc(strlen(newDir) + 1);
|
|
|
- if (sdi->dirName == NULL)
|
|
|
- {
|
|
|
- free(sdi);
|
|
|
- reader->close(reader);
|
|
|
- __PHYSFS_setError(ERR_OUT_OF_MEMORY);
|
|
|
- return(0);
|
|
|
- } /* if */
|
|
|
-
|
|
|
- sdi->dirReader = dirReader;
|
|
|
- strcpy(sdi->dirName, newDir);
|
|
|
+ BAIL_IF_MACRO(di == NULL, NULL, 0);
|
|
|
|
|
|
if (appendToPath)
|
|
|
{
|
|
|
- sdi->next = searchPath;
|
|
|
- searchPath = sdi;
|
|
|
+ di->next = searchPath;
|
|
|
+ searchPath = di;
|
|
|
} /* if */
|
|
|
else
|
|
|
{
|
|
|
- SearchDirInfo *i = searchPath;
|
|
|
- SearchDirInfo *prev = NULL;
|
|
|
+ DirInfo *i = searchPath;
|
|
|
+ DirInfo *prev = NULL;
|
|
|
|
|
|
- sdi->next = NULL;
|
|
|
+ di->next = NULL;
|
|
|
while (i != NULL)
|
|
|
prev = i;
|
|
|
|
|
|
if (prev == NULL)
|
|
|
- searchPath = sdi;
|
|
|
+ searchPath = di;
|
|
|
else
|
|
|
- prev->next = sdi;
|
|
|
+ prev->next = di;
|
|
|
} /* else */
|
|
|
|
|
|
return(1);
|
|
|
@@ -419,9 +461,9 @@ int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
|
|
|
|
|
int PHYSFS_removeFromSearchPath(const char *oldDir)
|
|
|
{
|
|
|
- SearchDirInfo *i;
|
|
|
- SearchDirInfo *prev = NULL;
|
|
|
- SearchDirInfo *next = NULL;
|
|
|
+ DirInfo *i;
|
|
|
+ DirInfo *prev = NULL;
|
|
|
+ DirInfo *next = NULL;
|
|
|
|
|
|
BAIL_IF_MACRO(oldDir == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
|
|
|
@@ -430,8 +472,7 @@ int PHYSFS_removeFromSearchPath(const char *oldDir)
|
|
|
if (strcmp(i->dirName, oldDir) == 0)
|
|
|
{
|
|
|
next = i->next;
|
|
|
- if (!freeSearchDir(i))
|
|
|
- return(0);
|
|
|
+ BAIL_IF_MACRO(!freeDirInfo(i, openReadList), NULL, 0);
|
|
|
|
|
|
if (prev == NULL)
|
|
|
searchPath = next;
|
|
|
@@ -452,7 +493,7 @@ char **PHYSFS_getSearchPath(void)
|
|
|
{
|
|
|
int count = 1;
|
|
|
int x;
|
|
|
- SearchDirInfo *i;
|
|
|
+ DirInfo *i;
|
|
|
char **retval;
|
|
|
|
|
|
for (i = searchPath; i != NULL; i = i->next)
|
|
|
@@ -501,13 +542,12 @@ int PHYSFS_setSaneConfig(const char *appName, const char *archiveExt,
|
|
|
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
|
sprintf(str, "%s%s.%s", userdir, dirsep, appName);
|
|
|
rc = PHYSFS_setWriteDir(str);
|
|
|
- if (!rc)
|
|
|
- return(0); /* error set by PHYSFS_setWriteDir() ... */
|
|
|
+ BAIL_IF_MACRO(!rc, NULL, 0);
|
|
|
|
|
|
/* Put write dir related dirs on search path... */
|
|
|
PHYSFS_addToSearchPath(str, 1);
|
|
|
PHYSFS_mkdir(appName); /* don't care if this fails. */
|
|
|
- strcat(str, dirSep);
|
|
|
+ strcat(str, dirsep);
|
|
|
strcat(str, appName);
|
|
|
PHYSFS_addToSearchPath(str, 1);
|
|
|
free(str);
|
|
|
@@ -530,12 +570,12 @@ int PHYSFS_setSaneConfig(const char *appName, const char *archiveExt,
|
|
|
char **i;
|
|
|
for (i = cds; *i != NULL; i++)
|
|
|
{
|
|
|
- PHYSFS_addToSearchPath(*i);
|
|
|
+ PHYSFS_addToSearchPath(*i, 1);
|
|
|
str = malloc(strlen(*i) + strlen(appName) + strlen(dirsep) + 1);
|
|
|
if (str != NULL)
|
|
|
{
|
|
|
sprintf(str, "%s%s%s", *i, dirsep, appName);
|
|
|
- PHYSFS_addToSearchPath(str);
|
|
|
+ PHYSFS_addToSearchPath(str, 1);
|
|
|
free(str);
|
|
|
} /* if */
|
|
|
} /* for */
|
|
|
@@ -563,7 +603,7 @@ int PHYSFS_setSaneConfig(const char *appName, const char *archiveExt,
|
|
|
if (str != NULL)
|
|
|
{
|
|
|
sprintf(str, "%s%s%s", d, dirsep, *i);
|
|
|
- PHYSFS_addToSearchPath(d, str);
|
|
|
+ PHYSFS_addToSearchPath(str, archivesFirst == 0);
|
|
|
free(str);
|
|
|
} /* if */
|
|
|
} /* if */
|
|
|
@@ -577,11 +617,16 @@ int PHYSFS_setSaneConfig(const char *appName, const char *archiveExt,
|
|
|
} /* PHYSFS_setSaneConfig */
|
|
|
|
|
|
|
|
|
+void PHYSFS_permitSymbolicLinks(int allow)
|
|
|
+{
|
|
|
+ allowSymLinks = allow;
|
|
|
+} /* PHYSFS_permitSymbolicLinks */
|
|
|
+
|
|
|
+
|
|
|
/* string manipulation in C makes my ass itch. */
|
|
|
-/* be sure to free this crap after you're done with it. */
|
|
|
-static char *convertToDependentNotation(const char *prepend,
|
|
|
- const char *dirName,
|
|
|
- const char *append)
|
|
|
+char *__PHYSFS_convertToDependentNotation(const char *prepend,
|
|
|
+ const char *dirName,
|
|
|
+ const char *append)
|
|
|
{
|
|
|
const char *dirsep = PHYSFS_getDirSeparator();
|
|
|
int sepsize = strlen(dirsep);
|
|
|
@@ -590,7 +635,7 @@ static char *convertToDependentNotation(const char *prepend,
|
|
|
char *i2;
|
|
|
size_t allocSize;
|
|
|
|
|
|
- allocSize = strlen(dirName) + strlen(writeDir) + sepsize + 1;
|
|
|
+ allocSize = strlen(dirName) + 1;
|
|
|
if (prepend != NULL)
|
|
|
allocSize += strlen(prepend) + sepsize;
|
|
|
if (append != NULL)
|
|
|
@@ -599,11 +644,16 @@ static char *convertToDependentNotation(const char *prepend,
|
|
|
/* make sure there's enough space if the dir separator is bigger. */
|
|
|
if (sepsize > 1)
|
|
|
{
|
|
|
- for (str = dirName; *str != '\0'; str++)
|
|
|
+ str = (char *) dirName;
|
|
|
+ do
|
|
|
{
|
|
|
- if (*str == '/')
|
|
|
+ str = strchr(str, '/');
|
|
|
+ if (str != NULL)
|
|
|
+ {
|
|
|
allocSize += (sepsize - 1);
|
|
|
- } /* for */
|
|
|
+ str++;
|
|
|
+ } /* if */
|
|
|
+ } while (str != NULL);
|
|
|
} /* if */
|
|
|
|
|
|
str = (char *) malloc(allocSize);
|
|
|
@@ -616,7 +666,7 @@ static char *convertToDependentNotation(const char *prepend,
|
|
|
strcat(str, dirsep);
|
|
|
} /* if */
|
|
|
|
|
|
- for (i1 = dirName, i2 = str + strlen(str); *i1 != '\0'; i1++, i2++)
|
|
|
+ for (i1 = (char *) dirName, i2 = str + strlen(str); *i1; i1++, i2++)
|
|
|
{
|
|
|
if (*i1 == '/')
|
|
|
{
|
|
|
@@ -637,78 +687,123 @@ static char *convertToDependentNotation(const char *prepend,
|
|
|
} /* if */
|
|
|
|
|
|
return(str);
|
|
|
-} /* convertToDependentNotation */
|
|
|
+} /* __PHYSFS_convertToDependentNotation */
|
|
|
|
|
|
|
|
|
-int PHYSFS_mkdir(const char *dirName)
|
|
|
+int __PHYSFS_verifySecurity(DirHandle *h, const char *fname)
|
|
|
{
|
|
|
+ int retval = 1;
|
|
|
+ char *start;
|
|
|
+ char *end;
|
|
|
char *str;
|
|
|
- int rc;
|
|
|
|
|
|
- BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, NULL);
|
|
|
+ start = str = malloc(strlen(fname) + 1);
|
|
|
+ BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
|
+ strcpy(str, fname);
|
|
|
|
|
|
- str = convertToDependentNotation(writeDir, dirName, NULL);
|
|
|
- if (str == NULL) /* __PHYSFS_setError is called in convert call. */
|
|
|
- return(0);
|
|
|
+ while (1)
|
|
|
+ {
|
|
|
+ end = strchr(start, '/');
|
|
|
+ if (end != NULL)
|
|
|
+ *end = '\0';
|
|
|
+
|
|
|
+ if ( (strcmp(start, ".") == 0) ||
|
|
|
+ (strcmp(start, "..") == 0) ||
|
|
|
+ (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 */
|
|
|
|
|
|
- rc = createDirs_dependent(str);
|
|
|
free(str);
|
|
|
- return(rc);
|
|
|
-} /* PHYSFS_mkdir */
|
|
|
+ return(retval);
|
|
|
+} /* __PHYSFS_verifySecurity */
|
|
|
|
|
|
|
|
|
-int PHYSFS_delete(const char *filename)
|
|
|
+int PHYSFS_mkdir(const char *dirName)
|
|
|
{
|
|
|
+ DirHandle *h;
|
|
|
char *str;
|
|
|
- int rc;
|
|
|
+ char *start;
|
|
|
+ char *end;
|
|
|
+ int retval = 0;
|
|
|
|
|
|
- BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, NULL);
|
|
|
+ BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
|
|
|
+ h = writeDir->dirHandle;
|
|
|
+ BAIL_IF_MACRO(h->funcs->mkdir == NULL, ERR_NOT_SUPPORTED, 0);
|
|
|
+ BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, dirName), NULL, 0);
|
|
|
|
|
|
- str = convertToDependentNotation(writeDir, fileName, NULL);
|
|
|
- if (str == NULL) /* __PHYSFS_setError is called in convert call. */
|
|
|
- return(0);
|
|
|
+ start = str = malloc(strlen(dirName) + 1);
|
|
|
+ BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
|
+ strcpy(str, dirName);
|
|
|
|
|
|
- rc = remove(str);
|
|
|
- free(str);
|
|
|
+ while (1)
|
|
|
+ {
|
|
|
+ end = strchr(start, '/');
|
|
|
+ if (end != NULL)
|
|
|
+ *end = '\0';
|
|
|
|
|
|
- rc = (rc == 0);
|
|
|
- if (!rc)
|
|
|
- __PHYSFS_setError(strerror(errno));
|
|
|
+ retval = h->funcs->mkdir(h, str);
|
|
|
+ if (!retval)
|
|
|
+ break;
|
|
|
|
|
|
- return(rc);
|
|
|
-} /* PHYSFS_delete */
|
|
|
+ if (end == NULL)
|
|
|
+ break;
|
|
|
|
|
|
+ *end = '/';
|
|
|
+ start = end + 1;
|
|
|
+ } /* while */
|
|
|
|
|
|
-void PHYSFS_permitSymbolicLinks(int allow)
|
|
|
+ free(str);
|
|
|
+ return(retval);
|
|
|
+} /* PHYSFS_mkdir */
|
|
|
+
|
|
|
+
|
|
|
+int PHYSFS_delete(const char *fname)
|
|
|
{
|
|
|
- allowSymLinks = allow;
|
|
|
-} /* PHYSFS_permitSymbolicLinks */
|
|
|
+ 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(!__PHYSFS_verifySecurity(h, fname), NULL, 0);
|
|
|
+ return(h->funcs->remove(h, fname));
|
|
|
+} /* PHYSFS_delete */
|
|
|
|
|
|
|
|
|
-/**
|
|
|
- * Figure out where in the search path a file resides. The file is specified
|
|
|
- * in platform-independent notation. The returned filename will be the
|
|
|
- * element of the search path where the file was found, which may be a
|
|
|
- * directory, or an archive. Even if there are multiple matches in different
|
|
|
- * parts of the search path, only the first one found is used, just like
|
|
|
- * when opening a file.
|
|
|
- *
|
|
|
- * So, if you look for "maps/level1.map", and C:\mygame is in your search
|
|
|
- * path and C:\mygame\maps\level1.map exists, then "C:\mygame" is returned.
|
|
|
- *
|
|
|
- * If a match is a symbolic link, and you've not explicitly permitted symlinks,
|
|
|
- * then it will be ignored, and the search for a match will continue.
|
|
|
- *
|
|
|
- * @param filename file to look for.
|
|
|
- * @return READ ONLY string of element of search path containing the
|
|
|
- * the file in question. NULL if not found.
|
|
|
- */
|
|
|
const char *PHYSFS_getRealDir(const char *filename)
|
|
|
{
|
|
|
+ DirInfo *i;
|
|
|
+
|
|
|
+ for (i = searchPath; i != NULL; i = i->next)
|
|
|
+ {
|
|
|
+ DirHandle *h = i->dirHandle;
|
|
|
+ if (__PHYSFS_verifySecurity(h, filename))
|
|
|
+ {
|
|
|
+ if (h->funcs->exists(h, filename))
|
|
|
+ return(i->dirName);
|
|
|
+ } /* if */
|
|
|
+ } /* for */
|
|
|
+
|
|
|
+ return(NULL);
|
|
|
} /* PHYSFS_getRealDir */
|
|
|
|
|
|
|
|
|
-static void countList(LinkedStringList *list)
|
|
|
+static int countList(LinkedStringList *list)
|
|
|
{
|
|
|
int retval = 0;
|
|
|
LinkedStringList *i;
|
|
|
@@ -797,16 +892,19 @@ static void interpolateStringLists(LinkedStringList **final,
|
|
|
|
|
|
char **PHYSFS_enumerateFiles(const char *path)
|
|
|
{
|
|
|
- SearchDirInfo *i;
|
|
|
+ DirInfo *i;
|
|
|
char **retval = NULL;
|
|
|
LinkedStringList *rc;
|
|
|
LinkedStringList *finalList = NULL;
|
|
|
|
|
|
for (i = searchPath; i != NULL; i = i->next)
|
|
|
{
|
|
|
- assert(i->reader->funcs->enumerateFiles != NULL);
|
|
|
- rc = i->reader->funcs->enumerateFiles(path);
|
|
|
- interpolateStringLists(&finalList, rc);
|
|
|
+ DirHandle *h = i->dirHandle;
|
|
|
+ if (__PHYSFS_verifySecurity(h, path))
|
|
|
+ {
|
|
|
+ rc = h->funcs->enumerateFiles(h, path);
|
|
|
+ interpolateStringLists(&finalList, rc);
|
|
|
+ } /* if */
|
|
|
} /* for */
|
|
|
|
|
|
retval = convertStringListToPhysFSList(finalList);
|
|
|
@@ -814,6 +912,50 @@ char **PHYSFS_enumerateFiles(const char *path)
|
|
|
} /* PHYSFS_enumerateFiles */
|
|
|
|
|
|
|
|
|
+int PHYSFS_exists(const char *fname)
|
|
|
+{
|
|
|
+ return(PHYSFS_getRealDir(fname) != NULL);
|
|
|
+} /* PHYSFS_exists */
|
|
|
+
|
|
|
+
|
|
|
+int PHYSFS_isDirectory(const char *fname)
|
|
|
+{
|
|
|
+ DirInfo *i;
|
|
|
+
|
|
|
+ for (i = searchPath; i != NULL; i = i->next)
|
|
|
+ {
|
|
|
+ DirHandle *h = i->dirHandle;
|
|
|
+ if (__PHYSFS_verifySecurity(h, fname))
|
|
|
+ {
|
|
|
+ if (h->funcs->exists(h, fname))
|
|
|
+ return(h->funcs->isDirectory(h, fname));
|
|
|
+ } /* if */
|
|
|
+ } /* for */
|
|
|
+
|
|
|
+ return(0);
|
|
|
+} /* PHYSFS_isDirectory */
|
|
|
+
|
|
|
+
|
|
|
+int PHYSFS_isSymbolicLink(const char *fname)
|
|
|
+{
|
|
|
+ DirInfo *i;
|
|
|
+
|
|
|
+ if (!allowSymLinks)
|
|
|
+ return(0);
|
|
|
+
|
|
|
+ for (i = searchPath; i != NULL; i = i->next)
|
|
|
+ {
|
|
|
+ DirHandle *h = i->dirHandle;
|
|
|
+ if (__PHYSFS_verifySecurity(h, fname))
|
|
|
+ {
|
|
|
+ if (h->funcs->exists(h, fname))
|
|
|
+ return(h->funcs->isSymLink(h, fname));
|
|
|
+ } /* if */
|
|
|
+ } /* for */
|
|
|
+
|
|
|
+ return(0);
|
|
|
+} /* PHYSFS_isSymbolicLink */
|
|
|
+
|
|
|
/**
|
|
|
* Open a file for writing, in platform-independent notation and in relation
|
|
|
* to the write path as the root of the writable filesystem. The specified
|
|
|
@@ -826,6 +968,7 @@ char **PHYSFS_enumerateFiles(const char *path)
|
|
|
*/
|
|
|
PHYSFS_file *PHYSFS_openWrite(const char *filename)
|
|
|
{
|
|
|
+return NULL;
|
|
|
} /* PHYSFS_openWrite */
|
|
|
|
|
|
|
|
|
@@ -842,6 +985,7 @@ PHYSFS_file *PHYSFS_openWrite(const char *filename)
|
|
|
*/
|
|
|
PHYSFS_file *PHYSFS_openAppend(const char *filename)
|
|
|
{
|
|
|
+return NULL;
|
|
|
} /* PHYSFS_openAppend */
|
|
|
|
|
|
|
|
|
@@ -857,44 +1001,31 @@ PHYSFS_file *PHYSFS_openAppend(const char *filename)
|
|
|
*/
|
|
|
PHYSFS_file *PHYSFS_openRead(const char *filename)
|
|
|
{
|
|
|
+return NULL;
|
|
|
} /* PHYSFS_openRead */
|
|
|
|
|
|
|
|
|
-/**
|
|
|
- * Close a PhysicsFS filehandle. This call is capable of failing if the
|
|
|
- * operating system was buffering writes to this file, and (now forced to
|
|
|
- * write those changes to physical media) can not store the data for any
|
|
|
- * reason. In such a case, the filehandle stays open. A well-written program
|
|
|
- * should ALWAYS check the return value from the close call in addition to
|
|
|
- * every writing call!
|
|
|
- *
|
|
|
- * @param handle handle returned from PHYSFS_open*().
|
|
|
- * @return nonzero on success, zero on error. Specifics of the error can be
|
|
|
- * gleaned from PHYSFS_getLastError().
|
|
|
- */
|
|
|
int PHYSFS_close(PHYSFS_file *handle)
|
|
|
{
|
|
|
FileHandle *h = (FileHandle *) handle->opaque;
|
|
|
FileHandleList *i;
|
|
|
- FileHandleList **lists[] = { &openWriteList, &openReadList, NULL };
|
|
|
+ FileHandleList *prev;
|
|
|
+ FileHandleList **_lists[] = { &openWriteList, &openReadList, NULL };
|
|
|
+ FileHandleList ***lists = _lists; /* gay. */
|
|
|
int rc;
|
|
|
|
|
|
- assert(h != NULL);
|
|
|
- assert(h->funcs != NULL);
|
|
|
- assert(h->funcs->close != NULL);
|
|
|
-
|
|
|
while (lists != NULL)
|
|
|
{
|
|
|
- for (i = *(*lists); i != NULL; i = i->next)
|
|
|
+ for (i = *(*lists), prev = NULL; i != NULL; prev = i, i = i->next)
|
|
|
{
|
|
|
- if (i->handle == h)
|
|
|
+ if (((FileHandle *) i->handle->opaque) == h)
|
|
|
{
|
|
|
- rc = h->close(h);
|
|
|
+ rc = h->funcs->close(h);
|
|
|
if (!rc)
|
|
|
return(0);
|
|
|
|
|
|
if (prev == NULL)
|
|
|
- *lists = i->next;
|
|
|
+ *(*lists) = i->next;
|
|
|
else
|
|
|
prev->next = i->next;
|
|
|
free(i);
|
|
|
@@ -905,7 +1036,8 @@ int PHYSFS_close(PHYSFS_file *handle)
|
|
|
lists++;
|
|
|
} /* while */
|
|
|
|
|
|
- assert(0); /* shouldn't EVER hit this. */
|
|
|
+ __PHYSFS_setError(ERR_NOT_A_HANDLE);
|
|
|
+ return(0);
|
|
|
} /* PHYSFS_close */
|
|
|
|
|
|
|
|
|
@@ -960,5 +1092,6 @@ int PHYSFS_seek(PHYSFS_file *handle, int pos)
|
|
|
return(h->funcs->seek(h, pos));
|
|
|
} /* PHYSFS_seek */
|
|
|
|
|
|
+
|
|
|
/* end of physfs.c ... */
|
|
|
|