diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 2a371af..524fec6 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -133,6 +133,7 @@ set(PHYSFS_SRCS src/archiver_qpak.c src/archiver_wad.c src/archiver_zip.c + src/archiver_apk.c src/archiver_slb.c src/archiver_iso9660.c ${PHYSFS_BEOS_SRCS} @@ -216,8 +217,13 @@ endif() # Archivers ... +option(PHYSFS_ARCHIVE_APK "Enable APK support" TRUE) +if(PHYSFS_ARCHIVE_APK) + add_definitions(-DPHYSFS_SUPPORTS_APK=1) +endif() + option(PHYSFS_ARCHIVE_ZIP "Enable ZIP support" TRUE) -if(PHYSFS_ARCHIVE_ZIP) +if(PHYSFS_ARCHIVE_ZIP OR PHYSFS_ARCHIVE_APK) add_definitions(-DPHYSFS_SUPPORTS_ZIP=1) endif() diff --git a/source/src/archiver_apk.c b/source/src/archiver_apk.c new file mode 100644 index 0000000..6acde20 --- /dev/null +++ b/source/src/archiver_apk.c @@ -0,0 +1,141 @@ +/* + * APK support routines for PhysicsFS. + * + * Please see the file LICENSE.txt in the source's root directory. + * + * This file written by Reto Schneider. + * Based on archiver_zip.c by Ryan C. Gordon. + */ + +#define __PHYSICSFS_INTERNAL__ +#include "physfs_internal.h" + +#if PHYSFS_SUPPORTS_APK + +#include +#include +#include + +extern const PHYSFS_Archiver __PHYSFS_Archiver_ZIP; +static const char prefix[] = "assets/"; +static const int prefixLen = sizeof(prefix) - 1; + +/** + * \brief Prefix requested filename with the assets folder string. + * + * \param filename Filename to extend. + * + * \return Null-terminated string. NULL if there was a problem + * (read: OUT OF MEMORY). Caller needs to free the string. + */ +char* extendFilename(const char* filename) +{ + int filenameLen = strlen(filename); + char *extendedFilename = allocator.Malloc(prefixLen + filenameLen + 1); + + BAIL_IF_MACRO( extendedFilename == NULL, PHYSFS_ERR_OUT_OF_MEMORY, 0); + + strcpy(extendedFilename, prefix); + strcat(extendedFilename, filename); + + return extendedFilename; +} + +static void *APK_openArchive(PHYSFS_Io *io, const char *name, int forWriting) +{ + return __PHYSFS_Archiver_ZIP.openArchive(io, name, forWriting); +} /* APK_openArchive */ + + +static void APK_enumerateFiles(void *opaque, const char *dname, + PHYSFS_EnumFilesCallback cb, + const char *origdir, void *callbackdata) +{ + __PHYSFS_Archiver_ZIP.enumerateFiles(opaque, dname, cb, origdir, callbackdata); +} /* APK_enumerateFiles */ + + +static PHYSFS_Io *APK_openRead(void *opaque, const char *filename) +{ + PHYSFS_Io *retval = NULL; + char* prefixedFilename = extendFilename(filename); + + BAIL_IF_MACRO( prefixedFilename == NULL, PHYSFS_ERR_OUT_OF_MEMORY, 0); + + retval = __PHYSFS_Archiver_ZIP.openRead(opaque, prefixedFilename); + + allocator.Free(prefixedFilename); + + return retval; +} /* APK_openRead */ + + +static PHYSFS_Io *APK_openWrite(void *opaque, const char *filename) +{ + BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL); +} /* APK_openWrite */ + + +static PHYSFS_Io *APK_openAppend(void *opaque, const char *filename) +{ + BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL); +} /* APK_openAppend */ + + +static void APK_closeArchive(void *opaque) +{ + __PHYSFS_Archiver_ZIP.closeArchive(opaque); +} /* APK_closeArchive */ + + +static int APK_remove(void *opaque, const char *name) +{ + BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0); +} /* APK_remove */ + + +static int APK_mkdir(void *opaque, const char *name) +{ + BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0); +} /* APK_mkdir */ + + +static int APK_stat(void *opaque, const char *filename, PHYSFS_Stat *stat) +{ + char* prefixedFilename = extendFilename(filename); + + BAIL_IF_MACRO( prefixedFilename == NULL, PHYSFS_ERR_OUT_OF_MEMORY, 0); + + int retval = __PHYSFS_Archiver_ZIP.stat(opaque, prefixedFilename, stat); + + allocator.Free(prefixedFilename); + + return retval; +} /* APK_stat */ + + +const PHYSFS_Archiver __PHYSFS_Archiver_APK = +{ + CURRENT_PHYSFS_ARCHIVER_API_VERSION, + { + "APK", + "Android APK file", + "Reto Schneider