Replaced some Malloc and all the alloca() calls with __PHYSFS_smallAlloc(),
which will stack allocate small (128 or less bytes) blocks and Malloc the rest...naturally these now have to be paired with __PHYSFS_smallFree() calls, so you can't be as lazy as a basic alloca() would let you be. The benefit is both less malloc pressure for those temporary allocations and better stack overflow safety (so if some jerk tries to push a 78 megabyte string through the library as a filename, we won't try to strcpy it to the stack).
This commit is contained in:
parent
80ec45d88a
commit
7386320811
|
@ -1,6 +1,18 @@
|
||||||
/*
|
/*
|
||||||
* CHANGELOG.
|
* CHANGELOG.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
03222007 - Replaced some Malloc and all the alloca() calls with
|
||||||
|
__PHYSFS_smallAlloc(), which will stack allocate small (128 or
|
||||||
|
less bytes) blocks and Malloc the rest...naturally these now have
|
||||||
|
to be paired with __PHYSFS_smallFree() calls, so you can't be as
|
||||||
|
lazy as a basic alloca() would let you be. The benefit is both less
|
||||||
|
malloc pressure for those temporary allocations and better stack
|
||||||
|
overflow safety (so if some jerk tries to push a 78 megabyte string
|
||||||
|
through the library as a filename, we won't try to strcpy it to
|
||||||
|
the stack). Hopefully some internal interfaces can now get
|
||||||
|
refactored to stop generating heap pointers and let the caller use
|
||||||
|
smallAlloc to further reduce malloc pressure.
|
||||||
03212007 - Replaced LONGLONGLITERAL with __PHYSFS_UI64/__PHYSFS_SI64 ...
|
03212007 - Replaced LONGLONGLITERAL with __PHYSFS_UI64/__PHYSFS_SI64 ...
|
||||||
03202007 - Removed platform/skeleton.c (it was out of date), added
|
03202007 - Removed platform/skeleton.c (it was out of date), added
|
||||||
platform/macosx.c (To further Macify the code and get the #ifdefs
|
platform/macosx.c (To further Macify the code and get the #ifdefs
|
||||||
|
|
|
@ -479,13 +479,14 @@ static void *LZMA_openArchive(const char *name, int forWriting)
|
||||||
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
||||||
const char *odir, const char *str, PHYSFS_sint32 ln)
|
const char *odir, const char *str, PHYSFS_sint32 ln)
|
||||||
{
|
{
|
||||||
char *newstr = alloca(ln + 1);
|
char *newstr = __PHYSFS_smallAlloc(ln + 1);
|
||||||
if (newstr == NULL)
|
if (newstr == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(newstr, str, ln);
|
memcpy(newstr, str, ln);
|
||||||
newstr[ln] = '\0';
|
newstr[ln] = '\0';
|
||||||
cb(callbackdata, odir, newstr);
|
cb(callbackdata, odir, newstr);
|
||||||
|
__PHYSFS_smallFree(newstr);
|
||||||
} /* doEnumCallback */
|
} /* doEnumCallback */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -378,13 +378,14 @@ static PHYSFS_sint32 qpak_find_start_of_dir(QPAKinfo *info, const char *path,
|
||||||
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
||||||
const char *odir, const char *str, PHYSFS_sint32 ln)
|
const char *odir, const char *str, PHYSFS_sint32 ln)
|
||||||
{
|
{
|
||||||
char *newstr = alloca(ln + 1);
|
char *newstr = __PHYSFS_smallAlloc(ln + 1);
|
||||||
if (newstr == NULL)
|
if (newstr == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(newstr, str, ln);
|
memcpy(newstr, str, ln);
|
||||||
newstr[ln] = '\0';
|
newstr[ln] = '\0';
|
||||||
cb(callbackdata, odir, newstr);
|
cb(callbackdata, odir, newstr);
|
||||||
|
__PHYSFS_smallFree(newstr);
|
||||||
} /* doEnumCallback */
|
} /* doEnumCallback */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -682,15 +682,15 @@ static int zip_resolve_symlink(void *in, ZIPinfo *info, ZIPentry *entry)
|
||||||
else /* symlink target path is compressed... */
|
else /* symlink target path is compressed... */
|
||||||
{
|
{
|
||||||
z_stream stream;
|
z_stream stream;
|
||||||
PHYSFS_uint32 compsize = entry->compressed_size;
|
PHYSFS_uint32 complen = entry->compressed_size;
|
||||||
PHYSFS_uint8 *compressed = (PHYSFS_uint8 *) allocator.Malloc(compsize);
|
PHYSFS_uint8 *compressed = (PHYSFS_uint8*) __PHYSFS_smallAlloc(complen);
|
||||||
if (compressed != NULL)
|
if (compressed != NULL)
|
||||||
{
|
{
|
||||||
if (__PHYSFS_platformRead(in, compressed, compsize, 1) == 1)
|
if (__PHYSFS_platformRead(in, compressed, complen, 1) == 1)
|
||||||
{
|
{
|
||||||
initializeZStream(&stream);
|
initializeZStream(&stream);
|
||||||
stream.next_in = compressed;
|
stream.next_in = compressed;
|
||||||
stream.avail_in = compsize;
|
stream.avail_in = complen;
|
||||||
stream.next_out = (unsigned char *) path;
|
stream.next_out = (unsigned char *) path;
|
||||||
stream.avail_out = size;
|
stream.avail_out = size;
|
||||||
if (zlib_err(inflateInit2(&stream, -MAX_WBITS)) == Z_OK)
|
if (zlib_err(inflateInit2(&stream, -MAX_WBITS)) == Z_OK)
|
||||||
|
@ -702,7 +702,7 @@ static int zip_resolve_symlink(void *in, ZIPinfo *info, ZIPentry *entry)
|
||||||
rc = ((rc == Z_OK) || (rc == Z_STREAM_END));
|
rc = ((rc == Z_OK) || (rc == Z_STREAM_END));
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* if */
|
} /* if */
|
||||||
allocator.Free(compressed);
|
__PHYSFS_smallFree(compressed);
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* else */
|
} /* else */
|
||||||
|
|
||||||
|
@ -1177,13 +1177,14 @@ static PHYSFS_sint32 zip_find_start_of_dir(ZIPinfo *info, const char *path,
|
||||||
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
|
||||||
const char *odir, const char *str, PHYSFS_sint32 ln)
|
const char *odir, const char *str, PHYSFS_sint32 ln)
|
||||||
{
|
{
|
||||||
char *newstr = alloca(ln + 1);
|
char *newstr = __PHYSFS_smallAlloc(ln + 1);
|
||||||
if (newstr == NULL)
|
if (newstr == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(newstr, str, ln);
|
memcpy(newstr, str, ln);
|
||||||
newstr[ln] = '\0';
|
newstr[ln] = '\0';
|
||||||
cb(callbackdata, odir, newstr);
|
cb(callbackdata, odir, newstr);
|
||||||
|
__PHYSFS_smallFree(newstr);
|
||||||
} /* doEnumCallback */
|
} /* doEnumCallback */
|
||||||
|
|
||||||
|
|
||||||
|
|
521
physfs.c
521
physfs.c
|
@ -538,15 +538,17 @@ static DirHandle *createDirHandle(const char *newDir,
|
||||||
int forWriting)
|
int forWriting)
|
||||||
{
|
{
|
||||||
DirHandle *dirHandle = NULL;
|
DirHandle *dirHandle = NULL;
|
||||||
|
char *tmpmntpnt = NULL;
|
||||||
|
|
||||||
GOTO_IF_MACRO(!newDir, ERR_INVALID_ARGUMENT, badDirHandle);
|
GOTO_IF_MACRO(!newDir, ERR_INVALID_ARGUMENT, badDirHandle);
|
||||||
if (mountPoint != NULL)
|
if (mountPoint != NULL)
|
||||||
{
|
{
|
||||||
char *mntpnt = (char *) alloca(strlen(mountPoint) + 1);
|
const size_t len = strlen(mountPoint) + 1;
|
||||||
GOTO_IF_MACRO(!mntpnt, ERR_OUT_OF_MEMORY, badDirHandle);
|
tmpmntpnt = (char *) __PHYSFS_smallAlloc(len);
|
||||||
if (!sanitizePlatformIndependentPath(mountPoint, mntpnt))
|
GOTO_IF_MACRO(!tmpmntpnt, ERR_OUT_OF_MEMORY, badDirHandle);
|
||||||
|
if (!sanitizePlatformIndependentPath(mountPoint, tmpmntpnt))
|
||||||
goto badDirHandle;
|
goto badDirHandle;
|
||||||
mountPoint = mntpnt; /* sanitized version. */
|
mountPoint = tmpmntpnt; /* sanitized version. */
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
dirHandle = openDirectory(newDir, forWriting);
|
dirHandle = openDirectory(newDir, forWriting);
|
||||||
|
@ -564,6 +566,7 @@ static DirHandle *createDirHandle(const char *newDir,
|
||||||
strcat(dirHandle->mountPoint, "/");
|
strcat(dirHandle->mountPoint, "/");
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
|
__PHYSFS_smallFree(tmpmntpnt);
|
||||||
return(dirHandle);
|
return(dirHandle);
|
||||||
|
|
||||||
badDirHandle:
|
badDirHandle:
|
||||||
|
@ -575,6 +578,7 @@ badDirHandle:
|
||||||
allocator.Free(dirHandle);
|
allocator.Free(dirHandle);
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
|
__PHYSFS_smallFree(tmpmntpnt);
|
||||||
return(NULL);
|
return(NULL);
|
||||||
} /* createDirHandle */
|
} /* createDirHandle */
|
||||||
|
|
||||||
|
@ -620,8 +624,7 @@ static char *calculateUserDir(void)
|
||||||
else
|
else
|
||||||
sprintf(retval, "%susers%s%s", baseDir, dirsep, str);
|
sprintf(retval, "%susers%s%s", baseDir, dirsep, str);
|
||||||
|
|
||||||
if (uname != NULL)
|
allocator.Free((void *) uname);
|
||||||
allocator.Free((void *) uname);
|
|
||||||
} /* else */
|
} /* else */
|
||||||
|
|
||||||
return(retval);
|
return(retval);
|
||||||
|
@ -1053,6 +1056,22 @@ void PHYSFS_getSearchPathCallback(PHYSFS_StringCallback callback, void *data)
|
||||||
} /* PHYSFS_getSearchPathCallback */
|
} /* PHYSFS_getSearchPathCallback */
|
||||||
|
|
||||||
|
|
||||||
|
/* Split out to avoid stack allocation in a loop. */
|
||||||
|
static void setSaneCfgAddPath(const char *i, const size_t l, const char *dirsep,
|
||||||
|
int archivesFirst)
|
||||||
|
{
|
||||||
|
const char *d = PHYSFS_getRealDir(i);
|
||||||
|
const size_t allocsize = strlen(d) + strlen(dirsep) + l + 1;
|
||||||
|
char *str = (char *) __PHYSFS_smallAlloc(allocsize);
|
||||||
|
if (str != NULL)
|
||||||
|
{
|
||||||
|
sprintf(str, "%s%s%s", d, dirsep, i);
|
||||||
|
PHYSFS_addToSearchPath(str, archivesFirst == 0);
|
||||||
|
__PHYSFS_smallFree(str);
|
||||||
|
} /* if */
|
||||||
|
} /* setSaneCfgAddPath */
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_setSaneConfig(const char *organization, const char *appName,
|
int PHYSFS_setSaneConfig(const char *organization, const char *appName,
|
||||||
const char *archiveExt, int includeCdRoms,
|
const char *archiveExt, int includeCdRoms,
|
||||||
int archivesFirst)
|
int archivesFirst)
|
||||||
|
@ -1060,15 +1079,17 @@ int PHYSFS_setSaneConfig(const char *organization, const char *appName,
|
||||||
const char *basedir = PHYSFS_getBaseDir();
|
const char *basedir = PHYSFS_getBaseDir();
|
||||||
const char *userdir = PHYSFS_getUserDir();
|
const char *userdir = PHYSFS_getUserDir();
|
||||||
const char *dirsep = PHYSFS_getDirSeparator();
|
const char *dirsep = PHYSFS_getDirSeparator();
|
||||||
char *str;
|
PHYSFS_uint64 len = 0;
|
||||||
|
char *str = NULL;
|
||||||
|
|
||||||
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
|
||||||
|
|
||||||
/* set write dir... */
|
/* set write dir... */
|
||||||
str = (char *) allocator.Malloc(
|
len = (strlen(userdir) + (strlen(organization) * 2) +
|
||||||
strlen(userdir) + (strlen(organization) * 2) +
|
|
||||||
(strlen(appName) * 2) + (strlen(dirsep) * 3) + 2);
|
(strlen(appName) * 2) + (strlen(dirsep) * 3) + 2);
|
||||||
|
|
||||||
|
str = (char *) __PHYSFS_smallAlloc(len);
|
||||||
|
|
||||||
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||||
sprintf(str, "%s.%s%s%s", userdir, organization, dirsep, appName);
|
sprintf(str, "%s.%s%s%s", userdir, organization, dirsep, appName);
|
||||||
|
|
||||||
|
@ -1091,14 +1112,14 @@ int PHYSFS_setSaneConfig(const char *organization, const char *appName,
|
||||||
if (no_write)
|
if (no_write)
|
||||||
{
|
{
|
||||||
PHYSFS_setWriteDir(NULL); /* just in case. */
|
PHYSFS_setWriteDir(NULL); /* just in case. */
|
||||||
allocator.Free(str);
|
__PHYSFS_smallFree(str);
|
||||||
BAIL_MACRO(ERR_CANT_SET_WRITE_DIR, 0);
|
BAIL_MACRO(ERR_CANT_SET_WRITE_DIR, 0);
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
/* Put write dir first in search path... */
|
/* Put write dir first in search path... */
|
||||||
PHYSFS_addToSearchPath(str, 0);
|
PHYSFS_addToSearchPath(str, 0);
|
||||||
allocator.Free(str);
|
__PHYSFS_smallFree(str);
|
||||||
|
|
||||||
/* Put base path on search path... */
|
/* Put base path on search path... */
|
||||||
PHYSFS_addToSearchPath(basedir, 1);
|
PHYSFS_addToSearchPath(basedir, 1);
|
||||||
|
@ -1129,17 +1150,7 @@ int PHYSFS_setSaneConfig(const char *organization, const char *appName,
|
||||||
{
|
{
|
||||||
ext = (*i) + (l - extlen);
|
ext = (*i) + (l - extlen);
|
||||||
if (__PHYSFS_stricmpASCII(ext, archiveExt) == 0)
|
if (__PHYSFS_stricmpASCII(ext, archiveExt) == 0)
|
||||||
{
|
setSaneCfgAddPath(*i, l, dirsep, archivesFirst);
|
||||||
const char *d = PHYSFS_getRealDir(*i);
|
|
||||||
size_t allocsize = strlen(d) + strlen(dirsep) + l + 1;
|
|
||||||
str = (char *) allocator.Malloc(allocsize);
|
|
||||||
if (str != NULL)
|
|
||||||
{
|
|
||||||
sprintf(str, "%s%s%s", d, dirsep, *i);
|
|
||||||
PHYSFS_addToSearchPath(str, archivesFirst == 0);
|
|
||||||
allocator.Free(str);
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* for */
|
} /* for */
|
||||||
|
|
||||||
|
@ -1315,17 +1326,14 @@ static int verifyPath(DirHandle *h, char **_fname, int allowMissing)
|
||||||
} /* verifyPath */
|
} /* verifyPath */
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_mkdir(const char *_dname)
|
static int doMkdir(const char *_dname, char *dname)
|
||||||
{
|
{
|
||||||
DirHandle *h;
|
DirHandle *h;
|
||||||
char *start;
|
char *start;
|
||||||
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(!sanitizePlatformIndependentPath(_dname, dname), NULL, 0);
|
BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_dname, dname), NULL, 0);
|
||||||
|
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
@ -1359,16 +1367,29 @@ int PHYSFS_mkdir(const char *_dname)
|
||||||
|
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
return(retval);
|
return(retval);
|
||||||
|
} /* doMkdir */
|
||||||
|
|
||||||
|
|
||||||
|
int PHYSFS_mkdir(const char *_dname)
|
||||||
|
{
|
||||||
|
int retval = 0;
|
||||||
|
char *dname;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(_dname == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
|
len = strlen(_dname) + 1;
|
||||||
|
dname = (char *) __PHYSFS_smallAlloc(len);
|
||||||
|
BAIL_IF_MACRO(dname == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||||
|
retval = doMkdir(_dname, dname);
|
||||||
|
__PHYSFS_smallFree(dname);
|
||||||
|
return(retval);
|
||||||
} /* PHYSFS_mkdir */
|
} /* PHYSFS_mkdir */
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_delete(const char *_fname)
|
static int doDelete(const char *_fname, 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(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
||||||
|
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
@ -1380,32 +1401,54 @@ int PHYSFS_delete(const char *_fname)
|
||||||
|
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
return(retval);
|
return(retval);
|
||||||
|
} /* doDelete */
|
||||||
|
|
||||||
|
|
||||||
|
int PHYSFS_delete(const char *_fname)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
char *fname;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
BAIL_IF_MACRO(_fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
||||||
|
len = strlen(_fname) + 1;
|
||||||
|
fname = (char *) __PHYSFS_smallAlloc(len);
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||||
|
retval = doDelete(_fname, fname);
|
||||||
|
__PHYSFS_smallFree(fname);
|
||||||
|
return(retval);
|
||||||
} /* PHYSFS_delete */
|
} /* PHYSFS_delete */
|
||||||
|
|
||||||
|
|
||||||
const char *PHYSFS_getRealDir(const char *_fname)
|
const char *PHYSFS_getRealDir(const char *_fname)
|
||||||
{
|
{
|
||||||
DirHandle *i;
|
|
||||||
const char *retval = NULL;
|
const char *retval = NULL;
|
||||||
|
char *fname = NULL;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
BAIL_IF_MACRO(_fname == NULL, ERR_INVALID_ARGUMENT, NULL);
|
||||||
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL);
|
len = strlen(_fname) + 1;
|
||||||
BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, NULL);
|
fname = __PHYSFS_smallAlloc(len);
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
if (sanitizePlatformIndependentPath(_fname, fname))
|
||||||
for (i = searchPath; ((i != NULL) && (retval == NULL)); i = i->next)
|
|
||||||
{
|
{
|
||||||
char *arcfname = fname;
|
DirHandle *i;
|
||||||
if (partOfMountPoint(i, arcfname))
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
retval = i->dirName;
|
for (i = searchPath; ((i != NULL) && (retval == NULL)); i = i->next)
|
||||||
else if (verifyPath(i, &arcfname, 0))
|
|
||||||
{
|
{
|
||||||
if (i->funcs->exists(i->opaque, arcfname))
|
char *arcfname = fname;
|
||||||
|
if (partOfMountPoint(i, arcfname))
|
||||||
retval = i->dirName;
|
retval = i->dirName;
|
||||||
} /* if */
|
else if (verifyPath(i, &arcfname, 0))
|
||||||
} /* for */
|
{
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
if (i->funcs->exists(i->opaque, arcfname))
|
||||||
|
retval = i->dirName;
|
||||||
|
} /* if */
|
||||||
|
} /* for */
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
__PHYSFS_smallFree(fname);
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* PHYSFS_getRealDir */
|
} /* PHYSFS_getRealDir */
|
||||||
|
|
||||||
|
@ -1491,54 +1534,69 @@ char **PHYSFS_enumerateFiles(const char *path)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Broke out to seperate function so we can use alloca() gratuitously.
|
* Broke out to seperate function so we can use stack allocation gratuitously.
|
||||||
*/
|
*/
|
||||||
static void enumerateFromMountPoint(DirHandle *i, const char *arcfname,
|
static void enumerateFromMountPoint(DirHandle *i, const char *arcfname,
|
||||||
PHYSFS_EnumFilesCallback callback,
|
PHYSFS_EnumFilesCallback callback,
|
||||||
const char *_fname, void *data)
|
const char *_fname, void *data)
|
||||||
{
|
{
|
||||||
size_t len = strlen(arcfname);
|
const size_t len = strlen(arcfname);
|
||||||
char *ptr = NULL;
|
char *ptr = NULL;
|
||||||
char *end = NULL;
|
char *end = NULL;
|
||||||
char *mountPoint = (char *) alloca(strlen(i->mountPoint) + 1);
|
const size_t slen = strlen(i->mountPoint) + 1;
|
||||||
|
char *mountPoint = (char *) __PHYSFS_smallAlloc(slen);
|
||||||
|
|
||||||
|
if (mountPoint == NULL)
|
||||||
|
return; /* oh well. */
|
||||||
|
|
||||||
strcpy(mountPoint, i->mountPoint);
|
strcpy(mountPoint, i->mountPoint);
|
||||||
ptr = mountPoint + ((len) ? len + 1 : 0);
|
ptr = mountPoint + ((len) ? len + 1 : 0);
|
||||||
end = strchr(ptr, '/');
|
end = strchr(ptr, '/');
|
||||||
assert(end); /* should always find a terminating '/'. */
|
assert(end); /* should always find a terminating '/'. */
|
||||||
*end = '\0';
|
*end = '\0';
|
||||||
callback(data, _fname, ptr);
|
callback(data, _fname, ptr);
|
||||||
|
__PHYSFS_smallFree(mountPoint);
|
||||||
} /* enumerateFromMountPoint */
|
} /* enumerateFromMountPoint */
|
||||||
|
|
||||||
|
|
||||||
|
/* !!! FIXME: this should report error conditions. */
|
||||||
void PHYSFS_enumerateFilesCallback(const char *_fname,
|
void PHYSFS_enumerateFilesCallback(const char *_fname,
|
||||||
PHYSFS_EnumFilesCallback callback,
|
PHYSFS_EnumFilesCallback callback,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
DirHandle *i;
|
size_t len;
|
||||||
int noSyms;
|
char *fname;
|
||||||
char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
|
||||||
if ((fname == NULL) || (callback == NULL))
|
|
||||||
return; /* oh well. */
|
|
||||||
|
|
||||||
if (!sanitizePlatformIndependentPath(_fname, fname))
|
BAIL_IF_MACRO(_fname == NULL, ERR_INVALID_ARGUMENT, /*0*/);
|
||||||
return;
|
BAIL_IF_MACRO(callback == NULL, ERR_INVALID_ARGUMENT, /*0*/);
|
||||||
|
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
len = strlen(_fname) + 1;
|
||||||
noSyms = !allowSymLinks;
|
fname = (char *) __PHYSFS_smallAlloc(len);
|
||||||
for (i = searchPath; i != NULL; i = i->next)
|
BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, /*0*/);
|
||||||
|
|
||||||
|
if (sanitizePlatformIndependentPath(_fname, fname))
|
||||||
{
|
{
|
||||||
char *arcfname = fname;
|
DirHandle *i;
|
||||||
if (partOfMountPoint(i, arcfname))
|
int noSyms;
|
||||||
enumerateFromMountPoint(i, arcfname, callback, _fname, data);
|
|
||||||
|
|
||||||
else if (verifyPath(i, &arcfname, 0))
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
noSyms = !allowSymLinks;
|
||||||
|
for (i = searchPath; i != NULL; i = i->next)
|
||||||
{
|
{
|
||||||
i->funcs->enumerateFiles(i->opaque, arcfname, noSyms,
|
char *arcfname = fname;
|
||||||
callback, _fname, data);
|
if (partOfMountPoint(i, arcfname))
|
||||||
} /* else if */
|
enumerateFromMountPoint(i, arcfname, callback, _fname, data);
|
||||||
} /* for */
|
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
else if (verifyPath(i, &arcfname, 0))
|
||||||
|
{
|
||||||
|
i->funcs->enumerateFiles(i->opaque, arcfname, noSyms,
|
||||||
|
callback, _fname, data);
|
||||||
|
} /* else if */
|
||||||
|
} /* for */
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
__PHYSFS_smallFree(fname);
|
||||||
} /* PHYSFS_enumerateFilesCallback */
|
} /* PHYSFS_enumerateFilesCallback */
|
||||||
|
|
||||||
|
|
||||||
|
@ -1550,130 +1608,178 @@ int PHYSFS_exists(const char *fname)
|
||||||
|
|
||||||
PHYSFS_sint64 PHYSFS_getLastModTime(const char *_fname)
|
PHYSFS_sint64 PHYSFS_getLastModTime(const char *_fname)
|
||||||
{
|
{
|
||||||
DirHandle *i;
|
|
||||||
PHYSFS_sint64 retval = -1;
|
PHYSFS_sint64 retval = -1;
|
||||||
int fileExists = 0;
|
char *fname;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
|
BAIL_IF_MACRO(_fname == NULL, ERR_INVALID_ARGUMENT, -1);
|
||||||
BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
|
len = strlen(_fname) + 1;
|
||||||
BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
fname = (char *) __PHYSFS_smallAlloc(len);
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, -1);
|
||||||
|
|
||||||
if (*fname == '\0') /* eh...punt if it's the root dir. */
|
if (sanitizePlatformIndependentPath(_fname, fname))
|
||||||
return(1); /* !!! FIXME: Maybe this should be an error? */
|
|
||||||
|
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
|
||||||
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
|
|
||||||
{
|
{
|
||||||
char *arcfname = fname;
|
if (*fname == '\0') /* eh...punt if it's the root dir. */
|
||||||
fileExists = partOfMountPoint(i, arcfname);
|
retval = 1; /* !!! FIXME: Maybe this should be an error? */
|
||||||
if (fileExists)
|
else
|
||||||
retval = 1; /* !!! FIXME: What's the right value? */
|
{
|
||||||
else if (verifyPath(i, &arcfname, 0))
|
DirHandle *i;
|
||||||
retval = i->funcs->getLastModTime(i->opaque,arcfname,&fileExists);
|
int exists = 0;
|
||||||
} /* for */
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
for (i = searchPath; ((i != NULL) && (!exists)); i = i->next)
|
||||||
|
{
|
||||||
|
char *arcfname = fname;
|
||||||
|
exists = partOfMountPoint(i, arcfname);
|
||||||
|
if (exists)
|
||||||
|
retval = 1; /* !!! FIXME: What's the right value? */
|
||||||
|
else if (verifyPath(i, &arcfname, 0))
|
||||||
|
{
|
||||||
|
retval = i->funcs->getLastModTime(i->opaque, arcfname,
|
||||||
|
&exists);
|
||||||
|
} /* else if */
|
||||||
|
} /* for */
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
} /* else */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
__PHYSFS_smallFree(fname);
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* PHYSFS_getLastModTime */
|
} /* PHYSFS_getLastModTime */
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_isDirectory(const char *_fname)
|
int PHYSFS_isDirectory(const char *_fname)
|
||||||
{
|
{
|
||||||
DirHandle *i;
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
int fileExists = 0;
|
size_t len;
|
||||||
|
char *fname;
|
||||||
|
|
||||||
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);
|
len = strlen(_fname) + 1;
|
||||||
BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
fname = (char *) __PHYSFS_smallAlloc(len);
|
||||||
BAIL_IF_MACRO(*fname == '\0', NULL, 1); /* Root is always a dir. :) */
|
BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||||
|
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
if (!sanitizePlatformIndependentPath(_fname, fname))
|
||||||
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
|
retval = 0;
|
||||||
|
|
||||||
|
else if (*fname == '\0')
|
||||||
|
retval = 1; /* Root is always a dir. :) */
|
||||||
|
|
||||||
|
else
|
||||||
{
|
{
|
||||||
char *arcfname = fname;
|
DirHandle *i;
|
||||||
if ((fileExists = partOfMountPoint(i, arcfname)) != 0)
|
int exists = 0;
|
||||||
retval = 1;
|
|
||||||
else if (verifyPath(i, &arcfname, 0))
|
|
||||||
retval = i->funcs->isDirectory(i->opaque, arcfname, &fileExists);
|
|
||||||
} /* for */
|
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
for (i = searchPath; ((i != NULL) && (!exists)); i = i->next)
|
||||||
|
{
|
||||||
|
char *arcfname = fname;
|
||||||
|
if ((exists = partOfMountPoint(i, arcfname)) != 0)
|
||||||
|
retval = 1;
|
||||||
|
else if (verifyPath(i, &arcfname, 0))
|
||||||
|
retval = i->funcs->isDirectory(i->opaque, arcfname, &exists);
|
||||||
|
} /* for */
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
} /* else */
|
||||||
|
|
||||||
|
__PHYSFS_smallFree(fname);
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* PHYSFS_isDirectory */
|
} /* PHYSFS_isDirectory */
|
||||||
|
|
||||||
|
|
||||||
int PHYSFS_isSymbolicLink(const char *_fname)
|
int PHYSFS_isSymbolicLink(const char *_fname)
|
||||||
{
|
{
|
||||||
DirHandle *i;
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
int fileExists = 0;
|
size_t len;
|
||||||
char *fname;
|
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);
|
len = strlen(_fname) + 1;
|
||||||
BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
fname = (char *) __PHYSFS_smallAlloc(len);
|
||||||
BAIL_IF_MACRO(*fname == '\0', NULL, 0); /* Root is never a symlink */
|
BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||||
|
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
if (!sanitizePlatformIndependentPath(_fname, fname))
|
||||||
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
|
retval = 0;
|
||||||
|
|
||||||
|
else if (*fname == '\0')
|
||||||
|
retval = 1; /* Root is never a symlink. */
|
||||||
|
|
||||||
|
else
|
||||||
{
|
{
|
||||||
char *arcfname = fname;
|
DirHandle *i;
|
||||||
if ((fileExists = partOfMountPoint(i, arcfname)) != 0)
|
int fileExists = 0;
|
||||||
retval = 0; /* virtual dir...not a symlink. */
|
|
||||||
else if (verifyPath(i, &arcfname, 0))
|
|
||||||
retval = i->funcs->isSymLink(i->opaque, arcfname, &fileExists);
|
|
||||||
} /* for */
|
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
|
||||||
|
{
|
||||||
|
char *arcfname = fname;
|
||||||
|
if ((fileExists = partOfMountPoint(i, arcfname)) != 0)
|
||||||
|
retval = 0; /* virtual dir...not a symlink. */
|
||||||
|
else if (verifyPath(i, &arcfname, 0))
|
||||||
|
retval = i->funcs->isSymLink(i->opaque, arcfname, &fileExists);
|
||||||
|
} /* for */
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
|
} /* else */
|
||||||
|
|
||||||
|
__PHYSFS_smallFree(fname);
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* 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;
|
|
||||||
FileHandle *fh = NULL;
|
FileHandle *fh = NULL;
|
||||||
DirHandle *h = NULL;
|
size_t len;
|
||||||
const PHYSFS_Archiver *f;
|
char *fname;
|
||||||
|
|
||||||
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);
|
len = strlen(_fname) + 1;
|
||||||
BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
fname = (char *) __PHYSFS_smallAlloc(len);
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||||
|
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
if (sanitizePlatformIndependentPath(_fname, fname))
|
||||||
BAIL_IF_MACRO_MUTEX(!writeDir, ERR_NO_WRITE_DIR, stateLock, NULL);
|
|
||||||
|
|
||||||
h = writeDir;
|
|
||||||
BAIL_IF_MACRO_MUTEX(!verifyPath(h, &fname, 0), NULL, stateLock, NULL);
|
|
||||||
|
|
||||||
f = h->funcs;
|
|
||||||
if (appending)
|
|
||||||
opaque = f->openAppend(h->opaque, fname);
|
|
||||||
else
|
|
||||||
opaque = f->openWrite(h->opaque, fname);
|
|
||||||
|
|
||||||
BAIL_IF_MACRO_MUTEX(opaque == NULL, NULL, stateLock, NULL);
|
|
||||||
|
|
||||||
fh = (FileHandle *) allocator.Malloc(sizeof (FileHandle));
|
|
||||||
if (fh == NULL)
|
|
||||||
{
|
{
|
||||||
f->fileClose(opaque);
|
void *opaque = NULL;
|
||||||
BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL);
|
DirHandle *h = NULL;
|
||||||
|
const PHYSFS_Archiver *f;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
|
||||||
|
GOTO_IF_MACRO(!writeDir, ERR_NO_WRITE_DIR, doOpenWriteEnd);
|
||||||
|
|
||||||
|
h = writeDir;
|
||||||
|
GOTO_IF_MACRO(!verifyPath(h, &fname, 0), NULL, doOpenWriteEnd);
|
||||||
|
|
||||||
|
f = h->funcs;
|
||||||
|
if (appending)
|
||||||
|
opaque = f->openAppend(h->opaque, fname);
|
||||||
|
else
|
||||||
|
opaque = f->openWrite(h->opaque, fname);
|
||||||
|
|
||||||
|
GOTO_IF_MACRO(opaque == NULL, NULL, doOpenWriteEnd);
|
||||||
|
|
||||||
|
fh = (FileHandle *) allocator.Malloc(sizeof (FileHandle));
|
||||||
|
if (fh == NULL)
|
||||||
|
{
|
||||||
|
f->fileClose(opaque);
|
||||||
|
GOTO_MACRO(ERR_OUT_OF_MEMORY, doOpenWriteEnd);
|
||||||
|
} /* if */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(fh, '\0', sizeof (FileHandle));
|
||||||
|
fh->opaque = opaque;
|
||||||
|
fh->dirHandle = h;
|
||||||
|
fh->funcs = h->funcs;
|
||||||
|
fh->next = openWriteList;
|
||||||
|
openWriteList = fh;
|
||||||
|
} /* else */
|
||||||
|
|
||||||
|
doOpenWriteEnd:
|
||||||
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
} /* if */
|
} /* if */
|
||||||
else
|
|
||||||
{
|
|
||||||
memset(fh, '\0', sizeof (FileHandle));
|
|
||||||
fh->opaque = opaque;
|
|
||||||
fh->dirHandle = h;
|
|
||||||
fh->funcs = h->funcs;
|
|
||||||
fh->next = openWriteList;
|
|
||||||
openWriteList = fh;
|
|
||||||
} /* else */
|
|
||||||
|
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
__PHYSFS_smallFree(fname);
|
||||||
return((PHYSFS_File *) fh);
|
return((PHYSFS_File *) fh);
|
||||||
} /* doOpenWrite */
|
} /* doOpenWrite */
|
||||||
|
|
||||||
|
@ -1693,51 +1799,62 @@ PHYSFS_File *PHYSFS_openAppend(const char *filename)
|
||||||
PHYSFS_File *PHYSFS_openRead(const char *_fname)
|
PHYSFS_File *PHYSFS_openRead(const char *_fname)
|
||||||
{
|
{
|
||||||
FileHandle *fh = NULL;
|
FileHandle *fh = NULL;
|
||||||
int fileExists = 0;
|
char *fname;
|
||||||
DirHandle *i = NULL;
|
size_t len;
|
||||||
fvoid *opaque = NULL;
|
|
||||||
|
|
||||||
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);
|
len = strlen(_fname) + 1;
|
||||||
BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
|
fname = (char *) __PHYSFS_smallAlloc(len);
|
||||||
|
BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, 0);
|
||||||
|
|
||||||
__PHYSFS_platformGrabMutex(stateLock);
|
if (sanitizePlatformIndependentPath(_fname, fname))
|
||||||
|
|
||||||
BAIL_IF_MACRO_MUTEX(!searchPath, ERR_NO_SUCH_PATH, stateLock, NULL);
|
|
||||||
|
|
||||||
/* !!! FIXME: Why aren't we using a for loop here? */
|
|
||||||
i = searchPath;
|
|
||||||
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
char *arcfname = fname;
|
int fileExists = 0;
|
||||||
if (verifyPath(i, &arcfname, 0))
|
DirHandle *i = NULL;
|
||||||
|
fvoid *opaque = NULL;
|
||||||
|
|
||||||
|
__PHYSFS_platformGrabMutex(stateLock);
|
||||||
|
|
||||||
|
GOTO_IF_MACRO(!searchPath, ERR_NO_SUCH_PATH, openReadEnd);
|
||||||
|
|
||||||
|
/* !!! FIXME: Why aren't we using a for loop here? */
|
||||||
|
i = searchPath;
|
||||||
|
|
||||||
|
do
|
||||||
{
|
{
|
||||||
opaque = i->funcs->openRead(i->opaque, arcfname, &fileExists);
|
char *arcfname = fname;
|
||||||
if (opaque)
|
if (verifyPath(i, &arcfname, 0))
|
||||||
break;
|
{
|
||||||
|
opaque = i->funcs->openRead(i->opaque, arcfname, &fileExists);
|
||||||
|
if (opaque)
|
||||||
|
break;
|
||||||
|
} /* if */
|
||||||
|
i = i->next;
|
||||||
|
} while ((i != NULL) && (!fileExists));
|
||||||
|
|
||||||
|
/* !!! FIXME: may not set an error if openRead didn't fail. */
|
||||||
|
GOTO_IF_MACRO(opaque == NULL, NULL, openReadEnd);
|
||||||
|
|
||||||
|
fh = (FileHandle *) allocator.Malloc(sizeof (FileHandle));
|
||||||
|
if (fh == NULL)
|
||||||
|
{
|
||||||
|
i->funcs->fileClose(opaque);
|
||||||
|
GOTO_MACRO(ERR_OUT_OF_MEMORY, openReadEnd);
|
||||||
} /* if */
|
} /* if */
|
||||||
i = i->next;
|
|
||||||
} while ((i != NULL) && (!fileExists));
|
|
||||||
|
|
||||||
BAIL_IF_MACRO_MUTEX(opaque == NULL, NULL, stateLock, NULL);
|
memset(fh, '\0', sizeof (FileHandle));
|
||||||
|
fh->opaque = opaque;
|
||||||
|
fh->forReading = 1;
|
||||||
|
fh->dirHandle = i;
|
||||||
|
fh->funcs = i->funcs;
|
||||||
|
fh->next = openReadList;
|
||||||
|
openReadList = fh;
|
||||||
|
|
||||||
fh = (FileHandle *) allocator.Malloc(sizeof (FileHandle));
|
openReadEnd:
|
||||||
if (fh == NULL)
|
__PHYSFS_platformReleaseMutex(stateLock);
|
||||||
{
|
|
||||||
i->funcs->fileClose(opaque);
|
|
||||||
BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL);
|
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
memset(fh, '\0', sizeof (FileHandle));
|
__PHYSFS_smallFree(fname);
|
||||||
fh->opaque = opaque;
|
|
||||||
fh->forReading = 1;
|
|
||||||
fh->dirHandle = i;
|
|
||||||
fh->funcs = i->funcs;
|
|
||||||
fh->next = openReadList;
|
|
||||||
openReadList = fh;
|
|
||||||
__PHYSFS_platformReleaseMutex(stateLock);
|
|
||||||
|
|
||||||
return((PHYSFS_File *) fh);
|
return((PHYSFS_File *) fh);
|
||||||
} /* PHYSFS_openRead */
|
} /* PHYSFS_openRead */
|
||||||
|
|
||||||
|
@ -2055,5 +2172,37 @@ static void setDefaultAllocator(void)
|
||||||
} /* if */
|
} /* if */
|
||||||
} /* setDefaultAllocator */
|
} /* setDefaultAllocator */
|
||||||
|
|
||||||
|
|
||||||
|
void *__PHYSFS_initSmallAlloc(void *ptr, PHYSFS_uint64 len)
|
||||||
|
{
|
||||||
|
const char useHeap = ((ptr == NULL) ? 1 : 0);
|
||||||
|
if (useHeap) /* too large for stack allocation or alloca() failed. */
|
||||||
|
ptr = allocator.Malloc(len+1);
|
||||||
|
|
||||||
|
if (ptr != NULL)
|
||||||
|
{
|
||||||
|
char *retval = (char *) ptr;
|
||||||
|
/*printf("%s alloc'd (%d) bytes at (%p).\n",
|
||||||
|
useHeap ? "heap" : "stack", (int) len, ptr);*/
|
||||||
|
*retval = useHeap;
|
||||||
|
return(retval+1);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
return(NULL); /* allocation failed. */
|
||||||
|
} /* __PHYSFS_initSmallAlloc */
|
||||||
|
|
||||||
|
|
||||||
|
void __PHYSFS_smallFree(void *ptr)
|
||||||
|
{
|
||||||
|
if (ptr != NULL)
|
||||||
|
{
|
||||||
|
char *block = ((char *) ptr) - 1;
|
||||||
|
const char useHeap = *block;
|
||||||
|
if (useHeap)
|
||||||
|
allocator.Free(block);
|
||||||
|
/*printf("%s free'd (%p).\n", useHeap ? "heap" : "stack", block);*/
|
||||||
|
} /* if */
|
||||||
|
} /* __PHYSFS_smallFree */
|
||||||
|
|
||||||
/* end of physfs.c ... */
|
/* end of physfs.c ... */
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,38 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interface for small allocations. If you need a little scratch space for
|
||||||
|
* a throwaway buffer or string, use this. It will make small allocations
|
||||||
|
* on the stack if possible, and use allocator.Malloc() if they are too
|
||||||
|
* large. This helps reduce malloc pressure.
|
||||||
|
* There are some rules, though:
|
||||||
|
* NEVER return a pointer from this, as stack-allocated buffers go away
|
||||||
|
* when your function returns.
|
||||||
|
* NEVER allocate in a loop, as stack-allocated pointers will pile up. Call
|
||||||
|
* a function that uses smallAlloc from your loop, so the allocation can
|
||||||
|
* free each time.
|
||||||
|
* NEVER call smallAlloc with any complex expression (it's a macro that WILL
|
||||||
|
* have side effects...it references the argument multiple times). Use a
|
||||||
|
* variable or a literal.
|
||||||
|
* NEVER free a pointer from this with anything but smallFree. It will not
|
||||||
|
* be a valid pointer to the allocator, regardless of where the memory came
|
||||||
|
* from.
|
||||||
|
* NEVER realloc a pointer from this.
|
||||||
|
* NEVER forget to use smallFree: it may not be a pointer from the stack.
|
||||||
|
* NEVER forget to check for NULL...allocation can fail here, of course!
|
||||||
|
*/
|
||||||
|
#define __PHYSFS_SMALLALLOCTHRESHOLD 128
|
||||||
|
void *__PHYSFS_initSmallAlloc(void *ptr, PHYSFS_uint64 len);
|
||||||
|
|
||||||
|
#define __PHYSFS_smallAlloc(bytes) ( \
|
||||||
|
__PHYSFS_initSmallAlloc(((bytes < __PHYSFS_SMALLALLOCTHRESHOLD) ? \
|
||||||
|
alloca(bytes+1) : NULL), bytes) \
|
||||||
|
)
|
||||||
|
|
||||||
|
void __PHYSFS_smallFree(void *ptr);
|
||||||
|
|
||||||
|
|
||||||
/* Use the allocation hooks. */
|
/* Use the allocation hooks. */
|
||||||
#define malloc(x) Do not use malloc() directly.
|
#define malloc(x) Do not use malloc() directly.
|
||||||
#define realloc(x, y) Do not use realloc() directly.
|
#define realloc(x, y) Do not use realloc() directly.
|
||||||
|
|
|
@ -64,12 +64,14 @@ static const char *win32strerror(void)
|
||||||
return((const char *) msgbuf);
|
return((const char *) msgbuf);
|
||||||
} /* win32strerror */
|
} /* win32strerror */
|
||||||
|
|
||||||
|
|
||||||
|
/* !!! FIXME: need to check all of these for NULLs. */
|
||||||
#define UTF8_TO_UNICODE_STACK_MACRO(w_assignto, str) { \
|
#define UTF8_TO_UNICODE_STACK_MACRO(w_assignto, str) { \
|
||||||
if (str == NULL) \
|
if (str == NULL) \
|
||||||
w_assignto = NULL; \
|
w_assignto = NULL; \
|
||||||
else { \
|
else { \
|
||||||
const PHYSFS_uint64 len = (PHYSFS_uint64) ((strlen(str) * 4) + 1); \
|
const PHYSFS_uint64 len = (PHYSFS_uint64) ((strlen(str) * 4) + 1); \
|
||||||
w_assignto = (char *) alloca(len); \
|
w_assignto = (char *) __PHYSFS_smallAlloc(len); \
|
||||||
PHYSFS_uc2fromutf8(str, (PHYSFS_uint16 *) w_assignto, len); \
|
PHYSFS_uc2fromutf8(str, (PHYSFS_uint16 *) w_assignto, len); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
@ -86,6 +88,7 @@ static char *getExePath()
|
||||||
|
|
||||||
retval[0] = _T('\0');
|
retval[0] = _T('\0');
|
||||||
/* !!! FIXME: don't preallocate here? */
|
/* !!! FIXME: don't preallocate here? */
|
||||||
|
/* !!! FIXME: use smallAlloc? */
|
||||||
buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
|
buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
|
||||||
if (buflen <= 0)
|
if (buflen <= 0)
|
||||||
__PHYSFS_setError(win32strerror());
|
__PHYSFS_setError(win32strerror());
|
||||||
|
@ -172,6 +175,7 @@ int __PHYSFS_platformExists(const char *fname)
|
||||||
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
|
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
|
||||||
if (w_fname != NULL)
|
if (w_fname != NULL)
|
||||||
retval = (GetFileAttributes(w_fname) != INVALID_FILE_ATTRIBUTES);
|
retval = (GetFileAttributes(w_fname) != INVALID_FILE_ATTRIBUTES);
|
||||||
|
__PHYSFS_smallFree(w_fname);
|
||||||
|
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* __PHYSFS_platformExists */
|
} /* __PHYSFS_platformExists */
|
||||||
|
@ -191,6 +195,7 @@ int __PHYSFS_platformIsDirectory(const char *fname)
|
||||||
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
|
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
|
||||||
if (w_fname != NULL)
|
if (w_fname != NULL)
|
||||||
retval = ((GetFileAttributes(w_fname) & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
retval = ((GetFileAttributes(w_fname) & FILE_ATTRIBUTE_DIRECTORY) != 0);
|
||||||
|
__PHYSFS_smallFree(w_fname);
|
||||||
|
|
||||||
return(retval);
|
return(retval);
|
||||||
} /* __PHYSFS_platformIsDirectory */
|
} /* __PHYSFS_platformIsDirectory */
|
||||||
|
@ -228,9 +233,10 @@ char *__PHYSFS_platformCvtToDependent(const char *prepend,
|
||||||
static int doEnumCallback(const wchar_t *w_fname)
|
static int doEnumCallback(const wchar_t *w_fname)
|
||||||
{
|
{
|
||||||
const PHYSFS_uint64 len = (PHYSFS_uint64) ((wcslen(w_fname) * 4) + 1);
|
const PHYSFS_uint64 len = (PHYSFS_uint64) ((wcslen(w_fname) * 4) + 1);
|
||||||
char *str = (char *) alloca(len);
|
char *str = (char *) __PHYSFS_smallAlloc(len);
|
||||||
PHYSFS_utf8fromucs2((const PHYSFS_uint16 *) w_fname, str, len);
|
PHYSFS_utf8fromucs2((const PHYSFS_uint16 *) w_fname, str, len);
|
||||||
callback(callbackdata, origdir, str);
|
callback(callbackdata, origdir, str);
|
||||||
|
__PHYSFS_smallFree(str);
|
||||||
return 1;
|
return 1;
|
||||||
} /* doEnumCallback */
|
} /* doEnumCallback */
|
||||||
|
|
||||||
|
@ -248,7 +254,7 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||||
size_t len = strlen(dirname);
|
size_t len = strlen(dirname);
|
||||||
|
|
||||||
/* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
|
/* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
|
||||||
SearchPath = (char *) alloca(len + 3);
|
SearchPath = (char *) __PHYSFS_smallAlloc(len + 3);
|
||||||
BAIL_IF_MACRO(SearchPath == NULL, ERR_OUT_OF_MEMORY, NULL);
|
BAIL_IF_MACRO(SearchPath == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||||
|
|
||||||
/* Copy current dirname */
|
/* Copy current dirname */
|
||||||
|
@ -265,7 +271,9 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||||
strcat(SearchPath, "*");
|
strcat(SearchPath, "*");
|
||||||
|
|
||||||
UTF8_TO_UNICODE_STACK_MACRO(w_SearchPath, SearchPath);
|
UTF8_TO_UNICODE_STACK_MACRO(w_SearchPath, SearchPath);
|
||||||
|
__PHYSFS_smallFree(SearchPath);
|
||||||
dir = FindFirstFile(w_SearchPath, &ent);
|
dir = FindFirstFile(w_SearchPath, &ent);
|
||||||
|
__PHYSFS_smallFree(w_SearchPath);
|
||||||
|
|
||||||
if (dir == INVALID_HANDLE_VALUE)
|
if (dir == INVALID_HANDLE_VALUE)
|
||||||
return;
|
return;
|
||||||
|
@ -304,9 +312,15 @@ char *__PHYSFS_platformRealPath(const char *path)
|
||||||
|
|
||||||
int __PHYSFS_platformMkDir(const char *path)
|
int __PHYSFS_platformMkDir(const char *path)
|
||||||
{
|
{
|
||||||
|
int retval = 0;
|
||||||
wchar_t *w_path = NULL;
|
wchar_t *w_path = NULL;
|
||||||
UTF8_TO_UNICODE_STACK_MACRO(w_path, path);
|
UTF8_TO_UNICODE_STACK_MACRO(w_path, path);
|
||||||
return ( (w_path != NULL) && (CreateDirectory(w_path, NULL)) );
|
if (w_path != NULL)
|
||||||
|
{
|
||||||
|
retval = CreateDirectory(w_path, NULL);
|
||||||
|
__PHYSFS_smallFree(w_fname);
|
||||||
|
} /* if */
|
||||||
|
return(retval);
|
||||||
} /* __PHYSFS_platformMkDir */
|
} /* __PHYSFS_platformMkDir */
|
||||||
|
|
||||||
|
|
||||||
|
@ -317,9 +331,9 @@ static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly)
|
||||||
wchar_t *w_fname = NULL;
|
wchar_t *w_fname = NULL;
|
||||||
|
|
||||||
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
|
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
|
||||||
|
|
||||||
fileHandle = CreateFile(w_fname, mode, FILE_SHARE_READ, NULL,
|
fileHandle = CreateFile(w_fname, mode, FILE_SHARE_READ, NULL,
|
||||||
creation, FILE_ATTRIBUTE_NORMAL, NULL);
|
creation, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
__PHYSFS_smallFree(w_fname);
|
||||||
|
|
||||||
BAIL_IF_MACRO(fileHandle == INVALID_HANDLE_VALUE, win32strerror(), NULL);
|
BAIL_IF_MACRO(fileHandle == INVALID_HANDLE_VALUE, win32strerror(), NULL);
|
||||||
|
|
||||||
|
@ -533,11 +547,13 @@ int __PHYSFS_platformDelete(const char *path)
|
||||||
if (GetFileAttributes(w_path) == FILE_ATTRIBUTE_DIRECTORY)
|
if (GetFileAttributes(w_path) == FILE_ATTRIBUTE_DIRECTORY)
|
||||||
{
|
{
|
||||||
int retval = !RemoveDirectory(w_path);
|
int retval = !RemoveDirectory(w_path);
|
||||||
|
__PHYSFS_smallFree(w_path);
|
||||||
BAIL_IF_MACRO(retval, win32strerror(), 0);
|
BAIL_IF_MACRO(retval, win32strerror(), 0);
|
||||||
} /* if */
|
} /* if */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int retval = !DeleteFile(w_path);
|
int retval = !DeleteFile(w_path);
|
||||||
|
__PHYSFS_smallFree(w_path);
|
||||||
BAIL_IF_MACRO(retval, win32strerror(), 0);
|
BAIL_IF_MACRO(retval, win32strerror(), 0);
|
||||||
} /* else */
|
} /* else */
|
||||||
|
|
||||||
|
|
|
@ -186,8 +186,7 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||||
dir = opendir(dirname);
|
dir = opendir(dirname);
|
||||||
if (dir == NULL)
|
if (dir == NULL)
|
||||||
{
|
{
|
||||||
if (buf != NULL)
|
allocator.Free(buf);
|
||||||
allocator.Free(buf);
|
|
||||||
return;
|
return;
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
||||||
|
@ -220,9 +219,7 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||||
callback(callbackdata, origdir, ent->d_name);
|
callback(callbackdata, origdir, ent->d_name);
|
||||||
} /* while */
|
} /* while */
|
||||||
|
|
||||||
if (buf != NULL)
|
allocator.Free(buf);
|
||||||
allocator.Free(buf);
|
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
} /* __PHYSFS_platformEnumerateFiles */
|
} /* __PHYSFS_platformEnumerateFiles */
|
||||||
|
|
||||||
|
|
|
@ -21,14 +21,6 @@
|
||||||
|
|
||||||
#include "physfs_internal.h"
|
#include "physfs_internal.h"
|
||||||
|
|
||||||
#if (!defined alloca)
|
|
||||||
#if ((defined _MSC_VER)
|
|
||||||
#define alloca(x) _alloca(x)
|
|
||||||
#elif (defined __MINGW32__) /* scary...hopefully this is okay. */
|
|
||||||
#define alloca(x) __builtin_alloca(x)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LOWORDER_UINT64(pos) (PHYSFS_uint32) \
|
#define LOWORDER_UINT64(pos) (PHYSFS_uint32) \
|
||||||
(pos & 0x00000000FFFFFFFF)
|
(pos & 0x00000000FFFFFFFF)
|
||||||
#define HIGHORDER_UINT64(pos) (PHYSFS_uint32) \
|
#define HIGHORDER_UINT64(pos) (PHYSFS_uint32) \
|
||||||
|
@ -116,6 +108,8 @@ static char *getExePath(const char *argv0)
|
||||||
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
|
||||||
|
|
||||||
retval[0] = '\0';
|
retval[0] = '\0';
|
||||||
|
/* !!! FIXME: don't preallocate here? */
|
||||||
|
/* !!! FIXME: use smallAlloc? */
|
||||||
buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
|
buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
|
||||||
if (buflen <= 0)
|
if (buflen <= 0)
|
||||||
__PHYSFS_setError(win32strerror());
|
__PHYSFS_setError(win32strerror());
|
||||||
|
@ -390,7 +384,7 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||||
char *SearchPath;
|
char *SearchPath;
|
||||||
|
|
||||||
/* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
|
/* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
|
||||||
SearchPath = (char *) alloca(len + 3);
|
SearchPath = (char *) __PHYSFS_smallAlloc(len + 3);
|
||||||
if (SearchPath == NULL)
|
if (SearchPath == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -408,6 +402,7 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
|
||||||
strcat(SearchPath, "*");
|
strcat(SearchPath, "*");
|
||||||
|
|
||||||
dir = FindFirstFile(SearchPath, &ent);
|
dir = FindFirstFile(SearchPath, &ent);
|
||||||
|
__PHYSFS_smallFree(SearchPath);
|
||||||
if (dir == INVALID_HANDLE_VALUE)
|
if (dir == INVALID_HANDLE_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue