Two important PHYSFS_mkdir() fixes (one involving a change to
authorRyan C. Gordon <icculus@icculus.org>
Wed, 19 Mar 2003 06:04:09 +0000
changeset 549 1282b8cbfc0b
parent 548 e4bc305a1d3e
child 550 2116f9dc14bc
Two important PHYSFS_mkdir() fixes (one involving a change to __PHYSFS_verifySecurity()...).
physfs.c
physfs_internal.h
--- a/physfs.c	Wed Mar 19 06:01:41 2003 +0000
+++ b/physfs.c	Wed Mar 19 06:04:09 2003 +0000
@@ -1191,7 +1191,7 @@
 } /* __PHYSFS_convertToDependent */
 
 
-int __PHYSFS_verifySecurity(DirHandle *h, const char *fname)
+int __PHYSFS_verifySecurity(DirHandle *h, const char *fname, int allowMissing)
 {
     int retval = 1;
     char *start;
@@ -1232,7 +1232,7 @@
             } /* if */
 
             /* break out early if path element is missing. */
-            if (!retval)
+            if ((!retval) && (!allowMissing))
             {
                 /*
                  * We need to clear it if it's the last element of the path,
@@ -1272,18 +1272,23 @@
     __PHYSFS_platformGrabMutex(stateLock);
     BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
     h = writeDir->dirHandle;
-    BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, dname), NULL, stateLock, 0);
+    BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h,dname,1),NULL,stateLock,0);
     start = str = malloc(strlen(dname) + 1);
     BAIL_IF_MACRO_MUTEX(str == NULL, ERR_OUT_OF_MEMORY, stateLock, 0);
     strcpy(str, dname);
 
     while (1)
     {
+        int already_exists;
+
         end = strchr(start, '/');
         if (end != NULL)
             *end = '\0';
 
-        retval = h->funcs->mkdir(h, str);
+        retval = h->funcs->isDirectory(h, str, &already_exists);
+        if ((!retval) && (!already_exists))
+            retval = h->funcs->mkdir(h, str);
+
         if (!retval)
             break;
 
@@ -1314,7 +1319,7 @@
 
     BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
     h = writeDir->dirHandle;
-    BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, fname), NULL, stateLock, 0);
+    BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h,fname,0),NULL,stateLock,0);
     retval = h->funcs->remove(h, fname);
 
     __PHYSFS_platformReleaseMutex(stateLock);
@@ -1334,7 +1339,7 @@
     for (i = searchPath; ((i != NULL) && (retval == NULL)); i = i->next)
     {
         DirHandle *h = i->dirHandle;
-        if (__PHYSFS_verifySecurity(h, filename))
+        if (__PHYSFS_verifySecurity(h, filename, 0))
         {
             if (h->funcs->exists(h, filename))
                 retval = i->dirName;
@@ -1451,7 +1456,7 @@
     for (i = searchPath; i != NULL; i = i->next)
     {
         DirHandle *h = i->dirHandle;
-        if (__PHYSFS_verifySecurity(h, path))
+        if (__PHYSFS_verifySecurity(h, path, 0))
         {
             rc = h->funcs->enumerateFiles(h, path, omitSymLinks);
             interpolateStringLists(&finalList, rc);
@@ -1491,7 +1496,7 @@
     for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
     {
         DirHandle *h = i->dirHandle;
-        if (__PHYSFS_verifySecurity(h, fname))
+        if (__PHYSFS_verifySecurity(h, fname, 0))
             retval = h->funcs->getLastModTime(h, fname, &fileExists);
     } /* for */
     __PHYSFS_platformReleaseMutex(stateLock);
@@ -1516,7 +1521,7 @@
     for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
     {
         DirHandle *h = i->dirHandle;
-        if (__PHYSFS_verifySecurity(h, fname))
+        if (__PHYSFS_verifySecurity(h, fname, 0))
             retval = h->funcs->isDirectory(h, fname, &fileExists);
     } /* for */
     __PHYSFS_platformReleaseMutex(stateLock);
@@ -1543,7 +1548,7 @@
     for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
     {
         DirHandle *h = i->dirHandle;
-        if (__PHYSFS_verifySecurity(h, fname))
+        if (__PHYSFS_verifySecurity(h, fname, 0))
             retval = h->funcs->isSymLink(h, fname, &fileExists);
     } /* for */
     __PHYSFS_platformReleaseMutex(stateLock);
@@ -1567,7 +1572,7 @@
     __PHYSFS_platformGrabMutex(stateLock);
     h = (writeDir == NULL) ? NULL : writeDir->dirHandle;
     BAIL_IF_MACRO_MUTEX(!h, ERR_NO_WRITE_DIR, stateLock, NULL);
-    BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, fname), NULL,
+    BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, fname, 0), NULL,
                         stateLock, NULL);
 
     list = (FileHandleList *) malloc(sizeof (FileHandleList));
@@ -1622,7 +1627,7 @@
     for (i = searchPath; ((i != NULL) && (!fileExists)); i = i->next)
     {
         DirHandle *h = i->dirHandle;
-        if (__PHYSFS_verifySecurity(h, fname))
+        if (__PHYSFS_verifySecurity(h, fname, 0))
             rc = h->funcs->openRead(h, fname, &fileExists);
     } /* for */
     BAIL_IF_MACRO_MUTEX(rc == NULL, NULL, stateLock, NULL);
--- a/physfs_internal.h	Wed Mar 19 06:01:41 2003 +0000
+++ b/physfs_internal.h	Wed Mar 19 06:04:09 2003 +0000
@@ -1108,10 +1108,13 @@
  *  for symlinks (if they aren't permitted). Also, elements such as
  *  ".", "..", or ":" are flagged.
  *
+ * With some exceptions (like PHYSFS_mkdir(), which builds multiple subdirs
+ *  at a time), you should always pass zero for "allowMissing" for efficiency.
+ *
  * Returns non-zero if string is safe, zero if there's a security issue.
  *  PHYSFS_getLastError() will specify what was wrong.
  */
-int __PHYSFS_verifySecurity(DirHandle *h, const char *fname);
+int __PHYSFS_verifySecurity(DirHandle *h, const char *fname, int allowMissing);
 
 
 /*