فهرست منبع

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).
Ryan C. Gordon 13 سال پیش
والد
کامیت
e40d80b00f
16فایلهای تغییر یافته به همراه520 افزوده شده و 226 حذف شده
  1. 10 9
      src/archiver_dir.c
  2. 1 0
      src/archiver_grp.c
  3. 1 0
      src/archiver_hog.c
  4. 12 11
      src/archiver_iso9660.c
  5. 12 11
      src/archiver_lzma.c
  6. 1 0
      src/archiver_mvl.c
  7. 1 0
      src/archiver_qpak.c
  8. 1 0
      src/archiver_slb.c
  9. 10 11
      src/archiver_unpacked.c
  10. 1 0
      src/archiver_wad.c
  11. 10 9
      src/archiver_zip.c
  12. 206 25
      src/physfs.c
  13. 235 4
      src/physfs.h
  14. 12 139
      src/physfs_internal.h
  15. 2 2
      src/platform_posix.c
  16. 5 5
      src/platform_windows.c

+ 10 - 9
src/archiver_dir.c

@@ -66,7 +66,7 @@ static void *DIR_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
 } /* DIR_openArchive */
 } /* 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,
                                int omitSymLinks, PHYSFS_EnumFilesCallback cb,
                                const char *origdir, void *callbackdata)
                                const char *origdir, void *callbackdata)
 {
 {
@@ -82,7 +82,7 @@ static void DIR_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
 } /* DIR_enumerateFiles */
 } /* 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)
                          const int mode, int *fileExists)
 {
 {
     char *f;
     char *f;
@@ -114,25 +114,25 @@ static PHYSFS_Io *doOpen(PHYSFS_Dir *opaque, const char *name,
 } /* doOpen */
 } /* 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);
     return doOpen(opaque, fnm, 'r', exist);
 } /* DIR_openRead */
 } /* 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);
     return doOpen(opaque, filename, 'w', NULL);
 } /* DIR_openWrite */
 } /* 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);
     return doOpen(opaque, filename, 'a', NULL);
 } /* DIR_openAppend */
 } /* DIR_openAppend */
 
 
 
 
-static int DIR_remove(PHYSFS_Dir *opaque, const char *name)
+static int DIR_remove(void *opaque, const char *name)
 {
 {
     int retval;
     int retval;
     char *f;
     char *f;
@@ -145,7 +145,7 @@ static int DIR_remove(PHYSFS_Dir *opaque, const char *name)
 } /* DIR_remove */
 } /* DIR_remove */
 
 
 
 
-static int DIR_mkdir(PHYSFS_Dir *opaque, const char *name)
+static int DIR_mkdir(void *opaque, const char *name)
 {
 {
     int retval;
     int retval;
     char *f;
     char *f;
@@ -158,13 +158,13 @@ static int DIR_mkdir(PHYSFS_Dir *opaque, const char *name)
 } /* DIR_mkdir */
 } /* DIR_mkdir */
 
 
 
 
-static void DIR_closeArchive(PHYSFS_Dir *opaque)
+static void DIR_closeArchive(void *opaque)
 {
 {
     allocator.Free(opaque);
     allocator.Free(opaque);
 } /* DIR_closeArchive */
 } /* 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 *exists, PHYSFS_Stat *stat)
 {
 {
     int retval = 0;
     int retval = 0;
@@ -180,6 +180,7 @@ static int DIR_stat(PHYSFS_Dir *opaque, const char *name,
 
 
 const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
 const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
 {
 {
+    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
     {
     {
         "",
         "",
         "Non-archive, direct filesystem I/O",
         "Non-archive, direct filesystem I/O",

+ 1 - 0
src/archiver_grp.c

@@ -87,6 +87,7 @@ static void *GRP_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
 
 
 const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
 const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
 {
 {
+    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
     {
     {
         "GRP",
         "GRP",
         "Build engine Groupfile format",
         "Build engine Groupfile format",

+ 1 - 0
src/archiver_hog.c

@@ -93,6 +93,7 @@ static void *HOG_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
 
 
 const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
 const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
 {
 {
+    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
     {
     {
         "HOG",
         "HOG",
         "Descent I/II HOG file format",
         "Descent I/II HOG file format",

+ 12 - 11
src/archiver_iso9660.c

@@ -291,8 +291,8 @@ static int iso_extractfilenameISO(ISO9660FileDescriptor *descriptor,
         for(;pos < descriptor->filenamelen; pos++)
         for(;pos < descriptor->filenamelen; pos++)
             if (descriptor->filename[pos] == ';')
             if (descriptor->filename[pos] == ';')
                 lastfound = 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);
         strncpy(filename, descriptor->filename, lastfound);
         if (filename[lastfound - 1] == '.')
         if (filename[lastfound - 1] == '.')
             filename[lastfound - 1] = '\0'; /* consume trailing ., as done in all implementations */
             filename[lastfound - 1] = '\0'; /* consume trailing ., as done in all implementations */
