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.
*/
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 ...
03202007 - Removed platform/skeleton.c (it was out of date), added
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,
const char *odir, const char *str, PHYSFS_sint32 ln)
{
char *newstr = alloca(ln + 1);
char *newstr = __PHYSFS_smallAlloc(ln + 1);
if (newstr == NULL)
return;
memcpy(newstr, str, ln);
newstr[ln] = '\0';
cb(callbackdata, odir, newstr);
__PHYSFS_smallFree(newstr);
} /* 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,
const char *odir, const char *str, PHYSFS_sint32 ln)
{
char *newstr = alloca(ln + 1);
char *newstr = __PHYSFS_smallAlloc(ln + 1);
if (newstr == NULL)
return;
memcpy(newstr, str, ln);
newstr[ln] = '\0';
cb(callbackdata, odir, newstr);
__PHYSFS_smallFree(newstr);
} /* doEnumCallback */

View File

@ -682,15 +682,15 @@ static int zip_resolve_symlink(void *in, ZIPinfo *info, ZIPentry *entry)
else /* symlink target path is compressed... */
{
z_stream stream;
PHYSFS_uint32 compsize = entry->compressed_size;
PHYSFS_uint8 *compressed = (PHYSFS_uint8 *) allocator.Malloc(compsize);
PHYSFS_uint32 complen = entry->compressed_size;
PHYSFS_uint8 *compressed = (PHYSFS_uint8*) __PHYSFS_smallAlloc(complen);
if (compressed != NULL)
{
if (__PHYSFS_platformRead(in, compressed, compsize, 1) == 1)
if (__PHYSFS_platformRead(in, compressed, complen, 1) == 1)
{
initializeZStream(&stream);
stream.next_in = compressed;
stream.avail_in = compsize;
stream.avail_in = complen;
stream.next_out = (unsigned char *) path;
stream.avail_out = size;
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));
} /* if */
} /* if */
allocator.Free(compressed);
__PHYSFS_smallFree(compressed);
} /* if */
} /* 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,
const char *odir, const char *str, PHYSFS_sint32 ln)
{
char *newstr = alloca(ln + 1);
char *newstr = __PHYSFS_smallAlloc(ln + 1);
if (newstr == NULL)
return;
memcpy(newstr, str, ln);
newstr[ln] = '\0';
cb(callbackdata, odir, newstr);
__PHYSFS_smallFree(newstr);
} /* doEnumCallback */

521
physfs.c
View File

