mirror of
https://github.com/love2d/love-android.git
synced 2026-08-16 08:11:44 +02:00
307 lines
7.9 KiB
C
307 lines
7.9 KiB
C
/*
|
|
* APK support routines for PhysicsFS.
|
|
* Based von zip.c.
|
|
*
|
|
* A apk (android) file is just a zip file. But for LÖVE
|
|
* only the assets/ content is necessary and therefore
|
|
* this hides everything outside the assets/ directory
|
|
* (like a chroot into assets/).
|
|
*
|
|
* Please see the file LICENSE.txt in the source's root directory.
|
|
*
|
|
* This file is heavily based on zip.c by Ryan C. Gordon
|
|
*/
|
|
|
|
#if (defined PHYSFS_SUPPORTS_APK)
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#ifndef _WIN32_WCE
|
|
#include <errno.h>
|
|
#include <time.h>
|
|
#endif
|
|
#include "physfs.h"
|
|
#include "zlib.h"
|
|
|
|
#define __PHYSICSFS_INTERNAL__
|
|
#include "physfs_internal.h"
|
|
|
|
extern const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_ZIP;
|
|
extern const PHYSFS_Archiver __PHYSFS_Archiver_ZIP;
|
|
|
|
static PHYSFS_sint64 APK_read(fvoid *opaque, void *buf,
|
|
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
{
|
|
return __PHYSFS_Archiver_ZIP.read(opaque, buf, objSize, objCount);
|
|
} /* APK_read */
|
|
|
|
|
|
static PHYSFS_sint64 APK_write(fvoid *opaque, const void *buf,
|
|
PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
|
|
{
|
|
return __PHYSFS_Archiver_ZIP.write(opaque, buf, objSize, objCount);
|
|
} /* APK_write */
|
|
|
|
|
|
static int APK_eof(fvoid *opaque)
|
|
{
|
|
return __PHYSFS_Archiver_ZIP.eof(opaque);
|
|
} /* APK_eof */
|
|
|
|
|
|
static PHYSFS_sint64 APK_tell(fvoid *opaque)
|
|
{
|
|
return __PHYSFS_Archiver_ZIP.tell(opaque);
|
|
} /* APK_tell */
|
|
|
|
|
|
static int APK_seek(fvoid *opaque, PHYSFS_uint64 offset)
|
|
{
|
|
return __PHYSFS_Archiver_ZIP.seek(opaque, offset);
|
|
} /* APK_seek */
|
|
|
|
|
|
static PHYSFS_sint64 APK_fileLength(fvoid *opaque)
|
|
{
|
|
return __PHYSFS_Archiver_ZIP.fileLength(opaque);
|
|
} /* APK_fileLength */
|
|
|
|
|
|
static int APK_fileClose(fvoid *opaque)
|
|
{
|
|
return __PHYSFS_Archiver_ZIP.fileClose(opaque);
|
|
} /* APK_fileClose */
|
|
|
|
|
|
|
|
static int APK_isArchive(const char *filename, int forWriting)
|
|
{
|
|
int filename_len = 0;
|
|
|
|
// does not end with .apk? then ignore this archive
|
|
filename_len = strlen(filename);
|
|
if ((filename_len <= 4) ||
|
|
(filename[filename_len - 4] != '.') ||
|
|
(filename[filename_len - 3] != 'a' && filename[filename_len - 3] != 'A') ||
|
|
(filename[filename_len - 2] != 'p' && filename[filename_len - 2] != 'P') ||
|
|
(filename[filename_len - 1] != 'k' && filename[filename_len - 1] != 'K'))
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return __PHYSFS_Archiver_ZIP.isArchive(filename, forWriting);
|
|
}
|
|
} /* APK_isArchive */
|
|
|
|
|
|
|
|
static void *APK_openArchive(const char *name, int forWriting)
|
|
{
|
|
return __PHYSFS_Archiver_ZIP.openArchive(name, forWriting);
|
|
} /* APK_openArchive */
|
|
|
|
|
|
/**
|
|
* Allocates a new string and appends assets/ name.
|
|
* Result must be freed manually with allocator.Free
|
|
* if not necessary anymore
|
|
*/
|
|
char *append_assets(const char *name)
|
|
{
|
|
char *patched_name;
|
|
int name_len = strlen(name);
|
|
|
|
patched_name = allocator.Malloc(7 + name_len + 1);
|
|
|
|
memcpy(patched_name, "assets/", 7);
|
|
memcpy(patched_name + 7, name, name_len);
|
|
patched_name[7 + name_len + 1 - 1] = 0;
|
|
|
|
return patched_name;
|
|
}
|
|
|
|
|
|
/**
|
|
* just stores the parameter to an APK_enumerateFiles call to use them
|
|
* in the delegated call to cb
|
|
*/
|
|
typedef struct APK_originalEnumerateFileCallParameter
|
|
{
|
|
dvoid *opaque;
|
|
const char *dname;
|
|
int omitSymLinks;
|
|
PHYSFS_EnumFilesCallback cb;
|
|
const char *origdir;
|
|
void *callbackdata;
|
|
} APK_originalEnumerateFileCallParameter;
|
|
|
|
static void apk_enumerateFilesCallback(void *data, const char *origdir,
|
|
const char *fname)
|
|
{
|
|
APK_originalEnumerateFileCallParameter *callParameterPtr;
|
|
|
|
callParameterPtr = (APK_originalEnumerateFileCallParameter *)data;
|
|
|
|
(callParameterPtr->cb)(callParameterPtr->callbackdata, callParameterPtr->origdir, fname);
|
|
}
|
|
|
|
static void APK_enumerateFiles(dvoid *opaque, const char *dname,
|
|
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
|
|
const char *origdir, void *callbackdata)
|
|
{
|
|
char *patched_dname;
|
|
APK_originalEnumerateFileCallParameter callParameter;
|
|
|
|
callParameter.opaque = opaque;
|
|
callParameter.dname = dname;
|
|
callParameter.omitSymLinks = omitSymLinks;
|
|
callParameter.cb = cb;
|
|
callParameter.origdir = origdir;
|
|
callParameter.callbackdata = callbackdata;
|
|
|
|
patched_dname = append_assets(dname);
|
|
|
|
__PHYSFS_Archiver_ZIP.enumerateFiles(opaque, patched_dname, omitSymLinks, apk_enumerateFilesCallback, origdir, &callParameter);
|
|
|
|
allocator.Free(patched_dname);
|
|
} /* APK_enumerateFiles */
|
|
|
|
|
|
static int APK_exists(dvoid *opaque, const char *name)
|
|
{
|
|
int retval = 0;
|
|
char *patched_name = append_assets(name);
|
|
|
|
retval = __PHYSFS_Archiver_ZIP.exists(opaque, patched_name);
|
|
|
|
allocator.Free(patched_name);
|
|
|
|
return retval;
|
|
} /* APK_exists */
|
|
|
|
|
|
static PHYSFS_sint64 APK_getLastModTime(dvoid *opaque,
|
|
const char *name,
|
|
int *fileExists)
|
|
{
|
|
int retval = 0;
|
|
char *patched_name = append_assets(name);
|
|
|
|
retval = __PHYSFS_Archiver_ZIP.getLastModTime(opaque, patched_name, fileExists);
|
|
|
|
allocator.Free(patched_name);
|
|
|
|
return retval;
|
|
} /* APK_getLastModTime */
|
|
|
|
|
|
static int APK_isDirectory(dvoid *opaque, const char *name, int *fileExists)
|
|
{
|
|
int retval = 0;
|
|
char *patched_name = append_assets(name);
|
|
|
|
retval = __PHYSFS_Archiver_ZIP.isDirectory(opaque, patched_name, fileExists);
|
|
|
|
allocator.Free(patched_name);
|
|
|
|
return retval;
|
|
} /* APK_isDirectory */
|
|
|
|
|
|
static int APK_isSymLink(dvoid *opaque, const char *name, int *fileExists)
|
|
{
|
|
int retval = 0;
|
|
char *patched_name = append_assets(name);
|
|
|
|
retval = __PHYSFS_Archiver_ZIP.isSymLink(opaque, patched_name, fileExists);
|
|
|
|
allocator.Free(patched_name);
|
|
|
|
return retval;
|
|
} /* APK_isSymLink */
|
|
|
|
|
|
static fvoid *APK_openRead(dvoid *opaque, const char *fnm, int *fileExists)
|
|
{
|
|
fvoid * retval;
|
|
char *patched_name = append_assets(fnm);
|
|
|
|
retval = __PHYSFS_Archiver_ZIP.openRead(opaque, patched_name, fileExists);
|
|
|
|
allocator.Free(patched_name);
|
|
|
|
return retval;
|
|
} /* APK_openRead */
|
|
|
|
|
|
static fvoid *APK_openWrite(dvoid *opaque, const char *filename)
|
|
{
|
|
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
} /* APK_openWrite */
|
|
|
|
|
|
static fvoid *APK_openAppend(dvoid *opaque, const char *filename)
|
|
{
|
|
BAIL_MACRO(ERR_NOT_SUPPORTED, NULL);
|
|
} /* APK_openAppend */
|
|
|
|
|
|
static void APK_dirClose(dvoid *opaque)
|
|
{
|
|
__PHYSFS_Archiver_ZIP.dirClose(opaque);
|
|
} /* APK_dirClose */
|
|
|
|
|
|
static int APK_remove(dvoid *opaque, const char *name)
|
|
{
|
|
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
} /* APK_remove */
|
|
|
|
|
|
static int APK_mkdir(dvoid *opaque, const char *name)
|
|
{
|
|
BAIL_MACRO(ERR_NOT_SUPPORTED, 0);
|
|
} /* APK_mkdir */
|
|
|
|
|
|
const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_APK =
|
|
{
|
|
"APK",
|
|
APK_ARCHIVE_DESCRIPTION,
|
|
"based on __PHYSFS_Archiver_ZIP.ARCHIVE by Ryan C. Gordon <icculus@icculus.org>",
|
|
"http://icculus.org/physfs/",
|
|
};
|
|
|
|
|
|
const PHYSFS_Archiver __PHYSFS_Archiver_APK =
|
|
{
|
|
&__PHYSFS_ArchiveInfo_APK,
|
|
APK_isArchive, /* isArchive() method */
|
|
APK_openArchive, /* openArchive() method */
|
|
APK_enumerateFiles, /* enumerateFiles() method */
|
|
APK_exists, /* exists() method */
|
|
APK_isDirectory, /* isDirectory() method */
|
|
APK_isSymLink, /* isSymLink() method */
|
|
APK_getLastModTime, /* getLastModTime() method */
|
|
APK_openRead, /* openRead() method */
|
|
APK_openWrite, /* openWrite() method */
|
|
APK_openAppend, /* openAppend() method */
|
|
APK_remove, /* remove() method */
|
|
APK_mkdir, /* mkdir() method */
|
|
APK_dirClose, /* dirClose() method */
|
|
APK_read, /* read() method */
|
|
APK_write, /* write() method */
|
|
APK_eof, /* eof() method */
|
|
APK_tell, /* tell() method */
|
|
APK_seek, /* seek() method */
|
|
APK_fileLength, /* fileLength() method */
|
|
APK_fileClose /* fileClose() method */
|
|
};
|
|
|
|
#endif /* defined PHYSFS_SUPPORTS_APK */
|
|
|
|
/* end of apk.c ... */
|
|
|