@@ -638,7 +638,7 @@ errorcleanup:
 } /* ISO9660_openArchive */
 } /* ISO9660_openArchive */
 
 
 
 
-static void ISO9660_closeArchive(PHYSFS_Dir *opaque)
+static void ISO9660_closeArchive(void *opaque)
 {
 {
     ISO9660Handle *handle = (ISO9660Handle*) opaque;
     ISO9660Handle *handle = (ISO9660Handle*) opaque;
     handle->io->destroy(handle->io);
     handle->io->destroy(handle->io);
@@ -766,7 +766,7 @@ closefile:
 } /* iso_file_open_foreign */
 } /* 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)
                                    int *exists)
 {
 {
     PHYSFS_Io *retval = NULL;
     PHYSFS_Io *retval = NULL;
@@ -785,7 +785,7 @@ static PHYSFS_Io *ISO9660_openRead(PHYSFS_Dir *opaque, const char *filename,
     /* find file descriptor */
     /* find file descriptor */
     rc = iso_find_dir_entry(handle, filename, &descriptor, exists);
     rc = iso_find_dir_entry(handle, filename, &descriptor, exists);
     GOTO_IF_MACRO(rc, ERRPASS, errorhandling);
     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->startblock = descriptor.extentpos + descriptor.extattributelen;
     fhandle->filesize = descriptor.datalen;
     fhandle->filesize = descriptor.datalen;
@@ -816,7 +816,7 @@ errorhandling:
  * Information gathering functions
  * Information gathering functions
  ******************************************************************************/
  ******************************************************************************/
 
 
-static void ISO9660_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
+static void ISO9660_enumerateFiles(void *opaque, const char *dname,
                                    int omitSymLinks,
                                    int omitSymLinks,
                                    PHYSFS_EnumFilesCallback cb,
                                    PHYSFS_EnumFilesCallback cb,
                                    const char *origdir, void *callbackdata)
                                    const char *origdir, void *callbackdata)
@@ -873,7 +873,7 @@ static void ISO9660_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
 } /* ISO9660_enumerateFiles */
 } /* 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)
                         PHYSFS_Stat *stat)
 {
 {
     ISO9660Handle *handle = (ISO9660Handle*) opaque;
     ISO9660Handle *handle = (ISO9660Handle*) opaque;
@@ -920,25 +920,25 @@ static int ISO9660_stat(PHYSFS_Dir *opaque, const char *name, int *exists,
  * Not supported functions
  * 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
 } /* ISO9660_openWrite */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
 } /* ISO9660_openAppend */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
 } /* ISO9660_remove */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
 } /* ISO9660_mkdir */
 } /* ISO9660_mkdir */
