Browse Source

physfs: add PHYSFS_canUnmount

Fix unmount on a RW archive not checking if writable files are open
Alex Szpakowski 4 years ago
parent
commit
f00f5cb51a
2 changed files with 47 additions and 0 deletions
  1. 41 0
      src/libraries/physfs/physfs.c
  2. 6 0
      src/libraries/physfs/physfs.h

+ 41 - 0
src/libraries/physfs/physfs.c

@@ -1104,6 +1104,23 @@ static int freeDirHandle(DirHandle *dh, FileHandle *openList)
 } /* freeDirHandle */
 
 
+static int dirHandleFilesOpen(DirHandle *dh, FileHandle *openList)
+{
+    FileHandle *i;
+
+    if (dh == NULL)
+        return 0;
+
+    for (i = openList; i != NULL; i = i->next)
+    {
+        if (i->dirHandle == dh)
+            return 1;
+    }
+
+    return 0;
+} /* dirHandleFilesOpen */
+
+
 static char *calculateBaseDir(const char *argv0)
 {
     const char dirsep = __PHYSFS_platformDirSeparator;
@@ -1891,6 +1908,8 @@ int PHYSFS_unmount(const char *oldDir)
         if (strcmp(i->dirName, oldDir) == 0)
         {
             next = i->next;
+            if (i->forWriting && dirHandleFilesOpen(i, openWriteList))
+                BAIL_MUTEX(PHYSFS_ERR_FILES_STILL_OPEN, stateLock, 0);
             BAIL_IF_MUTEX_ERRPASS(!freeDirHandle(i, openReadList),
                                 stateLock, 0);
 
@@ -1908,6 +1927,28 @@ int PHYSFS_unmount(const char *oldDir)
 } /* PHYSFS_unmount */
 
 
+int PHYSFS_canUnmount(const char *oldDir)
+{
+    DirHandle *i;
+
+    BAIL_IF(oldDir == NULL, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+
+    __PHYSFS_platformGrabMutex(stateLock);
+    for (i = searchPath; i != NULL; i = i->next)
+    {
+        if (strcmp(i->dirName, oldDir) == 0)
+        {
+            if (i->forWriting && dirHandleFilesOpen(i, openWriteList))
+                BAIL_MUTEX(PHYSFS_ERR_OK, stateLock, 0);
+            if (dirHandleFilesOpen(i, openReadList))
+                BAIL_MUTEX(PHYSFS_ERR_OK, stateLock, 0);
+            BAIL_MUTEX(PHYSFS_ERR_OK, stateLock, 1);
+        }
+    }
+
+    BAIL_MUTEX(PHYSFS_ERR_NOT_MOUNTED, stateLock, 0);
+} /* PHYSFS_canUnmount */
+
 char **PHYSFS_getSearchPath(void)
 {
     return doEnumStringList(PHYSFS_getSearchPathCallback);

+ 6 - 0
src/libraries/physfs/physfs.h

@@ -2787,6 +2787,12 @@ PHYSFS_DECL int PHYSFS_enumerate(const char *dir, PHYSFS_EnumerateCallback c,
  */
 PHYSFS_DECL int PHYSFS_unmount(const char *oldDir);
 
+/**
+ * \fn int PHYSFS_canUnmount(const char *oldDir)
+ * \brief Check whether a directory or archive can be unmounted.
+ */
+PHYSFS_DECL int PHYSFS_canUnmount(const char *oldDir);
+
 
 /**
  * \fn const PHYSFS_Allocator *PHYSFS_getAllocator(void)