|
@@ -489,12 +489,67 @@ static DirHandle *openDirectory(const char *d, int forWriting)
|
|
|
} /* openDirectory */
|
|
} /* openDirectory */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * Make a platform-independent path string sane. Doesn't actually check the
|
|
|
|
|
+ * file hierarchy, it just cleans up the string.
|
|
|
|
|
+ * (dst) must be a buffer at least as big as (src), as this is where the
|
|
|
|
|
+ * cleaned up string is deposited.
|
|
|
|
|
+ * If there are illegal bits in the path (".." entries, etc) then we
|
|
|
|
|
+ * return zero and (dst) is undefined. Non-zero if the path was sanitized.
|
|
|
|
|
+ */
|
|
|
|
|
+static int sanitizePlatformIndependentPath(const char *src, char *dst)
|
|
|
|
|
+{
|
|
|
|
|
+ char *prev;
|
|
|
|
|
+ char ch;
|
|
|
|
|
+
|
|
|
|
|
+ while (*src == '/') /* skip initial '/' chars... */
|
|
|
|
|
+ src++;
|
|
|
|
|
+
|
|
|
|
|
+ prev = dst;
|
|
|
|
|
+ do
|
|
|
|
|
+ {
|
|
|
|
|
+ ch = *(src++);
|
|
|
|
|
+
|
|
|
|
|
+ if ((ch == ':') || (ch == '\\')) /* illegal chars in a physfs path. */
|
|
|
|
|
+ BAIL_MACRO(ERR_INSECURE_FNAME, 0);
|
|
|
|
|
+
|
|
|
|
|
+ if (ch == '/') /* path separator. */
|
|
|
|
|
+ {
|
|
|
|
|
+ *dst = '\0'; /* "." and ".." are illegal pathnames. */
|
|
|
|
|
+ if ((strcmp(prev, ".") == 0) || (strcmp(prev, "..") == 0))
|
|
|
|
|
+ BAIL_MACRO(ERR_INSECURE_FNAME, 0);
|
|
|
|
|
+
|
|
|
|
|
+ while (*src == '/') /* chop out doubles... */
|
|
|
|
|
+ src++;
|
|
|
|
|
+
|
|
|
|
|
+ if (*src == '\0') /* ends with a pathsep? */
|
|
|
|
|
+ break; /* we're done, don't add final pathsep to dst. */
|
|
|
|
|
+
|
|
|
|
|
+ prev = dst + 1;
|
|
|
|
|
+ } /* if */
|
|
|
|
|
+
|
|
|
|
|
+ *(dst++) = ch;
|
|
|
|
|
+ } while (ch != '\0');
|
|
|
|
|
+
|
|
|
|
|
+ return(1);
|
|
|
|
|
+} /* sanitizePlatformIndependentPath */
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
static DirHandle *createDirHandle(const char *newDir,
|
|
static DirHandle *createDirHandle(const char *newDir,
|
|
|
const char *mountPoint,
|
|
const char *mountPoint,
|
|
|
int forWriting)
|
|
int forWriting)
|
|
|
{
|
|
{
|
|
|
DirHandle *dirHandle = NULL;
|
|
DirHandle *dirHandle = NULL;
|
|
|
|
|
+
|
|
|
GOTO_IF_MACRO(!newDir, ERR_INVALID_ARGUMENT, badDirHandle);
|
|
GOTO_IF_MACRO(!newDir, ERR_INVALID_ARGUMENT, badDirHandle);
|
|
|
|
|
+ if (mountPoint != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ char *mntpnt = (char *) alloca(strlen(mountPoint) + 1);
|
|
|
|
|
+ GOTO_IF_MACRO(!mntpnt, ERR_OUT_OF_MEMORY, badDirHandle);
|
|
|
|
|
+ if (!sanitizePlatformIndependentPath(mountPoint, mntpnt))
|
|
|
|
|
+ goto badDirHandle;
|
|
|
|
|
+ mountPoint = mntpnt; /* sanitized version. */
|
|
|
|
|
+ } /* if */
|
|
|
|
|
|
|
|
dirHandle = openDirectory(newDir, forWriting);
|
|
dirHandle = openDirectory(newDir, forWriting);
|
|
|
GOTO_IF_MACRO(!dirHandle, NULL, badDirHandle);
|
|
GOTO_IF_MACRO(!dirHandle, NULL, badDirHandle);
|
|
@@ -505,7 +560,6 @@ static DirHandle *createDirHandle(const char *newDir,
|
|
|
|
|
|
|
|
if ((mountPoint != NULL) && (*mountPoint != '\0'))
|
|
if ((mountPoint != NULL) && (*mountPoint != '\0'))
|
|
|
{
|
|
{
|
|
|
- /* !!! FIXME: Sanitize the string here. */
|
|
|
|
|
dirHandle->mountPoint = (char *) malloc(strlen(mountPoint) + 2);
|
|
dirHandle->mountPoint = (char *) malloc(strlen(mountPoint) + 2);
|
|
|
GOTO_IF_MACRO(!dirHandle->mountPoint, ERR_OUT_OF_MEMORY, badDirHandle);
|
|
GOTO_IF_MACRO(!dirHandle->mountPoint, ERR_OUT_OF_MEMORY, badDirHandle);
|
|
|
strcpy(dirHandle->mountPoint, mountPoint);
|
|
strcpy(dirHandle->mountPoint, mountPoint);
|
|
@@ -928,7 +982,7 @@ int PHYSFS_mount(const char *newDir, const char *mountPoint, int appendToPath)
|
|
|
|
|
|
|
|
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
|
int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
|
|
|
{
|
|
{
|
|
|
- return(PHYSFS_mount(newDir, "/", appendToPath));
|
|
|
|
|
|
|
+ return(PHYSFS_mount(newDir, NULL, appendToPath));
|
|
|
} /* PHYSFS_addToSearchPath */
|
|
} /* PHYSFS_addToSearchPath */
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1103,7 +1157,7 @@ char * __PHYSFS_convertToDependent(const char *prepend,
|
|
|
if (append != NULL)
|
|
if (append != NULL)
|
|
|
allocSize += strlen(append) + sepsize;
|
|
allocSize += strlen(append) + sepsize;
|
|
|
|
|
|
|
|
- /* make sure there's enough space if the dir separator is bigger. */
|
|
|
|
|
|
|
+ /* make sure there's enough space if the dir separator is bigger. */
|
|
|
if (sepsize > 1)
|
|
if (sepsize > 1)
|
|
|
{
|
|
{
|
|
|
str = (char *) dirName;
|
|
str = (char *) dirName;
|
|
@@ -1156,17 +1210,22 @@ char * __PHYSFS_convertToDependent(const char *prepend,
|
|
|
/*
|
|
/*
|
|
|
* Verify that (fname) (in platform-independent notation), in relation
|
|
* Verify that (fname) (in platform-independent notation), in relation
|
|
|
* to (h) is secure. That means that each element of fname is checked
|
|
* to (h) is secure. That means that each element of fname is checked
|
|
|
- * for symlinks (if they aren't permitted). Also, elements such as
|
|
|
|
|
- * ".", "..", or ":" are flagged. This also allows for quick rejection of
|
|
|
|
|
- * files that exist outside an archive's mountpoint.
|
|
|
|
|
|
|
+ * for symlinks (if they aren't permitted). This also allows for quick
|
|
|
|
|
+ * rejection of files that exist outside an archive's mountpoint.
|
|
|
*
|
|
*
|
|
|
* With some exceptions (like PHYSFS_mkdir(), which builds multiple subdirs
|
|
* With some exceptions (like PHYSFS_mkdir(), which builds multiple subdirs
|
|
|
* at a time), you should always pass zero for "allowMissing" for efficiency.
|
|
* at a time), you should always pass zero for "allowMissing" for efficiency.
|
|
|
*
|
|
*
|
|
|
|
|
+ * (fname) must be an output fromsanitizePlatformIndependentPath(), since it
|
|
|
|
|
+ * will make sure that path names are in the right format for passing certain
|
|
|
|
|
+ * checks. It will also do checks for "insecure" pathnames like ".." which
|
|
|
|
|
+ * should be done once instead of once per archive. This also gives us
|
|
|
|
|
+ * license to treat (fname) as scratch space in this function.
|
|
|
|
|
+ *
|
|
|
* Returns non-zero if string is safe, zero if there's a security issue.
|
|
* Returns non-zero if string is safe, zero if there's a security issue.
|
|
|
* PHYSFS_getLastError() will specify what was wrong.
|
|
* PHYSFS_getLastError() will specify what was wrong.
|
|
|
*/
|
|
*/
|
|
|
-int __PHYSFS_verifySecurity(DirHandle *h, const char *fname, int allowMissing)
|
|
|
|
|
|
|
+int __PHYSFS_verifySecurity(DirHandle *h, char *fname, int allowMissing)
|
|
|
{
|
|
{
|
|
|
int retval = 1;
|
|
int retval = 1;
|
|
|
char *start;
|
|
char *start;
|
|
@@ -1181,6 +1240,9 @@ int __PHYSFS_verifySecurity(DirHandle *h, const char *fname, int allowMissing)
|
|
|
/* !!! FIXME: Case insensitive? */
|
|
/* !!! FIXME: Case insensitive? */
|
|
|
size_t mntpntlen = strlen(h->mountPoint);
|
|
size_t mntpntlen = strlen(h->mountPoint);
|
|
|
assert(mntpntlen > 1); /* root mount points should be NULL. */
|
|
assert(mntpntlen > 1); /* root mount points should be NULL. */
|
|
|
|
|
+ size_t len = strlen(fname);
|
|
|
|
|
+ if (len < mntpntlen)
|
|
|
|
|
+ return(0); /* not under the mountpoint, so skip this archive. */
|
|
|
if (strncmp(h->mountPoint, fname, mntpntlen) != 0)
|
|
if (strncmp(h->mountPoint, fname, mntpntlen) != 0)
|
|
|
return(0); /* not under the mountpoint, so skip this archive. */
|
|
return(0); /* not under the mountpoint, so skip this archive. */
|
|
|
|
|
|
|
@@ -1192,24 +1254,14 @@ int __PHYSFS_verifySecurity(DirHandle *h, const char *fname, int allowMissing)
|
|
|
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
|
|
strcpy(str, fname);
|
|
strcpy(str, fname);
|
|
|
|
|
|
|
|
- while (1)
|
|
|
|
|
|
|
+ if (!allowSymLinks)
|
|
|
{
|
|
{
|
|
|
- end = strchr(start, '/');
|
|
|
|
|
- if (end != NULL)
|
|
|
|
|
- *end = '\0';
|
|
|
|
|
-
|
|
|
|
|
- if ( (strcmp(start, ".") == 0) ||
|
|
|
|
|
- (strcmp(start, "..") == 0) ||
|
|
|
|
|
- (strchr(start, '\\') != NULL) ||
|
|
|
|
|
- (strchr(start, ':') != NULL) )
|
|
|
|
|
|
|
+ while (1)
|
|
|
{
|
|
{
|
|
|
- __PHYSFS_setError(ERR_INSECURE_FNAME);
|
|
|
|
|
- retval = 0;
|
|
|
|
|
- break;
|
|
|
|
|
- } /* if */
|
|
|
|
|
|
|
+ end = strchr(start, '/');
|
|
|
|
|
+ if (end != NULL)
|
|
|
|
|
+ *end = '\0';
|
|
|
|
|
|
|
|
- if (!allowSymLinks)
|
|
|
|
|
- {
|
|
|
|
|
if (h->funcs->isSymLink(h->opaque, str, &retval))
|
|
if (h->funcs->isSymLink(h->opaque, str, &retval))
|
|
|
{
|
|
{
|
|
|
__PHYSFS_setError(ERR_SYMLINK_DISALLOWED);
|
|
__PHYSFS_setError(ERR_SYMLINK_DISALLOWED);
|
|
@@ -1229,21 +1281,20 @@ int __PHYSFS_verifySecurity(DirHandle *h, const char *fname, int allowMissing)
|
|
|
retval = 1;
|
|
retval = 1;
|
|
|
break;
|
|
break;
|
|
|
} /* if */
|
|
} /* if */
|
|
|
- } /* if */
|
|
|
|
|
|
|
|
|
|
- if (end == NULL)
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ if (end == NULL)
|
|
|
|
|
+ break;
|
|
|
|
|
|
|
|
- *end = '/';
|
|
|
|
|
- start = end + 1;
|
|
|
|
|
- } /* while */
|
|
|
|
|
|
|
+ *end = '/';
|
|
|
|
|
+ start = end + 1;
|
|
|
|
|
+ } /* while */
|
|
|
|
|
+ } /* if */
|
|
|
|
|
|
|
|
- free(str);
|
|
|
|
|
return(retval);
|
|
return(retval);
|
|
|
} /* __PHYSFS_verifySecurity */
|
|
} /* __PHYSFS_verifySecurity */
|
|
|
|
|
|
|
|
|
|
|
|
|
-int PHYSFS_mkdir(const char *dname)
|
|
|
|
|
|
|
+int PHYSFS_mkdir(const char *_dname)
|
|
|
{
|
|
{
|
|
|
DirHandle *h;
|
|
DirHandle *h;
|
|
|
char *str;
|
|
char *str;
|
|
@@ -1251,16 +1302,17 @@ int PHYSFS_mkdir(const char *dname)
|
|
|
char *end;
|
|
char *end;
|
|
|
int retval = 0;
|
|
int retval = 0;
|
|
|
int exists = 1; /* force existance check on first path element. */
|
|
int exists = 1; /* force existance check on first path element. */
|
|
|
|
|
+ char *dname;
|
|
|
|
|
|
|
|
|
|
+ dname = ((_dname) ? (char *) alloca(strlen(_dname) + 1) : NULL);
|
|
|
BAIL_IF_MACRO(dname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
BAIL_IF_MACRO(dname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
- while (*dname == '/')
|
|
|
|
|
- dname++;
|
|
|
|
|
|
|
+ BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_dname, dname), NULL, 0);
|
|
|
|
|
|
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
|
BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
|
|
BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
|
|
|
h = writeDir;
|
|
h = writeDir;
|
|
|
BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h,dname,1),NULL,stateLock,0);
|
|
BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h,dname,1),NULL,stateLock,0);
|
|
|
- start = str = malloc(strlen(dname) + 1);
|
|
|
|
|
|
|
+ start = str = dname;
|
|
|
BAIL_IF_MACRO_MUTEX(str == NULL, ERR_OUT_OF_MEMORY, stateLock, 0);
|
|
BAIL_IF_MACRO_MUTEX(str == NULL, ERR_OUT_OF_MEMORY, stateLock, 0);
|
|
|
strcpy(str, dname);
|
|
strcpy(str, dname);
|
|
|
|
|
|
|
@@ -1288,20 +1340,18 @@ int PHYSFS_mkdir(const char *dname)
|
|
|
} /* while */
|
|
} /* while */
|
|
|
|
|
|
|
|
__PHYSFS_platformReleaseMutex(stateLock);
|
|
__PHYSFS_platformReleaseMutex(stateLock);
|
|
|
-
|
|
|
|
|
- free(str);
|
|
|
|
|
return(retval);
|
|
return(retval);
|
|
|
} /* PHYSFS_mkdir */
|
|
} /* PHYSFS_mkdir */
|
|
|
|
|
|
|
|
|
|
|
|
|
-int PHYSFS_delete(const char *fname)
|
|
|
|
|
|
|
+int PHYSFS_delete(const char *_fname)
|
|
|
{
|
|
{
|
|
|
int retval;
|
|
int retval;
|
|
|
DirHandle *h;
|
|
DirHandle *h;
|
|
|
|
|
|
|
|
|
|
+ char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
|
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
- while (*fname == '/')
|
|
|
|
|
- fname++;
|
|
|
|
|
|
|
+ BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
|
|
|
|
|
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
|
|
|
|
|
@@ -1315,20 +1365,21 @@ int PHYSFS_delete(const char *fname)
|
|
|
} /* PHYSFS_delete */
|
|
} /* PHYSFS_delete */
|
|
|
|
|
|
|
|
|
|
|
|
|
-const char *PHYSFS_getRealDir(const char *filename)
|
|
|
|
|
|
|
+const char *PHYSFS_getRealDir(const char *_fname)
|
|
|
{
|
|
{
|
|
|
DirHandle *i;
|
|
DirHandle *i;
|
|
|
const char *retval = NULL;
|
|
const char *retval = NULL;
|
|
|
|
|
|
|
|
- while (*filename == '/')
|
|
|
|
|
- filename++;
|
|
|
|
|
|
|
+ char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
|
|
|
|
+ BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL);
|
|
|
|
|
+ BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, NULL);
|
|
|
|
|
|
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
|
for (i = searchPath; ((i != NULL) && (retval == NULL)); i = i->next)
|
|
for (i = searchPath; ((i != NULL) && (retval == NULL)); i = i->next)
|
|
|
{
|
|
{
|
|
|
- if (__PHYSFS_verifySecurity(i, filename, 0))
|
|
|
|
|
|
|
+ if (__PHYSFS_verifySecurity(i, fname, 0))
|
|
|
{
|
|
{
|
|
|
- if (i->funcs->exists(i->opaque, filename))
|
|
|
|
|
|
|
+ if (i->funcs->exists(i->opaque, fname))
|
|
|
retval = i->dirName;
|
|
retval = i->dirName;
|
|
|
} /* if */
|
|
} /* if */
|
|
|
} /* for */
|
|
} /* for */
|
|
@@ -1428,25 +1479,25 @@ char **PHYSFS_enumerateFiles(const char *path)
|
|
|
} /* PHYSFS_enumerateFiles */
|
|
} /* PHYSFS_enumerateFiles */
|
|
|
|
|
|
|
|
|
|
|
|
|
-void PHYSFS_enumerateFilesCallback(const char *path,
|
|
|
|
|
|
|
+void PHYSFS_enumerateFilesCallback(const char *_fname,
|
|
|
PHYSFS_StringCallback callback,
|
|
PHYSFS_StringCallback callback,
|
|
|
void *data)
|
|
void *data)
|
|
|
{
|
|
{
|
|
|
DirHandle *i;
|
|
DirHandle *i;
|
|
|
int noSyms;
|
|
int noSyms;
|
|
|
|
|
+ char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
|
|
|
|
+ if ((fname == NULL) || (callback == NULL))
|
|
|
|
|
+ return; /* oh well. */
|
|
|
|
|
|
|
|
- if ((path == NULL) || (callback == NULL))
|
|
|
|
|
|
|
+ if (!sanitizePlatformIndependentPath(_fname, fname))
|
|
|
return;
|
|
return;
|
|
|
|
|
|
|
|
- while (*path == '/')
|
|
|
|
|
- path++;
|
|
|
|
|
-
|
|
|
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
|
noSyms = !allowSymLinks;
|
|
noSyms = !allowSymLinks;
|
|
|
for (i = searchPath; i != NULL; i = i->next)
|
|
for (i = searchPath; i != NULL; i = i->next)
|
|
|
{
|
|
{
|
|
|
- if (__PHYSFS_verifySecurity(i, path, 0))
|
|
|
|
|
- i->funcs->enumerateFiles(i->opaque, path, noSyms, callback, data);
|
|
|
|
|
|
|
+ if (__PHYSFS_verifySecurity(i, fname, 0))
|
|
|
|
|
+ i->funcs->enumerateFiles(i->opaque, fname, noSyms, callback, data);
|
|
|
} /* for */
|
|
} /* for */
|
|
|
__PHYSFS_platformReleaseMutex(stateLock);
|
|
__PHYSFS_platformReleaseMutex(stateLock);
|
|
|
} /* PHYSFS_enumerateFilesCallback */
|
|
} /* PHYSFS_enumerateFilesCallback */
|
|
@@ -1454,26 +1505,22 @@ void PHYSFS_enumerateFilesCallback(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 == '/')
|
|
|
|
|
- fname++;
|
|
|
|
|
-
|
|
|
|
|
return(PHYSFS_getRealDir(fname) != NULL);
|
|
return(PHYSFS_getRealDir(fname) != NULL);
|
|
|
} /* PHYSFS_exists */
|
|
} /* PHYSFS_exists */
|
|
|
|
|
|
|
|
|
|
|
|
|
-PHYSFS_sint64 PHYSFS_getLastModTime(const char *fname)
|
|
|
|
|
|
|
+PHYSFS_sint64 PHYSFS_getLastModTime(const char *_fname)
|
|
|
{
|
|
{
|
|
|
DirHandle *i;
|
|
DirHandle *i;
|
|
|
PHYSFS_sint64 retval = -1;
|
|
PHYSFS_sint64 retval = -1;
|
|
|
int fileExists = 0;
|
|
int fileExists = 0;
|
|
|
|
|
|
|
|
|
|
+ char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
|
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
- while (*fname == '/')
|
|
|
|
|
- fname++;
|
|
|
|
|
|
|
+ BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
|
|
|
|
|
|
|
if (*fname == '\0') /* eh...punt if it's the root dir. */
|
|
if (*fname == '\0') /* eh...punt if it's the root dir. */
|
|
|
- return(1);
|
|
|
|
|
|
|
+ return(1); /* !!! FIXME: Maybe this should be an error? */
|
|
|
|
|
|
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
|
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
|
|
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
|
|
@@ -1487,16 +1534,15 @@ PHYSFS_sint64 PHYSFS_getLastModTime(const char *fname)
|
|
|
} /* PHYSFS_getLastModTime */
|
|
} /* PHYSFS_getLastModTime */
|
|
|
|
|
|
|
|
|
|
|
|
|
-int PHYSFS_isDirectory(const char *fname)
|
|
|
|
|
|
|
+int PHYSFS_isDirectory(const char *_fname)
|
|
|
{
|
|
{
|
|
|
DirHandle *i;
|
|
DirHandle *i;
|
|
|
int retval = 0;
|
|
int retval = 0;
|
|
|
int fileExists = 0;
|
|
int fileExists = 0;
|
|
|
|
|
|
|
|
|
|
+ char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
|
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
- while (*fname == '/')
|
|
|
|
|
- fname++;
|
|
|
|
|
-
|
|
|
|
|
|
|
+ BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
|
|
BAIL_IF_MACRO(*fname == '\0', NULL, 1); /* Root is always a dir. :) */
|
|
BAIL_IF_MACRO(*fname == '\0', NULL, 1); /* Root is always a dir. :) */
|
|
|
|
|
|
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
@@ -1511,18 +1557,18 @@ int PHYSFS_isDirectory(const char *fname)
|
|
|
} /* PHYSFS_isDirectory */
|
|
} /* PHYSFS_isDirectory */
|
|
|
|
|
|
|
|
|
|
|
|
|
-int PHYSFS_isSymbolicLink(const char *fname)
|
|
|
|
|
|
|
+int PHYSFS_isSymbolicLink(const char *_fname)
|
|
|
{
|
|
{
|
|
|
DirHandle *i;
|
|
DirHandle *i;
|
|
|
int retval = 0;
|
|
int retval = 0;
|
|
|
int fileExists = 0;
|
|
int fileExists = 0;
|
|
|
|
|
+ char *fname;
|
|
|
|
|
|
|
|
BAIL_IF_MACRO(!allowSymLinks, ERR_SYMLINK_DISALLOWED, 0);
|
|
BAIL_IF_MACRO(!allowSymLinks, ERR_SYMLINK_DISALLOWED, 0);
|
|
|
|
|
|
|
|
|
|
+ fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
|
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
- while (*fname == '/')
|
|
|
|
|
- fname++;
|
|
|
|
|
-
|
|
|
|
|
|
|
+ BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
|
|
BAIL_IF_MACRO(*fname == '\0', NULL, 0); /* Root is never a symlink */
|
|
BAIL_IF_MACRO(*fname == '\0', NULL, 0); /* Root is never a symlink */
|
|
|
|
|
|
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
@@ -1537,16 +1583,16 @@ int PHYSFS_isSymbolicLink(const char *fname)
|
|
|
} /* PHYSFS_isSymbolicLink */
|
|
} /* PHYSFS_isSymbolicLink */
|
|
|
|
|
|
|
|
|
|
|
|
|
-static PHYSFS_File *doOpenWrite(const char *fname, int appending)
|
|
|
|
|
|
|
+static PHYSFS_File *doOpenWrite(const char *_fname, int appending)
|
|
|
{
|
|
{
|
|
|
void *opaque = NULL;
|
|
void *opaque = NULL;
|
|
|
FileHandle *fh = NULL;
|
|
FileHandle *fh = NULL;
|
|
|
DirHandle *h = NULL;
|
|
DirHandle *h = NULL;
|
|
|
const PHYSFS_Archiver *f;
|
|
const PHYSFS_Archiver *f;
|
|
|
|
|
|
|
|
- BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL);
|
|
|
|
|
- while (*fname == '/')
|
|
|
|
|
- fname++;
|
|
|
|
|
|
|
+ char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
|
|
|
|
+ BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
|
|
+ BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
|
|
|
|
|
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
|
BAIL_IF_MACRO_MUTEX(!writeDir, ERR_NO_WRITE_DIR, stateLock, NULL);
|
|
BAIL_IF_MACRO_MUTEX(!writeDir, ERR_NO_WRITE_DIR, stateLock, NULL);
|
|
@@ -1596,16 +1642,16 @@ PHYSFS_File *PHYSFS_openAppend(const char *filename)
|
|
|
} /* PHYSFS_openAppend */
|
|
} /* PHYSFS_openAppend */
|
|
|
|
|
|
|
|
|
|
|
|
|
-PHYSFS_File *PHYSFS_openRead(const char *fname)
|
|
|
|
|
|
|
+PHYSFS_File *PHYSFS_openRead(const char *_fname)
|
|
|
{
|
|
{
|
|
|
FileHandle *fh = NULL;
|
|
FileHandle *fh = NULL;
|
|
|
int fileExists = 0;
|
|
int fileExists = 0;
|
|
|
DirHandle *i = NULL;
|
|
DirHandle *i = NULL;
|
|
|
fvoid *opaque = NULL;
|
|
fvoid *opaque = NULL;
|
|
|
|
|
|
|
|
- BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL);
|
|
|
|
|
- while (*fname == '/')
|
|
|
|
|
- fname++;
|
|
|
|
|
|
|
+ char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
|
|
|
|
+ BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
|
|
|
|
+ BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
|
|
|
|
|
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
__PHYSFS_platformGrabMutex(stateLock);
|
|
|
BAIL_IF_MACRO_MUTEX(!searchPath, ERR_NOT_IN_SEARCH_PATH, stateLock, NULL);
|
|
BAIL_IF_MACRO_MUTEX(!searchPath, ERR_NOT_IN_SEARCH_PATH, stateLock, NULL);
|
|
@@ -1851,6 +1897,7 @@ int PHYSFS_setBuffer(PHYSFS_File *handle, PHYSFS_uint64 _bufsize)
|
|
|
FileHandle *fh = (FileHandle *) handle;
|
|
FileHandle *fh = (FileHandle *) handle;
|
|
|
PHYSFS_uint32 bufsize;
|
|
PHYSFS_uint32 bufsize;
|
|
|
|
|
|
|
|
|
|
+ /* !!! FIXME: Unlocalized string. */
|
|
|
BAIL_IF_MACRO(_bufsize > 0xFFFFFFFF, "buffer must fit in 32-bits", 0);
|
|
BAIL_IF_MACRO(_bufsize > 0xFFFFFFFF, "buffer must fit in 32-bits", 0);
|
|
|
bufsize = (PHYSFS_uint32) _bufsize;
|
|
bufsize = (PHYSFS_uint32) _bufsize;
|
|
|
|
|
|