@@ -946,6 +946,7 @@ static int ISO9660_mkdir(PHYSFS_Dir *opaque, const char *name)
 
 
 const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660 =
 const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660 =
 {
 {
+    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
     {
     {
         "ISO",
         "ISO",
         "ISO9660 image file",
         "ISO9660 image file",

+ 12 - 11
src/archiver_lzma.c

@@ -205,7 +205,7 @@ static LZMAfile * lzma_find_file(const LZMAarchive *archive, const char *name)
 {
 {
     LZMAfile *file = bsearch(name, archive->files, archive->db.Database.NumFiles, sizeof(*archive->files), lzma_file_cmp_stdlib); /* FIXME: Should become __PHYSFS_search!!! */
     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;
     return file;
 } /* lzma_find_file */
 } /* lzma_find_file */
@@ -531,7 +531,7 @@ static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
 } /* doEnumCallback */
 } /* 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,
                                 int omitSymLinks, PHYSFS_EnumFilesCallback cb,
                                 const char *origdir, void *callbackdata)
                                 const char *origdir, void *callbackdata)
 {
 {
@@ -551,7 +551,7 @@ static void LZMA_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
             file = archive->files;
             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)
     while (file < lastFile)
     {
     {
@@ -575,7 +575,7 @@ static void LZMA_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
 } /* LZMA_enumerateFiles */
 } /* 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)
                                 int *fileExists)
 {
 {
     LZMAarchive *archive = (LZMAarchive *) opaque;
     LZMAarchive *archive = (LZMAarchive *) opaque;
@@ -583,7 +583,7 @@ static PHYSFS_Io *LZMA_openRead(PHYSFS_Dir *opaque, const char *name,
     PHYSFS_Io *io = NULL;
     PHYSFS_Io *io = NULL;
 
 
     *fileExists = (file != 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);
     BAIL_IF_MACRO(file->folder == NULL, PHYSFS_ERR_NOT_A_FILE, NULL);
 
 
     file->position = 0;
     file->position = 0;
@@ -598,19 +598,19 @@ static PHYSFS_Io *LZMA_openRead(PHYSFS_Dir *opaque, const char *name,
 } /* LZMA_openRead */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
 } /* LZMA_openWrite */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
 } /* LZMA_openAppend */
 } /* LZMA_openAppend */
 
 
 
 
-static void LZMA_closeArchive(PHYSFS_Dir *opaque)
+static void LZMA_closeArchive(void *opaque)
 {
 {
     LZMAarchive *archive = (LZMAarchive *) opaque;
     LZMAarchive *archive = (LZMAarchive *) opaque;
 
 
@@ -628,18 +628,18 @@ static void LZMA_closeArchive(PHYSFS_Dir *opaque)
 } /* LZMA_closeArchive */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
 } /* LZMA_remove */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
 } /* LZMA_mkdir */
 } /* 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)
                      int *exists, PHYSFS_Stat *stat)
 {
 {
     const LZMAarchive *archive = (const LZMAarchive *) opaque;
     const LZMAarchive *archive = (const LZMAarchive *) opaque;
@@ -678,6 +678,7 @@ static int LZMA_stat(PHYSFS_Dir *opaque, const char *filename,
 
 
 const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
 const PHYSFS_Archiver __PHYSFS_Archiver_LZMA =
 {
 {
+    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
     {
     {
         "7Z",
         "7Z",
         "LZMA (7zip) format",
         "LZMA (7zip) format",

+ 1 - 0
src/archiver_mvl.c

@@ -80,6 +80,7 @@ static void *MVL_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
 
 
 const PHYSFS_Archiver __PHYSFS_Archiver_MVL =
 const PHYSFS_Archiver __PHYSFS_Archiver_MVL =
 {
 {
+    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
     {
     {
         "MVL",
         "MVL",
         "Descent II Movielib format",
         "Descent II Movielib format",

+ 1 - 0
src/archiver_qpak.c

@@ -96,6 +96,7 @@ static void *QPAK_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
 
 
 const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
 const PHYSFS_Archiver __PHYSFS_Archiver_QPAK =
 {
 {
+    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
     {
     {
         "PAK",
         "PAK",
         "Quake I/II format",
         "Quake I/II format",

+ 1 - 0
src/archiver_slb.c

@@ -101,6 +101,7 @@ static void *SLB_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
 
 
 const PHYSFS_Archiver __PHYSFS_Archiver_SLB =
 const PHYSFS_Archiver __PHYSFS_Archiver_SLB =
 {
 {
+    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
     {
     {
         "SLB",
         "SLB",
         "I-War / Independence War Slab file",
         "I-War / Independence War Slab file",

+ 10 - 11
src/archiver_unpacked.c

@@ -34,7 +34,7 @@ typedef struct
 } UNPKfileinfo;
 } UNPKfileinfo;
 
 
 
 
-void UNPK_closeArchive(PHYSFS_Dir *opaque)
+void UNPK_closeArchive(void *opaque)
 {
 {
     UNPKinfo *info = ((UNPKinfo *) opaque);
     UNPKinfo *info = ((UNPKinfo *) opaque);
     info->io->destroy(info->io);
     info->io->destroy(info->io);
@@ -242,7 +242,7 @@ static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
 } /* doEnumCallback */
 } /* doEnumCallback */
 
 
 
 
