Jelajahi Sumber

Split off sanitizePlatformIndependentPath() from verifySecurity(), which makes
this faster and reduces malloc() pressure. Plus cleanups, and other mount
work.

Ryan C. Gordon 21 tahun lalu
induk
melakukan
67776da8cc
2 mengubah file dengan 123 tambahan dan 75 penghapusan
  1. 121 74
      physfs.c
  2. 2 1
      physfs.h

+ 121 - 74
physfs.c

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

+ 2 - 1
physfs.h

@@ -698,6 +698,7 @@ __EXPORT__ int PHYSFS_setWriteDir(const char *newDir);
  *                   platform-dependent notation.
  *                   platform-dependent notation.
  *   \param mountPoint Location in the interpolated tree that this archive
  *   \param mountPoint Location in the interpolated tree that this archive
  *                     will be "mounted", in platform-independent notation.
  *                     will be "mounted", in platform-independent notation.
+ *                     NULL or "" is equivalent to "/".
  *   \param appendToPath nonzero to append to search path, zero to prepend.
  *   \param appendToPath nonzero to append to search path, zero to prepend.
  *  \return nonzero if added to path, zero on failure (bogus archive, dir
  *  \return nonzero if added to path, zero on failure (bogus archive, dir
  *                   missing, etc). Specifics of the error can be
  *                   missing, etc). Specifics of the error can be
@@ -711,7 +712,7 @@ __EXPORT__ int PHYSFS_mount(const char *newDir, const char *mountPoint, int appe
  * \brief Add an archive or directory to the search path.
  * \brief Add an archive or directory to the search path.
  *
  *
  * This is a legacy call, equivalent to:
  * This is a legacy call, equivalent to:
- *     PHYSFS_mount(newDir, "/", appendToPath);
+ *     PHYSFS_mount(newDir, NULL, appendToPath);
  *
  *
  * \sa PHYSFS_mount
  * \sa PHYSFS_mount
  * \sa PHYSFS_unmount
  * \sa PHYSFS_unmount