mirror of
https://github.com/love2d/love.git
synced 2026-08-16 00:02:12 +02:00
@@ -12,8 +12,6 @@
|
||||
#include "physfs_internal.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <stdarg.h>
|
||||
|
||||
/* this code came from https://stackoverflow.com/a/8712996 */
|
||||
int __PHYSFS_msvc_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
|
||||
{
|
||||
@@ -104,8 +102,8 @@ static inline int __PHYSFS_atomicAdd(int *ptrval, const int val)
|
||||
{
|
||||
int retval;
|
||||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
*ptrval += val;
|
||||
retval = *ptrval;
|
||||
*ptrval = retval + val;
|
||||
__PHYSFS_platformReleaseMutex(stateLock);
|
||||
return retval;
|
||||
} /* __PHYSFS_atomicAdd */
|
||||
@@ -923,12 +921,12 @@ static DirHandle *openDirectory(PHYSFS_Io *io, const char *d, int forWriting)
|
||||
retval = tryOpenDir(io, *i, d, forWriting, &claimed);
|
||||
} /* else */
|
||||
|
||||
errcode = currentErrorCode();
|
||||
errcode = claimed ? currentErrorCode() : PHYSFS_ERR_UNSUPPORTED;
|
||||
|
||||
if ((!retval) && (created_io))
|
||||
io->destroy(io);
|
||||
|
||||
BAIL_IF(!retval, claimed ? errcode : PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
BAIL_IF(!retval, errcode, NULL);
|
||||
return retval;
|
||||
} /* openDirectory */
|
||||
|
||||
@@ -1095,6 +1093,8 @@ static int freeDirHandle(DirHandle *dh, FileHandle *openList)
|
||||
BAIL_IF(i->dirHandle == dh, PHYSFS_ERR_FILES_STILL_OPEN, 0);
|
||||
|
||||
dh->funcs->closeArchive(dh->opaque);
|
||||
|
||||
if (dh->root) allocator.Free(dh->root);
|
||||
allocator.Free(dh->dirName);
|
||||
allocator.Free(dh->mountPoint);
|
||||
allocator.Free(dh);
|
||||
@@ -1233,7 +1233,9 @@ int PHYSFS_init(const char *argv0)
|
||||
if (!userDir) goto initFailed;
|
||||
|
||||
/* Platform layer is required to append a dirsep. */
|
||||
#ifndef __ANDROID__ /* it's an APK file, not a directory, on Android. */
|
||||
assert(baseDir[strlen(baseDir) - 1] == __PHYSFS_platformDirSeparator);
|
||||
#endif
|
||||
assert(userDir[strlen(userDir) - 1] == __PHYSFS_platformDirSeparator);
|
||||
|
||||
if (!initStaticArchivers()) goto initFailed;
|
||||
@@ -1433,15 +1435,60 @@ char *__PHYSFS_strdup(const char *str)
|
||||
} /* __PHYSFS_strdup */
|
||||
|
||||
|
||||
PHYSFS_uint32 __PHYSFS_hashString(const char *str, size_t len)
|
||||
PHYSFS_uint32 __PHYSFS_hashString(const char *str)
|
||||
{
|
||||
PHYSFS_uint32 hash = 5381;
|
||||
while (len--)
|
||||
hash = ((hash << 5) + hash) ^ *(str++);
|
||||
while (1)
|
||||
{
|
||||
const char ch = *(str++);
|
||||
if (ch == 0)
|
||||
break;
|
||||
hash = ((hash << 5) + hash) ^ ch;
|
||||
} /* while */
|
||||
return hash;
|
||||
} /* __PHYSFS_hashString */
|
||||
|
||||
|
||||
PHYSFS_uint32 __PHYSFS_hashStringCaseFold(const char *str)
|
||||
{
|
||||
PHYSFS_uint32 hash = 5381;
|
||||
while (1)
|
||||
{
|
||||
const PHYSFS_uint32 cp = __PHYSFS_utf8codepoint(&str);
|
||||
if (cp == 0)
|
||||
break;
|
||||
else
|
||||
{
|
||||
PHYSFS_uint32 folded[3];
|
||||
const int numbytes = (int) (PHYSFS_caseFold(cp, folded) * sizeof (PHYSFS_uint32));
|
||||
const char *bytes = (const char *) folded;
|
||||
int i;
|
||||
for (i = 0; i < numbytes; i++)
|
||||
hash = ((hash << 5) + hash) ^ *(bytes++);
|
||||
} /* else */
|
||||
} /* while */
|
||||
|
||||
return hash;
|
||||
} /* __PHYSFS_hashStringCaseFold */
|
||||
|
||||
|
||||
PHYSFS_uint32 __PHYSFS_hashStringCaseFoldUSAscii(const char *str)
|
||||
{
|
||||
PHYSFS_uint32 hash = 5381;
|
||||
while (1)
|
||||
{
|
||||
char ch = *(str++);
|
||||
if (ch == 0)
|
||||
break;
|
||||
else if ((ch >= 'A') && (ch <= 'Z'))
|
||||
ch -= ('A' - 'a');
|
||||
|
||||
hash = ((hash << 5) + hash) ^ ch;
|
||||
} /* while */
|
||||
return hash;
|
||||
} /* __PHYSFS_hashStringCaseFoldUSAscii */
|
||||
|
||||
|
||||
/* MAKE SURE you hold stateLock before calling this! */
|
||||
static int doRegisterArchiver(const PHYSFS_Archiver *_archiver)
|
||||
{
|
||||
@@ -1733,10 +1780,10 @@ int PHYSFS_setRoot(const char *archive, const char *subdir)
|
||||
if (i->root)
|
||||
allocator.Free(i->root);
|
||||
i->root = ptr;
|
||||
i->rootlen = len;
|
||||
i->rootlen = strlen(i->root); /* in case sanitizePlatformIndependentPath changed subdir */
|
||||
|
||||
if (longest_root < len)
|
||||
longest_root = len;
|
||||
if (longest_root < i->rootlen)
|
||||
longest_root = i->rootlen;
|
||||
} /* else */
|
||||
|
||||
break;
|
||||
@@ -2107,10 +2154,10 @@ static int verifyPath(DirHandle *h, char **_fname, int allowMissing)
|
||||
if (h->root)
|
||||
{
|
||||
const int isempty = (*fname == '\0');
|
||||
fname -= h->rootlen - 1;
|
||||
fname -= h->rootlen + (isempty ? 0 : 1);
|
||||
strcpy(fname, h->root);
|
||||
if (!isempty)
|
||||
fname[h->rootlen - 2] = '/';
|
||||
fname[h->rootlen] = '/';
|
||||
*_fname = fname;
|
||||
} /* if */
|
||||
|
||||
@@ -2187,7 +2234,12 @@ static int doMkdir(const char *_dname, char *dname)
|
||||
const int rc = h->funcs->stat(h->opaque, dname, &statbuf);
|
||||
if ((!rc) && (currentErrorCode() == PHYSFS_ERR_NOT_FOUND))
|
||||
exists = 0;
|
||||
retval = ((rc) && (statbuf.filetype == PHYSFS_FILETYPE_DIRECTORY));
|
||||
/* verifyPath made sure that (dname) doesn't have symlinks if they aren't
|
||||
allowed, but it's possible the mounted writeDir itself has symlinks in it,
|
||||
(for example "/var" on iOS is a symlink, and the prefpath will be somewhere
|
||||
under that)...if we mounted that writeDir, we must allow those symlinks here
|
||||
unconditionally. */
|
||||
retval = ( (rc) && ((statbuf.filetype == PHYSFS_FILETYPE_DIRECTORY) || (statbuf.filetype == PHYSFS_FILETYPE_SYMLINK)) );
|
||||
} /* if */
|
||||
|
||||
if (!exists)
|
||||
@@ -2265,10 +2317,10 @@ static DirHandle *getRealDirHandle(const char *_fname)
|
||||
BAIL_IF(!_fname, PHYSFS_ERR_INVALID_ARGUMENT, NULL);
|
||||
|
||||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
len = strlen(_fname) + longest_root + 1;
|
||||
len = strlen(_fname) + longest_root + 2;
|
||||
allocated_fname = __PHYSFS_smallAlloc(len);
|
||||
BAIL_IF_MUTEX(!allocated_fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, NULL);
|
||||
fname = allocated_fname + longest_root;
|
||||
fname = allocated_fname + longest_root + 1;
|
||||
if (sanitizePlatformIndependentPath(_fname, fname))
|
||||
{
|
||||
DirHandle *i;
|
||||
@@ -2496,10 +2548,10 @@ int PHYSFS_enumerate(const char *_fn, PHYSFS_EnumerateCallback cb, void *data)
|
||||
|
||||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
|
||||
len = strlen(_fn) + longest_root + 1;
|
||||
len = strlen(_fn) + longest_root + 2;
|
||||
allocated_fname = (char *) __PHYSFS_smallAlloc(len);
|
||||
BAIL_IF_MUTEX(!allocated_fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
|
||||
fname = allocated_fname + longest_root;
|
||||
fname = allocated_fname + longest_root + 1;
|
||||
if (!sanitizePlatformIndependentPath(_fn, fname))
|
||||
retval = PHYSFS_ENUM_STOP;
|
||||
else
|
||||
@@ -2702,10 +2754,10 @@ PHYSFS_File *PHYSFS_openRead(const char *_fname)
|
||||
|
||||
BAIL_IF_MUTEX(!searchPath, PHYSFS_ERR_NOT_FOUND, stateLock, 0);
|
||||
|
||||
len = strlen(_fname) + longest_root + 1;
|
||||
len = strlen(_fname) + longest_root + 2;
|
||||
allocated_fname = (char *) __PHYSFS_smallAlloc(len);
|
||||
BAIL_IF_MUTEX(!allocated_fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
|
||||
fname = allocated_fname + longest_root;
|
||||
fname = allocated_fname + longest_root + 1;
|
||||
|
||||
if (sanitizePlatformIndependentPath(_fname, fname))
|
||||
{
|
||||
@@ -2731,13 +2783,15 @@ PHYSFS_File *PHYSFS_openRead(const char *_fname)
|
||||
io->destroy(io);
|
||||
PHYSFS_setErrorCode(PHYSFS_ERR_OUT_OF_MEMORY);
|
||||
} /* if */
|
||||
|
||||
memset(fh, '\0', sizeof (FileHandle));
|
||||
fh->io = io;
|
||||
fh->forReading = 1;
|
||||
fh->dirHandle = i;
|
||||
fh->next = openReadList;
|
||||
openReadList = fh;
|
||||
else
|
||||
{
|
||||
memset(fh, '\0', sizeof (FileHandle));
|
||||
fh->io = io;
|
||||
fh->forReading = 1;
|
||||
fh->dirHandle = i;
|
||||
fh->next = openReadList;
|
||||
openReadList = fh;
|
||||
} /* else */
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
@@ -3091,10 +3145,10 @@ int PHYSFS_stat(const char *_fname, PHYSFS_Stat *stat)
|
||||
stat->readonly = 1;
|
||||
|
||||
__PHYSFS_platformGrabMutex(stateLock);
|
||||
len = strlen(_fname) + longest_root + 1;
|
||||
len = strlen(_fname) + longest_root + 2;
|
||||
allocated_fname = (char *) __PHYSFS_smallAlloc(len);
|
||||
BAIL_IF_MUTEX(!allocated_fname, PHYSFS_ERR_OUT_OF_MEMORY, stateLock, 0);
|
||||
fname = allocated_fname + longest_root;
|
||||
fname = allocated_fname + longest_root + 1;
|
||||
|
||||
if (sanitizePlatformIndependentPath(_fname, fname))
|
||||
{
|
||||
@@ -3227,7 +3281,7 @@ static void setDefaultAllocator(void)
|
||||
} /* setDefaultAllocator */
|
||||
|
||||
|
||||
int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen)
|
||||
int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen, const int case_sensitive, const int only_usascii)
|
||||
{
|
||||
static char rootpath[2] = { '/', '\0' };
|
||||
size_t alloclen;
|
||||
@@ -3235,6 +3289,8 @@ int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen)
|
||||
assert(entrylen >= sizeof (__PHYSFS_DirTreeEntry));
|
||||
|
||||
memset(dt, '\0', sizeof (*dt));
|
||||
dt->case_sensitive = case_sensitive;
|
||||
dt->only_usascii = only_usascii;
|
||||
|
||||
dt->root = (__PHYSFS_DirTreeEntry *) allocator.Malloc(entrylen);
|
||||
BAIL_IF(!dt->root, PHYSFS_ERR_OUT_OF_MEMORY, 0);
|
||||
@@ -3255,9 +3311,10 @@ int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen)
|
||||
} /* __PHYSFS_DirTreeInit */
|
||||
|
||||
|
||||
static inline PHYSFS_uint32 hashPathName(__PHYSFS_DirTree *dt, const char *name)
|
||||
static PHYSFS_uint32 hashPathName(__PHYSFS_DirTree *dt, const char *name)
|
||||
{
|
||||
return __PHYSFS_hashString(name, strlen(name)) % dt->hashBuckets;
|
||||
const PHYSFS_uint32 hashval = dt->case_sensitive ? __PHYSFS_hashString(name) : dt->only_usascii ? __PHYSFS_hashStringCaseFoldUSAscii(name) : __PHYSFS_hashStringCaseFold(name);
|
||||
return hashval % dt->hashBuckets;
|
||||
} /* hashPathName */
|
||||
|
||||
|
||||
@@ -3318,6 +3375,7 @@ void *__PHYSFS_DirTreeAdd(__PHYSFS_DirTree *dt, char *name, const int isdir)
|
||||
/* Find the __PHYSFS_DirTreeEntry for a path in platform-independent notation. */
|
||||
void *__PHYSFS_DirTreeFind(__PHYSFS_DirTree *dt, const char *path)
|
||||
{
|
||||
const int cs = dt->case_sensitive;
|
||||
PHYSFS_uint32 hashval;
|
||||
__PHYSFS_DirTreeEntry *prev = NULL;
|
||||
__PHYSFS_DirTreeEntry *retval;
|
||||
@@ -3328,7 +3386,8 @@ void *__PHYSFS_DirTreeFind(__PHYSFS_DirTree *dt, const char *path)
|
||||
hashval = hashPathName(dt, path);
|
||||
for (retval = dt->hash[hashval]; retval; retval = retval->hashnext)
|
||||
{
|
||||
if (strcmp(retval->name, path) == 0)
|
||||
const int cmp = cs ? strcmp(retval->name, path) : PHYSFS_utf8stricmp(retval->name, path);
|
||||
if (cmp == 0)
|
||||
{
|
||||
if (prev != NULL) /* move this to the front of the list */
|
||||
{
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
* - .ISO (ISO9660 files, CD-ROM images)
|
||||
* - .GRP (Build Engine groupfile archives)
|
||||
* - .PAK (Quake I/II archive format)
|
||||
* - .HOG (Descent I/II HOG file archives)
|
||||
* - .HOG (Descent I/II/III HOG file archives)
|
||||
* - .MVL (Descent II movielib archives)
|
||||
* - .WAD (DOOM engine archives)
|
||||
* - .VDF (Gothic I/II engine archives)
|
||||
@@ -225,7 +225,9 @@ extern "C" {
|
||||
|
||||
#if defined(PHYSFS_DECL)
|
||||
/* do nothing. */
|
||||
#elif defined(_MSC_VER)
|
||||
#elif defined(PHYSFS_STATIC)
|
||||
#define PHYSFS_DECL /**/
|
||||
#elif defined(_WIN32) || defined(__OS2__)
|
||||
#define PHYSFS_DECL __declspec(dllexport)
|
||||
#elif defined(__SUNPRO_C)
|
||||
#define PHYSFS_DECL __global
|
||||
@@ -433,7 +435,7 @@ typedef struct PHYSFS_Version
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_IGNORE_THIS
|
||||
#define PHYSFS_VER_MAJOR 3
|
||||
#define PHYSFS_VER_MINOR 1
|
||||
#define PHYSFS_VER_MINOR 2
|
||||
#define PHYSFS_VER_PATCH 0
|
||||
#endif /* DOXYGEN_SHOULD_IGNORE_THIS */
|
||||
|
||||
@@ -493,6 +495,14 @@ typedef struct PHYSFS_Version
|
||||
PHYSFS_DECL void PHYSFS_getLinkedVersion(PHYSFS_Version *ver);
|
||||
|
||||
|
||||
#ifdef __ANDROID__
|
||||
typedef struct PHYSFS_AndroidInit
|
||||
{
|
||||
void *jnienv;
|
||||
void *context;
|
||||
} PHYSFS_AndroidInit;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \fn int PHYSFS_init(const char *argv0)
|
||||
* \brief Initialize the PhysicsFS library.
|
||||
@@ -502,11 +512,22 @@ PHYSFS_DECL void PHYSFS_getLinkedVersion(PHYSFS_Version *ver);
|
||||
* This should be called prior to any attempts to change your process's
|
||||
* current working directory.
|
||||
*
|
||||
* \warning On Android, argv0 should be a non-NULL pointer to a
|
||||
* PHYSFS_AndroidInit struct. This struct must hold a valid JNIEnv *
|
||||
* and a JNI jobject of a Context (either the application context or
|
||||
* the current Activity is fine). Both are cast to a void * so we
|
||||
* don't need jni.h included wherever physfs.h is. PhysicsFS
|
||||
* uses these objects to query some system details. PhysicsFS does
|
||||
* not hold a reference to the JNIEnv or Context past the call to
|
||||
* PHYSFS_init(). If you pass a NULL here, PHYSFS_init can still
|
||||
* succeed, but PHYSFS_getBaseDir() and PHYSFS_getPrefDir() will be
|
||||
* incorrect.
|
||||
*
|
||||
* \param argv0 the argv[0] string passed to your program's mainline.
|
||||
* This may be NULL on most platforms (such as ones without a
|
||||
* standard main() function), but you should always try to pass
|
||||
* something in here. Unix-like systems such as Linux _need_ to
|
||||
* pass argv[0] from main() in here.
|
||||
* something in here. Many Unix-like systems _need_ to pass argv[0]
|
||||
* from main() in here. See warning about Android, too!
|
||||
* \return nonzero on success, zero on error. Specifics of the error can be
|
||||
* gleaned from PHYSFS_getLastError().
|
||||
*
|
||||
@@ -762,6 +783,15 @@ PHYSFS_DECL char **PHYSFS_getCdRomDirs(void);
|
||||
*
|
||||
* You should probably use the base dir in your search path.
|
||||
*
|
||||
* \warning On most platforms, this is a directory; on Android, this gives
|
||||
* you the path to the app's package (APK) file. As APK files are
|
||||
* just .zip files, you can mount them in PhysicsFS like regular
|
||||
* directories. You'll probably want to call
|
||||
* PHYSFS_setRoot(basedir, "/assets") after mounting to make your
|
||||
* app's actual data available directly without all the Android
|
||||
* metadata and directory offset. Note that if you passed a NULL to
|
||||
* PHYSFS_init(), you will not get the APK file here.
|
||||
*
|
||||
* \return READ ONLY string of base dir in platform-dependent notation.
|
||||
*
|
||||
* \sa PHYSFS_getPrefDir
|
||||
@@ -2702,10 +2732,10 @@ typedef PHYSFS_EnumerateCallbackResult (*PHYSFS_EnumerateCallback)(void *data,
|
||||
*
|
||||
* \code
|
||||
*
|
||||
* static int printDir(void *data, const char *origdir, const char *fname)
|
||||
* static PHYSFS_EnumerateCallbackResult printDir(void *data, const char *origdir, const char *fname)
|
||||
* {
|
||||
* printf(" * We've got [%s] in [%s].\n", fname, origdir);
|
||||
* return 1; // give me more data, please.
|
||||
* return PHYSFS_ENUM_OK; // give me more data, please.
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
|
||||
@@ -185,7 +185,7 @@ static int szipLoadEntries(SZIPinfo *info)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (__PHYSFS_DirTreeInit(&info->tree, sizeof (SZIPentry)))
|
||||
if (__PHYSFS_DirTreeInit(&info->tree, sizeof (SZIPentry), 1, 0))
|
||||
{
|
||||
const PHYSFS_uint32 count = info->db.NumFiles;
|
||||
PHYSFS_uint32 i;
|
||||
@@ -285,13 +285,16 @@ static PHYSFS_Io *SZIP_openRead(void *opaque, const char *path)
|
||||
&blockIndex, &outBuffer, &outBufferSize, &offset,
|
||||
&outSizeProcessed, alloc, alloc);
|
||||
GOTO_IF(rc != SZ_OK, szipErrorCode(rc), SZIP_openRead_failed);
|
||||
GOTO_IF(outBuffer == NULL, PHYSFS_ERR_OUT_OF_MEMORY, SZIP_openRead_failed);
|
||||
|
||||
io->destroy(io);
|
||||
io = NULL;
|
||||
|
||||
buf = allocator.Malloc(outSizeProcessed);
|
||||
GOTO_IF(rc != SZ_OK, PHYSFS_ERR_OUT_OF_MEMORY, SZIP_openRead_failed);
|
||||
memcpy(buf, outBuffer + offset, outSizeProcessed);
|
||||
buf = allocator.Malloc(outSizeProcessed ? outSizeProcessed : 1);
|
||||
GOTO_IF(buf == NULL, PHYSFS_ERR_OUT_OF_MEMORY, SZIP_openRead_failed);
|
||||
|
||||
if (outSizeProcessed > 0)
|
||||
memcpy(buf, outBuffer + offset, outSizeProcessed);
|
||||
|
||||
alloc->Free(alloc, outBuffer);
|
||||
outBuffer = NULL;
|
||||
|
||||
@@ -76,7 +76,7 @@ static void *GRP_openArchive(PHYSFS_Io *io, const char *name,
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof(count)), NULL);
|
||||
count = PHYSFS_swapULE32(count);
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
unpkarc = UNPK_openArchive(io, 0, 1);
|
||||
BAIL_IF_ERRPASS(!unpkarc, NULL);
|
||||
|
||||
if (!grpLoadEntries(io, count, unpkarc))
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* HOG support routines for PhysicsFS.
|
||||
*
|
||||
* This driver handles Descent I/II HOG archives.
|
||||
* This driver handles Descent I/II/III HOG archives.
|
||||
*
|
||||
* The format is very simple:
|
||||
* The Descent I/II format is very simple:
|
||||
*
|
||||
* The file always starts with the 3-byte signature "DHF" (Descent
|
||||
* HOG file). After that the files of a HOG are just attached after
|
||||
@@ -23,10 +23,23 @@
|
||||
*
|
||||
* (That info is from http://www.descent2.com/ddn/specs/hog/)
|
||||
*
|
||||
* Descent 3 moved to HOG2 format, which starts with the chars "HOG2",
|
||||
* then 32-bits for the number of contained files, 32 bits for the offset
|
||||
* to the first file's data, then 56 bytes of 0xFF (reserved?). Then for
|
||||
* each file, there's 36 bytes for filename (null-terminated, rest of bytes
|
||||
* are garbage), 32-bits unknown/reserved (always zero?), 32-bits of length
|
||||
* of file data, 32-bits of time since Unix epoch. Then immediately following,
|
||||
* for each file is their uncompressed content, you can find its offset
|
||||
* by starting at the initial data offset and adding the filesize of each
|
||||
* prior file.
|
||||
*
|
||||
* This information was found at:
|
||||
* https://web.archive.org/web/20020213004051/http://descent-3.com/ddn/specs/hog/
|
||||
*
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Bradley Bell.
|
||||
* Based on grp.c by Ryan C. Gordon.
|
||||
* This file written by Bradley Bell and Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
@@ -34,7 +47,15 @@
|
||||
|
||||
#if PHYSFS_SUPPORTS_HOG
|
||||
|
||||
static int hogLoadEntries(PHYSFS_Io *io, void *arc)
|
||||
static int readui32(PHYSFS_Io *io, PHYSFS_uint32 *val)
|
||||
{
|
||||
PHYSFS_uint32 v;
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
|
||||
*val = PHYSFS_swapULE32(v);
|
||||
return 1;
|
||||
} /* readui32 */
|
||||
|
||||
static int hog1LoadEntries(PHYSFS_Io *io, void *arc)
|
||||
{
|
||||
const PHYSFS_uint64 iolen = io->length(io);
|
||||
PHYSFS_uint32 pos = 3;
|
||||
@@ -45,11 +66,10 @@ static int hogLoadEntries(PHYSFS_Io *io, void *arc)
|
||||
char name[13];
|
||||
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, name, 13), 0);
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &size, 4), 0);
|
||||
BAIL_IF_ERRPASS(!readui32(io, &size), 0);
|
||||
name[12] = '\0'; /* just in case. */
|
||||
pos += 13 + 4;
|
||||
|
||||
size = PHYSFS_swapULE32(size);
|
||||
BAIL_IF_ERRPASS(!UNPK_addEntry(arc, name, 0, -1, -1, pos, size), 0);
|
||||
pos += size;
|
||||
|
||||
@@ -60,24 +80,60 @@ static int hogLoadEntries(PHYSFS_Io *io, void *arc)
|
||||
return 1;
|
||||
} /* hogLoadEntries */
|
||||
|
||||
static int hog2LoadEntries(PHYSFS_Io *io, void *arc)
|
||||
{
|
||||
PHYSFS_uint32 numfiles;
|
||||
PHYSFS_uint32 pos;
|
||||
PHYSFS_uint32 i;
|
||||
|
||||
BAIL_IF_ERRPASS(!readui32(io, &numfiles), 0);
|
||||
BAIL_IF_ERRPASS(!readui32(io, &pos), 0);
|
||||
BAIL_IF_ERRPASS(!io->seek(io, 68), 0); /* skip to end of header. */
|
||||
|
||||
for (i = 0; i < numfiles; i++) {
|
||||
char name[37];
|
||||
PHYSFS_uint32 reserved;
|
||||
PHYSFS_uint32 size;
|
||||
PHYSFS_uint32 mtime;
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, name, 36), 0);
|
||||
BAIL_IF_ERRPASS(!readui32(io, &reserved), 0);
|
||||
BAIL_IF_ERRPASS(!readui32(io, &size), 0);
|
||||
BAIL_IF_ERRPASS(!readui32(io, &mtime), 0);
|
||||
name[36] = '\0'; /* just in case */
|
||||
BAIL_IF_ERRPASS(!UNPK_addEntry(arc, name, 0, mtime, mtime, pos, size), 0);
|
||||
pos += size;
|
||||
}
|
||||
|
||||
return 1;
|
||||
} /* hog2LoadEntries */
|
||||
|
||||
|
||||
static void *HOG_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
PHYSFS_uint8 buf[3];
|
||||
void *unpkarc = NULL;
|
||||
int hog1 = 0;
|
||||
|
||||
assert(io != NULL); /* shouldn't ever happen. */
|
||||
BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, buf, 3), NULL);
|
||||
BAIL_IF(memcmp(buf, "DHF", 3) != 0, PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
|
||||
if (memcmp(buf, "DHF", 3) == 0)
|
||||
hog1 = 1; /* original HOG (Descent 1 and 2) archive */
|
||||
else
|
||||
{
|
||||
BAIL_IF(memcmp(buf, "HOG", 3) != 0, PHYSFS_ERR_UNSUPPORTED, NULL); /* Not HOG2 */
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, buf, 1), NULL);
|
||||
BAIL_IF(buf[0] != '2', PHYSFS_ERR_UNSUPPORTED, NULL); /* Not HOG2 */
|
||||
} /* else */
|
||||
|
||||
*claimed = 1;
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
unpkarc = UNPK_openArchive(io, 0, 1);
|
||||
BAIL_IF_ERRPASS(!unpkarc, NULL);
|
||||
|
||||
if (!hogLoadEntries(io, unpkarc))
|
||||
if (!(hog1 ? hog1LoadEntries(io, unpkarc) : hog2LoadEntries(io, unpkarc)))
|
||||
{
|
||||
UNPK_abandonArchive(unpkarc);
|
||||
return NULL;
|
||||
@@ -92,7 +148,7 @@ const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
|
||||
CURRENT_PHYSFS_ARCHIVER_API_VERSION,
|
||||
{
|
||||
"HOG",
|
||||
"Descent I/II HOG file format",
|
||||
"Descent I/II/III HOG file format",
|
||||
"Bradley Bell <btb@icculus.org>",
|
||||
"https://icculus.org/physfs/",
|
||||
0, /* supportsSymlinks */
|
||||
|
||||
@@ -251,7 +251,7 @@ static int parseVolumeDescriptor(PHYSFS_Io *io, PHYSFS_uint64 *_rootpos,
|
||||
pos += 2048; /* each volume descriptor is 2048 bytes */
|
||||
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &type, 1), 0);
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &identifier, 5), 0);
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, identifier, 5), 0);
|
||||
|
||||
if (memcmp(identifier, "CD001", 5) != 0) /* maybe not an iso? */
|
||||
{
|
||||
@@ -346,7 +346,8 @@ static void *ISO9660_openArchive(PHYSFS_Io *io, const char *filename,
|
||||
if (!parseVolumeDescriptor(io, &rootpos, &len, &joliet, claimed))
|
||||
return NULL;
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
/* !!! FIXME: check case_sensitive and only_usascii params for this archive. */
|
||||
unpkarc = UNPK_openArchive(io, 1, 0);
|
||||
BAIL_IF_ERRPASS(!unpkarc, NULL);
|
||||
|
||||
if (!iso9660LoadEntries(io, joliet, "", rootpos, rootpos + len, unpkarc))
|
||||
|
||||
@@ -70,7 +70,7 @@ static void *MVL_openArchive(PHYSFS_Io *io, const char *name,
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof(count)), NULL);
|
||||
count = PHYSFS_swapULE32(count);
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
unpkarc = UNPK_openArchive(io, 0, 1);
|
||||
BAIL_IF_ERRPASS(!unpkarc, NULL);
|
||||
|
||||
if (!mvlLoadEntries(io, count, unpkarc))
|
||||
|
||||
@@ -86,7 +86,8 @@ static void *QPAK_openArchive(PHYSFS_Io *io, const char *name,
|
||||
|
||||
BAIL_IF_ERRPASS(!io->seek(io, pos), NULL);
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
/* !!! FIXME: check case_sensitive and only_usascii params for this archive. */
|
||||
unpkarc = UNPK_openArchive(io, 1, 0);
|
||||
BAIL_IF_ERRPASS(!unpkarc, NULL);
|
||||
|
||||
if (!qpakLoadEntries(io, count, unpkarc))
|
||||
|
||||
@@ -36,7 +36,7 @@ static int slbLoadEntries(PHYSFS_Io *io, const PHYSFS_uint32 count, void *arc)
|
||||
BAIL_IF(backslash != '\\', PHYSFS_ERR_CORRUPT, 0);
|
||||
|
||||
/* read the rest of the buffer, 63 bytes */
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &name, 63), 0);
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, name, 63), 0);
|
||||
name[63] = '\0'; /* in case the name lacks the null terminator */
|
||||
|
||||
/* convert backslashes */
|
||||
@@ -94,7 +94,8 @@ static void *SLB_openArchive(PHYSFS_Io *io, const char *name,
|
||||
/* seek to the table of contents */
|
||||
BAIL_IF_ERRPASS(!io->seek(io, tocPos), NULL);
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
/* !!! FIXME: check case_sensitive and only_usascii params for this archive. */
|
||||
unpkarc = UNPK_openArchive(io, 1, 0);
|
||||
BAIL_IF_ERRPASS(!unpkarc, NULL);
|
||||
|
||||
if (!slbLoadEntries(io, count, unpkarc))
|
||||
|
||||
@@ -285,12 +285,12 @@ void *UNPK_addEntry(void *opaque, char *name, const int isdir,
|
||||
} /* UNPK_addEntry */
|
||||
|
||||
|
||||
void *UNPK_openArchive(PHYSFS_Io *io)
|
||||
void *UNPK_openArchive(PHYSFS_Io *io, const int case_sensitive, const int only_usascii)
|
||||
{
|
||||
UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo));
|
||||
BAIL_IF(!info, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
if (!__PHYSFS_DirTreeInit(&info->tree, sizeof (UNPKentry)))
|
||||
if (!__PHYSFS_DirTreeInit(&info->tree, sizeof (UNPKentry), case_sensitive, only_usascii))
|
||||
{
|
||||
allocator.Free(info);
|
||||
return NULL;
|
||||
|
||||
@@ -129,7 +129,8 @@ static void *VDF_openArchive(PHYSFS_Io *io, const char *name,
|
||||
|
||||
BAIL_IF_ERRPASS(!io->seek(io, rootCatOffset), NULL);
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
/* !!! FIXME: check case_sensitive and only_usascii params for this archive. */
|
||||
unpkarc = UNPK_openArchive(io, 1, 0);
|
||||
BAIL_IF_ERRPASS(!unpkarc, NULL);
|
||||
|
||||
if (!vdfLoadEntries(io, count, vdfDosTimeToEpoch(timestamp), unpkarc))
|
||||
|
||||
@@ -95,7 +95,7 @@ static void *WAD_openArchive(PHYSFS_Io *io, const char *name,
|
||||
|
||||
BAIL_IF_ERRPASS(!io->seek(io, directoryOffset), 0);
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
unpkarc = UNPK_openArchive(io, 0, 1);
|
||||
BAIL_IF_ERRPASS(!unpkarc, NULL);
|
||||
|
||||
if (!wadLoadEntries(io, count, unpkarc))
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#if (PHYSFS_BYTEORDER == PHYSFS_LIL_ENDIAN)
|
||||
#define MINIZ_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define MINIZ_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
#include "physfs_miniz.h"
|
||||
|
||||
/*
|
||||
@@ -568,7 +573,7 @@ static PHYSFS_sint64 zip_find_end_of_central_dir(PHYSFS_Io *io, PHYSFS_sint64 *l
|
||||
{
|
||||
if (!__PHYSFS_readAll(io, buf, maxread - 4))
|
||||
return -1;
|
||||
memcpy(&buf[maxread - 4], &extra, sizeof (extra));
|
||||
memcpy(&buf[maxread - 4], extra, sizeof (extra));
|
||||
totalread += maxread - 4;
|
||||
} /* if */
|
||||
else
|
||||
@@ -578,7 +583,7 @@ static PHYSFS_sint64 zip_find_end_of_central_dir(PHYSFS_Io *io, PHYSFS_sint64 *l
|
||||
totalread += maxread;
|
||||
} /* else */
|
||||
|
||||
memcpy(&extra, buf, sizeof (extra));
|
||||
memcpy(extra, buf, sizeof (extra));
|
||||
|
||||
for (i = maxread - 4; i > 0; i--)
|
||||
{
|
||||
@@ -833,7 +838,10 @@ static int zip_parse_local(PHYSFS_Io *io, ZIPentry *entry)
|
||||
BAIL_IF_ERRPASS(!readui32(io, &ui32), 0);
|
||||
BAIL_IF(ui32 != ZIP_LOCAL_FILE_SIG, PHYSFS_ERR_CORRUPT, 0);
|
||||
BAIL_IF_ERRPASS(!readui16(io, &ui16), 0);
|
||||
BAIL_IF(ui16 != entry->version_needed, PHYSFS_ERR_CORRUPT, 0);
|
||||
/* Windows Explorer might rewrite the entire central directory, setting
|
||||
this field to 2.0/MS-DOS for all files, so favor the local version,
|
||||
which it leaves intact if it didn't alter that specific file. */
|
||||
entry->version_needed = ui16;
|
||||
BAIL_IF_ERRPASS(!readui16(io, &ui16), 0); /* general bits. */
|
||||
BAIL_IF_ERRPASS(!readui16(io, &ui16), 0);
|
||||
BAIL_IF(ui16 != entry->compression_method, PHYSFS_ERR_CORRUPT, 0);
|
||||
@@ -1482,7 +1490,7 @@ static void *ZIP_openArchive(PHYSFS_Io *io, const char *name,
|
||||
|
||||
if (!zip_parse_end_of_central_dir(info, &dstart, &cdir_ofs, &count))
|
||||
goto ZIP_openarchive_failed;
|
||||
else if (!__PHYSFS_DirTreeInit(&info->tree, sizeof (ZIPentry)))
|
||||
else if (!__PHYSFS_DirTreeInit(&info->tree, sizeof (ZIPentry), 1, 0))
|
||||
goto ZIP_openarchive_failed;
|
||||
|
||||
root = (ZIPentry *) info->tree.root;
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#ifdef PHYSFS_PLATFORM_SOLARIS
|
||||
#if defined(PHYSFS_PLATFORM_SOLARIS) || defined(PHYSFS_PLATFORM_LINUX)
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
@@ -69,7 +69,7 @@ extern "C" {
|
||||
All file-private symbols need to be marked "static".
|
||||
Everything shared between PhysicsFS sources needs to be in this
|
||||
file between the visibility pragma blocks. */
|
||||
#if PHYSFS_MINIMUM_GCC_VERSION(4,0) || defined(__clang__)
|
||||
#if !defined(_WIN32) && (PHYSFS_MINIMUM_GCC_VERSION(4,0) || defined(__clang__))
|
||||
#define PHYSFS_HAVE_PRAGMA_VISIBILITY 1
|
||||
#endif
|
||||
|
||||
@@ -95,6 +95,7 @@ extern const PHYSFS_Archiver __PHYSFS_Archiver_VDF;
|
||||
/* a real C99-compliant snprintf() is in Visual Studio 2015,
|
||||
but just use this everywhere for binary compatibility. */
|
||||
#if defined(_MSC_VER)
|
||||
#include <stdarg.h>
|
||||
int __PHYSFS_msvc_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap);
|
||||
int __PHYSFS_msvc_snprintf(char *outBuf, size_t size, const char *format, ...);
|
||||
#define vsnprintf __PHYSFS_msvc_vsnprintf
|
||||
@@ -108,14 +109,24 @@ const void *__PHYSFS_winrtCalcPrefDir(void);
|
||||
#endif
|
||||
|
||||
/* atomic operations. */
|
||||
/* increment/decrement operations return the final incremented/decremented value. */
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1500)
|
||||
#include <intrin.h>
|
||||
__PHYSFS_COMPILE_TIME_ASSERT(LongEqualsInt, sizeof (int) == sizeof (long));
|
||||
#define __PHYSFS_ATOMIC_INCR(ptrval) _InterlockedIncrement((long*)(ptrval))
|
||||
#define __PHYSFS_ATOMIC_DECR(ptrval) _InterlockedDecrement((long*)(ptrval))
|
||||
#elif defined(__clang__) || (defined(__GNUC__) && (((__GNUC__ * 10000) + (__GNUC_MINOR__ * 100)) >= 40100))
|
||||
#define __PHYSFS_ATOMIC_INCR(ptrval) __sync_fetch_and_add(ptrval, 1)
|
||||
#define __PHYSFS_ATOMIC_DECR(ptrval) __sync_fetch_and_add(ptrval, -1)
|
||||
#define __PHYSFS_ATOMIC_INCR(ptrval) __sync_add_and_fetch(ptrval, 1)
|
||||
#define __PHYSFS_ATOMIC_DECR(ptrval) __sync_add_and_fetch(ptrval, -1)
|
||||
#elif defined(__WATCOMC__) && defined(__386__)
|
||||
extern __inline int _xadd_watcom(volatile int *a, int v);
|
||||
#pragma aux _xadd_watcom = \
|
||||
"lock xadd [ecx], eax" \
|
||||
parm [ecx] [eax] \
|
||||
value [eax] \
|
||||
modify exact [eax];
|
||||
#define __PHYSFS_ATOMIC_INCR(ptrval) (_xadd_watcom(ptrval, 1)+1)
|
||||
#define __PHYSFS_ATOMIC_DECR(ptrval) (_xadd_watcom(ptrval, -1)-1)
|
||||
#else
|
||||
#define PHYSFS_NEED_ATOMIC_OP_FALLBACK 1
|
||||
int __PHYSFS_ATOMIC_INCR(int *ptrval);
|
||||
@@ -213,6 +224,7 @@ extern void SZIP_global_init(void);
|
||||
/* The latest supported PHYSFS_Archiver::version value. */
|
||||
#define CURRENT_PHYSFS_ARCHIVER_API_VERSION 0
|
||||
|
||||
|
||||
/* This byteorder stuff was lifted from SDL. https://www.libsdl.org/ */
|
||||
#define PHYSFS_LIL_ENDIAN 1234
|
||||
#define PHYSFS_BIG_ENDIAN 4321
|
||||
@@ -220,11 +232,26 @@ extern void SZIP_global_init(void);
|
||||
#ifdef __linux__
|
||||
#include <endian.h>
|
||||
#define PHYSFS_BYTEORDER __BYTE_ORDER
|
||||
#else /* __linux__ */
|
||||
#elif defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#include <endian.h>
|
||||
#define PHYSFS_BYTEORDER BYTE_ORDER
|
||||
#elif defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
#include <sys/endian.h>
|
||||
#define PHYSFS_BYTEORDER BYTE_ORDER
|
||||
/* predefs from newer gcc and clang versions: */
|
||||
#elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__)
|
||||
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
#define PHYSFS_BYTEORDER PHYSFS_LIL_ENDIAN
|
||||
#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
#define PHYSFS_BYTEORDER PHYSFS_BIG_ENDIAN
|
||||
#else
|
||||
#error Unsupported endianness
|
||||
#endif /**/
|
||||
#else
|
||||
#if defined(__hppa__) || \
|
||||
defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
|
||||
(defined(__MIPS__) && defined(__MISPEB__)) || \
|
||||
defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
|
||||
(defined(__MIPS__) && defined(__MIPSEB__)) || \
|
||||
defined(__ppc__) || defined(__POWERPC__) || defined(__powerpc__) || defined(__PPC__) || \
|
||||
defined(__sparc__)
|
||||
#define PHYSFS_BYTEORDER PHYSFS_BIG_ENDIAN
|
||||
#else
|
||||
@@ -312,7 +339,18 @@ char *__PHYSFS_strdup(const char *str);
|
||||
/*
|
||||
* Give a hash value for a C string (uses djb's xor hashing algorithm).
|
||||
*/
|
||||
PHYSFS_uint32 __PHYSFS_hashString(const char *str, size_t len);
|
||||
PHYSFS_uint32 __PHYSFS_hashString(const char *str);
|
||||
|
||||
/*
|
||||
* Give a hash value for a C string (uses djb's xor hashing algorithm), case folding as it goes.
|
||||
*/
|
||||
PHYSFS_uint32 __PHYSFS_hashStringCaseFold(const char *str);
|
||||
|
||||
/*
|
||||
* Give a hash value for a C string (uses djb's xor hashing algorithm), case folding as it goes,
|
||||
* assuming that this is only US-ASCII chars (one byte per char, only 'A' through 'Z' need folding).
|
||||
*/
|
||||
PHYSFS_uint32 __PHYSFS_hashStringCaseFoldUSAscii(const char *str);
|
||||
|
||||
|
||||
/*
|
||||
@@ -348,9 +386,10 @@ int __PHYSFS_readAll(PHYSFS_Io *io, void *buf, const size_t len);
|
||||
|
||||
/* These are shared between some archivers. */
|
||||
|
||||
/* LOTS of legacy formats that only use US ASCII, not actually UTF-8, so let them optimize here. */
|
||||
void *UNPK_openArchive(PHYSFS_Io *io, const int case_sensitive, const int only_usascii);
|
||||
void UNPK_abandonArchive(void *opaque);
|
||||
void UNPK_closeArchive(void *opaque);
|
||||
void *UNPK_openArchive(PHYSFS_Io *io);
|
||||
void *UNPK_addEntry(void *opaque, char *name, const int isdir,
|
||||
const PHYSFS_sint64 ctime, const PHYSFS_sint64 mtime,
|
||||
const PHYSFS_uint64 pos, const PHYSFS_uint64 len);
|
||||
@@ -382,10 +421,13 @@ typedef struct __PHYSFS_DirTree
|
||||
__PHYSFS_DirTreeEntry **hash; /* all entries hashed for fast lookup. */
|
||||
size_t hashBuckets; /* number of buckets in hash. */
|
||||
size_t entrylen; /* size in bytes of entries (including subclass). */
|
||||
int case_sensitive; /* non-zero to treat entries as case-sensitive in DirTreeFind */
|
||||
int only_usascii; /* non-zero to treat paths as US ASCII only (one byte per char, only 'A' through 'Z' are considered for case folding). */
|
||||
} __PHYSFS_DirTree;
|
||||
|
||||
|
||||
int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen);
|
||||
/* LOTS of legacy formats that only use US ASCII, not actually UTF-8, so let them optimize here. */
|
||||
int __PHYSFS_DirTreeInit(__PHYSFS_DirTree *dt, const size_t entrylen, const int case_sensitive, const int only_usascii);
|
||||
void *__PHYSFS_DirTreeAdd(__PHYSFS_DirTree *dt, char *name, const int isdir);
|
||||
void *__PHYSFS_DirTreeFind(__PHYSFS_DirTree *dt, const char *path);
|
||||
PHYSFS_EnumerateCallbackResult __PHYSFS_DirTreeEnumerate(void *opaque,
|
||||
@@ -715,6 +757,11 @@ int __PHYSFS_platformGrabMutex(void *mutex);
|
||||
*/
|
||||
void __PHYSFS_platformReleaseMutex(void *mutex);
|
||||
|
||||
|
||||
/* !!! FIXME: move to public API? */
|
||||
PHYSFS_uint32 __PHYSFS_utf8codepoint(const char **_str);
|
||||
|
||||
|
||||
#if PHYSFS_HAVE_PRAGMA_VISIBILITY
|
||||
#pragma GCC visibility pop
|
||||
#endif
|
||||
|
||||
@@ -506,6 +506,7 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_AMD64) \
|
||||
|| defined(_M_ARM64) \
|
||||
|| defined(_M_IA64) \
|
||||
|| defined(__AARCH64EL__) \
|
||||
|| defined(__AARCH64EB__)
|
||||
@@ -531,6 +532,8 @@ MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned mem
|
||||
|
||||
#if defined(_WIN32) && defined(_M_ARM)
|
||||
#define MY_CPU_ARM_LE
|
||||
#elif defined(_WIN64) && defined(_M_ARM64)
|
||||
#define MY_CPU_ARM_LE
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(_M_IA64)
|
||||
|
||||
@@ -22,12 +22,14 @@ typedef unsigned long mz_ulong;
|
||||
typedef void *(*mz_alloc_func)(void *opaque, unsigned int items, unsigned int size);
|
||||
typedef void (*mz_free_func)(void *opaque, void *address);
|
||||
|
||||
#ifndef MINIZ_LITTLE_ENDIAN /* if not defined by PHYSFS */
|
||||
#if defined(_M_IX86) || defined(_M_X64)
|
||||
/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 if integer loads and stores to unaligned addresses are acceptable on the target platform (slightly faster). */
|
||||
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
|
||||
/* Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. */
|
||||
#define MINIZ_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
#endif /**/
|
||||
|
||||
#if defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__)
|
||||
/* Set MINIZ_HAS_64BIT_REGISTERS to 1 if the processor has 64-bit general purpose registers (enables 64-bit bitbuffer in inflator) */
|
||||
@@ -117,6 +119,8 @@ struct tinfl_decompressor_tag
|
||||
#define MZ_MAX(a,b) (((a)>(b))?(a):(b))
|
||||
#define MZ_MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
|
||||
#define MZ_CLEAR_ARR(obj) memset((obj), 0, sizeof(obj))
|
||||
#define MZ_CLEAR_PTR(obj) memset((obj), 0, sizeof(*obj))
|
||||
|
||||
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
|
||||
#define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
|
||||
@@ -166,13 +170,17 @@ struct tinfl_decompressor_tag
|
||||
if (temp >= 0) { \
|
||||
code_len = temp >> 9; \
|
||||
if ((code_len) && (num_bits >= code_len)) \
|
||||
break; \
|
||||
break; \
|
||||
} else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \
|
||||
code_len = TINFL_FAST_LOOKUP_BITS; \
|
||||
do { \
|
||||
temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
|
||||
} while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \
|
||||
} TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \
|
||||
} while ((temp < 0) && (num_bits >= (code_len + 1))); \
|
||||
if (temp >= 0) break; \
|
||||
} \
|
||||
TINFL_GET_BYTE(state_index, c); \
|
||||
bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
|
||||
num_bits += 8; \
|
||||
} while (num_bits < 15);
|
||||
|
||||
/* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */
|
||||
@@ -274,13 +282,13 @@ static tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_
|
||||
else
|
||||
{
|
||||
for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; }
|
||||
MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
|
||||
MZ_CLEAR_ARR(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; }
|
||||
r->m_table_sizes[2] = 19;
|
||||
}
|
||||
for ( ; (int)r->m_type >= 0; r->m_type--)
|
||||
{
|
||||
int tree_next, tree_cur; tinfl_huff_table *pTable;
|
||||
mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree);
|
||||
mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_ARR(total_syms); MZ_CLEAR_ARR(pTable->m_look_up); MZ_CLEAR_ARR(pTable->m_tree);
|
||||
for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++;
|
||||
used_syms = 0, total = 0; next_code[0] = next_code[1] = 0;
|
||||
for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); }
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Android support routines for PhysicsFS.
|
||||
*
|
||||
* Please see the file LICENSE.txt in the source's root directory.
|
||||
*
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_platforms.h"
|
||||
|
||||
#ifdef PHYSFS_PLATFORM_ANDROID
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include "physfs_internal.h"
|
||||
|
||||
static char *prefpath = NULL;
|
||||
|
||||
|
||||
int __PHYSFS_platformInit(void)
|
||||
{
|
||||
return 1; /* always succeed. */
|
||||
} /* __PHYSFS_platformInit */
|
||||
|
||||
|
||||
void __PHYSFS_platformDeinit(void)
|
||||
{
|
||||
if (prefpath)
|
||||
{
|
||||
allocator.Free(prefpath);
|
||||
prefpath = NULL;
|
||||
} /* if */
|
||||
} /* __PHYSFS_platformDeinit */
|
||||
|
||||
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
/* no-op. */
|
||||
} /* __PHYSFS_platformDetectAvailableCDs */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
{
|
||||
/* as a cheat, we expect argv0 to be a PHYSFS_AndroidInit* on Android. */
|
||||
PHYSFS_AndroidInit *ainit = (PHYSFS_AndroidInit *) argv0;
|
||||
char *retval = NULL;
|
||||
JNIEnv *jenv = NULL;
|
||||
jobject jcontext;
|
||||
|
||||
if (ainit == NULL)
|
||||
return __PHYSFS_strdup("/"); /* oh well. */
|
||||
|
||||
jenv = (JNIEnv *) ainit->jnienv;
|
||||
jcontext = (jobject) ainit->context;
|
||||
|
||||
if ((*jenv)->PushLocalFrame(jenv, 16) >= 0)
|
||||
{
|
||||
jobject jfileobj = 0;
|
||||
jmethodID jmeth = 0;
|
||||
jthrowable jexception = 0;
|
||||
jstring jstr = 0;
|
||||
|
||||
jmeth = (*jenv)->GetMethodID(jenv, (*jenv)->GetObjectClass(jenv, jcontext), "getPackageResourcePath", "()Ljava/lang/String;");
|
||||
jstr = (jstring)(*jenv)->CallObjectMethod(jenv, jcontext, jmeth);
|
||||
jexception = (*jenv)->ExceptionOccurred(jenv); /* this can't throw an exception, right? Just in case. */
|
||||
if (jexception != NULL)
|
||||
(*jenv)->ExceptionClear(jenv);
|
||||
else
|
||||
{
|
||||
const char *path = (*jenv)->GetStringUTFChars(jenv, jstr, NULL);
|
||||
retval = __PHYSFS_strdup(path);
|
||||
(*jenv)->ReleaseStringUTFChars(jenv, jstr, path);
|
||||
} /* else */
|
||||
|
||||
/* We only can rely on the Activity being valid during this function call,
|
||||
so go ahead and grab the prefpath too. */
|
||||
jmeth = (*jenv)->GetMethodID(jenv, (*jenv)->GetObjectClass(jenv, jcontext), "getFilesDir", "()Ljava/io/File;");
|
||||
jfileobj = (*jenv)->CallObjectMethod(jenv, jcontext, jmeth);
|
||||
if (jfileobj)
|
||||
{
|
||||
jmeth = (*jenv)->GetMethodID(jenv, (*jenv)->GetObjectClass(jenv, jfileobj), "getCanonicalPath", "()Ljava/lang/String;");
|
||||
jstr = (jstring)(*jenv)->CallObjectMethod(jenv, jfileobj, jmeth);
|
||||
jexception = (*jenv)->ExceptionOccurred(jenv);
|
||||
if (jexception != NULL)
|
||||
(*jenv)->ExceptionClear(jenv);
|
||||
else
|
||||
{
|
||||
const char *path = (*jenv)->GetStringUTFChars(jenv, jstr, NULL);
|
||||
const size_t len = strlen(path) + 2;
|
||||
prefpath = allocator.Malloc(len);
|
||||
if (prefpath)
|
||||
snprintf(prefpath, len, "%s/", path);
|
||||
(*jenv)->ReleaseStringUTFChars(jenv, jstr, path);
|
||||
} /* else */
|
||||
} /* if */
|
||||
|
||||
(*jenv)->PopLocalFrame(jenv, NULL);
|
||||
} /* if */
|
||||
|
||||
/* we can't return NULL because then PhysicsFS will treat argv0 as a string, but it's a non-NULL jobject! */
|
||||
if (retval == NULL)
|
||||
retval = __PHYSFS_strdup("/"); /* we pray this works. */
|
||||
|
||||
return retval;
|
||||
} /* __PHYSFS_platformCalcBaseDir */
|
||||
|
||||
|
||||
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app)
|
||||
{
|
||||
return __PHYSFS_strdup(prefpath ? prefpath : "/");
|
||||
} /* __PHYSFS_platformCalcPrefDir */
|
||||
|
||||
#endif /* PHYSFS_PLATFORM_ANDROID */
|
||||
|
||||
/* end of physfs_platform_android.c ... */
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#ifdef PHYSFS_PLATFORM_APPLE
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "physfs_internal.h"
|
||||
|
||||
@@ -99,7 +100,7 @@ static int darwinIsWholeMedia(io_service_t service)
|
||||
} /* darwinIsWholeMedia */
|
||||
|
||||
|
||||
static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
|
||||
static int darwinIsMountedDisc(char *bsdName, mach_port_t mainPort)
|
||||
{
|
||||
int retval = 0;
|
||||
CFMutableDictionaryRef matchingDict;
|
||||
@@ -107,10 +108,10 @@ static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
|
||||
io_iterator_t iter;
|
||||
io_service_t service;
|
||||
|
||||
if ((matchingDict = IOBSDNameMatching(masterPort, 0, bsdName)) == NULL)
|
||||
if ((matchingDict = IOBSDNameMatching(mainPort, 0, bsdName)) == NULL)
|
||||
return 0;
|
||||
|
||||
rc = IOServiceGetMatchingServices(masterPort, matchingDict, &iter);
|
||||
rc = IOServiceGetMatchingServices(mainPort, matchingDict, &iter);
|
||||
if ((rc != KERN_SUCCESS) || (!iter))
|
||||
return 0;
|
||||
|
||||
@@ -158,13 +159,25 @@ static int darwinIsMountedDisc(char *bsdName, mach_port_t masterPort)
|
||||
void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
{
|
||||
#if !defined(PHYSFS_NO_CDROM_SUPPORT)
|
||||
/* macOS 12.0 changed "master" names to "main". */
|
||||
typedef kern_return_t (*ioMainPortFn)(mach_port_t, mach_port_t *);
|
||||
static ioMainPortFn ioMainPort = NULL;
|
||||
const char *devPrefix = "/dev/";
|
||||
const int prefixLen = strlen(devPrefix);
|
||||
mach_port_t masterPort = 0;
|
||||
mach_port_t mainPort = 0;
|
||||
struct statfs *mntbufp;
|
||||
int i, mounts;
|
||||
|
||||
if (IOMasterPort(MACH_PORT_NULL, &masterPort) != KERN_SUCCESS)
|
||||
if (ioMainPort == NULL)
|
||||
{
|
||||
ioMainPort = (ioMainPortFn) dlsym(RTLD_DEFAULT, "IOMainPort");
|
||||
if (!ioMainPort)
|
||||
ioMainPort = (ioMainPortFn) dlsym(RTLD_DEFAULT, "IOMasterPort");
|
||||
if (!ioMainPort)
|
||||
return; /* oh well, no CD-ROMs for you. */
|
||||
} /* if */
|
||||
|
||||
if (ioMainPort(MACH_PORT_NULL, &mainPort) != KERN_SUCCESS)
|
||||
BAIL(PHYSFS_ERR_OS_ERROR, ) /*return void*/;
|
||||
|
||||
mounts = getmntinfo(&mntbufp, MNT_WAIT); /* NOT THREAD SAFE! */
|
||||
@@ -176,7 +189,7 @@ void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data)
|
||||
continue;
|
||||
|
||||
dev += prefixLen;
|
||||
if (darwinIsMountedDisc(dev, masterPort))
|
||||
if (darwinIsMountedDisc(dev, mainPort))
|
||||
cb(data, mnt);
|
||||
} /* for */
|
||||
#endif /* !defined(PHYSFS_NO_CDROM_SUPPORT) */
|
||||
|
||||
@@ -222,7 +222,7 @@ static char *cvtPathToCorrectCase(char *buf)
|
||||
if (ptr != NULL) /* isolate element to find (fname is the start). */
|
||||
*ptr = '\0';
|
||||
|
||||
rc = DosFindFirst((unsigned char *) spec, &hdir, FILE_DIRECTORY,
|
||||
rc = DosFindFirst(spec, &hdir, FILE_DIRECTORY,
|
||||
&fb, sizeof (fb), &count, FIL_STANDARD);
|
||||
if (rc == NO_ERROR)
|
||||
{
|
||||
@@ -331,7 +331,7 @@ static int isCdRomDrive(ULONG drive)
|
||||
ULONG ul1, ul2;
|
||||
APIRET rc;
|
||||
HFILE hfile = NULLHANDLE;
|
||||
unsigned char drivename[3] = { 0, ':', '\0' };
|
||||
char drivename[3] = { 0, ':', '\0' };
|
||||
|
||||
drivename[0] = 'A' + drive;
|
||||
|
||||
@@ -443,7 +443,7 @@ PHYSFS_EnumerateCallbackResult __PHYSFS_platformEnumerate(const char *dirname,
|
||||
__PHYSFS_smallFree(utf8);
|
||||
BAIL_IF_ERRPASS(!cpspec, PHYSFS_ENUM_ERROR);
|
||||
|
||||
rc = DosFindFirst((unsigned char *) cpspec, &hdir,
|
||||
rc = DosFindFirst(cpspec, &hdir,
|
||||
FILE_DIRECTORY | FILE_ARCHIVED |
|
||||
FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM,
|
||||
&fb, sizeof (fb), &count, FIL_STANDARD);
|
||||
@@ -535,7 +535,7 @@ int __PHYSFS_platformMkDir(const char *filename)
|
||||
APIRET rc;
|
||||
char *cpstr = cvtUtf8ToCodepage(filename);
|
||||
BAIL_IF_ERRPASS(!cpstr, 0);
|
||||
rc = DosCreateDir((unsigned char *) cpstr, NULL);
|
||||
rc = DosCreateDir(cpstr, NULL);
|
||||
allocator.Free(cpstr);
|
||||
BAIL_IF(rc != NO_ERROR, errcodeFromAPIRET(rc), 0);
|
||||
return 1;
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
/* !!! FIXME: check for EINTR? */
|
||||
|
||||
#define __PHYSICSFS_INTERNAL__
|
||||
#include "physfs_platforms.h"
|
||||
|
||||
@@ -157,19 +155,41 @@ int __PHYSFS_platformMkDir(const char *path)
|
||||
} /* __PHYSFS_platformMkDir */
|
||||
|
||||
|
||||
#if !defined(O_CLOEXEC) && defined(FD_CLOEXEC)
|
||||
static inline void set_CLOEXEC(int fildes)
|
||||
{
|
||||
int flags = fcntl(fildes, F_GETFD);
|
||||
if (flags != -1) {
|
||||
fcntl(fildes, F_SETFD, flags | FD_CLOEXEC);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *doOpen(const char *filename, int mode)
|
||||
{
|
||||
const int appending = (mode & O_APPEND);
|
||||
int fd;
|
||||
int *retval;
|
||||
|
||||
errno = 0;
|
||||
|
||||
/* O_APPEND doesn't actually behave as we'd like. */
|
||||
mode &= ~O_APPEND;
|
||||
|
||||
fd = open(filename, mode, S_IRUSR | S_IWUSR);
|
||||
#ifdef O_CLOEXEC
|
||||
/* Add O_CLOEXEC if defined */
|
||||
mode |= O_CLOEXEC;
|
||||
#endif
|
||||
|
||||
do {
|
||||
fd = open(filename, mode, S_IRUSR | S_IWUSR);
|
||||
} while ((fd < 0) && (errno == EINTR));
|
||||
BAIL_IF(fd < 0, errcodeFromErrno(), NULL);
|
||||
|
||||
#if !defined(O_CLOEXEC) && defined(FD_CLOEXEC)
|
||||
set_CLOEXEC(fd);
|
||||
#endif
|
||||
|
||||
if (appending)
|
||||
{
|
||||
if (lseek(fd, 0, SEEK_END) < 0)
|
||||
@@ -219,7 +239,9 @@ PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buffer,
|
||||
if (!__PHYSFS_ui64FitsAddressSpace(len))
|
||||
BAIL(PHYSFS_ERR_INVALID_ARGUMENT, -1);
|
||||
|
||||
rc = read(fd, buffer, (size_t) len);
|
||||
do {
|
||||
rc = read(fd, buffer, (size_t) len);
|
||||
} while ((rc == -1) && (errno == EINTR));
|
||||
BAIL_IF(rc == -1, errcodeFromErrno(), -1);
|
||||
assert(rc >= 0);
|
||||
assert(rc <= len);
|
||||
@@ -236,7 +258,9 @@ PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer,
|
||||
if (!__PHYSFS_ui64FitsAddressSpace(len))
|
||||
BAIL(PHYSFS_ERR_INVALID_ARGUMENT, -1);
|
||||
|
||||
rc = write(fd, (void *) buffer, (size_t) len);
|
||||
do {
|
||||
rc = write(fd, (void *) buffer, (size_t) len);
|
||||
} while ((rc == -1) && (errno == EINTR));
|
||||
BAIL_IF(rc == -1, errcodeFromErrno(), rc);
|
||||
assert(rc >= 0);
|
||||
assert(rc <= len);
|
||||
@@ -275,8 +299,13 @@ PHYSFS_sint64 __PHYSFS_platformFileLength(void *opaque)
|
||||
int __PHYSFS_platformFlush(void *opaque)
|
||||
{
|
||||
const int fd = *((int *) opaque);
|
||||
if ((fcntl(fd, F_GETFL) & O_ACCMODE) != O_RDONLY)
|
||||
BAIL_IF(fsync(fd) == -1, errcodeFromErrno(), 0);
|
||||
int rc = -1;
|
||||
if ((fcntl(fd, F_GETFL) & O_ACCMODE) != O_RDONLY) {
|
||||
do {
|
||||
rc = fsync(fd);
|
||||
} while ((rc == -1) && (errno == EINTR));
|
||||
BAIL_IF(rc == -1, errcodeFromErrno(), 0);
|
||||
}
|
||||
return 1;
|
||||
} /* __PHYSFS_platformFlush */
|
||||
|
||||
@@ -284,7 +313,10 @@ int __PHYSFS_platformFlush(void *opaque)
|
||||
void __PHYSFS_platformClose(void *opaque)
|
||||
{
|
||||
const int fd = *((int *) opaque);
|
||||
(void) close(fd); /* we don't check this. You should have used flush! */
|
||||
int rc = -1;
|
||||
do {
|
||||
rc = close(fd); /* we don't check this. You should have used flush! */
|
||||
} while ((rc == -1) && (errno == EINTR));
|
||||
allocator.Free(opaque);
|
||||
} /* __PHYSFS_platformClose */
|
||||
|
||||
|
||||
@@ -261,12 +261,6 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
if (sysctl(mib, 4, fullpath, &buflen, NULL, 0) != -1)
|
||||
retval = __PHYSFS_strdup(fullpath);
|
||||
}
|
||||
#elif defined(PHYSFS_PLATFORM_SOLARIS)
|
||||
{
|
||||
const char *path = getexecname();
|
||||
if ((path != NULL) && (path[0] == '/')) /* must be absolute path... */
|
||||
retval = __PHYSFS_strdup(path);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If there's a Linux-like /proc filesystem, you can get the full path to
|
||||
@@ -278,6 +272,7 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
retval = readSymLink("/proc/self/exe");
|
||||
if (!retval) retval = readSymLink("/proc/curproc/file");
|
||||
if (!retval) retval = readSymLink("/proc/curproc/exe");
|
||||
if (!retval) retval = readSymLink("/proc/self/path/a.out");
|
||||
if (retval == NULL)
|
||||
{
|
||||
/* older kernels don't have /proc/self ... try PID version... */
|
||||
@@ -289,6 +284,15 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
|
||||
} /* if */
|
||||
} /* if */
|
||||
|
||||
#if defined(PHYSFS_PLATFORM_SOLARIS)
|
||||
if (!retval) /* try getexecname() if /proc didn't pan out. This may not be an absolute path! */
|
||||
{
|
||||
const char *path = getexecname();
|
||||
if ((path != NULL) && (path[0] == '/')) /* must be absolute path... */
|
||||
retval = __PHYSFS_strdup(path);
|
||||
} /* if */
|
||||
#endif
|
||||
|
||||
if (retval != NULL) /* chop off filename. */
|
||||
{
|
||||
char *ptr = strrchr(retval, '/');
|
||||
|
||||
@@ -101,7 +101,7 @@ static char *unicodeToUtf8Heap(const WCHAR *w_str)
|
||||
|
||||
static inline HANDLE winFindFirstFileW(const WCHAR *path, LPWIN32_FIND_DATAW d)
|
||||
{
|
||||
#ifdef PHYSFS_PLATFORM_WINRT
|
||||
#if defined(PHYSFS_PLATFORM_WINRT) || (_WIN32_WINNT >= 0x0501) // Windows XP+
|
||||
return FindFirstFileExW(path, FindExInfoStandard, d,
|
||||
FindExSearchNameMatch, NULL, 0);
|
||||
#else
|
||||
@@ -111,7 +111,7 @@ static inline HANDLE winFindFirstFileW(const WCHAR *path, LPWIN32_FIND_DATAW d)
|
||||
|
||||
static inline BOOL winInitializeCriticalSection(LPCRITICAL_SECTION lpcs)
|
||||
{
|
||||
#ifdef PHYSFS_PLATFORM_WINRT
|
||||
#if defined(PHYSFS_PLATFORM_WINRT) || (_WIN32_WINNT >= 0x0600) // Windows Vista+
|
||||
return InitializeCriticalSectionEx(lpcs, 2000, 0);
|
||||
#else
|
||||
InitializeCriticalSection(lpcs);
|
||||
@@ -123,7 +123,7 @@ static inline HANDLE winCreateFileW(const WCHAR *wfname, const DWORD mode,
|
||||
const DWORD creation)
|
||||
{
|
||||
const DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
||||
#ifdef PHYSFS_PLATFORM_WINRT
|
||||
#if defined(PHYSFS_PLATFORM_WINRT) || (_WIN32_WINNT >= 0x0602) // Windows 8+
|
||||
return CreateFile2(wfname, mode, share, creation, NULL);
|
||||
#else
|
||||
return CreateFileW(wfname, mode, share, NULL, creation,
|
||||
@@ -134,7 +134,7 @@ static inline HANDLE winCreateFileW(const WCHAR *wfname, const DWORD mode,
|
||||
static BOOL winSetFilePointer(HANDLE h, const PHYSFS_sint64 pos,
|
||||
PHYSFS_sint64 *_newpos, const DWORD whence)
|
||||
{
|
||||
#ifdef PHYSFS_PLATFORM_WINRT
|
||||
#if defined(PHYSFS_PLATFORM_WINRT) || (_WIN32_WINNT >= 0x0501) // Windows XP+
|
||||
LARGE_INTEGER lipos;
|
||||
LARGE_INTEGER linewpos;
|
||||
BOOL rc;
|
||||
@@ -158,7 +158,7 @@ static BOOL winSetFilePointer(HANDLE h, const PHYSFS_sint64 pos,
|
||||
|
||||
static PHYSFS_sint64 winGetFileSize(HANDLE h)
|
||||
{
|
||||
#ifdef PHYSFS_PLATFORM_WINRT
|
||||
#if defined(PHYSFS_PLATFORM_WINRT) || (_WIN32_WINNT >= 0x0600) // Windows Vista+
|
||||
FILE_STANDARD_INFO info;
|
||||
const BOOL rc = GetFileInformationByHandleEx(h, FileStandardInfo,
|
||||
&info, sizeof (info));
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
# define PHYSFS_PLATFORM_POSIX 1
|
||||
#elif defined(macintosh)
|
||||
# error Classic Mac OS support was dropped from PhysicsFS 2.0. Move to OS X.
|
||||
#elif defined(ANDROID)
|
||||
# define PHYSFS_PLATFORM_LINUX 1
|
||||
# define PHYSFS_PLATFORM_UNIX 1
|
||||
# define PHYSFS_PLATFORM_POSIX 1
|
||||
# define PHYSFS_NO_CDROM_SUPPORT 1
|
||||
#elif defined(__ANDROID__)
|
||||
# define PHYSFS_PLATFORM_LINUX 1
|
||||
# define PHYSFS_PLATFORM_ANDROID 1
|
||||
# define PHYSFS_PLATFORM_POSIX 1
|
||||
# define PHYSFS_NO_CDROM_SUPPORT 1
|
||||
#elif defined(__linux)
|
||||
# define PHYSFS_PLATFORM_LINUX 1
|
||||
# define PHYSFS_PLATFORM_UNIX 1
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
/*
|
||||
* This may not be the best value, but it's one that isn't represented
|
||||
* in Unicode (0x10FFFF is the largest codepoint value). We return this
|
||||
* value from utf8codepoint() if there's bogus bits in the
|
||||
* stream. utf8codepoint() will turn this value into something
|
||||
* value from __PHYSFS_utf8codepoint() if there's bogus bits in the
|
||||
* stream. __PHYSFS_utf8codepoint() will turn this value into something
|
||||
* reasonable (like a question mark), for text that wants to try to recover,
|
||||
* whereas utf8valid() will use the value to determine if a string has bad
|
||||
* bits.
|
||||
@@ -35,7 +35,7 @@
|
||||
*/
|
||||
#define UNICODE_BOGUS_CHAR_CODEPOINT '?'
|
||||
|
||||
static PHYSFS_uint32 utf8codepoint(const char **_str)
|
||||
PHYSFS_uint32 __PHYSFS_utf8codepoint(const char **_str)
|
||||
{
|
||||
const char *str = *_str;
|
||||
PHYSFS_uint32 retval = 0;
|
||||
@@ -188,6 +188,11 @@ static PHYSFS_uint32 utf8codepoint(const char **_str)
|
||||
} /* else if */
|
||||
|
||||
return UNICODE_BOGUS_CHAR_VALUE;
|
||||
} /* __PHYSFS_utf8codepoint */
|
||||
|
||||
static inline PHYSFS_uint32 utf8codepoint(const char **_str)
|
||||
{
|
||||
return __PHYSFS_utf8codepoint(_str);
|
||||
} /* utf8codepoint */
|
||||
|
||||
static PHYSFS_uint32 utf16codepoint(const PHYSFS_uint16 **_str)
|
||||
@@ -210,7 +215,7 @@ static PHYSFS_uint32 utf16codepoint(const PHYSFS_uint16 **_str)
|
||||
else
|
||||
{
|
||||
src++; /* eat the other surrogate. */
|
||||
cp = (((cp - 0xD800) << 10) | (pair - 0xDC00));
|
||||
cp = 0x10000 + (((cp - 0xD800) << 10) | (pair - 0xDC00));
|
||||
} /* else */
|
||||
} /* else if */
|
||||
|
||||
@@ -238,7 +243,7 @@ void PHYSFS_utf8ToUcs4(const char *src, PHYSFS_uint32 *dst, PHYSFS_uint64 len)
|
||||
len -= sizeof (PHYSFS_uint32); /* save room for null char. */
|
||||
while (len >= sizeof (PHYSFS_uint32))
|
||||
{
|
||||
PHYSFS_uint32 cp = utf8codepoint(&src);
|
||||
PHYSFS_uint32 cp = __PHYSFS_utf8codepoint(&src);
|
||||
if (cp == 0)
|
||||
break;
|
||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
||||
@@ -256,7 +261,7 @@ void PHYSFS_utf8ToUcs2(const char *src, PHYSFS_uint16 *dst, PHYSFS_uint64 len)
|
||||
len -= sizeof (PHYSFS_uint16); /* save room for null char. */
|
||||
while (len >= sizeof (PHYSFS_uint16))
|
||||
{
|
||||
PHYSFS_uint32 cp = utf8codepoint(&src);
|
||||
PHYSFS_uint32 cp = __PHYSFS_utf8codepoint(&src);
|
||||
if (cp == 0)
|
||||
break;
|
||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
||||
@@ -278,7 +283,7 @@ void PHYSFS_utf8ToUtf16(const char *src, PHYSFS_uint16 *dst, PHYSFS_uint64 len)
|
||||
len -= sizeof (PHYSFS_uint16); /* save room for null char. */
|
||||
while (len >= sizeof (PHYSFS_uint16))
|
||||
{
|
||||
PHYSFS_uint32 cp = utf8codepoint(&src);
|
||||
PHYSFS_uint32 cp = __PHYSFS_utf8codepoint(&src);
|
||||
if (cp == 0)
|
||||
break;
|
||||
else if (cp == UNICODE_BOGUS_CHAR_VALUE)
|
||||
|
||||
@@ -123,6 +123,13 @@ const char *Filesystem::getName() const
|
||||
|
||||
void Filesystem::init(const char *arg0)
|
||||
{
|
||||
#ifdef LOVE_ANDROID
|
||||
// TODO: This should be a pointer to an initializeed PHYSFS_AndroidInit
|
||||
// struct on android. But it's only used for PHYSFS_getBaseDir and
|
||||
// PHYSFS_getPrefDir, which we don't use right now...
|
||||
arg0 = nullptr;
|
||||
#endif
|
||||
|
||||
if (!PHYSFS_init(arg0))
|
||||
throw love::Exception("Failed to initialize filesystem: %s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user