-void UNPK_enumerateFiles(PHYSFS_Dir *opaque, const char *dname,
+void UNPK_enumerateFiles(void *opaque, const char *dname,
                          int omitSymLinks, PHYSFS_EnumFilesCallback cb,
                          int omitSymLinks, PHYSFS_EnumFilesCallback cb,
                          const char *origdir, void *callbackdata)
                          const char *origdir, void *callbackdata)
 {
 {
@@ -340,11 +340,11 @@ static UNPKentry *findEntry(const UNPKinfo *info, const char *path, int *isDir)
     if (isDir != NULL)
     if (isDir != NULL)
         *isDir = 0;
         *isDir = 0;
 
 
-    BAIL_MACRO(PHYSFS_ERR_NO_SUCH_PATH, NULL);
+    BAIL_MACRO(PHYSFS_ERR_NOT_FOUND, NULL);
 } /* findEntry */
 } /* 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;
     PHYSFS_Io *retval = NULL;
     UNPKinfo *info = (UNPKinfo *) opaque;
     UNPKinfo *info = (UNPKinfo *) opaque;
@@ -390,31 +390,31 @@ UNPK_openRead_failed:
 } /* UNPK_openRead */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
 } /* UNPK_openWrite */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
 } /* UNPK_openAppend */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
 } /* UNPK_remove */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
 } /* UNPK_mkdir */
 } /* 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 *exists, PHYSFS_Stat *stat)
 {
 {
     int isDir = 0;
     int isDir = 0;
@@ -448,8 +448,7 @@ int UNPK_stat(PHYSFS_Dir *opaque, const char *filename,
 } /* UNPK_stat */
 } /* 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));
     UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo));
     if (info == NULL)
     if (info == NULL)

+ 1 - 0
src/archiver_wad.c

@@ -104,6 +104,7 @@ static void *WAD_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
 
 
 const PHYSFS_Archiver __PHYSFS_Archiver_WAD =
 const PHYSFS_Archiver __PHYSFS_Archiver_WAD =
 {
 {
+    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
     {
     {
         "WAD",
         "WAD",
         "DOOM engine format",
         "DOOM engine format",

+ 10 - 9
src/archiver_zip.c

@@ -600,7 +600,7 @@ static ZIPentry *zip_find_entry(const ZIPinfo *info, const char *path,
     if (isDir != NULL)
     if (isDir != NULL)
         *isDir = 0;
         *isDir = 0;
 
 
-    BAIL_MACRO(PHYSFS_ERR_NO_SUCH_PATH, NULL);
+    BAIL_MACRO(PHYSFS_ERR_NOT_FOUND, NULL);
 } /* zip_find_entry */
 } /* zip_find_entry */
 
 
 
 
@@ -1487,7 +1487,7 @@ static void doEnumCallback(PHYSFS_EnumFilesCallback cb, void *callbackdata,
 } /* doEnumCallback */
 } /* 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,
                                int omitSymLinks, PHYSFS_EnumFilesCallback cb,
                                const char *origdir, void *callbackdata)
                                const char *origdir, void *callbackdata)
 {
 {
@@ -1560,7 +1560,7 @@ static PHYSFS_Io *zip_get_io(PHYSFS_Io *io, ZIPinfo *inf, ZIPentry *entry)
 } /* zip_get_io */
 } /* 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)
                                int *fileExists)
 {
 {
     PHYSFS_Io *retval = NULL;
     PHYSFS_Io *retval = NULL;
@@ -1619,19 +1619,19 @@ ZIP_openRead_failed:
 } /* ZIP_openRead */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
 } /* ZIP_openWrite */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, NULL);
 } /* ZIP_openAppend */
 } /* ZIP_openAppend */
 
 
 
 
