Allow application-supplied archivers.
This lets an application supply its own archivers, where they will work like
any built-in archiver. This allows abstract directory interfaces the same
way that PHYSFS_Io allows stream implementations.
This is a work in progress still. The API is still changing, and will remain
at version 0 until it is finalized (a theoretical future version 1 will be
for when the final public interface changes, not when we evolve the initial
API design).
--- a/src/archiver_dir.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_dir.c Wed Nov 28 01:36:13 2012 -0500
@@ -66,7 +66,7 @@
} /* DIR_openArchive */
-static void DIR_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
+static void DIR_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
@@ -82,7 +82,7 @@
} /* DIR_enumerateFiles */
-static PHYSFS_Io *doOpen(PHYSFS_Dir *opaque, const char *name,
+static PHYSFS_Io *doOpen(void *opaque, const char *name,
const int mode, int *fileExists)
{
char *f;
@@ -114,25 +114,25 @@
} /* doOpen */
-static PHYSFS_Io *DIR_openRead(PHYSFS_Dir *opaque, const char *fnm, int *exist)
+static PHYSFS_Io *DIR_openRead(void *opaque, const char *fnm, int *exist)
{
return doOpen(opaque, fnm, 'r', exist);
} /* DIR_openRead */
-static PHYSFS_Io *DIR_openWrite(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *DIR_openWrite(void *opaque, const char *filename)
{
return doOpen(opaque, filename, 'w', NULL);
} /* DIR_openWrite */
-static PHYSFS_Io *DIR_openAppend(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *DIR_openAppend(void *opaque, const char *filename)
{
return doOpen(opaque, filename, 'a', NULL);
} /* DIR_openAppend */
-static int DIR_remove(PHYSFS_Dir *opaque, const char *name)
+static int DIR_remove(void *opaque, const char *name)
{
int retval;
char *f;
@@ -145,7 +145,7 @@
} /* DIR_remove */
-static int DIR_mkdir(PHYSFS_Dir *opaque, const char *name)
+static int DIR_mkdir(void *opaque, const char *name)
{
int retval;
char *f;
@@ -158,13 +158,13 @@
} /* DIR_mkdir */
-static void DIR_closeArchive(PHYSFS_Dir *opaque)
+static void DIR_closeArchive(void *opaque)
{
allocator.Free(opaque);
} /* DIR_closeArchive */
-static int DIR_stat(PHYSFS_Dir *opaque, const char *name,
+static int DIR_stat(void *opaque, const char *name,
int *exists, PHYSFS_Stat *stat)
{
int retval = 0;
@@ -180,6 +180,7 @@
const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"",
"Non-archive, direct filesystem I/O",
--- a/src/archiver_grp.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_grp.c Wed Nov 28 01:36:13 2012 -0500
@@ -87,6 +87,7 @@
const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"GRP",
"Build engine Groupfile format",
--- a/src/archiver_hog.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_hog.c Wed Nov 28 01:36:13 2012 -0500
@@ -93,6 +93,7 @@
const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"HOG",
"Descent I/II HOG file format",
--- a/src/archiver_iso9660.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_iso9660.c Wed Nov 28 01:36:13 2012 -0500
@@ -291,8 +291,8 @@
for(;pos < descriptor->filenamelen; pos++)
if (descriptor->filename[pos] == ';')
lastfound = pos;
- BAIL_IF_MACRO(lastfound < 1, PHYSFS_ERR_NO_SUCH_PATH /* !!! FIXME: PHYSFS_ERR_BAD_FILENAME */, -1);
- BAIL_IF_MACRO(lastfound == (descriptor->filenamelen -1), PHYSFS_ERR_NO_SUCH_PATH /* !!! PHYSFS_ERR_BAD_FILENAME */, -1);
+ BAIL_IF_MACRO(lastfound < 1, PHYSFS_ERR_NOT_FOUND /* !!! FIXME: PHYSFS_ERR_BAD_FILENAME */, -1);
+ BAIL_IF_MACRO(lastfound == (descriptor->filenamelen -1), PHYSFS_ERR_NOT_FOUND /* !!! PHYSFS_ERR_BAD_FILENAME */, -1);
strncpy(filename, descriptor->filename, lastfound);
if (filename[lastfound - 1] == '.')
filename[lastfound - 1] = '\0'; /* consume trailing ., as done in all implementations */
@@ -638,7 +638,7 @@
} /* ISO9660_openArchive */
-static void ISO9660_closeArchive(PHYSFS_Dir *opaque)
+static void ISO9660_closeArchive(void *opaque)
{
ISO9660Handle *handle = (ISO9660Handle*) opaque;
handle->io->destroy(handle->io);
@@ -766,7 +766,7 @@
} /* iso_file_open_foreign */
-static PHYSFS_Io *ISO9660_openRead(PHYSFS_Dir *opaque, const char *filename,
+static PHYSFS_Io *ISO9660_openRead(void *opaque, const char *filename,
int *exists)
{
PHYSFS_Io *retval = NULL;
@@ -785,7 +785,7 @@
/* find file descriptor */
rc = iso_find_dir_entry(handle, filename, &descriptor, exists);
GOTO_IF_MACRO(rc, ERRPASS, errorhandling);
- GOTO_IF_MACRO(!*exists, PHYSFS_ERR_NO_SUCH_PATH, errorhandling);
+ GOTO_IF_MACRO(!*exists, PHYSFS_ERR_NOT_FOUND, errorhandling);
fhandle->startblock = descriptor.extentpos + descriptor.extattributelen;
fhandle->filesize = descriptor.datalen;
@@ -816,7 +816,7 @@
* Information gathering functions
******************************************************************************/
-static void ISO9660_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
+static void ISO9660_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks,
PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
@@ -873,7 +873,7 @@
} /* ISO9660_enumerateFiles */
-static int ISO9660_stat(PHYSFS_Dir *opaque, const char *name, int *exists,
+static int ISO9660_stat(void *opaque, const char *name, int *exists,
PHYSFS_Stat *stat)
{
ISO9660Handle *handle = (ISO9660Handle*) opaque;
@@ -920,25 +920,25 @@
* Not supported functions
******************************************************************************/
-static PHYSFS_Io *ISO9660_openWrite(PHYSFS_Dir *opaque, const char *name)
+static PHYSFS_Io *ISO9660_openWrite(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* ISO9660_openWrite */
-static PHYSFS_Io *ISO9660_openAppend(PHYSFS_Dir *opaque, const char *name)
+static PHYSFS_Io *ISO9660_openAppend(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* ISO9660_openAppend */
-static int ISO9660_remove(PHYSFS_Dir *opaque, const char *name)
+static int ISO9660_remove(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* ISO9660_remove */
-static int ISO9660_mkdir(PHYSFS_Dir *opaque, const char *name)
+static int ISO9660_mkdir(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* ISO9660_mkdir */
@@ -946,6 +946,7 @@
const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660 =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"ISO",
"ISO9660 image file",
--- a/src/archiver_lzma.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_lzma.c Wed Nov 28 01:36:13 2012 -0500
@@ -205,7 +205,7 @@
{
LZMAfile *file = bsearch(name, archive->files, archive->db.Database.NumFiles, sizeof(*archive->files), lzma_file_cmp_stdlib); /* FIXME: Should become __PHYSFS_search!!! */
- BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NO_SUCH_PATH, NULL);
+ BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NOT_FOUND, NULL);
return file;
} /* lzma_find_file */
@@ -531,7 +531,7 @@
} /* doEnumCallback */
-static void LZMA_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
+static void LZMA_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
@@ -551,7 +551,7 @@
file = archive->files;
}
- BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NO_SUCH_PATH, );
+ BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NOT_FOUND, );
while (file < lastFile)
{
@@ -575,7 +575,7 @@
} /* LZMA_enumerateFiles */
-static PHYSFS_Io *LZMA_openRead(PHYSFS_Dir *opaque, const char *name,
+static PHYSFS_Io *LZMA_openRead(void *opaque, const char *name,
int *fileExists)
{
LZMAarchive *archive = (LZMAarchive *) opaque;
@@ -583,7 +583,7 @@
PHYSFS_Io *io = NULL;
*fileExists = (file != NULL);
- BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NO_SUCH_PATH, NULL);
+ BAIL_IF_MACRO(file == NULL, PHYSFS_ERR_NOT_FOUND, NULL);
BAIL_IF_MACRO(file->folder == NULL, PHYSFS_ERR_NOT_A_FILE, NULL);
file->position = 0;
@@ -598,19 +598,19 @@
} /* LZMA_openRead */
-static PHYSFS_Io *LZMA_openWrite(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *LZMA_openWrite(void *opaque, const char *filename)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* LZMA_openWrite */
-static PHYSFS_Io *LZMA_openAppend(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *LZMA_openAppend(void *opaque, const char *filename)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* LZMA_openAppend */
-static void LZMA_closeArchive(PHYSFS_Dir *opaque)
+static void LZMA_closeArchive(void *opaque)
{
LZMAarchive *archive = (LZMAarchive *) opaque;
@@ -628,18 +628,18 @@
} /* LZMA_closeArchive */
-static int LZMA_remove(PHYSFS_Dir *opaque, const char *name)
+static int LZMA_remove(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* LZMA_remove */
-static int LZMA_mkdir(PHYSFS_Dir *opaque, const char *name)
+static int LZMA_mkdir(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* LZMA_mkdir */
-static int LZMA_stat(PHYSFS_Dir *opaque, const char *filename,
+static int LZMA_stat(void *opaque, const char *filename,
int *exists, PHYSFS_Stat *stat)
{
const LZMAarchive *archive = (const LZMAarchive *) opaque;
@@ -678,6 +678,7 @@
const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"7Z",
"LZMA (7zip) format",
--- a/src/archiver_mvl.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_mvl.c Wed Nov 28 01:36:13 2012 -0500
@@ -80,6 +80,7 @@
const PHYSFS_Archiver __PHYSFS_Archiver_MVL =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"MVL",
"Descent II Movielib format",
--- a/src/archiver_qpak.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_qpak.c Wed Nov 28 01:36:13 2012 -0500
@@ -96,6 +96,7 @@
const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"PAK",
"Quake I/II format",
--- a/src/archiver_slb.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_slb.c Wed Nov 28 01:36:13 2012 -0500
@@ -101,6 +101,7 @@
const PHYSFS_Archiver __PHYSFS_Archiver_SLB =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"SLB",
"I-War / Independence War Slab file",
--- a/src/archiver_unpacked.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_unpacked.c Wed Nov 28 01:36:13 2012 -0500
@@ -34,7 +34,7 @@
} UNPKfileinfo;
-void UNPK_closeArchive(PHYSFS_Dir *opaque)
+void UNPK_closeArchive(void *opaque)
{
UNPKinfo *info = ((UNPKinfo *) opaque);
info->io->destroy(info->io);
@@ -242,7 +242,7 @@
} /* doEnumCallback */
-void UNPK_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
+void UNPK_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
@@ -340,11 +340,11 @@
if (isDir != NULL)
*isDir = 0;
- BAIL_MACRO(PHYSFS_ERR_NO_SUCH_PATH, NULL);
+ BAIL_MACRO(PHYSFS_ERR_NOT_FOUND, NULL);
} /* findEntry */
-PHYSFS_Io *UNPK_openRead(PHYSFS_Dir *opaque, const char *fnm, int *fileExists)
+PHYSFS_Io *UNPK_openRead(void *opaque, const char *fnm, int *fileExists)
{
PHYSFS_Io *retval = NULL;
UNPKinfo *info = (UNPKinfo *) opaque;
@@ -390,31 +390,31 @@
} /* UNPK_openRead */
-PHYSFS_Io *UNPK_openWrite(PHYSFS_Dir *opaque, const char *name)
+PHYSFS_Io *UNPK_openWrite(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* UNPK_openWrite */
-PHYSFS_Io *UNPK_openAppend(PHYSFS_Dir *opaque, const char *name)
+PHYSFS_Io *UNPK_openAppend(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* UNPK_openAppend */
-int UNPK_remove(PHYSFS_Dir *opaque, const char *name)
+int UNPK_remove(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* UNPK_remove */
-int UNPK_mkdir(PHYSFS_Dir *opaque, const char *name)
+int UNPK_mkdir(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* UNPK_mkdir */
-int UNPK_stat(PHYSFS_Dir *opaque, const char *filename,
+int UNPK_stat(void *opaque, const char *filename,
int *exists, PHYSFS_Stat *stat)
{
int isDir = 0;
@@ -448,8 +448,7 @@
} /* UNPK_stat */
-PHYSFS_Dir *UNPK_openArchive(PHYSFS_Io *io, UNPKentry *e,
- const PHYSFS_uint32 num)
+void *UNPK_openArchive(PHYSFS_Io *io, UNPKentry *e, const PHYSFS_uint32 num)
{
UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo));
if (info == NULL)
--- a/src/archiver_wad.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_wad.c Wed Nov 28 01:36:13 2012 -0500
@@ -104,6 +104,7 @@
const PHYSFS_Archiver __PHYSFS_Archiver_WAD =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"WAD",
"DOOM engine format",
--- a/src/archiver_zip.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/archiver_zip.c Wed Nov 28 01:36:13 2012 -0500
@@ -600,7 +600,7 @@
if (isDir != NULL)
*isDir = 0;
- BAIL_MACRO(PHYSFS_ERR_NO_SUCH_PATH, NULL);
+ BAIL_MACRO(PHYSFS_ERR_NOT_FOUND, NULL);
} /* zip_find_entry */
@@ -1487,7 +1487,7 @@
} /* doEnumCallback */
-static void ZIP_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
+static void ZIP_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata)
{
@@ -1560,7 +1560,7 @@
} /* zip_get_io */
-static PHYSFS_Io *ZIP_openRead(PHYSFS_Dir *opaque, const char *fnm,
+static PHYSFS_Io *ZIP_openRead(void *opaque, const char *fnm,
int *fileExists)
{
PHYSFS_Io *retval = NULL;
@@ -1619,19 +1619,19 @@
} /* ZIP_openRead */
-static PHYSFS_Io *ZIP_openWrite(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *ZIP_openWrite(void *opaque, const char *filename)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* ZIP_openWrite */
-static PHYSFS_Io *ZIP_openAppend(PHYSFS_Dir *opaque, const char *filename)
+static PHYSFS_Io *ZIP_openAppend(void *opaque, const char *filename)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
} /* ZIP_openAppend */
-static void ZIP_closeArchive(PHYSFS_Dir *opaque)
+static void ZIP_closeArchive(void *opaque)
{
ZIPinfo *zi = (ZIPinfo *) (opaque);
zi->io->destroy(zi->io);
@@ -1640,19 +1640,19 @@
} /* ZIP_closeArchive */
-static int ZIP_remove(PHYSFS_Dir *opaque, const char *name)
+static int ZIP_remove(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* ZIP_remove */
-static int ZIP_mkdir(PHYSFS_Dir *opaque, const char *name)
+static int ZIP_mkdir(void *opaque, const char *name)
{
BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
} /* ZIP_mkdir */
-static int ZIP_stat(PHYSFS_Dir *opaque, const char *filename, int *exists,
+static int ZIP_stat(void *opaque, const char *filename, int *exists,
PHYSFS_Stat *stat)
{
int isDir = 0;
@@ -1694,6 +1694,7 @@
const PHYSFS_Archiver __PHYSFS_Archiver_ZIP =
{
+ CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"ZIP",
"PkZip/WinZip/Info-Zip compatible",
--- a/src/physfs.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/physfs.c Wed Nov 28 01:36:13 2012 -0500
@@ -58,7 +58,7 @@
extern const PHYSFS_Archiver __PHYSFS_Archiver_DIR;
extern const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660;
-static const PHYSFS_Archiver *staticArchivers[] =
+static const PHYSFS_Archiver * const staticArchivers[] =
{
#if PHYSFS_SUPPORTS_ZIP
&__PHYSFS_Archiver_ZIP,
@@ -105,6 +105,7 @@
static int allowSymLinks = 0;
static const PHYSFS_Archiver **archivers = NULL;
static const PHYSFS_ArchiveInfo **archiveInfo = NULL;
+static volatile size_t numArchivers = 0;
/* mutexes ... */
static void *errorLock = NULL; /* protects error message list. */
@@ -752,7 +753,7 @@
case PHYSFS_ERR_FILES_STILL_OPEN: return "files still open";
case PHYSFS_ERR_INVALID_ARGUMENT: return "invalid argument";
case PHYSFS_ERR_NOT_MOUNTED: return "not mounted";
- case PHYSFS_ERR_NO_SUCH_PATH: return "no such path";
+ case PHYSFS_ERR_NOT_FOUND: return "not found";
case PHYSFS_ERR_SYMLINK_FORBIDDEN: return "symlinks are forbidden";
case PHYSFS_ERR_NO_WRITE_DIR: return "write directory is not set";
case PHYSFS_ERR_OPEN_FOR_READING: return "file open for reading";
@@ -768,6 +769,7 @@
case PHYSFS_ERR_BUSY: return "tried to modify a file the OS needs";
case PHYSFS_ERR_DIR_NOT_EMPTY: return "directory isn't empty";
case PHYSFS_ERR_OS_ERROR: return "OS reported an error";
+ case PHYSFS_ERR_DUPLICATE: return "duplicate resource";
} /* switch */
return NULL; /* don't know this error code. */
@@ -890,14 +892,14 @@
/* Look for archivers with matching file extensions first... */
for (i = archivers; (*i != NULL) && (retval == NULL); i++)
{
- if (__PHYSFS_stricmpASCII(ext, (*i)->info.extension) == 0)
+ if (__PHYSFS_utf8stricmp(ext, (*i)->info.extension) == 0)
retval = tryOpenDir(io, *i, d, forWriting);
} /* for */
/* failing an exact file extension match, try all the others... */
for (i = archivers; (*i != NULL) && (retval == NULL); i++)
{
- if (__PHYSFS_stricmpASCII(ext, (*i)->info.extension) != 0)
+ if (__PHYSFS_utf8stricmp(ext, (*i)->info.extension) != 0)
retval = tryOpenDir(io, *i, d, forWriting);
} /* for */
} /* if */
@@ -1125,32 +1127,26 @@
} /* initializeMutexes */
-static void setDefaultAllocator(void);
+static int doRegisterArchiver(const PHYSFS_Archiver *_archiver);
static int initStaticArchivers(void)
{
- const size_t numStaticArchivers = __PHYSFS_ARRAYLEN(staticArchivers);
- const size_t len = numStaticArchivers * sizeof (void *);
- size_t i;
-
- assert(numStaticArchivers > 0); /* seriously, none at all?! */
- assert(staticArchivers[numStaticArchivers - 1] == NULL);
-
- archiveInfo = (const PHYSFS_ArchiveInfo **) allocator.Malloc(len);
- BAIL_IF_MACRO(!archiveInfo, PHYSFS_ERR_OUT_OF_MEMORY, 0);
- archivers = (const PHYSFS_Archiver **) allocator.Malloc(len);
- BAIL_IF_MACRO(!archivers, PHYSFS_ERR_OUT_OF_MEMORY, 0);
-
- for (i = 0; i < numStaticArchivers - 1; i++)
- archiveInfo[i] = &staticArchivers[i]->info;
- archiveInfo[numStaticArchivers - 1] = NULL;
-
- memcpy(archivers, staticArchivers, len);
+ const PHYSFS_Archiver * const *i;
+
+ assert(__PHYSFS_ARRAYLEN(staticArchivers) > 0); /* at least a NULL. */
+ assert(staticArchivers[__PHYSFS_ARRAYLEN(staticArchivers) - 1] == NULL);
+
+ for (i = staticArchivers; *i != NULL; i++)
+ {
+ if (!doRegisterArchiver(*i))
+ return 0;
+ } /* for */
return 1;
} /* initStaticArchivers */
+static void setDefaultAllocator(void);
static int doDeinit(void);
int PHYSFS_init(const char *argv0)
@@ -1243,6 +1239,63 @@
} /* freeSearchPath */
+/* MAKE SURE you hold stateLock before calling this! */
+static int archiverInUse(const PHYSFS_Archiver *arc, const DirHandle *list)
+{
+ const DirHandle *i;
+ for (i = list; i != NULL; i = i->next)
+ {
+ if (i->funcs == arc)
+ return 1;
+ } /* for */
+
+ return 0; /* not in use */
+} /* archiverInUse */
+
+
+/* MAKE SURE you hold stateLock before calling this! */
+static int doDeregisterArchiver(const size_t idx)
+{
+ const size_t len = (numArchivers - idx) * sizeof (void *);
+ const PHYSFS_ArchiveInfo *info = archiveInfo[idx];
+ const PHYSFS_Archiver *arc = archivers[idx];
+
+ /* make sure nothing is still using this archiver */
+ if (archiverInUse(arc, searchPath) || archiverInUse(arc, writeDir))
+ BAIL_MACRO(PHYSFS_ERR_FILES_STILL_OPEN, 0);
+
+ allocator.Free((void *) info->extension);
+ allocator.Free((void *) info->description);
+ allocator.Free((void *) info->author);
+ allocator.Free((void *) info->url);
+ allocator.Free((void *) arc);
+
+ memmove(&archiveInfo[idx], &archiveInfo[idx+1], len);
+ memmove(&archivers[idx], &archivers[idx+1], len);
+
+ assert(numArchivers > 0);
+ numArchivers--;
+
+ return 1;
+} /* doDeregisterArchiver */
+
+
+/* Does NOT hold the state lock; we're shutting down. */
+static void freeArchivers(void)
+{
+ while (numArchivers > 0)
+ {
+ const int rc = doDeregisterArchiver(numArchivers - 1);
+ assert(rc); /* nothing should be mounted during shutdown. */
+ } /* while */
+
+ allocator.Free(archivers);
+ allocator.Free(archiveInfo);
+ archivers = NULL;
+ archiveInfo = NULL;
+} /* freeArchivers */
+
+
static int doDeinit(void)
{
BAIL_IF_MACRO(!__PHYSFS_platformDeinit(), ERRPASS, 0);
@@ -1251,6 +1304,7 @@
BAIL_IF_MACRO(!PHYSFS_setWriteDir(NULL), PHYSFS_ERR_FILES_STILL_OPEN, 0);
freeSearchPath();
+ freeArchivers();
freeErrorStates();
if (baseDir != NULL)
@@ -1310,6 +1364,133 @@
} /* PHYSFS_isInit */
+static char *PHYSFS_strdup(const char *str)
+{
+ char *retval = (char *) allocator.Malloc(strlen(str) + 1);
+ if (retval)
+ strcpy(retval, str);
+ return retval;
+} /* PHYSFS_strdup */
+
+
+/* MAKE SURE you hold stateLock before calling this! */
+static int doRegisterArchiver(const PHYSFS_Archiver *_archiver)
+{
+ const PHYSFS_uint32 maxver = CURRENT_PHYSFS_ARCHIVER_API_VERSION;
+ const size_t len = (numArchivers + 2) * sizeof (void *);
+ PHYSFS_Archiver *archiver = NULL;
+ PHYSFS_ArchiveInfo *info = NULL;
+ const char *ext = NULL;
+ void *ptr = NULL;
+ size_t i;
+
+ BAIL_IF_MACRO(!_archiver, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(_archiver->version > maxver, PHYSFS_ERR_UNSUPPORTED, 0);
+ BAIL_IF_MACRO(!_archiver->info.extension, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->info.description, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->info.author, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->info.url, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->openArchive, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->enumerateFiles, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->openRead, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->openWrite, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->openAppend, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->remove, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->mkdir, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->closeArchive, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+ BAIL_IF_MACRO(!_archiver->stat, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+
+ ext = _archiver->info.extension;
+ for (i = 0; i < numArchivers; i++)
+ {
+ if (__PHYSFS_utf8stricmp(archiveInfo[i]->extension, ext) == 0)
+ BAIL_MACRO(PHYSFS_ERR_DUPLICATE, 0); // !!! FIXME: better error? ERR_IN_USE?
+ } /* for */
+
+ /* make a copy of the data. */
+ archiver = (PHYSFS_Archiver *) allocator.Malloc(sizeof (*archiver));
+ GOTO_IF_MACRO(!archiver, PHYSFS_ERR_OUT_OF_MEMORY, regfailed);
+
+ /* Must copy sizeof (OLD_VERSION_OF_STRUCT) when version changes! */
+ memcpy(archiver, _archiver, sizeof (*archiver));
+
+ info = (PHYSFS_ArchiveInfo *) &archiver->info;
+ memset(info, '\0', sizeof (*info)); /* NULL in case an alloc fails. */
+ #define CPYSTR(item) \
+ info->item = PHYSFS_strdup(_archiver->info.item); \
+ GOTO_IF_MACRO(!info->item, PHYSFS_ERR_OUT_OF_MEMORY, regfailed);
+ CPYSTR(extension);
+ CPYSTR(description);
+ CPYSTR(author);
+ CPYSTR(url);
+ #undef CPYSTR
+
+ ptr = allocator.Realloc(archiveInfo, len);
+ GOTO_IF_MACRO(!ptr, PHYSFS_ERR_OUT_OF_MEMORY, regfailed);
+ archiveInfo = (const PHYSFS_ArchiveInfo **) ptr;
+
+ ptr = allocator.Realloc(archivers, len);
+ GOTO_IF_MACRO(!ptr, PHYSFS_ERR_OUT_OF_MEMORY, regfailed);
+ archivers = (const PHYSFS_Archiver **) ptr;
+
+ archiveInfo[numArchivers] = info;
+ archiveInfo[numArchivers + 1] = NULL;
+
+ archivers[numArchivers] = archiver;
+ archivers[numArchivers + 1] = NULL;
+
+ numArchivers++;
+
+ return 1;
+
+regfailed:
+ if (info != NULL)
+ {
+ allocator.Free((void *) info->extension);
+ allocator.Free((void *) info->description);
+ allocator.Free((void *) info->author);
+ allocator.Free((void *) info->url);
+ } /* if */
+ allocator.Free(archiver);
+
+ return 0;
+} /* doRegisterArchiver */
+
+
+int PHYSFS_registerArchiver(const PHYSFS_Archiver *archiver)
+{
+ int retval;
+ BAIL_IF_MACRO(!initialized, PHYSFS_ERR_NOT_INITIALIZED, 0);
+ __PHYSFS_platformGrabMutex(stateLock);
+ retval = doRegisterArchiver(archiver);
+ __PHYSFS_platformReleaseMutex(stateLock);
+ return retval;
+} /* PHYSFS_registerArchiver */
+
+
+int PHYSFS_deregisterArchiver(const char *ext)
+{
+ size_t i;
+
+ BAIL_IF_MACRO(!initialized, PHYSFS_ERR_NOT_INITIALIZED, 0);
+ BAIL_IF_MACRO(!ext, PHYSFS_ERR_INVALID_ARGUMENT, 0);
+
+ __PHYSFS_platformGrabMutex(stateLock);
+ for (i = 0; i < numArchivers; i++)
+ {
+ if (__PHYSFS_utf8stricmp(archiveInfo[i]->extension, ext) == 0)
+ {
+ const int retval = doDeregisterArchiver(i);
+ __PHYSFS_platformReleaseMutex(stateLock);
+ return retval;
+ } /* if */
+ } /* for */
+ __PHYSFS_platformReleaseMutex(stateLock);
+
+ BAIL_MACRO(PHYSFS_ERR_NOT_FOUND, 0);
+} /* PHYSFS_deregisterArchiver */
+
+
const PHYSFS_ArchiveInfo **PHYSFS_supportedArchiveTypes(void)
{
BAIL_IF_MACRO(!initialized, PHYSFS_ERR_NOT_INITIALIZED, NULL);
@@ -1702,7 +1883,7 @@
if ((l > extlen) && ((*i)[l - extlen - 1] == '.'))
{
ext = (*i) + (l - extlen);
- if (__PHYSFS_stricmpASCII(ext, archiveExt) == 0)
+ if (__PHYSFS_utf8stricmp(ext, archiveExt) == 0)
setSaneCfgAddPath(*i, l, dirsep, archivesFirst);
} /* if */
} /* for */
@@ -1763,12 +1944,12 @@
size_t len = strlen(fname);
assert(mntpntlen > 1); /* root mount points should be NULL. */
/* not under the mountpoint, so skip this archive. */
- BAIL_IF_MACRO(len < mntpntlen-1, PHYSFS_ERR_NO_SUCH_PATH, 0);
+ BAIL_IF_MACRO(len < mntpntlen-1, PHYSFS_ERR_NOT_FOUND, 0);
/* !!! FIXME: Case insensitive? */
retval = strncmp(h->mountPoint, fname, mntpntlen-1);
- BAIL_IF_MACRO(retval != 0, PHYSFS_ERR_NO_SUCH_PATH, 0);
+ BAIL_IF_MACRO(retval != 0, PHYSFS_ERR_NOT_FOUND, 0);
if (len > mntpntlen-1) /* corner case... */
- BAIL_IF_MACRO(fname[mntpntlen-1]!='/', PHYSFS_ERR_NO_SUCH_PATH, 0);
+ BAIL_IF_MACRO(fname[mntpntlen-1]!='/', PHYSFS_ERR_NOT_FOUND, 0);
fname += mntpntlen-1; /* move to start of actual archive path. */
if (*fname == '/')
fname++;
@@ -2222,7 +2403,7 @@
__PHYSFS_platformGrabMutex(stateLock);
- GOTO_IF_MACRO(!searchPath, PHYSFS_ERR_NO_SUCH_PATH, openReadEnd);
+ GOTO_IF_MACRO(!searchPath, PHYSFS_ERR_NOT_FOUND, openReadEnd);
for (i = searchPath; (i != NULL) && (!fileExists); i = i->next)
{
--- a/src/physfs.h Wed Nov 28 01:30:29 2012 -0500
+++ b/src/physfs.h Wed Nov 28 01:36:13 2012 -0500
@@ -399,6 +399,8 @@
* supported.
*
* \sa PHYSFS_supportedArchiveTypes
+ * \sa PHYSFS_registerArchiver
+ * \sa PHYSFS_deregisterArchiver
*/
typedef struct PHYSFS_ArchiveInfo
{
@@ -573,9 +575,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);
@@ -3129,7 +3135,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. */
@@ -3144,7 +3150,8 @@
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_ErrorCode;
@@ -3307,9 +3314,233 @@
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().
+ */
+ const PHYSFS_ArchiveInfo info;
+
+ /**
+ * \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.
+ * You should omit symlinks if (omitSymLinks) is non-zero.
+ * If you have a failure, report as much as you can.
+ * (dirname) is in platform-independent notation.
+ */
+
+// !!! FIXME: get rid of this omitsymlinks nonsense.
+ void (*enumerateFiles)(void *opaque, const char *dirname,
+ int omitSymLinks, 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.
+ *
+ * Regardless of success or failure, please set *exists to
+ * non-zero if the file existed (even if it's a broken symlink!),
+ * zero if it did not.
+ */
+// !!! FIXME: get rid of the exists nonsense, check error code instead.
+ PHYSFS_Io *(*openRead)(void *opaque, const char *fnm, int *exists);
+
+ /**
+ * 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);
+
+ // !!! FIXME: reorder these methods.
+ /**
+ * 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);
+
+ /**
+ * Obtain basic file metadata.
+ * Returns non-zero on success, zero on failure.
+ * On failure, call PHYSFS_setErrorCode().
+ */
+// !!! FIXME: remove this exists nonsense (check error code instead)
+ int (*stat)(void *opaque, const char *fn, int *exists, PHYSFS_Stat *stat);
+} 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
--- a/src/physfs_internal.h Wed Nov 28 01:30:29 2012 -0500
+++ b/src/physfs_internal.h Wed Nov 28 01:36:13 2012 -0500
@@ -124,137 +124,10 @@
/* The latest supported PHYSFS_Io::version value. */
#define CURRENT_PHYSFS_IO_API_VERSION 0
-/* Opaque data for file and dir handlers... */
-typedef void PHYSFS_Dir;
-
-typedef struct
-{
- /*
- * Basic info about this archiver...
- */
- const PHYSFS_ArchiveInfo info;
-
-
- /*
- * DIRECTORY ROUTINES:
- * These functions are for dir handles. Generate a handle with the
- * openArchive() method, then pass it as the "opaque" PHYSFS_Dir to the
- * others.
- *
- * 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.
- */
-
- /*
- * Open a dirhandle for dir/archive data 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.
- * Returns NULL on failure. We ignore any error code you set here.
- * Returns non-NULL on success. The pointer returned will be
- * passed as the "opaque" parameter for later calls.
- */
- PHYSFS_Dir *(*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.
- * You should omit symlinks if (omitSymLinks) is non-zero.
- * If you have a failure, report as much as you can.
- * (dirname) is in platform-independent notation.
- */
- void (*enumerateFiles)(PHYSFS_Dir *opaque, const char *dirname,
- int omitSymLinks, 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_setError().
- * Returns non-NULL on success. The pointer returned will be
- * passed as the "opaque" parameter for later file calls.
- *
- * Regardless of success or failure, please set *exists to
- * non-zero if the file existed (even if it's a broken symlink!),
- * zero if it did not.
- */
- PHYSFS_Io *(*openRead)(PHYSFS_Dir *opaque, const char *fnm, int *exists);
+/* The latest supported PHYSFS_Archiver::version value. */
+#define CURRENT_PHYSFS_ARCHIVER_API_VERSION 0
- /*
- * 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_setError().
- * Returns non-NULL on success. The pointer returned will be
- * passed as the "opaque" parameter for later file calls.
- */
- PHYSFS_Io *(*openWrite)(PHYSFS_Dir *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_setError().
- * Returns non-NULL on success. The pointer returned will be
- * passed as the "opaque" parameter for later file calls.
- */
- PHYSFS_Io *(*openAppend)(PHYSFS_Dir *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_setError().
- */
- int (*remove)(PHYSFS_Dir *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_setError().
- */
- int (*mkdir)(PHYSFS_Dir *opaque, const char *filename);
-
- /*
- * 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)(PHYSFS_Dir *opaque);
-
- /*
- * Obtain basic file metadata.
- * Returns non-zero on success, zero on failure.
- * On failure, call __PHYSFS_setError().
- */
- int (*stat)(PHYSFS_Dir *opaque, const char *fn,
- int *exists, PHYSFS_Stat *stat);
-} PHYSFS_Archiver;
-
-
-/*
+/* !!! FIXME: update this documentation.
* Call this to set the message returned by PHYSFS_getLastError().
* Please only use the ERR_* constants above, or add new constants to the
* above group, but I want these all in one place.
@@ -425,17 +298,17 @@
PHYSFS_uint32 size;
} UNPKentry;
-void UNPK_closeArchive(PHYSFS_Dir *opaque);
-PHYSFS_Dir *UNPK_openArchive(PHYSFS_Io *io,UNPKentry *e,const PHYSFS_uint32 n);
-void UNPK_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
+void UNPK_closeArchive(void *opaque);
+void *UNPK_openArchive(PHYSFS_Io *io,UNPKentry *e,const PHYSFS_uint32 n);
+void UNPK_enumerateFiles(void *opaque, const char *dname,
int omitSymLinks, PHYSFS_EnumFilesCallback cb,
const char *origdir, void *callbackdata);
-PHYSFS_Io *UNPK_openRead(PHYSFS_Dir *opaque, const char *fnm, int *fileExists);
-PHYSFS_Io *UNPK_openWrite(PHYSFS_Dir *opaque, const char *name);
-PHYSFS_Io *UNPK_openAppend(PHYSFS_Dir *opaque, const char *name);
-int UNPK_remove(PHYSFS_Dir *opaque, const char *name);
-int UNPK_mkdir(PHYSFS_Dir *opaque, const char *name);
-int UNPK_stat(PHYSFS_Dir *opaque, const char *fn, int *exist, PHYSFS_Stat *st);
+PHYSFS_Io *UNPK_openRead(void *opaque, const char *fnm, int *fileExists);
+PHYSFS_Io *UNPK_openWrite(void *opaque, const char *name);
+PHYSFS_Io *UNPK_openAppend(void *opaque, const char *name);
+int UNPK_remove(void *opaque, const char *name);
+int UNPK_mkdir(void *opaque, const char *name);
+int UNPK_stat(void *opaque, const char *fn, int *exist, PHYSFS_Stat *st);
/*--------------------------------------------------------------------------*/
--- a/src/platform_posix.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/platform_posix.c Wed Nov 28 01:36:13 2012 -0500
@@ -41,9 +41,9 @@
case ELOOP: return PHYSFS_ERR_SYMLINK_LOOP;
case EMLINK: return PHYSFS_ERR_NO_SPACE;
case ENAMETOOLONG: return PHYSFS_ERR_BAD_FILENAME;
- case ENOENT: return PHYSFS_ERR_NO_SUCH_PATH;
+ case ENOENT: return PHYSFS_ERR_NOT_FOUND;
case ENOSPC: return PHYSFS_ERR_NO_SPACE;
- case ENOTDIR: return PHYSFS_ERR_NO_SUCH_PATH;
+ case ENOTDIR: return PHYSFS_ERR_NOT_FOUND;
case EISDIR: return PHYSFS_ERR_NOT_A_FILE;
case EROFS: return PHYSFS_ERR_READ_ONLY;
case ETXTBSY: return PHYSFS_ERR_BUSY;
--- a/src/platform_windows.c Wed Nov 28 01:30:29 2012 -0500
+++ b/src/platform_windows.c Wed Nov 28 01:36:13 2012 -0500
@@ -124,13 +124,13 @@
case ERROR_INVALID_NAME: return PHYSFS_ERR_BAD_FILENAME;
case ERROR_BAD_PATHNAME: return PHYSFS_ERR_BAD_FILENAME;
case ERROR_DIRECTORY: return PHYSFS_ERR_BAD_FILENAME;
- case ERROR_FILE_NOT_FOUND: return PHYSFS_ERR_NO_SUCH_PATH;
- case ERROR_PATH_NOT_FOUND: return PHYSFS_ERR_NO_SUCH_PATH;
- case ERROR_DELETE_PENDING: return PHYSFS_ERR_NO_SUCH_PATH;
- case ERROR_INVALID_DRIVE: return PHYSFS_ERR_NO_SUCH_PATH;
+ case ERROR_FILE_NOT_FOUND: return PHYSFS_ERR_NOT_FOUND;
+ case ERROR_PATH_NOT_FOUND: return PHYSFS_ERR_NOT_FOUND;
+ case ERROR_DELETE_PENDING: return PHYSFS_ERR_NOT_FOUND;
+ case ERROR_INVALID_DRIVE: return PHYSFS_ERR_NOT_FOUND;
case ERROR_HANDLE_DISK_FULL: return PHYSFS_ERR_NO_SPACE;
case ERROR_DISK_FULL: return PHYSFS_ERR_NO_SPACE;
- /* !!! FIXME: ?? case ENOTDIR: return PHYSFS_ERR_NO_SUCH_PATH; */
+ /* !!! FIXME: ?? case ENOTDIR: return PHYSFS_ERR_NOT_FOUND; */
/* !!! FIXME: ?? case EISDIR: return PHYSFS_ERR_NOT_A_FILE; */
case ERROR_WRITE_PROTECT: return PHYSFS_ERR_READ_ONLY;
case ERROR_LOCK_VIOLATION: return PHYSFS_ERR_BUSY;