diff -r ea891871f481 -r bb5522e88ab2 misc/libphysfs/physfs.h --- 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