-static void ZIP_closeArchive(PHYSFS_Dir *opaque)
+static void ZIP_closeArchive(void *opaque)
 {
 {
     ZIPinfo *zi = (ZIPinfo *) (opaque);
     ZIPinfo *zi = (ZIPinfo *) (opaque);
     zi->io->destroy(zi->io);
     zi->io->destroy(zi->io);
@@ -1640,19 +1640,19 @@ static void ZIP_closeArchive(PHYSFS_Dir *opaque)
 } /* ZIP_closeArchive */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
 } /* ZIP_remove */
 } /* 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);
     BAIL_MACRO(PHYSFS_ERR_READ_ONLY, 0);
 } /* ZIP_mkdir */
 } /* 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)
                     PHYSFS_Stat *stat)
 {
 {
     int isDir = 0;
     int isDir = 0;
@@ -1694,6 +1694,7 @@ static int ZIP_stat(PHYSFS_Dir *opaque, const char *filename, int *exists,
 
 
 const PHYSFS_Archiver __PHYSFS_Archiver_ZIP =
 const PHYSFS_Archiver __PHYSFS_Archiver_ZIP =
 {
 {
+    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
     {
     {
         "ZIP",
         "ZIP",
         "PkZip/WinZip/Info-Zip compatible",
         "PkZip/WinZip/Info-Zip compatible",

+ 206 - 25
src/physfs.c

@@ -58,7 +58,7 @@ extern const PHYSFS_Archiver __PHYSFS_Archiver_SLB;
 extern const PHYSFS_Archiver __PHYSFS_Archiver_DIR;
 extern const PHYSFS_Archiver __PHYSFS_Archiver_DIR;
 extern const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660;
 extern const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660;
 
 
-static const PHYSFS_Archiver *staticArchivers[] =
+static const PHYSFS_Archiver * const staticArchivers[] =
 {
 {
 #if PHYSFS_SUPPORTS_ZIP
 #if PHYSFS_SUPPORTS_ZIP
     &__PHYSFS_Archiver_ZIP,
     &__PHYSFS_Archiver_ZIP,
@@ -105,6 +105,7 @@ static char *prefDir = NULL;
 static int allowSymLinks = 0;
 static int allowSymLinks = 0;
 static const PHYSFS_Archiver **archivers = NULL;
 static const PHYSFS_Archiver **archivers = NULL;
 static const PHYSFS_ArchiveInfo **archiveInfo = NULL;
 static const PHYSFS_ArchiveInfo **archiveInfo = NULL;
+static volatile size_t numArchivers = 0;
 
 
 /* mutexes ... */
 /* mutexes ... */
 static void *errorLock = NULL;     /* protects error message list.        */
 static void *errorLock = NULL;     /* protects error message list.        */
@@ -752,7 +753,7 @@ PHYSFS_DECL const char *PHYSFS_getErrorByCode(PHYSFS_ErrorCode code)
         case PHYSFS_ERR_FILES_STILL_OPEN: return "files still open";
         case PHYSFS_ERR_FILES_STILL_OPEN: return "files still open";
         case PHYSFS_ERR_INVALID_ARGUMENT: return "invalid argument";
         case PHYSFS_ERR_INVALID_ARGUMENT: return "invalid argument";
         case PHYSFS_ERR_NOT_MOUNTED: return "not mounted";
         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_SYMLINK_FORBIDDEN: return "symlinks are forbidden";
         case PHYSFS_ERR_NO_WRITE_DIR: return "write directory is not set";
         case PHYSFS_ERR_NO_WRITE_DIR: return "write directory is not set";
         case PHYSFS_ERR_OPEN_FOR_READING: return "file open for reading";
         case PHYSFS_ERR_OPEN_FOR_READING: return "file open for reading";
@@ -768,6 +769,7 @@ PHYSFS_DECL const char *PHYSFS_getErrorByCode(PHYSFS_ErrorCode code)
         case PHYSFS_ERR_BUSY: return "tried to modify a file the OS needs";
         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_DIR_NOT_EMPTY: return "directory isn't empty";
         case PHYSFS_ERR_OS_ERROR: return "OS reported an error";
         case PHYSFS_ERR_OS_ERROR: return "OS reported an error";
