r864 - in trunk: . archivers platform
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Fri Mar 23 23:54:59 EDT 2007
Author: icculus
Date: 2007-03-23 23:54:58 -0400 (Fri, 23 Mar 2007)
New Revision: 864
Modified:
trunk/CHANGELOG.txt
trunk/archivers/lzma.c
trunk/archivers/qpak.c
trunk/archivers/zip.c
trunk/physfs.c
trunk/physfs_internal.h
trunk/platform/pocketpc.c
trunk/platform/posix.c
trunk/platform/windows.c
Log:
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).
Modified: trunk/CHANGELOG.txt
===================================================================
--- trunk/CHANGELOG.txt 2007-03-21 20:19:20 UTC (rev 863)
+++ trunk/CHANGELOG.txt 2007-03-24 03:54:58 UTC (rev 864)
@@ -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
Modified: trunk/archivers/lzma.c
===================================================================
--- trunk/archivers/lzma.c 2007-03-21 20:19:20 UTC (rev 863)
+++ trunk/archivers/lzma.c 2007-03-24 03:54:58 UTC (rev 864)
@@ -479,13 +479,14 @@
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 */
Modified: trunk/archivers/qpak.c
===================================================================
--- trunk/archivers/qpak.c 2007-03-21 20:19:20 UTC (rev 863)
+++ trunk/archivers/qpak.c 2007-03-24 03:54:58 UTC (rev 864)
@@ -378,13 +378,14 @@
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 */
Modified: trunk/archivers/zip.c
===================================================================
--- trunk/archivers/zip.c 2007-03-21 20:19:20 UTC (rev 863)
+++ trunk/archivers/zip.c 2007-03-24 03:54:58 UTC (rev 864)
@@ -682,15 +682,15 @@
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 @@
rc = ((rc == Z_OK) || (rc == Z_STREAM_END));
} /* if */
} /* if */
- allocator.Free(compressed);
+ __PHYSFS_smallFree(compressed);
} /* if */
} /* else */
@@ -1177,13 +1177,14 @@
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 */
Modified: trunk/physfs.c
===================================================================
--- trunk/physfs.c 2007-03-21 20:19:20 UTC (rev 863)
+++ trunk/physfs.c 2007-03-24 03:54:58 UTC (rev 864)
@@ -538,15 +538,17 @@
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 @@
strcat(dirHandle->mountPoint, "/");
} /* if */
+ __PHYSFS_smallFree(tmpmntpnt);
return(dirHandle);
badDirHandle:
@@ -575,6 +578,7 @@
allocator.Free(dirHandle);
} /* if */
+ __PHYSFS_smallFree(tmpmntpnt);
return(NULL);
} /* createDirHandle */
@@ -620,8 +624,7 @@
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 @@
} /* 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 @@
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 @@
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 @@
{
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 @@
} /* 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 @@
__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 @@
__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 @@
/*
- * 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 @@
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);
+ if (sanitizePlatformIndependentPath(_fname, fname))
+ {
+ void *opaque = NULL;
+ DirHandle *h = NULL;
+ const PHYSFS_Archiver *f;
- h = writeDir;
- BAIL_IF_MACRO_MUTEX(!verifyPath(h, &fname, 0), NULL, stateLock, NULL);
+ __PHYSFS_platformGrabMutex(stateLock);
- f = h->funcs;
- if (appending)
- opaque = f->openAppend(h->opaque, fname);
- else
- opaque = f->openWrite(h->opaque, fname);
+ GOTO_IF_MACRO(!writeDir, ERR_NO_WRITE_DIR, doOpenWriteEnd);
- BAIL_IF_MACRO_MUTEX(opaque == NULL, NULL, stateLock, NULL);
+ h = writeDir;
+ GOTO_IF_MACRO(!verifyPath(h, &fname, 0), NULL, doOpenWriteEnd);
- fh = (FileHandle *) allocator.Malloc(sizeof (FileHandle));
- if (fh == NULL)
- {
- f->fileClose(opaque);
- BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL);
+ 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_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);
+ if (sanitizePlatformIndependentPath(_fname, fname))
+ {
+ int fileExists = 0;
+ DirHandle *i = NULL;
+ fvoid *opaque = NULL;
- BAIL_IF_MACRO_MUTEX(!searchPath, ERR_NO_SUCH_PATH, stateLock, NULL);
+ __PHYSFS_platformGrabMutex(stateLock);
- /* !!! FIXME: Why aren't we using a for loop here? */
- i = searchPath;
+ GOTO_IF_MACRO(!searchPath, ERR_NO_SUCH_PATH, openReadEnd);
- do
- {
- char *arcfname = fname;
- if (verifyPath(i, &arcfname, 0))
+ /* !!! 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 @@
} /* 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 ... */
Modified: trunk/physfs_internal.h
===================================================================
--- trunk/physfs_internal.h 2007-03-21 20:19:20 UTC (rev 863)
+++ trunk/physfs_internal.h 2007-03-24 03:54:58 UTC (rev 864)
@@ -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.
Modified: trunk/platform/pocketpc.c
===================================================================
--- trunk/platform/pocketpc.c 2007-03-21 20:19:20 UTC (rev 863)
+++ trunk/platform/pocketpc.c 2007-03-24 03:54:58 UTC (rev 864)
@@ -64,12 +64,14 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 */
Modified: trunk/platform/posix.c
===================================================================
--- trunk/platform/posix.c 2007-03-21 20:19:20 UTC (rev 863)
+++ trunk/platform/posix.c 2007-03-24 03:54:58 UTC (rev 864)
@@ -186,8 +186,7 @@
dir = opendir(dirname);
if (dir == NULL)
{
- if (buf != NULL)
- allocator.Free(buf);
+ allocator.Free(buf);
return;
} /* if */
@@ -220,9 +219,7 @@
callback(callbackdata, origdir, ent->d_name);
} /* while */
- if (buf != NULL)
- allocator.Free(buf);
-
+ allocator.Free(buf);
closedir(dir);
} /* __PHYSFS_platformEnumerateFiles */
Modified: trunk/platform/windows.c
===================================================================
--- trunk/platform/windows.c 2007-03-21 20:19:20 UTC (rev 863)
+++ trunk/platform/windows.c 2007-03-24 03:54:58 UTC (rev 864)
@@ -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 @@
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 @@
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 @@
strcat(SearchPath, "*");
dir = FindFirstFile(SearchPath, &ent);
+ __PHYSFS_smallFree(SearchPath);
if (dir == INVALID_HANDLE_VALUE)
return;
More information about the physfs-commits
mailing list