--- a/misc/libphysfs/physfs.h Mon Apr 10 09:05:16 2017 -0400
+++ b/misc/libphysfs/physfs.h Mon Apr 10 12:06:43 2017 -0400
@@ -8,7 +8,7 @@
* \mainpage PhysicsFS
*
* The latest version of PhysicsFS can be found at:
- * http://icculus.org/physfs/
+ * https://icculus.org/physfs/
*
* PhysicsFS; a portable, flexible file i/o abstraction.
*
@@ -20,10 +20,6 @@
* - It's flexible. Archives (.ZIP files) can be used transparently as
* directory structures.
*
- * This system is largely inspired by Quake 3's PK3 files and the related
- * fs_* cvars. If you've ever tinkered with these, then this API will be
- * familiar to you.
- *
* With PhysicsFS, you have a single writing directory and multiple
* directories (the "search path") for reading. You can think of this as a
* filesystem within a filesystem. If (on Windows) you were to set the
@@ -128,9 +124,9 @@
*
* PhysicsFS is mostly thread safe. The error messages returned by
* PHYSFS_getLastError() are unique by thread, and library-state-setting
- * functions are mutex'd. For efficiency, individual file accesses are
- * not locked, so you can not safely read/write/seek/close/etc the same
- * file from two threads at the same time. Other race conditions are bugs
+ * functions are mutex'd. For efficiency, individual file accesses are
+ * not locked, so you can not safely read/write/seek/close/etc the same
+ * file from two threads at the same time. Other race conditions are bugs
* that should be reported/patched.
*
* While you CAN use stdio/syscall file access in a program that has PHYSFS_*
@@ -403,6 +399,8 @@
* supported.
*
* \sa PHYSFS_supportedArchiveTypes
+ * \sa PHYSFS_registerArchiver
+ * \sa PHYSFS_deregisterArchiver
*/
typedef struct PHYSFS_ArchiveInfo
{
@@ -410,6 +408,7 @@
const char *description; /**< Human-readable archive description. */
const char *author; /**< Person who did support for this archive. */
const char *url; /**< URL related to this archive */
+ int supportsSymlinks; /**< non-zero if archive offers symbolic links. */
} PHYSFS_ArchiveInfo;
@@ -577,9 +576,13 @@
*
* The return values are pointers to internal memory, and should
* be considered READ ONLY, and never freed. The returned values are
- * valid until the next call to PHYSFS_deinit().
+ * valid until the next call to PHYSFS_deinit(), PHYSFS_registerArchiver(),
+ * or PHYSFS_deregisterArchiver().
*
* \return READ ONLY Null-terminated array of READ ONLY structures.
+ *
+ * \sa PHYSFS_registerArchiver
+ * \sa PHYSFS_deregisterArchiver
*/
PHYSFS_DECL const PHYSFS_ArchiveInfo **PHYSFS_supportedArchiveTypes(void);
@@ -1094,8 +1097,9 @@
* We've got [z.sav].
* We've got [w.sav].\endverbatim
*
- * Feel free to sort the list however you like. We only promise there will
- * be no duplicates, but not what order the final list will come back in.
+ * Feel free to sort the list however you like. However, the returned data
+ * will always contain no duplicates, and will be always sorted in alphabetic
+ * (rather: Unicode) order for you.
*
* Don't forget to call PHYSFS_freeList() with the return value from this
* function when you are done with it.
@@ -1546,7 +1550,7 @@
* \param val value to convert
* \return converted value.
*
- * \warning Remember, PHYSFS_uint64 is only 32 bits on platforms without
+ * \warning Remember, PHYSFS_sint64 is only 32 bits on platforms without
* any sort of 64-bit support.
*/
PHYSFS_DECL PHYSFS_sint64 PHYSFS_swapSLE64(PHYSFS_sint64 val);
@@ -1629,7 +1633,7 @@
* \param val value to convert
* \return converted value.
*
- * \warning Remember, PHYSFS_uint64 is only 32 bits on platforms without
+ * \warning Remember, PHYSFS_sint64 is only 32 bits on platforms without
* any sort of 64-bit support.
*/
PHYSFS_DECL PHYSFS_sint64 PHYSFS_swapSBE64(PHYSFS_sint64 val);
@@ -1993,7 +1997,7 @@
* \return zero on failure, non-zero on success. On failure, you can
* find out what went wrong from PHYSFS_getLastError().
*
- * \warning Remember, PHYSFS_uint64 is only 32 bits on platforms without
+ * \warning Remember, PHYSFS_sint64 is only 32 bits on platforms without
* any sort of 64-bit support.
*/
PHYSFS_DECL int PHYSFS_writeSLE64(PHYSFS_File *file, PHYSFS_sint64 val);
@@ -2029,7 +2033,7 @@
* \return zero on failure, non-zero on success. On failure, you can
* find out what went wrong from PHYSFS_getLastError().
*
- * \warning Remember, PHYSFS_uint64 is only 32 bits on platforms without
+ * \warning Remember, PHYSFS_sint64 is only 32 bits on platforms without
* any sort of 64-bit support.
*/
PHYSFS_DECL int PHYSFS_writeSBE64(PHYSFS_File *file, PHYSFS_sint64 val);
@@ -2604,10 +2608,10 @@
*/
typedef enum PHYSFS_FileType
{
- PHYSFS_FILETYPE_REGULAR, /**< a normal file */
- PHYSFS_FILETYPE_DIRECTORY, /**< a directory */
- PHYSFS_FILETYPE_SYMLINK, /**< a symlink */
- PHYSFS_FILETYPE_OTHER /**< something completely different like a device */
+ PHYSFS_FILETYPE_REGULAR, /**< a normal file */
+ PHYSFS_FILETYPE_DIRECTORY, /**< a directory */
+ PHYSFS_FILETYPE_SYMLINK, /**< a symlink */
+ PHYSFS_FILETYPE_OTHER /**< something completely different like a device */
} PHYSFS_FileType;
/**
@@ -2628,12 +2632,12 @@
*/
typedef struct PHYSFS_Stat
{
- PHYSFS_sint64 filesize; /**< size in bytes, -1 for non-files and unknown */
- PHYSFS_sint64 modtime; /**< last modification time */
- PHYSFS_sint64 createtime; /**< like modtime, but for file creation time */
- PHYSFS_sint64 accesstime; /**< like modtime, but for file access time */
- PHYSFS_FileType filetype; /**< File? Directory? Symlink? */
- int readonly; /**< non-zero if read only, zero if writable. */
+ PHYSFS_sint64 filesize; /**< size in bytes, -1 for non-files and unknown */
+ PHYSFS_sint64 modtime; /**< last modification time */
+ PHYSFS_sint64 createtime; /**< like modtime, but for file creation time */
+ PHYSFS_sint64 accesstime; /**< like modtime, but for file access time */
+ PHYSFS_FileType filetype; /**< File? Directory? Symlink? */
+ int readonly; /**< non-zero if read only, zero if writable. */
} PHYSFS_Stat;
/**
@@ -3133,7 +3137,7 @@
PHYSFS_ERR_FILES_STILL_OPEN, /**< Files still open. */
PHYSFS_ERR_INVALID_ARGUMENT, /**< Bad parameter passed to an function. */
PHYSFS_ERR_NOT_MOUNTED, /**< Requested archive/dir not mounted. */
- PHYSFS_ERR_NO_SUCH_PATH, /**< No such file, directory, or parent. */
+ PHYSFS_ERR_NOT_FOUND, /**< File (or whatever) not found. */
PHYSFS_ERR_SYMLINK_FORBIDDEN,/**< Symlink seen when not permitted. */
PHYSFS_ERR_NO_WRITE_DIR, /**< No write dir has been specified. */
PHYSFS_ERR_OPEN_FOR_READING, /**< Wrote to a file opened for reading. */
@@ -3148,7 +3152,9 @@
PHYSFS_ERR_BAD_FILENAME, /**< Filename is bogus/insecure. */
PHYSFS_ERR_BUSY, /**< Tried to modify a file the OS needs. */
PHYSFS_ERR_DIR_NOT_EMPTY, /**< Tried to delete dir with files in it. */
- PHYSFS_ERR_OS_ERROR /**< Unspecified OS-level error. */
+ PHYSFS_ERR_OS_ERROR, /**< Unspecified OS-level error. */
+ PHYSFS_ERR_DUPLICATE, /**< Duplicate entry. */
+ PHYSFS_ERR_BAD_PASSWORD /**< Bad password. */
} PHYSFS_ErrorCode;
@@ -3311,9 +3317,224 @@
PHYSFS_DECL const char *PHYSFS_getPrefDir(const char *org, const char *app);
+/**
+ * \struct PHYSFS_Archiver
+ * \brief Abstract interface to provide support for user-defined archives.
+ *
+ * \warning This is advanced, hardcore stuff. You don't need this unless you
+ * really know what you're doing. Most apps will not need this.
+ *
+ * Historically, PhysicsFS provided a means to mount various archive file
+ * formats, and physical directories in the native filesystem. However,
+ * applications have been limited to the file formats provided by the
+ * library. This interface allows an application to provide their own
+ * archive file types.
+ *
+ * Conceptually, a PHYSFS_Archiver provides directory entries, while
+ * PHYSFS_Io provides data streams for those directory entries. The most
+ * obvious use of PHYSFS_Archiver is to provide support for an archive
+ * file type that isn't provided by PhysicsFS directly: perhaps some
+ * proprietary format that only your application needs to understand.
+ *
+ * Internally, all the built-in archive support uses this interface, so the
+ * best examples for building a PHYSFS_Archiver is the source code to
+ * PhysicsFS itself.
+ *
+ * An archiver is added to the system with PHYSFS_registerArchiver(), and then
+ * it will be available for use automatically with PHYSFS_mount(); if a
+ * given archive can be handled with your archiver, it will be given control
+ * as appropriate.
+ *
+ * These methods deal with dir handles. You have one instance of your
+ * archiver, and it generates a unique, opaque handle for each opened
+ * archive in its openArchive() method. Since the lifetime of an Archiver
+ * (not an archive) is generally the entire lifetime of the process, and it's
+ * assumed to be a singleton, we do not provide any instance data for the
+ * archiver itself; the app can just use some static variables if necessary.
+ *
+ * Symlinks should always be followed (except in stat()); PhysicsFS will
+ * use the stat() method to check for symlinks and make a judgement on
+ * whether to continue to call other methods based on that.
+ *
+ * Archivers, when necessary, should set the PhysicsFS error state with
+ * PHYSFS_setErrorCode() before returning. PhysicsFS will pass these errors
+ * back to the application unmolested in most cases.
+ *
+ * Thread safety: TO BE DECIDED. !!! FIXME
+ *
+ * \sa PHYSFS_registerArchiver
+ * \sa PHYSFS_deregisterArchiver
+ * \sa PHYSFS_supportedArchiveTypes
+ */
+typedef struct PHYSFS_Archiver
+{
+
+// !!! FIXME: split read/write interfaces?
+
+ /**
+ * \brief Binary compatibility information.
+ *
+ * This must be set to zero at this time. Future versions of this
+ * struct will increment this field, so we know what a given
+ * implementation supports. We'll presumably keep supporting older
+ * versions as we offer new features, though.
+ */
+ PHYSFS_uint32 version;
+
+ /**
+ * \brief Basic info about this archiver.
+ *
+ * This is used to identify your archive, and is returned in
+ * PHYSFS_supportedArchiveTypes().
+ */
+ PHYSFS_ArchiveInfo info;
+
+// !!! FIXME: documentation: \brief?
+ /**
+ * \brief
+ *
+ * Open an archive provided by (io).
+ * (name) is a filename associated with (io), but doesn't necessarily
+ * map to anything, let alone a real filename. This possibly-
+ * meaningless name is in platform-dependent notation.
+ * (forWrite) is non-zero if this is to be used for
+ * the write directory, and zero if this is to be used for an
+ * element of the search path.
+ * Return NULL on failure. We ignore any error code you set here;
+ * when PHYSFS_mount() returns, the error will be PHYSFS_ERR_UNSUPPORTED
+ * (no Archivers could handle this data). // !!! FIXME: yeah?
+ * Returns non-NULL on success. The pointer returned will be
+ * passed as the "opaque" parameter for later calls.
+ */
+ void *(*openArchive)(PHYSFS_Io *io, const char *name, int forWrite);
+
+ /**
+ * List all files in (dirname). Each file is passed to (cb),
+ * where a copy is made if appropriate, so you should dispose of
+ * it properly upon return from the callback.
+ * If you have a failure, report as much as you can.
+ * (dirname) is in platform-independent notation.
+ */
+ void (*enumerateFiles)(void *opaque, const char *dirname,
+ PHYSFS_EnumFilesCallback cb,
+ const char *origdir, void *callbackdata);
+
+ /**
+ * Open file for reading.
+ * This filename, (fnm), 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.
+ * Fail if the file does not exist.
+ * Returns NULL on failure, and calls PHYSFS_setErrorCode().
+ * Returns non-NULL on success. The pointer returned will be
+ * passed as the "opaque" parameter for later file calls.
+ */
+ PHYSFS_Io *(*openRead)(void *opaque, const char *fnm);
+
+ /**
+ * 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
+ * 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_setErrorCode().
+ * Returns non-NULL on success. The pointer returned will be
+ * passed as the "opaque" parameter for later file calls.
+ */
+ PHYSFS_Io *(*openWrite)(void *opaque, const char *filename);
+
+ /**
+ * Open file for appending.
+ * If the file does not exist, it should be created. The writing
+ * offset should be the end 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_setErrorCode().
+ * Returns non-NULL on success. The pointer returned will be
+ * passed as the "opaque" parameter for later file calls.
+ */
+ PHYSFS_Io *(*openAppend)(void *opaque, const char *filename);
+
+ /**
+ * Delete a file in the archive/directory.
+ * Return non-zero on success, zero on failure.
+ * This filename is in platform-independent notation.
+ * This method may be NULL.
+ * On failure, call PHYSFS_setErrorCode().
+ */
+ int (*remove)(void *opaque, const char *filename);
+
+ /**
+ * Create a directory in the archive/directory.
+ * If the application is trying to make multiple dirs, PhysicsFS
+ * will split them up into multiple calls before passing them to
+ * your driver.
+ * Return non-zero on success, zero on failure.
+ * This filename is in platform-independent notation.
+ * This method may be NULL.
+ * On failure, call PHYSFS_setErrorCode().
+ */
+ int (*mkdir)(void *opaque, const char *filename);
+
+ /**
+ * Obtain basic file metadata.
+ * Returns non-zero on success, zero on failure.
+ * On failure, call PHYSFS_setErrorCode().
+ */
+ int (*stat)(void *opaque, const char *fn, PHYSFS_Stat *stat);
+
+ /**
+ * Close directories/archives, and free any associated memory,
+ * including the original PHYSFS_Io and (opaque) itself, if
+ * applicable. Implementation can assume that it won't be called if
+ * there are still files open from this archive.
+ */
+ void (*closeArchive)(void *opaque);
+} PHYSFS_Archiver;
+
+/**
+ * \fn int PHYSFS_registerArchiver(const PHYSFS_Archiver *archiver)
+ * \brief Add a new archiver to the system.
+ *
+ * !!! FIXME: write me.
+ *
+ * You may not have two archivers that handle the same extension. If you are
+ * going to have a clash, you can deregister the other archiver (including
+ * built-in ones) with PHYSFS_deregisterArchiver().
+ *
+ * The data in (archiver) is copied; you may free this pointer when this
+ * function returns.
+ *
+ * \param archiver The archiver to register.
+ * \return Zero on error, non-zero on success.
+ *
+ * \sa PHYSFS_Archiver
+ * \sa PHYSFS_deregisterArchiver
+ */
+PHYSFS_DECL int PHYSFS_registerArchiver(const PHYSFS_Archiver *archiver);
+
+/**
+ * \fn int PHYSFS_deregisterArchiver(const char *ext)
+ * \brief Remove an archiver from the system.
+ *
+ * !!! FIXME: write me.
+ *
+ * This fails if there are any archives still open that use this archiver.
+ *
+ * \param ext Filename extension that the archiver handles.
+ * \return Zero on error, non-zero on success.
+ *
+ * \sa PHYSFS_Archiver
+ * \sa PHYSFS_registerArchiver
+ */
+PHYSFS_DECL int PHYSFS_deregisterArchiver(const char *ext);
+
+
/* Everything above this line is part of the PhysicsFS 2.1 API. */
-
#ifdef __cplusplus
}
#endif