physfs: Add PHYSFS_mountRW

This commit is contained in:
Alex Szpakowski
2020-12-30 22:54:08 -04:00
parent 801bc4b5d4
commit 9e9fa71589
2 changed files with 68 additions and 19 deletions
+60 -19
View File
@@ -49,6 +49,7 @@ typedef struct __PHYSFS_DIRHANDLE__
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) */
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. */
} DirHandle;
@@ -862,6 +863,7 @@ static DirHandle *tryOpenDir(PHYSFS_Io *io, const PHYSFS_Archiver *funcs,
retval->mountPoint = NULL;
retval->funcs = funcs;
retval->opaque = opaque;
retval->forWriting = forWriting;
} /* else */
} /* if */
@@ -1749,7 +1751,7 @@ int PHYSFS_setRoot(const char *archive, const char *subdir)
static int doMount(PHYSFS_Io *io, const char *fname,
const char *mountPoint, int appendToPath)
const char *mountPoint, int appendToPath, int forWriting)
{
DirHandle *dh;
DirHandle *prev = NULL;
@@ -1770,7 +1772,7 @@ static int doMount(PHYSFS_Io *io, const char *fname,
prev = i;
} /* for */
dh = createDirHandle(io, fname, mountPoint, 0);
dh = createDirHandle(io, fname, mountPoint, forWriting);
BAIL_IF_MUTEX_ERRPASS(!dh, stateLock, 0);
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(!fname, PHYSFS_ERR_INVALID_ARGUMENT, 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 */
@@ -1813,7 +1815,7 @@ int PHYSFS_mountMemory(const void *buf, PHYSFS_uint64 len, void (*del)(void *),
io = __PHYSFS_createMemoryIo(buf, len, del);
BAIL_IF_ERRPASS(!io, 0);
retval = doMount(io, fname, mountPoint, appendToPath);
retval = doMount(io, fname, mountPoint, appendToPath, 0);
if (!retval)
{
/* 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);
BAIL_IF_ERRPASS(!io, 0);
retval = doMount(io, fname, mountPoint, appendToPath);
retval = doMount(io, fname, mountPoint, appendToPath, 0);
if (!retval)
{
/* 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)
{
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 */
@@ -2159,10 +2168,39 @@ static int verifyPath(DirHandle *h, char **_fname, int allowMissing)
} /* verifyPath */
/* This must hold the stateLock before calling. */
static int doMkdir(const char *_dname, char *dname)
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. */
static int doMkdir(const char *_dname, char *dname, DirHandle *h)
{
DirHandle *h = writeDir;
char *start;
char *end;
int retval = 0;
@@ -2212,15 +2250,17 @@ int PHYSFS_mkdir(const char *_dname)
int retval = 0;
char *dname;
size_t len;
DirHandle *h = NULL;
BAIL_IF(!_dname, PHYSFS_ERR_INVALID_ARGUMENT, 0);
__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);
BAIL_IF_MUTEX(!dname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
retval = doMkdir(_dname, dname);
retval = doMkdir(_dname, dname, h);
__PHYSFS_platformReleaseMutex(stateLock);
__PHYSFS_smallFree(dname);
return retval;
@@ -2228,9 +2268,8 @@ int PHYSFS_mkdir(const char *_dname)
/* 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(!verifyPath(h, &fname, 0), 0);
return h->funcs->remove(h->opaque, fname);
@@ -2242,13 +2281,15 @@ int PHYSFS_delete(const char *_fname)
int retval;
char *fname;
size_t len;
DirHandle *h = NULL;
__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);
BAIL_IF_MUTEX(!fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
retval = doDelete(_fname, fname);
retval = doDelete(_fname, fname, h);
__PHYSFS_platformReleaseMutex(stateLock);
__PHYSFS_smallFree(fname);
return retval;
@@ -2631,7 +2672,7 @@ static PHYSFS_File *doOpenWrite(const char *_fname, const int appending)
__PHYSFS_platformGrabMutex(stateLock);
h = writeDir;
h = findWriteHandle(_fname);
BAIL_IF_MUTEX(!h, PHYSFS_ERR_NO_WRITE_DIR, stateLock, 0);
len = strlen(_fname) + dirHandleRootLen(h) + 1;
@@ -3115,7 +3156,7 @@ int PHYSFS_stat(const char *_fname, PHYSFS_Stat *stat)
if (exists)
{
stat->filetype = PHYSFS_FILETYPE_DIRECTORY;
stat->readonly = 1;
stat->readonly = !i->forWriting;
retval = 1;
} /* if */
else if (verifyPath(i, &arcfname, 0))
+8
View File
@@ -2204,6 +2204,14 @@ PHYSFS_DECL int PHYSFS_mount(const char *newDir,
const char *mountPoint,
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)
* \brief Determine a mounted archive's mountpoint.