[physfs] [PATCH][RFC] openReadWrite implementation
Matheus Izvekov
mizvekov at gmail.com
Fri May 1 03:08:33 EDT 2009
This implements openReadWrite API for physfs.
It opens a file for both reading and writing, creating a 0 byte file if it
doesn't exists. If the file exists outside the write dir, but not inside,
a 0 byte file is created.
This is the simplest possible implementation of this feature.
An alternative semantic is possible:
If the file exists outside the writing dir but not inside,
we copy it to the writing dir and start from there.
Also, for now, this patch only changes platform_posix.c to implement it.
It will fail to compile on other platforms.
If and when this patch is accepted, I will add others. Ofcourse help will
be appreciated.
---
diff -r 4413637bdcf2 src/archiver_dir.c
--- a/src/archiver_dir.c Mon Apr 20 23:48:16 2009 -0400
+++ b/src/archiver_dir.c Fri May 01 03:36:47 2009 -0300
@@ -201,6 +201,12 @@
} /* DIR_openRead */
+static fvoid *DIR_openReadWrite(dvoid *opaque, const char *filename)
+{
+ return(doOpen(opaque, filename, __PHYSFS_platformOpenReadWrite, NULL));
+} /* DIR_openReadWrite */
+
+
static fvoid *DIR_openWrite(dvoid *opaque, const char *filename)
{
return(doOpen(opaque, filename, __PHYSFS_platformOpenWrite, NULL));
@@ -265,6 +271,7 @@
DIR_isSymLink, /* isSymLink() method */
DIR_getLastModTime, /* getLastModTime() method */
DIR_openRead, /* openRead() method */
+ DIR_openReadWrite, /* openReadWrite() method */
DIR_openWrite, /* openWrite() method */
DIR_openAppend, /* openAppend() method */
DIR_remove, /* remove() method */
diff -r 4413637bdcf2 src/archiver_grp.c
--- a/src/archiver_grp.c Mon Apr 20 23:48:16 2009 -0400
+++ b/src/archiver_grp.c Fri May 01 03:36:47 2009 -0300
@@ -411,6 +411,12 @@
} /* GRP_openRead */
+static fvoid *GRP_openReadWrite(dvoid *opaque, const char *name)
+{
+ BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* GRP_openReadWrite */
+
+
static fvoid *GRP_openWrite(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
@@ -455,6 +461,7 @@
GRP_isSymLink, /* isSymLink() method */
GRP_getLastModTime, /* getLastModTime() method */
GRP_openRead, /* openRead() method */
+ GRP_openReadWrite, /* openReadWrite() method */
GRP_openWrite, /* openWrite() method */
GRP_openAppend, /* openAppend() method */
GRP_remove, /* remove() method */
diff -r 4413637bdcf2 src/archiver_hog.c
--- a/src/archiver_hog.c Mon Apr 20 23:48:16 2009 -0400
+++ b/src/archiver_hog.c Fri May 01 03:36:47 2009 -0300
@@ -450,6 +450,12 @@
} /* HOG_openRead */
+static fvoid *HOG_openReadWrite(dvoid *opaque, const char *name)
+{
+ BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* HOG_openReadWrite */
+
+
static fvoid *HOG_openWrite(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
@@ -494,6 +500,7 @@
HOG_isSymLink, /* isSymLink() method */
HOG_getLastModTime, /* getLastModTime() method */
HOG_openRead, /* openRead() method */
+ HOG_openReadWrite, /* openReadWrite() method */
HOG_openWrite, /* openWrite() method */
HOG_openAppend, /* openAppend() method */
HOG_remove, /* remove() method */
diff -r 4413637bdcf2 src/archiver_lzma.c
--- a/src/archiver_lzma.c Mon Apr 20 23:48:16 2009 -0400
+++ b/src/archiver_lzma.c Fri May 01 03:36:47 2009 -0300
@@ -655,6 +655,12 @@
} /* LZMA_openRead */
+static fvoid *LZMA_openReadWrite(dvoid *opaque, const char *filename)
+{
+ BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* LZMA_openReadWrite */
+
+
static fvoid *LZMA_openWrite(dvoid *opaque, const char *filename)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
@@ -715,6 +721,7 @@
LZMA_isSymLink, /* isSymLink() method */
LZMA_getLastModTime, /* getLastModTime() method */
LZMA_openRead, /* openRead() method */
+ LZMA_openReadWrite, /* openReadWrite() method */
LZMA_openWrite, /* openWrite() method */
LZMA_openAppend, /* openAppend() method */
LZMA_remove, /* remove() method */
diff -r 4413637bdcf2 src/archiver_mvl.c
--- a/src/archiver_mvl.c Mon Apr 20 23:48:16 2009 -0400
+++ b/src/archiver_mvl.c Fri May 01 03:36:47 2009 -0300
@@ -407,6 +407,12 @@
} /* MVL_openRead */
+static fvoid *MVL_openReadWrite(dvoid *opaque, const char *name)
+{
+ BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* MVL_openReadWrite */
+
+
static fvoid *MVL_openWrite(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
@@ -451,6 +457,7 @@
MVL_isSymLink, /* isSymLink() method */
MVL_getLastModTime, /* getLastModTime() method */
MVL_openRead, /* openRead() method */
+ MVL_openReadWrite, /* openReadWrite() method */
MVL_openWrite, /* openWrite() method */
MVL_openAppend, /* openAppend() method */
MVL_remove, /* remove() method */
diff -r 4413637bdcf2 src/archiver_qpak.c
--- a/src/archiver_qpak.c Mon Apr 20 23:48:16 2009 -0400
+++ b/src/archiver_qpak.c Fri May 01 03:36:47 2009 -0300
@@ -566,6 +566,12 @@
} /* QPAK_openRead */
+static fvoid *QPAK_openReadWrite(dvoid *opaque, const char *name)
+{
+ BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* QPAK_openReadWrite */
+
+
static fvoid *QPAK_openWrite(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
@@ -610,6 +616,7 @@
QPAK_isSymLink, /* isSymLink() method */
QPAK_getLastModTime, /* getLastModTime() method */
QPAK_openRead, /* openRead() method */
+ QPAK_openReadWrite, /* openReadWrite() method */
QPAK_openWrite, /* openWrite() method */
QPAK_openAppend, /* openAppend() method */
QPAK_remove, /* remove() method */
diff -r 4413637bdcf2 src/archiver_wad.c
--- a/src/archiver_wad.c Mon Apr 20 23:48:16 2009 -0400
+++ b/src/archiver_wad.c Fri May 01 03:36:47 2009 -0300
@@ -470,6 +470,12 @@
} /* WAD_openRead */
+static fvoid *WAD_openReadWrite(dvoid *opaque, const char *name)
+{
+ BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* WAD_openReadWrite */
+
+
static fvoid *WAD_openWrite(dvoid *opaque, const char *name)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
@@ -514,6 +520,7 @@
WAD_isSymLink, /* isSymLink() method */
WAD_getLastModTime, /* getLastModTime() method */
WAD_openRead, /* openRead() method */
+ WAD_openReadWrite, /* openReadWrite() method */
WAD_openWrite, /* openWrite() method */
WAD_openAppend, /* openAppend() method */
WAD_remove, /* remove() method */
diff -r 4413637bdcf2 src/archiver_zip.c
--- a/src/archiver_zip.c Mon Apr 20 23:48:16 2009 -0400
+++ b/src/archiver_zip.c Fri May 01 03:36:47 2009 -0300
@@ -1376,6 +1376,12 @@
} /* ZIP_openRead */
+static fvoid *ZIP_openReadWrite(dvoid *opaque, const char *filename)
+{
+ BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
+} /* ZIP_openReadWrite */
+
+
static fvoid *ZIP_openWrite(dvoid *opaque, const char *filename)
{
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
@@ -1429,6 +1435,7 @@
ZIP_isSymLink, /* isSymLink() method */
ZIP_getLastModTime, /* getLastModTime() method */
ZIP_openRead, /* openRead() method */
+ ZIP_openReadWrite, /* openReadWrite() method */
ZIP_openWrite, /* openWrite() method */
ZIP_openAppend, /* openAppend() method */
ZIP_remove, /* remove() method */
diff -r 4413637bdcf2 src/physfs.c
--- a/src/physfs.c Mon Apr 20 23:48:16 2009 -0400
+++ b/src/physfs.c Fri May 01 03:36:47 2009 -0300
@@ -30,7 +30,8 @@
typedef struct __PHYSFS_FILEHANDLE__
{
void *opaque; /* Instance data unique to the archiver for this file. */
- PHYSFS_uint8 forReading; /* Non-zero if reading, zero if write/append */
+ PHYSFS_uint8 forReading; /* Non-zero if reading */
+ PHYSFS_uint8 forWriting; /* Non-zero if writing */
const DirHandle *dirHandle; /* Archiver instance that created this */
const PHYSFS_Archiver *funcs; /* Ptr to archiver info for this handle. */
PHYSFS_uint8 *buffer; /* Buffer, if set (NULL otherwise). Don't touch! */
@@ -1742,7 +1743,7 @@
} /* PHYSFS_isSymbolicLink */
-static PHYSFS_File *doOpenWrite(const char *_fname, int appending)
+static PHYSFS_File *doOpenWrite(const char *_fname, int appending, int readwrite)
{
FileHandle *fh = NULL;
size_t len;
@@ -1767,7 +1768,9 @@
GOTO_IF_MACRO(!verifyPath(h, &fname, 0), NULL, doOpenWriteEnd);
f = h->funcs;
- if (appending)
+ if (readwrite)
+ opaque = f->openReadWrite(h->opaque, fname);
+ else if (appending)
opaque = f->openAppend(h->opaque, fname);
else
opaque = f->openWrite(h->opaque, fname);
@@ -1784,6 +1787,9 @@
{
memset(fh, '\0', sizeof (FileHandle));
fh->opaque = opaque;
+ if (readwrite)
+ fh->forReading = 1;
+ fh->forWriting = 1;
fh->dirHandle = h;
fh->funcs = h->funcs;
fh->next = openWriteList;
@@ -1799,15 +1805,21 @@
} /* doOpenWrite */
+PHYSFS_File *PHYSFS_openReadWrite(const char *filename)
+{
+ return(doOpenWrite(filename, 0, 1));
+} /* PHYSFS_openReadWrite */
+
+
PHYSFS_File *PHYSFS_openWrite(const char *filename)
{
- return(doOpenWrite(filename, 0));
+ return(doOpenWrite(filename, 0, 0));
} /* PHYSFS_openWrite */
PHYSFS_File *PHYSFS_openAppend(const char *filename)
{
- return(doOpenWrite(filename, 1));
+ return(doOpenWrite(filename, 1, 0));
} /* PHYSFS_openAppend */
@@ -1860,6 +1872,7 @@
memset(fh, '\0', sizeof (FileHandle));
fh->opaque = opaque;
fh->forReading = 1;
+ fh->forWriting = 0;
fh->dirHandle = i;
fh->funcs = i->funcs;
fh->next = openReadList;
@@ -2015,7 +2028,7 @@
{
FileHandle *fh = (FileHandle *) handle;
- BAIL_IF_MACRO(fh->forReading, ERR_FILE_ALREADY_OPEN_R, -1);
+ BAIL_IF_MACRO(!fh->forWriting, ERR_FILE_ALREADY_OPEN_R, -1);
BAIL_IF_MACRO(objSize == 0, NULL, 0);
BAIL_IF_MACRO(objCount == 0, NULL, 0);
if (fh->buffer != NULL)
@@ -2029,7 +2042,7 @@
{
FileHandle *fh = (FileHandle *) handle;
- if (!fh->forReading) /* never EOF on files opened for write/append. */
+ if (fh->forWriting) /* never EOF on files opened for write/append. */
return(0);
/* eof if buffer is empty and archiver says so. */
@@ -2041,7 +2054,7 @@
{
FileHandle *fh = (FileHandle *) handle;
PHYSFS_sint64 pos = fh->funcs->tell(fh->opaque);
- PHYSFS_sint64 retval = fh->forReading ?
+ PHYSFS_sint64 retval = (fh->forReading && !fh->forWriting) ?
(pos - fh->buffill) + fh->bufpos :
(pos + fh->buffill);
return(retval);
@@ -2053,7 +2066,7 @@
FileHandle *fh = (FileHandle *) handle;
BAIL_IF_MACRO(!PHYSFS_flush(handle), NULL, 0);
- if (fh->buffer && fh->forReading)
+ if (fh->buffer && fh->forReading && !fh->forWriting)
{
/* avoid throwing away our precious buffer if seeking within it. */
PHYSFS_sint64 offset = pos - PHYSFS_tell(handle);
@@ -2095,7 +2108,7 @@
* if we weren't buffering, so that the next read will get the
* right chunk of stuff from the file. PHYSFS_flush() handles writes.
*/
- if ((fh->forReading) && (fh->buffill != fh->bufpos))
+ if ((fh->forReading && !fh->forWriting) && (fh->buffill != fh->bufpos))
{
PHYSFS_uint64 pos;
PHYSFS_sint64 curpos = fh->funcs->tell(fh->opaque);
@@ -2132,7 +2145,7 @@
FileHandle *fh = (FileHandle *) handle;
PHYSFS_sint64 rc;
- if ((fh->forReading) || (fh->bufpos == fh->buffill))
+ if ((fh->forWriting) || (fh->bufpos == fh->buffill))
return(1); /* open for read or buffer empty are successful no-ops. */
/* dump buffer to disk. */
diff -r 4413637bdcf2 src/physfs.h
--- a/src/physfs.h Mon Apr 20 23:48:16 2009 -0400
+++ b/src/physfs.h Fri May 01 03:36:47 2009 -0300
@@ -1110,6 +1110,7 @@
* of the error can be gleaned from PHYSFS_getLastError().
*
* \sa PHYSFS_openRead
+ * \sa PHYSFS_openReadWrite
* \sa PHYSFS_openAppend
* \sa PHYSFS_write
* \sa PHYSFS_close
@@ -1136,6 +1137,7 @@
* of the error can be gleaned from PHYSFS_getLastError().
*
* \sa PHYSFS_openRead
+ * \sa PHYSFS_openReadWrite
* \sa PHYSFS_openWrite
* \sa PHYSFS_write
* \sa PHYSFS_close
@@ -1160,6 +1162,7 @@
* \return A valid PhysicsFS filehandle on success, NULL on error. Specifics
* of the error can be gleaned from PHYSFS_getLastError().
*
+ * \sa PHYSFS_openReadWrite
* \sa PHYSFS_openWrite
* \sa PHYSFS_openAppend
* \sa PHYSFS_read
@@ -1169,6 +1172,32 @@
/**
+ * \fn PHYSFS_File *PHYSFS_openReadWrite(const char *filename)
+ * \brief Open a file for reading and writing.
+ *
+ * Open a file for reading and writing, in platform-independent notation. The search path
+ * is checked one at a time until a matching file is found, in which case an
+ * abstract filehandle is associated with it, and reading may be done.
+ * The reading offset is set to the first byte of the file.
+ *
+ * Note that entries that are symlinks are ignored if
+ * PHYSFS_permitSymbolicLinks(1) hasn't been called, and opening a
+ * symlink with this function will fail in such a case.
+ *
+ * \param filename File to open.
+ * \return A valid PhysicsFS filehandle on success, NULL on error. Specifics
+ * of the error can be gleaned from PHYSFS_getLastError().
+ *
+ * \sa PHYSFS_openRead
+ * \sa PHYSFS_openWrite
+ * \sa PHYSFS_openAppend
+ * \sa PHYSFS_read
+ * \sa PHYSFS_close
+ */
+__EXPORT__ PHYSFS_File *PHYSFS_openReadWrite(const char *filename);
+
+
+/**
* \fn int PHYSFS_close(PHYSFS_File *handle)
* \brief Close a PhysicsFS filehandle.
*
@@ -1183,6 +1212,7 @@
* gleaned from PHYSFS_getLastError().
*
* \sa PHYSFS_openRead
+ * \sa PHYSFS_openReadWrite
* \sa PHYSFS_openWrite
* \sa PHYSFS_openAppend
*/
diff -r 4413637bdcf2 src/physfs_internal.h
--- a/src/physfs_internal.h Mon Apr 20 23:48:16 2009 -0400
+++ b/src/physfs_internal.h Fri May 01 03:36:47 2009 -0300
@@ -824,6 +824,19 @@
fvoid *(*openRead)(dvoid *opaque, const char *fname, int *fileExists);
/*
+ * Open file for reading and writing.
+ * If the file does not exist, it should be created.
+ * The offset should be the start of the file.
+ * This filename is in platform-independent notation.
+ * If you can't handle multiple opens of the same file,
+ * you can opt to fail for the second call.
+ * Returns NULL on failure, and calls __PHYSFS_setError().
+ * Returns non-NULL on success. The pointer returned will be
+ * passed as the "opaque" parameter for later file calls.
+ */
+ fvoid *(*openReadWrite)(dvoid *opaque, const char *filename);
+
+ /*
* Open file for writing.
* If the file does not exist, it should be created. If it exists,
* it should be truncated to zero bytes. The writing
@@ -1145,6 +1158,22 @@
/*
+ * Open a file for reading and writing. (filename) is in platform-dependent
+ * notation. If the file doesn't exists, it should be created as a zero-byte
+ * file. The file pointer should be positioned on the first byte of the file.
+ *
+ * The return value will be some platform-specific datatype that is opaque to
+ * the caller; it could be a (FILE *) under Unix, or a (HANDLE *) under win32,
+ * etc.
+ *
+ * Opening a file for read and write multiple times has undefined results.
+ *
+ * Call __PHYSFS_setError() and return (NULL) if the file can't be opened.
+ */
+void *__PHYSFS_platformOpenReadWrite(const char *filename);
+
+
+/*
* Open a file for writing. (filename) is in platform-dependent notation. If
* the file exists, it should be truncated to zero bytes, and if it doesn't
* exist, it should be created as a zero-byte file. The file pointer should
diff -r 4413637bdcf2 src/platform_posix.c
--- a/src/platform_posix.c Mon Apr 20 23:48:16 2009 -0400
+++ b/src/platform_posix.c Fri May 01 03:36:47 2009 -0300
@@ -274,6 +274,12 @@
} /* __PHYSFS_platformOpenRead */
+void *__PHYSFS_platformOpenReadWrite(const char *filename)
+{
+ return(doOpen(filename, O_RDWR | O_CREAT));
+} /* __PHYSFS_platformOpenReadWrite */
+
+
void *__PHYSFS_platformOpenWrite(const char *filename)
{
return(doOpen(filename, O_WRONLY | O_CREAT | O_TRUNC));
More information about the physfs
mailing list