Browse Source

physfs: Add PHYSFS_mountRW

Alex Szpakowski 4 years ago
parent
commit
9e9fa71589
2 changed files with 67 additions and 18 deletions
  1. 59 18
      src/libraries/physfs/physfs.c
  2. 8 0
      src/libraries/physfs/physfs.h

+ 59 - 18
src/libraries/physfs/physfs.c

@@ -49,6 +49,7 @@ typedef struct __PHYSFS_DIRHANDLE__
     char *root;  /* subdirectory of archiver to use as root of archive (NULL for actual root) */
     char *root;  /* subdirectory of archiver to use as root of archive (NULL for actual root) */
     size_t rootlen;  /* subdirectory of archiver to use as root of archive (NULL for actual root) */
     size_t rootlen;  /* subdirectory of archiver to use as root of archive (NULL for actual root) */
     const PHYSFS_Archiver *funcs;  /* Ptr to archiver info for this handle. */
     const PHYSFS_Archiver *funcs;  /* Ptr to archiver info for this handle. */
+	int forWriting; /* Whether this was opened for writing or not. */
     struct __PHYSFS_DIRHANDLE__ *next;  /* linked list stuff. */
     struct __PHYSFS_DIRHANDLE__ *next;  /* linked list stuff. */
 } DirHandle;
 } DirHandle;
 
 
@@ -862,6 +863,7 @@ static DirHandle *tryOpenDir(PHYSFS_Io *io, const PHYSFS_Archiver *funcs,
             retval->mountPoint = NULL;
             retval->mountPoint = NULL;
             retval->funcs = funcs;
             retval->funcs = funcs;
             retval->opaque = opaque;
             retval->opaque = opaque;
+			retval->forWriting = forWriting;
         } /* else */
         } /* else */
     } /* if */
     } /* if */
 
 
@@ -1749,7 +1751,7 @@ int PHYSFS_setRoot(const char *archive, const char *subdir)
 
 
 
 
 static int doMount(PHYSFS_Io *io, const char *fname,
 static int doMount(PHYSFS_Io *io, const char *fname,
-                   const char *mountPoint, int appendToPath)
+                   const char *mountPoint, int appendToPath, int forWriting)
 {
 {
     DirHandle *dh;
     DirHandle *dh;
     DirHandle *prev = NULL;
     DirHandle *prev = NULL;
@@ -1770,7 +1772,7 @@ static int doMount(PHYSFS_Io *io, const char *fname,
         prev = i;
         prev = i;
     } /* for */
     } /* for */
 
 
-    dh = createDirHandle(io, fname, mountPoint, 0);
+    dh = createDirHandle(io, fname, mountPoint, forWriting);
     BAIL_IF_MUTEX_ERRPASS(!dh, stateLock, 0);
     BAIL_IF_MUTEX_ERRPASS(!dh, stateLock, 0);
 
 
     if (appendToPath)
     if (appendToPath)
@@ -1797,7 +1799,7 @@ int PHYSFS_mountIo(PHYSFS_Io *io, const char *fname,
     BAIL_IF(!io, PHYSFS_ERR_INVALID_ARGUMENT, 0);
     BAIL_IF(!io, PHYSFS_ERR_INVALID_ARGUMENT, 0);
     BAIL_IF(!fname, PHYSFS_ERR_INVALID_ARGUMENT, 0);
     BAIL_IF(!fname, PHYSFS_ERR_INVALID_ARGUMENT, 0);
     BAIL_IF(io->version != 0, PHYSFS_ERR_UNSUPPORTED, 0);
     BAIL_IF(io->version != 0, PHYSFS_ERR_UNSUPPORTED, 0);
-    return doMount(io, fname, mountPoint, appendToPath);
+    return doMount(io, fname, mountPoint, appendToPath, 0);
 } /* PHYSFS_mountIo */
 } /* PHYSFS_mountIo */
 
 
 
 