@ -538,15 +538,17 @@ static DirHandle *createDirHandle(const char *newDir,
int forWriting)
{
DirHandle *dirHandle = NULL;
char *tmpmntpnt = NULL;
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))
const size_t len = strlen(mountPoint) + 1;
tmpmntpnt = (char *) __PHYSFS_smallAlloc(len);
GOTO_IF_MACRO(!tmpmntpnt, ERR_OUT_OF_MEMORY, badDirHandle);
if (!sanitizePlatformIndependentPath(mountPoint, tmpmntpnt))
goto badDirHandle;
mountPoint = mntpnt; /* sanitized version. */
mountPoint = tmpmntpnt; /* sanitized version. */
} /* if */
dirHandle = openDirectory(newDir, forWriting);
@ -564,6 +566,7 @@ static DirHandle *createDirHandle(const char *newDir,
strcat(dirHandle->mountPoint, "/");
} /* if */
__PHYSFS_smallFree(tmpmntpnt);
return(dirHandle);
badDirHandle:
@ -575,6 +578,7 @@ badDirHandle:
allocator.Free(dirHandle);
} /* if */
__PHYSFS_smallFree(tmpmntpnt);
return(NULL);
} /* createDirHandle */
@ -620,8 +624,7 @@ static char *calculateUserDir(void)
else
sprintf(retval, "%susers%s%s", baseDir, dirsep, str);
if (uname != NULL)
allocator.Free((void *) uname);
allocator.Free((void *) uname);
} /* else */
return(retval);
@ -1053,6 +1056,22 @@ void PHYSFS_getSearchPathCallback(PHYSFS_StringCallback callback, void *data)
} /* 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,
const char *archiveExt, int includeCdRoms,
int archivesFirst)
@ -1060,15 +1079,17 @@ int PHYSFS_setSaneConfig(const char *organization, const char *appName,
const char *basedir = PHYSFS_getBaseDir();
const char *userdir = PHYSFS_getUserDir();
const char *dirsep = PHYSFS_getDirSeparator();
char *str;
PHYSFS_uint64 len = 0;
char *str = NULL;
BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
/* set write dir... */
str = (char *) allocator.Malloc(
strlen(userdir) + (strlen(organization) * 2) +
len = (strlen(userdir) + (strlen(organization) * 2) +
(strlen(appName) * 2) + (strlen(dirsep) * 3) + 2);
str = (char *) __PHYSFS_smallAlloc(len);
BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
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)
{
PHYSFS_setWriteDir(NULL); /* just in case. */
allocator.Free(str);
__PHYSFS_smallFree(str);
BAIL_MACRO(ERR_CANT_SET_WRITE_DIR, 0);
} /* if */
} /* if */
/* Put write dir first in search path... */
PHYSFS_addToSearchPath(str, 0);
allocator.Free(str);
__PHYSFS_smallFree(str);
/* Put base path on search path... */
PHYSFS_addToSearchPath(basedir, 1);
@ -1129,17 +1150,7 @@ int PHYSFS_setSaneConfig(const char *organization, const char *appName,
{
ext = (*i) + (l - extlen);
if (__PHYSFS_stricmpASCII(ext, archiveExt) == 0)
{
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 */
setSaneCfgAddPath(*i, l, dirsep, archivesFirst);
} /* if */
} /* for */
@ -1315,17 +1326,14 @@ static int verifyPath(DirHandle *h, char **_fname, int allowMissing)
} /* verifyPath */
int PHYSFS_mkdir(const char *_dname)
static int doMkdir(const char *_dname, char *dname)
{
DirHandle *h;
char *start;
char *end;
int retval = 0;
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);
__PHYSFS_platformGrabMutex(stateLock);
@ -1359,16 +1367,29 @@ int PHYSFS_mkdir(const char *_dname)
__PHYSFS_platformReleaseMutex(stateLock);
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 */
int PHYSFS_delete(const char *_fname)
static int doDelete(const char *_fname, char *fname)
{
int retval;
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);
__PHYSFS_platformGrabMutex(stateLock);
@ -1380,32 +1401,54 @@ int PHYSFS_delete(const char *_fname)
__PHYSFS_platformReleaseMutex(stateLock);
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 */
const char *PHYSFS_getRealDir(const char *_fname)
{
DirHandle *i;
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(!sanitizePlatformIndependentPath(_fname, fname), NULL, NULL);
__PHYSFS_platformGrabMutex(stateLock);
for (i = searchPath; ((i != NULL) && (retval == NULL)); i = i->next)
BAIL_IF_MACRO(_fname == NULL, ERR_INVALID_ARGUMENT, NULL);
len = strlen(_fname) + 1;
fname = __PHYSFS_smallAlloc(len);
BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, NULL);
if (sanitizePlatformIndependentPath(_fname, fname))
{
char *arcfname = fname;
if (partOfMountPoint(i, arcfname))
retval = i->dirName;
else if (verifyPath(i, &arcfname, 0))
DirHandle *i;
__PHYSFS_platformGrabMutex(stateLock);
for (i = searchPath; ((i != NULL) && (retval == NULL)); i = i->next)
{
if (i->funcs->exists(i->opaque, arcfname))
char *arcfname = fname;
if (partOfMountPoint(i, arcfname))
retval = i->dirName;
} /* if */
} /* for */
__PHYSFS_platformReleaseMutex(stateLock);
else if (verifyPath(i, &arcfname, 0))
{
if (i->funcs->exists(i->opaque, arcfname))
retval = i->dirName;
} /* if */
} /* for */
__PHYSFS_platformReleaseMutex(stateLock);
} /* if */
__PHYSFS_smallFree(fname);
return(retval);
} /* 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,
PHYSFS_EnumFilesCallback callback,
const char *_fname, void *data)
{
size_t len = strlen(arcfname);
const size_t len = strlen(arcfname);
char *ptr = 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);
ptr = mountPoint + ((len) ? len + 1 : 0);
end = strchr(ptr, '/');
assert(end); /* should always find a terminating '/'. */
*end = '\0';
callback(data, _fname, ptr);
__PHYSFS_smallFree(mountPoint);
} /* enumerateFromMountPoint */
/* !!! FIXME: this should report error conditions. */
void PHYSFS_enumerateFilesCallback(const char *_fname,
PHYSFS_EnumFilesCallback callback,
void *data)
{
DirHandle *i;
int noSyms;
char *fname = ((_fname) ? (char *) alloca(strlen(_fname) + 1) : NULL);
if ((fname == NULL) || (callback == NULL))
return; /* oh well. */
size_t len;
char *fname;
if (!sanitizePlatformIndependentPath(_fname, fname))
return;
BAIL_IF_MACRO(_fname == NULL, ERR_INVALID_ARGUMENT, /*0*/);
BAIL_IF_MACRO(callback == NULL, ERR_INVALID_ARGUMENT, /*0*/);
__PHYSFS_platformGrabMutex(stateLock);
noSyms = !allowSymLinks;
for (i = searchPath; i != NULL; i = i->next)
len = strlen(_fname) + 1;
fname = (char *) __PHYSFS_smallAlloc(len);
BAIL_IF_MACRO(fname == NULL, ERR_OUT_OF_MEMORY, /*0*/);
if (sanitizePlatformIndependentPath(_fname, fname))
{
char *arcfname = fname;
if (partOfMountPoint(i, arcfname))
enumerateFromMountPoint(i, arcfname, callback, _fname, data);
DirHandle *i;
int noSyms;
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,
callback, _fname, data);
} /* else if */
} /* for */
__PHYSFS_platformReleaseMutex(stateLock);
char *arcfname = fname;
if (partOfMountPoint(i, arcfname))
enumerateFromMountPoint(i, arcfname, callback, _fname, data);
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 */
@ -1550,130 +1608,178 @@ int PHYSFS_exists(const char *fname)
PHYSFS_sint64 PHYSFS_getLastModTime(const char *_fname)
{
DirHandle *i;
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, 0);
BAIL_IF_MACRO(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
BAIL_IF_MACRO(_fname == NULL, ERR_INVALID_ARGUMENT, -1);
len = strlen(_fname) + 1;
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. */
return(1); /* !!! FIXME: Maybe this should be an error? */
__PHYSFS_platformGrabMutex(stateLock);
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
if (sanitizePlatformIndependentPath(_fname, fname))
{
char *arcfname = fname;
fileExists = partOfMountPoint(i, arcfname);
if (fileExists)
retval = 1; /* !!! FIXME: What's the right value? */
else if (verifyPath(i, &arcfname, 0))
retval = i->funcs->getLastModTime(i->opaque,arcfname,&fileExists);
} /* for */
__PHYSFS_platformReleaseMutex(stateLock);
if (*fname == '\0') /* eh...punt if it's the root dir. */
retval = 1; /* !!! FIXME: Maybe this should be an error? */
else
{
DirHandle *i;
int exists = 0;
__PHYSFS_platformGrabMutex(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);
} /* PHYSFS_getLastModTime */
int PHYSFS_isDirectory(const char *_fname)
{
DirHandle *i;
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(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
BAIL_IF_MACRO(*fname == '\0', NULL, 1); /* Root is always a dir. :) */
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);
__PHYSFS_platformGrabMutex(stateLock);
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
if (!sanitizePlatformIndependentPath(_fname, fname))
retval = 0;
else if (*fname == '\0')
retval = 1; /* Root is always a dir. :) */
else
{
char *arcfname = fname;
if ((fileExists = partOfMountPoint(i, arcfname)) != 0)
retval = 1;
else if (verifyPath(i, &arcfname, 0))
retval = i->funcs->isDirectory(i->opaque, arcfname, &fileExists);
} /* for */
__PHYSFS_platformReleaseMutex(stateLock);
DirHandle *i;
int exists = 0;
__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);
} /* PHYSFS_isDirectory */
int PHYSFS_isSymbolicLink(const char *_fname)
{
DirHandle *i;
int retval = 0;
int fileExists = 0;
size_t len;
char *fname;
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(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
BAIL_IF_MACRO(*fname == '\0', NULL, 0); /* Root is never a symlink */
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);
__PHYSFS_platformGrabMutex(stateLock);
for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
if (!sanitizePlatformIndependentPath(_fname, fname))
retval = 0;
else if (*fname == '\0')
retval = 1; /* Root is never a symlink. */
else
{
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);
DirHandle *i;
int fileExists = 0;
__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);
} /* PHYSFS_isSymbolicLink */
static PHYSFS_File *doOpenWrite(const char *_fname, int appending)
{
void *opaque = NULL;
FileHandle *fh = NULL;
DirHandle *h = NULL;
const PHYSFS_Archiver *f;
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(!sanitizePlatformIndependentPath(_fname, fname), NULL, 0);
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);
__PHYSFS_platformGrabMutex(stateLock);
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)
if (sanitizePlatformIndependentPath(_fname, fname))
{
f->fileClose(opaque);
BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL);
void *opaque = 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 */
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);
} /* doOpenWrite */
@ -1693,51 +1799,62 @@ PHYSFS_File *PHYSFS_openAppend(const char *filename)
PHYSFS_File *PHYSFS_openRead(const char *_fname)
{
FileHandle *fh = NULL;
int fileExists = 0;
DirHandle *i = NULL;
fvoid *opaque = NULL;
char *fname;
size_t len;
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(_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);
__PHYSFS_platformGrabMutex(stateLock);
BAIL_IF_MACRO_MUTEX(!searchPath, ERR_NO_SUCH_PATH, stateLock, NULL);
/* !!! FIXME: Why aren't we using a for loop here? */
i = searchPath;
do
if (sanitizePlatformIndependentPath(_fname, fname))
{
char *arcfname = fname;
if (verifyPath(i, &arcfname, 0))
int fileExists = 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);
if (opaque)
break;
char *arcfname = fname;
if (verifyPath(i, &arcfname, 0))
{
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 */
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));
if (fh == NULL)
{
i->funcs->fileClose(opaque);
BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL);
openReadEnd:
__PHYSFS_platformReleaseMutex(stateLock);
} /* if */
memset(fh, '\0', sizeof (FileHandle));
fh->opaque = opaque;
fh->forReading = 1;
fh->dirHandle = i;
fh->funcs = i->funcs;
fh->next = openReadList;
openReadList = fh;
__PHYSFS_platformReleaseMutex(stateLock);
__PHYSFS_smallFree(fname);
return((PHYSFS_File *) fh);
} /* PHYSFS_openRead */
@ -2055,5 +2172,37 @@ static void setDefaultAllocator(void)
} /* if */
} /* 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 ... */