+        case PHYSFS_ERR_DUPLICATE: return "duplicate resource";
     } /* switch */
     } /* switch */
 
 
     return NULL;  /* don't know this error code. */
     return NULL;  /* don't know this error code. */
@@ -890,14 +892,14 @@ static DirHandle *openDirectory(PHYSFS_Io *io, const char *d, int forWriting)
         /* Look for archivers with matching file extensions first... */
         /* Look for archivers with matching file extensions first... */
         for (i = archivers; (*i != NULL) && (retval == NULL); i++)
         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);
                 retval = tryOpenDir(io, *i, d, forWriting);
         } /* for */
         } /* for */
 
 
         /* failing an exact file extension match, try all the others... */
         /* failing an exact file extension match, try all the others... */
         for (i = archivers; (*i != NULL) && (retval == NULL); i++)
         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);
                 retval = tryOpenDir(io, *i, d, forWriting);
         } /* for */
         } /* for */
     } /* if */
     } /* if */
@@ -1125,32 +1127,26 @@ initializeMutexes_failed:
 } /* initializeMutexes */
 } /* initializeMutexes */
 
 
 
 
-static void setDefaultAllocator(void);
+static int doRegisterArchiver(const PHYSFS_Archiver *_archiver);
 
 
 static int initStaticArchivers(void)
 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);
+    const PHYSFS_Archiver * const *i;
 
 
-    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);
+    assert(__PHYSFS_ARRAYLEN(staticArchivers) > 0);  /* at least a NULL. */
+    assert(staticArchivers[__PHYSFS_ARRAYLEN(staticArchivers) - 1] == NULL);
 
 
-    for (i = 0; i < numStaticArchivers - 1; i++)
-        archiveInfo[i] = &staticArchivers[i]->info;
-    archiveInfo[numStaticArchivers - 1] = NULL;
-
-    memcpy(archivers, staticArchivers, len);
+    for (i = staticArchivers; *i != NULL; i++)
+    {
+        if (!doRegisterArchiver(*i))
+            return 0;
+    } /* for */
 
 
     return 1;
     return 1;
 } /* initStaticArchivers */
 } /* initStaticArchivers */
 
 
 
 
+static void setDefaultAllocator(void);
 static int doDeinit(void);
 static int doDeinit(void);
 
 
 int PHYSFS_init(const char *argv0)
 int PHYSFS_init(const char *argv0)
@@ -1243,6 +1239,63 @@ static void freeSearchPath(void)
 } /* freeSearchPath */
 } /* 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)
 static int doDeinit(void)
 {
 {
     BAIL_IF_MACRO(!__PHYSFS_platformDeinit(), ERRPASS, 0);
     BAIL_IF_MACRO(!__PHYSFS_platformDeinit(), ERRPASS, 0);
@@ -1251,6 +1304,7 @@ static int doDeinit(void)
     BAIL_IF_MACRO(!PHYSFS_setWriteDir(NULL), PHYSFS_ERR_FILES_STILL_OPEN, 0);
     BAIL_IF_MACRO(!PHYSFS_setWriteDir(NULL), PHYSFS_ERR_FILES_STILL_OPEN, 0);
 
 
     freeSearchPath();
     freeSearchPath();
+    freeArchivers();
     freeErrorStates();
     freeErrorStates();
 
 
     if (baseDir != NULL)
     if (baseDir != NULL)
@@ -1310,6 +1364,133 @@ int PHYSFS_isInit(void)
 } /* PHYSFS_isInit */
 } /* 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)
 const PHYSFS_ArchiveInfo **PHYSFS_supportedArchiveTypes(void)
 {
 {
     BAIL_IF_MACRO(!initialized, PHYSFS_ERR_NOT_INITIALIZED, NULL);
     BAIL_IF_MACRO(!initialized, PHYSFS_ERR_NOT_INITIALIZED, NULL);
@@ -1702,7 +1883,7 @@ int PHYSFS_setSaneConfig(const char *organization, const char *appName,
             if ((l > extlen) && ((*i)[l - extlen - 1] == '.'))
             if ((l > extlen) && ((*i)[l - extlen - 1] == '.'))
             {
             {
                 ext = (*i) + (l - extlen);
                 ext = (*i) + (l - extlen);
-                if (__PHYSFS_stricmpASCII(ext, archiveExt) == 0)
+                if (__PHYSFS_utf8stricmp(ext, archiveExt) == 0)
                     setSaneCfgAddPath(*i, l, dirsep, archivesFirst);
                     setSaneCfgAddPath(*i, l, dirsep, archivesFirst);
             } /* if */
             } /* if */
         } /* for */
         } /* for */