@@ -1813,7 +1815,7 @@ int PHYSFS_mountMemory(const void *buf, PHYSFS_uint64 len, void (*del)(void *),
 
 
     io = __PHYSFS_createMemoryIo(buf, len, del);
     io = __PHYSFS_createMemoryIo(buf, len, del);
     BAIL_IF_ERRPASS(!io, 0);
     BAIL_IF_ERRPASS(!io, 0);
-    retval = doMount(io, fname, mountPoint, appendToPath);
+    retval = doMount(io, fname, mountPoint, appendToPath, 0);
     if (!retval)
     if (!retval)
     {
     {
         /* docs say not to call (del) in case of failure, so cheat. */
         /* docs say not to call (del) in case of failure, so cheat. */
@@ -1837,7 +1839,7 @@ int PHYSFS_mountHandle(PHYSFS_File *file, const char *fname,
 
 
     io = __PHYSFS_createHandleIo(file);
     io = __PHYSFS_createHandleIo(file);
     BAIL_IF_ERRPASS(!io, 0);
     BAIL_IF_ERRPASS(!io, 0);
-    retval = doMount(io, fname, mountPoint, appendToPath);
+    retval = doMount(io, fname, mountPoint, appendToPath, 0);
     if (!retval)
     if (!retval)
     {
     {
         /* docs say not to destruct in case of failure, so cheat. */
         /* docs say not to destruct in case of failure, so cheat. */
@@ -1852,7 +1854,14 @@ int PHYSFS_mountHandle(PHYSFS_File *file, const char *fname,
 int PHYSFS_mount(const char *newDir, const char *mountPoint, int appendToPath)
 int PHYSFS_mount(const char *newDir, const char *mountPoint, int appendToPath)
 {
 {
     BAIL_IF(!newDir, PHYSFS_ERR_INVALID_ARGUMENT, 0);
     BAIL_IF(!newDir, PHYSFS_ERR_INVALID_ARGUMENT, 0);
-    return doMount(NULL, newDir, mountPoint, appendToPath);
+    return doMount(NULL, newDir, mountPoint, appendToPath, 0);
+} /* PHYSFS_mount */
+
+
+int PHYSFS_mountRW(const char *newDir, const char *mountPoint, int appendToPath)
+{
+	BAIL_IF(!newDir, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+	return doMount(NULL, newDir, mountPoint, appendToPath, 1);
 } /* PHYSFS_mount */
 } /* PHYSFS_mount */
 
 
 
 
@@ -2159,10 +2168,39 @@ static int verifyPath(DirHandle *h, char **_fname, int allowMissing)
 } /* verifyPath */
 } /* verifyPath */
 
 
 
 
+static DirHandle *findWriteHandle(const char *_fname)
+{
+	DirHandle *i = NULL;
+	char *allocated_fname;
+	char *fname;
+	size_t len;
+
+	len = strlen(_fname) + longest_root + 1;
+	allocated_fname = (char *) __PHYSFS_smallAlloc(len);
+	BAIL_IF(!allocated_fname, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
+	fname = allocated_fname + longest_root;
+
+	if (sanitizePlatformIndependentPath(_fname, fname))
+	{
+		for (i = searchPath; i != NULL; i = i->next)
+		{
+			char *arcfname = fname;
+			if (i->forWriting && verifyPath(i, &arcfname, 0))
+			{
+				break;
+			} /* if */
+		} /* for */
+	}
+
+	__PHYSFS_smallFree(allocated_fname);
+	
+	return i != NULL ? i : writeDir;
+} /* findWriteHandle */
+
+
 /* This must hold the stateLock before calling. */
 /* This must hold the stateLock before calling. */
-static int doMkdir(const char *_dname, char *dname)
+static int doMkdir(const char *_dname, char *dname, DirHandle *h)
 {
 {
-    DirHandle *h = writeDir;
     char *start;
     char *start;
     char *end;
     char *end;
     int retval = 0;
     int retval = 0;
@@ -2212,15 +2250,17 @@ int PHYSFS_mkdir(const char *_dname)
     int retval = 0;
     int retval = 0;
     char *dname;
     char *dname;
     size_t len;
     size_t len;
+	DirHandle *h = NULL;
 
 
     BAIL_IF(!_dname, PHYSFS_ERR_INVALID_ARGUMENT, 0);
     BAIL_IF(!_dname, PHYSFS_ERR_INVALID_ARGUMENT, 0);
 
 
     __PHYSFS_platformGrabMutex(stateLock);
     __PHYSFS_platformGrabMutex(stateLock);
-    BAIL_IF_MUTEX(!writeDir, PHYSFS_ERR_NO_WRITE_DIR, stateLock, 0);
-    len = strlen(_dname) + dirHandleRootLen(writeDir) + 1;
+	h = findWriteHandle(_dname);
+    BAIL_IF_MUTEX(!h, PHYSFS_ERR_NO_WRITE_DIR, stateLock, 0);
+    len = strlen(_dname) + dirHandleRootLen(h) + 1;
     dname = (char *) __PHYSFS_smallAlloc(len);
     dname = (char *) __PHYSFS_smallAlloc(len);
     BAIL_IF_MUTEX(!dname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
     BAIL_IF_MUTEX(!dname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
-    retval = doMkdir(_dname, dname);
+    retval = doMkdir(_dname, dname, h);
     __PHYSFS_platformReleaseMutex(stateLock);
     __PHYSFS_platformReleaseMutex(stateLock);
     __PHYSFS_smallFree(dname);
     __PHYSFS_smallFree(dname);
     return retval;
     return retval;
@@ -2228,9 +2268,8 @@ int PHYSFS_mkdir(const char *_dname)
 
 
 
 
 /* This must hold the stateLock before calling. */
 /* This must hold the stateLock before calling. */
-static int doDelete(const char *_fname, char *fname)
+static int doDelete(const char *_fname, char *fname, DirHandle *h)
 {
 {
-    DirHandle *h = writeDir;
     BAIL_IF_ERRPASS(!sanitizePlatformIndependentPathWithRoot(h, _fname, fname), 0);
     BAIL_IF_ERRPASS(!sanitizePlatformIndependentPathWithRoot(h, _fname, fname), 0);
     BAIL_IF_ERRPASS(!verifyPath(h, &fname, 0), 0);
     BAIL_IF_ERRPASS(!verifyPath(h, &fname, 0), 0);
     return h->funcs->remove(h->opaque, fname);
     return h->funcs->remove(h->opaque, fname);
@@ -2242,13 +2281,15 @@ int PHYSFS_delete(const char *_fname)
     int retval;
     int retval;
     char *fname;
     char *fname;
     size_t len;
     size_t len;
+	DirHandle *h = NULL;
 
 
     __PHYSFS_platformGrabMutex(stateLock);
     __PHYSFS_platformGrabMutex(stateLock);
-    BAIL_IF_MUTEX(!writeDir, PHYSFS_ERR_NO_WRITE_DIR, stateLock, 0);
-    len = strlen(_fname) + dirHandleRootLen(writeDir) + 1;
+	h = findWriteHandle(_fname);
+    BAIL_IF_MUTEX(!h, PHYSFS_ERR_NO_WRITE_DIR, stateLock, 0);
+    len = strlen(_fname) + dirHandleRootLen(h) + 1;
     fname = (char *) __PHYSFS_smallAlloc(len);
     fname = (char *) __PHYSFS_smallAlloc(len);
     BAIL_IF_MUTEX(!fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
     BAIL_IF_MUTEX(!fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
-    retval = doDelete(_fname, fname);
+    retval = doDelete(_fname, fname, h);
     __PHYSFS_platformReleaseMutex(stateLock);
     __PHYSFS_platformReleaseMutex(stateLock);
     __PHYSFS_smallFree(fname);
     __PHYSFS_smallFree(fname);
     return retval;
     return retval;
@@ -2631,7 +2672,7 @@ static PHYSFS_File *doOpenWrite(const char *_fname, const int appending)
 
 
     __PHYSFS_platformGrabMutex(stateLock);
     __PHYSFS_platformGrabMutex(stateLock);
 
 
-    h = writeDir;
+    h = findWriteHandle(_fname);
     BAIL_IF_MUTEX(!h, PHYSFS_ERR_NO_WRITE_DIR, stateLock, 0);
     BAIL_IF_MUTEX(!h, PHYSFS_ERR_NO_WRITE_DIR, stateLock, 0);
 
 
     len = strlen(_fname) + dirHandleRootLen(h) + 1;
     len = strlen(_fname) + dirHandleRootLen(h) + 1;
@@ -3115,7 +3156,7 @@ int PHYSFS_stat(const char *_fname, PHYSFS_Stat *stat)
                 if (exists)
                 if (exists)
                 {
                 {
                     stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
                     stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
-                    stat->readonly = 1;
+                    stat->readonly = !i->forWriting;
                     retval = 1;
                     retval = 1;
                 } /* if */
                 } /* if */
                 else if (verifyPath(i, &arcfname, 0))
                 else if (verifyPath(i, &arcfname, 0))

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

@@ -2204,6 +2204,14 @@ PHYSFS_DECL int PHYSFS_mount(const char *newDir,
                              const char *mountPoint,
                              const char *mountPoint,
                              int appendToPath);
                              int appendToPath);
 
 
+/**
+ * Just like mount() but attempts to open the directory for writing as well as
+ * reading.
+ */
+PHYSFS_DECL int PHYSFS_mountRW(const char *newDir,
+                               const char *mountPoint,
+                               int appendToPath);
+
 /**
 /**
  * \fn int PHYSFS_getMountPoint(const char *dir)
  * \fn int PHYSFS_getMountPoint(const char *dir)
  * \brief Determine a mounted archive's mountpoint.
  * \brief Determine a mounted archive's mountpoint.