View File

@ -33,6 +33,38 @@
extern "C" {
#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. */
#define malloc(x) Do not use malloc() 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);
} /* win32strerror */
/* !!! FIXME: need to check all of these for NULLs. */
#define UTF8_TO_UNICODE_STACK_MACRO(w_assignto, str) { \
if (str == NULL) \
w_assignto = NULL; \
else { \
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); \
} \
} \
@ -86,6 +88,7 @@ static char *getExePath()
retval[0] = _T('\0');
/* !!! FIXME: don't preallocate here? */
/* !!! FIXME: use smallAlloc? */
buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
if (buflen <= 0)
__PHYSFS_setError(win32strerror());
@ -172,6 +175,7 @@ int __PHYSFS_platformExists(const char *fname)
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
if (w_fname != NULL)
retval = (GetFileAttributes(w_fname) != INVALID_FILE_ATTRIBUTES);
__PHYSFS_smallFree(w_fname);
return(retval);
} /* __PHYSFS_platformExists */
@ -191,6 +195,7 @@ int __PHYSFS_platformIsDirectory(const char *fname)
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
if (w_fname != NULL)
retval = ((GetFileAttributes(w_fname) & FILE_ATTRIBUTE_DIRECTORY) != 0);
__PHYSFS_smallFree(w_fname);
return(retval);
} /* __PHYSFS_platformIsDirectory */
@ -228,9 +233,10 @@ char *__PHYSFS_platformCvtToDependent(const char *prepend,
static int doEnumCallback(const wchar_t *w_fname)
{
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);
callback(callbackdata, origdir, str);
__PHYSFS_smallFree(str);
return 1;
} /* doEnumCallback */
@ -248,7 +254,7 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
size_t len = strlen(dirname);
/* 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);
/* Copy current dirname */
@ -265,7 +271,9 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
strcat(SearchPath, "*");
UTF8_TO_UNICODE_STACK_MACRO(w_SearchPath, SearchPath);
__PHYSFS_smallFree(SearchPath);
dir = FindFirstFile(w_SearchPath, &ent);
__PHYSFS_smallFree(w_SearchPath);
if (dir == INVALID_HANDLE_VALUE)
return;
@ -304,9 +312,15 @@ char *__PHYSFS_platformRealPath(const char *path)
int __PHYSFS_platformMkDir(const char *path)
{
int retval = 0;
wchar_t *w_path = NULL;
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 */
@ -317,9 +331,9 @@ static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly)
wchar_t *w_fname = NULL;
UTF8_TO_UNICODE_STACK_MACRO(w_fname, fname);
fileHandle = CreateFile(w_fname, mode, FILE_SHARE_READ, NULL,
creation, FILE_ATTRIBUTE_NORMAL, NULL);
__PHYSFS_smallFree(w_fname);
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)
{
int retval = !RemoveDirectory(w_path);
__PHYSFS_smallFree(w_path);
BAIL_IF_MACRO(retval, win32strerror(), 0);
} /* if */
else
{
int retval = !DeleteFile(w_path);
__PHYSFS_smallFree(w_path);
BAIL_IF_MACRO(retval, win32strerror(), 0);
} /* else */