@@ -1763,12 +1944,12 @@ static int verifyPath(DirHandle *h, char **_fname, int allowMissing)
         size_t len = strlen(fname);
         size_t len = strlen(fname);
         assert(mntpntlen > 1); /* root mount points should be NULL. */
         assert(mntpntlen > 1); /* root mount points should be NULL. */
         /* not under the mountpoint, so skip this archive. */
         /* 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? */
         /* !!! FIXME: Case insensitive? */
         retval = strncmp(h->mountPoint, fname, mntpntlen-1);
         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... */
         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. */
         fname += mntpntlen-1;  /* move to start of actual archive path. */
         if (*fname == '/')
         if (*fname == '/')
             fname++;
             fname++;
@@ -2222,7 +2403,7 @@ PHYSFS_File *PHYSFS_openRead(const char *_fname)
 
 
         __PHYSFS_platformGrabMutex(stateLock);
         __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)
         for (i = searchPath; (i != NULL) && (!fileExists); i = i->next)
         {
         {

+ 235 - 4
src/physfs.h

@@ -399,6 +399,8 @@ typedef struct PHYSFS_File
  *          supported.
  *          supported.
  *
  *
  * \sa PHYSFS_supportedArchiveTypes
  * \sa PHYSFS_supportedArchiveTypes
+ * \sa PHYSFS_registerArchiver
+ * \sa PHYSFS_deregisterArchiver
  */
  */
 typedef struct PHYSFS_ArchiveInfo
 typedef struct PHYSFS_ArchiveInfo
 {
 {
@@ -573,9 +575,13 @@ PHYSFS_DECL int PHYSFS_deinit(void);
  *
  *
  * The return values are pointers to internal memory, and should
  * The return values are pointers to internal memory, and should
  *  be considered READ ONLY, and never freed. The returned values are
  *  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.
  *   \return READ ONLY Null-terminated array of READ ONLY structures.
+ *
+ * \sa PHYSFS_registerArchiver
+ * \sa PHYSFS_deregisterArchiver
  */
  */
 PHYSFS_DECL const PHYSFS_ArchiveInfo **PHYSFS_supportedArchiveTypes(void);
 PHYSFS_DECL const PHYSFS_ArchiveInfo **PHYSFS_supportedArchiveTypes(void);
 
 
@@ -3129,7 +3135,7 @@ typedef enum PHYSFS_ErrorCode
     PHYSFS_ERR_FILES_STILL_OPEN, /**< Files still open.                     */
     PHYSFS_ERR_FILES_STILL_OPEN, /**< Files still open.                     */
     PHYSFS_ERR_INVALID_ARGUMENT, /**< Bad parameter passed to an function.  */
     PHYSFS_ERR_INVALID_ARGUMENT, /**< Bad parameter passed to an function.  */
     PHYSFS_ERR_NOT_MOUNTED,      /**< Requested archive/dir not mounted.    */
     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_SYMLINK_FORBIDDEN,/**< Symlink seen when not permitted.      */
     PHYSFS_ERR_NO_WRITE_DIR,     /**< No write dir has been specified.      */
     PHYSFS_ERR_NO_WRITE_DIR,     /**< No write dir has been specified.      */
     PHYSFS_ERR_OPEN_FOR_READING, /**< Wrote to a file opened for reading.   */
     PHYSFS_ERR_OPEN_FOR_READING, /**< Wrote to a file opened for reading.   */
@@ -3144,7 +3150,8 @@ typedef enum PHYSFS_ErrorCode
     PHYSFS_ERR_BAD_FILENAME,     /**< Filename is bogus/insecure.           */
     PHYSFS_ERR_BAD_FILENAME,     /**< Filename is bogus/insecure.           */
     PHYSFS_ERR_BUSY,             /**< Tried to modify a file the OS needs.  */
     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_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;
 } PHYSFS_ErrorCode;
 
 
 
 
@@ -3307,8 +3314,232 @@ PHYSFS_DECL void PHYSFS_setErrorCode(PHYSFS_ErrorCode code);
 PHYSFS_DECL const char *PHYSFS_getPrefDir(const char *org, const char *app);
 PHYSFS_DECL const char *PHYSFS_getPrefDir(const char *org, const char *app);
 
 
 
 
-/* Everything above this line is part of the PhysicsFS 2.1 API. */
+/**
+ * \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
 #ifdef __cplusplus
 }
 }

+ 12 - 139
src/physfs_internal.h

@@ -124,137 +124,10 @@ void __PHYSFS_smallFree(void *ptr);
 /* The latest supported PHYSFS_Io::version value. */
 /* The latest supported PHYSFS_Io::version value. */
 #define CURRENT_PHYSFS_IO_API_VERSION 0
 #define CURRENT_PHYSFS_IO_API_VERSION 0
 
 
-/* Opaque data for file and dir handlers... */
-typedef void PHYSFS_Dir;
+/* The latest supported PHYSFS_Archiver::version value. */
+#define CURRENT_PHYSFS_ARCHIVER_API_VERSION 0
 
 
-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);
-
-        /*
-         * 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().
  * Call this to set the message returned by PHYSFS_getLastError().
  *  Please only use the ERR_* constants above, or add new constants to the
  *  Please only use the ERR_* constants above, or add new constants to the
  *  above group, but I want these all in one place.
  *  above group, but I want these all in one place.
@@ -425,17 +298,17 @@ typedef struct
     PHYSFS_uint32 size;
     PHYSFS_uint32 size;
 } UNPKentry;
 } 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,
                          int omitSymLinks, PHYSFS_EnumFilesCallback cb,
                          const char *origdir, void *callbackdata);
                          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);
 
 
 
 
 /*--------------------------------------------------------------------------*/
 /*--------------------------------------------------------------------------*/

+ 2 - 2
src/platform_posix.c

@@ -41,9 +41,9 @@ static PHYSFS_ErrorCode errcodeFromErrnoError(const int err)
         case ELOOP: return PHYSFS_ERR_SYMLINK_LOOP;
         case ELOOP: return PHYSFS_ERR_SYMLINK_LOOP;
         case EMLINK: return PHYSFS_ERR_NO_SPACE;
         case EMLINK: return PHYSFS_ERR_NO_SPACE;
         case ENAMETOOLONG: return PHYSFS_ERR_BAD_FILENAME;
         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 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 EISDIR: return PHYSFS_ERR_NOT_A_FILE;
         case EROFS: return PHYSFS_ERR_READ_ONLY;
         case EROFS: return PHYSFS_ERR_READ_ONLY;
         case ETXTBSY: return PHYSFS_ERR_BUSY;
         case ETXTBSY: return PHYSFS_ERR_BUSY;

+ 5 - 5
src/platform_windows.c

@@ -124,13 +124,13 @@ static PHYSFS_ErrorCode errcodeFromWinApiError(const DWORD err)
         case ERROR_INVALID_NAME: return PHYSFS_ERR_BAD_FILENAME;
         case ERROR_INVALID_NAME: return PHYSFS_ERR_BAD_FILENAME;
         case ERROR_BAD_PATHNAME: return PHYSFS_ERR_BAD_FILENAME;
         case ERROR_BAD_PATHNAME: return PHYSFS_ERR_BAD_FILENAME;
         case ERROR_DIRECTORY: 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_HANDLE_DISK_FULL: return PHYSFS_ERR_NO_SPACE;
         case ERROR_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; */
         /* !!! FIXME: ?? case EISDIR: return PHYSFS_ERR_NOT_A_FILE; */
         case ERROR_WRITE_PROTECT: return PHYSFS_ERR_READ_ONLY;
         case ERROR_WRITE_PROTECT: return PHYSFS_ERR_READ_ONLY;
         case ERROR_LOCK_VIOLATION: return PHYSFS_ERR_BUSY;
         case ERROR_LOCK_VIOLATION: return PHYSFS_ERR_BUSY;