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:
Ryan C. Gordon 2007-03-24 03:54:58 +00:00
parent 80ec45d88a
commit 7386320811
9 changed files with 417 additions and 213 deletions

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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
View File

@ -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 ... */

View File

@ -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.

View File

@ -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 */

View File

@ -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 */

View File

@ -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;