View File

@ -186,8 +186,7 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
dir = opendir(dirname);
if (dir == NULL)
{
if (buf != NULL)
allocator.Free(buf);
allocator.Free(buf);
return;
} /* if */
@ -220,9 +219,7 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
callback(callbackdata, origdir, ent->d_name);
} /* while */
if (buf != NULL)
allocator.Free(buf);
allocator.Free(buf);
closedir(dir);
} /* __PHYSFS_platformEnumerateFiles */

View File

@ -21,14 +21,6 @@
#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) \
(pos & 0x00000000FFFFFFFF)
#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);
retval[0] = '\0';
/* !!! FIXME: don't preallocate here? */
/* !!! FIXME: use smallAlloc? */
buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1);
if (buflen <= 0)
__PHYSFS_setError(win32strerror());
@ -390,7 +384,7 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
char *SearchPath;
/* Allocate a new string for path, maybe '\\', "*", and NULL terminator */
SearchPath = (char *) alloca(len + 3);
SearchPath = (char *) __PHYSFS_smallAlloc(len + 3);
if (SearchPath == NULL)
return;
@ -408,6 +402,7 @@ void __PHYSFS_platformEnumerateFiles(const char *dirname,
strcat(SearchPath, "*");
dir = FindFirstFile(SearchPath, &ent);
__PHYSFS_smallFree(SearchPath);
if (dir == INVALID_HANDLE_VALUE)
return;