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).
This commit is contained in:
parent
123313c3cd
commit
e40d80b00f
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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 < 1, PHYSFS_ERR_NOT_FOUND /* !!! 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 == (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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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,
|
void *UNPK_openArchive(PHYSFS_Io *io, UNPKentry *e, const PHYSFS_uint32 num)
|
||||||
const PHYSFS_uint32 num)
|
|
||||||
{
|
{
|
||||||
UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo));
|
UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo));
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
231
src/physfs.c
231
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 PHYSFS_Archiver * const *i;
|
||||||
const size_t len = numStaticArchivers * sizeof (void *);
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
assert(numStaticArchivers > 0); /* seriously, none at all?! */
|
assert(__PHYSFS_ARRAYLEN(staticArchivers) > 0); /* at least a NULL. */
|
||||||
assert(staticArchivers[numStaticArchivers - 1] == NULL);
|
assert(staticArchivers[__PHYSFS_ARRAYLEN(staticArchivers) - 1] == NULL);
|
||||||
|
|
||||||
archiveInfo = (const PHYSFS_ArchiveInfo **) allocator.Malloc(len);
|
for (i = staticArchivers; *i != NULL; i++)
|
||||||
BAIL_IF_MACRO(!archiveInfo, PHYSFS_ERR_OUT_OF_MEMORY, 0);
|
{
|
||||||
archivers = (const PHYSFS_Archiver **) allocator.Malloc(len);
|
if (!doRegisterArchiver(*i))
|
||||||
BAIL_IF_MACRO(!archivers, PHYSFS_ERR_OUT_OF_MEMORY, 0);
|
return 0;
|
||||||
|
} /* for */
|
||||||
for (i = 0; i < numStaticArchivers - 1; i++)
|
|
||||||
archiveInfo[i] = &staticArchivers[i]->info;
|
|
||||||
archiveInfo[numStaticArchivers - 1] = NULL;
|
|
||||||
|
|
||||||
memcpy(archivers, staticArchivers, len);
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
239
src/physfs.h
239
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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... */
|
/* The latest supported PHYSFS_Archiver::version value. */
|
||||||
typedef void PHYSFS_Dir;
|
#define CURRENT_PHYSFS_ARCHIVER_API_VERSION 0
|
||||||
|
|
||||||
typedef struct
|
/* !!! FIXME: update this documentation.
|
||||||
{
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
void UNPK_closeArchive(void *opaque);
|
||||||
PHYSFS_Dir *UNPK_openArchive(PHYSFS_Io *io,UNPKentry *e,const PHYSFS_uint32 n);
|
void *UNPK_openArchive(PHYSFS_Io *io,UNPKentry *e,const PHYSFS_uint32 n);
|
||||||
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);
|
||||||
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 *UNPK_openWrite(PHYSFS_Dir *opaque, const char *name);
|
PHYSFS_Io *UNPK_openWrite(void *opaque, const char *name);
|
||||||
PHYSFS_Io *UNPK_openAppend(PHYSFS_Dir *opaque, const char *name);
|
PHYSFS_Io *UNPK_openAppend(void *opaque, const char *name);
|
||||||
int UNPK_remove(PHYSFS_Dir *opaque, const char *name);
|
int UNPK_remove(void *opaque, const char *name);
|
||||||
int UNPK_mkdir(PHYSFS_Dir *opaque, const char *name);
|
int UNPK_mkdir(void *opaque, const char *name);
|
||||||
int UNPK_stat(PHYSFS_Dir *opaque, const char *fn, int *exist, PHYSFS_Stat *st);
|
int UNPK_stat(void *opaque, const char *fn, int *exist, PHYSFS_Stat *st);
|
||||||
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_FILE_NOT_FOUND: return PHYSFS_ERR_NOT_FOUND;
|
||||||
case ERROR_PATH_NOT_FOUND: return PHYSFS_ERR_NO_SUCH_PATH;
|
case ERROR_PATH_NOT_FOUND: return PHYSFS_ERR_NOT_FOUND;
|
||||||
case ERROR_DELETE_PENDING: return PHYSFS_ERR_NO_SUCH_PATH;
|
case ERROR_DELETE_PENDING: return PHYSFS_ERR_NOT_FOUND;
|
||||||
case ERROR_INVALID_DRIVE: return PHYSFS_ERR_NO_SUCH_PATH;
|
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;
|
||||||
|
|
Loading…
Reference in New Issue