Archivers can now specify whether an archive definitely was intended for them.
So if a zip file goes to the zip archiver but is corrupted, the system can now know not to bother trying other archivers once the zip archiver has had a shot at it, and just as important: it can report the real error from that archiver instead of a generic "unsupported."
This commit is contained in:
parent
2a6215394b
commit
3078acd1eb
26
src/physfs.c
26
src/physfs.c
|
@ -838,7 +838,7 @@ static const char *find_filename_extension(const char *fname)
|
|||
|
||||
|
||||
static DirHandle *tryOpenDir(PHYSFS_Io *io, const PHYSFS_Archiver *funcs,
|
||||
const char *d, int forWriting)
|
||||
const char *d, int forWriting, int *_claimed)
|
||||
{
|
||||
DirHandle *retval = NULL;
|
||||
void *opaque = NULL;
|
||||
|
@ -846,7 +846,7 @@ static DirHandle *tryOpenDir(PHYSFS_Io *io, const PHYSFS_Archiver *funcs,
|
|||
if (io != NULL)
|
||||
BAIL_IF_ERRPASS(!io->seek(io, 0), NULL);
|
||||
|
||||
opaque = funcs->openArchive(io, d, forWriting);
|
||||
opaque = funcs->openArchive(io, d, forWriting, _claimed);
|
||||
if (opaque != NULL)
|
||||
{
|
||||
retval = (DirHandle *) allocator.Malloc(sizeof (DirHandle));
|
||||
|
@ -871,14 +871,16 @@ static DirHandle *openDirectory(PHYSFS_Io *io, const char *d, int forWriting)
|
|||
PHYSFS_Archiver **i;
|
||||
const char *ext;
|
||||
int created_io = 0;
|
||||
int claimed = 0;
|
||||
PHYSFS_ErrorCode errcode;
|
||||
|
||||
assert((io != NULL) || (d != NULL));
|
||||
|
||||
if (io == NULL)
|
||||
{
|
||||
/* DIR gets first shot (unlike the rest, it doesn't deal with files). */
|
||||
retval = tryOpenDir(io, &__PHYSFS_Archiver_DIR, d, forWriting);
|
||||
if (retval != NULL)
|
||||
retval = tryOpenDir(io, &__PHYSFS_Archiver_DIR, d, forWriting, &claimed);
|
||||
if (retval || claimed)
|
||||
return retval;
|
||||
|
||||
io = __PHYSFS_createNativeIo(d, forWriting ? 'w' : 'r');
|
||||
|
@ -890,30 +892,32 @@ static DirHandle *openDirectory(PHYSFS_Io *io, const char *d, int forWriting)
|
|||
if (ext != NULL)
|
||||
{
|
||||
/* Look for archivers with matching file extensions first... */
|
||||
for (i = archivers; (*i != NULL) && (retval == NULL); i++)
|
||||
for (i = archivers; (*i != NULL) && (retval == NULL) && !claimed; i++)
|
||||
{
|
||||
if (PHYSFS_utf8stricmp(ext, (*i)->info.extension) == 0)
|
||||
retval = tryOpenDir(io, *i, d, forWriting);
|
||||
retval = tryOpenDir(io, *i, d, forWriting, &claimed);
|
||||
} /* for */
|
||||
|
||||
/* 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) && !claimed; i++)
|
||||
{
|
||||
if (PHYSFS_utf8stricmp(ext, (*i)->info.extension) != 0)
|
||||
retval = tryOpenDir(io, *i, d, forWriting);
|
||||
retval = tryOpenDir(io, *i, d, forWriting, &claimed);
|
||||
} /* for */
|
||||
} /* if */
|
||||
|
||||
else /* no extension? Try them all. */
|
||||
{
|
||||
for (i = archivers; (*i != NULL) && (retval == NULL); i++)
|
||||
retval = tryOpenDir(io, *i, d, forWriting);
|
||||
for (i = archivers; (*i != NULL) && (retval == NULL) && !claimed; i++)
|
||||
retval = tryOpenDir(io, *i, d, forWriting, &claimed);
|
||||
} /* else */
|
||||
|
||||
errcode = currentErrorCode();
|
||||
|
||||
if ((!retval) && (created_io))
|
||||
io->destroy(io);
|
||||
|
||||
BAIL_IF(!retval, PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
BAIL_IF(!retval, claimed ? errcode : PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
return retval;
|
||||
} /* openDirectory */
|
||||
|
||||
|
|
24
src/physfs.h
24
src/physfs.h
|
@ -3492,20 +3492,30 @@ typedef struct PHYSFS_Archiver
|
|||
/**
|
||||
* \brief Open an archive provided by (io).
|
||||
*
|
||||
* This is where resources are allocated and data is parsed when mounting an archive.
|
||||
* (name) is a filename associated with (io), but doesn't necessarily
|
||||
* This is where resources are allocated and data is parsed when mounting
|
||||
* an archive.
|
||||
* (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-3.0: yeah?
|
||||
* Returns non-NULL on success. The pointer returned will be
|
||||
* (claimed) should be set to 1 if this is definitely an archive your
|
||||
* archiver implementation can handle, even if it fails. We use to
|
||||
* decide if we should stop trying other archivers if you fail to open
|
||||
* it. For example: the .zip archiver will set this to 1 for something
|
||||
* that's got a .zip file signature, even if it failed because the file
|
||||
* was also truncated. No sense in trying other archivers here, we
|
||||
* already tried to handle it with the appropriate implementation!.
|
||||
* Return NULL on failure and set (claimed) appropriately. If no archiver
|
||||
* opened the archive or set (claimed), PHYSFS_mount() will report
|
||||
* PHYSFS_ERR_UNSUPPORTED. Otherwise, it will report the error from the
|
||||
* archiver that claimed the data through (claimed).
|
||||
* Return 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);
|
||||
void *(*openArchive)(PHYSFS_Io *io, const char *name,
|
||||
int forWrite, int *claimed);
|
||||
|
||||
/**
|
||||
* \brief List all files in (dirname).
|
||||
|
|
|
@ -210,14 +210,23 @@ static void SZIP_closeArchive(void *opaque)
|
|||
} /* SZIP_closeArchive */
|
||||
|
||||
|
||||
static void *SZIP_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
||||
static void *SZIP_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
static const PHYSFS_uint8 wantedsig[] = { '7','z',0xBC,0xAF,0x27,0x1C };
|
||||
SZIPLookToRead stream;
|
||||
ISzAlloc *alloc = &SZIP_SzAlloc;
|
||||
SZIPinfo *info = NULL;
|
||||
SRes rc;
|
||||
PHYSFS_uint8 sig[6];
|
||||
PHYSFS_sint64 pos;
|
||||
|
||||
BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
|
||||
pos = io->tell(io);
|
||||
BAIL_IF_ERRPASS(pos == -1, NULL);
|
||||
BAIL_IF_ERRPASS(io->read(io, sig, 6) != 6, NULL);
|
||||
*claimed = (memcmp(sig, wantedsig, 6) == 0);
|
||||
BAIL_IF_ERRPASS(!io->seek(io, pos), NULL);
|
||||
|
||||
info = (SZIPinfo *) allocator.Malloc(sizeof (SZIPinfo));
|
||||
BAIL_IF(!info, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
||||
|
|
|
@ -37,7 +37,8 @@ static char *cvtToDependent(const char *prepend, const char *path,
|
|||
|
||||
|
||||
|
||||
static void *DIR_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
||||
static void *DIR_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
PHYSFS_Stat st;
|
||||
const char dirsep = __PHYSFS_platformDirSeparator;
|
||||
|
@ -50,6 +51,7 @@ static void *DIR_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
|||
if (st.filetype != PHYSFS_FILETYPE_DIRECTORY)
|
||||
BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
|
||||
*claimed = 1;
|
||||
retval = allocator.Malloc(namelen + seplen + 1);
|
||||
BAIL_IF(retval == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
||||
|
||||
|
|
|
@ -56,7 +56,8 @@ static int grpLoadEntries(PHYSFS_Io *io, const PHYSFS_uint32 count, void *arc)
|
|||
} /* grpLoadEntries */
|
||||
|
||||
|
||||
static void *GRP_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
||||
static void *GRP_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
PHYSFS_uint8 buf[12];
|
||||
PHYSFS_uint32 count = 0;
|
||||
|
@ -70,6 +71,8 @@ static void *GRP_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
|||
if (memcmp(buf, "KenSilverman", sizeof (buf)) != 0)
|
||||
BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
|
||||
*claimed = 1;
|
||||
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof(count)), NULL);
|
||||
count = PHYSFS_swapULE32(count);
|
||||
|
||||
|
|
|
@ -61,7 +61,8 @@ static int hogLoadEntries(PHYSFS_Io *io, void *arc)
|
|||
} /* hogLoadEntries */
|
||||
|
||||
|
||||
static void *HOG_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
||||
static void *HOG_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
PHYSFS_uint8 buf[3];
|
||||
void *unpkarc = NULL;
|
||||
|
@ -71,6 +72,8 @@ static void *HOG_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
|||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, buf, 3), NULL);
|
||||
BAIL_IF(memcmp(buf, "DHF", 3) != 0, PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
|
||||
*claimed = 1;
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
BAIL_IF_ERRPASS(!unpkarc, NULL);
|
||||
|
||||
|
|
|
@ -215,11 +215,11 @@ static int iso9660LoadEntries(PHYSFS_Io *io, const int joliet,
|
|||
|
||||
|
||||
static int parseVolumeDescriptor(PHYSFS_Io *io, PHYSFS_uint64 *_rootpos,
|
||||
PHYSFS_uint64 *_rootlen, int *_joliet)
|
||||
PHYSFS_uint64 *_rootlen, int *_joliet,
|
||||
int *_claimed)
|
||||
{
|
||||
PHYSFS_uint64 pos = 32768; /* start at the Primary Volume Descriptor */
|
||||
int found = 0;
|
||||
int first = 1;
|
||||
int done = 0;
|
||||
|
||||
*_joliet = 0;
|
||||
|
@ -242,13 +242,13 @@ static int parseVolumeDescriptor(PHYSFS_Io *io, PHYSFS_uint64 *_rootpos,
|
|||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &type, 1), 0);
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &identifier, 5), 0);
|
||||
|
||||
if (memcmp(identifier, "CD001", 5) != 0)
|
||||
if (memcmp(identifier, "CD001", 5) != 0) /* maybe not an iso? */
|
||||
{
|
||||
BAIL_IF(first, PHYSFS_ERR_UNSUPPORTED, 0); /* maybe not an iso? */
|
||||
BAIL_IF(!*_claimed, PHYSFS_ERR_UNSUPPORTED, 0);
|
||||
continue; /* just skip this one */
|
||||
} /* if */
|
||||
|
||||
first = 0; /* okay, this is probably an iso. */
|
||||
*_claimed = 1; /* okay, this is probably an iso. */
|
||||
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &version, 1), 0); /* version */
|
||||
BAIL_IF(version != 1, PHYSFS_ERR_UNSUPPORTED, 0);
|
||||
|
@ -320,7 +320,8 @@ static int parseVolumeDescriptor(PHYSFS_Io *io, PHYSFS_uint64 *_rootpos,
|
|||
} /* parseVolumeDescriptor */
|
||||
|
||||
|
||||
static void *ISO9660_openArchive(PHYSFS_Io *io, const char *filename, int forWriting)
|
||||
static void *ISO9660_openArchive(PHYSFS_Io *io, const char *filename,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
PHYSFS_uint64 rootpos = 0;
|
||||
PHYSFS_uint64 len = 0;
|
||||
|
@ -330,7 +331,9 @@ static void *ISO9660_openArchive(PHYSFS_Io *io, const char *filename, int forWri
|
|||
assert(io != NULL); /* shouldn't ever happen. */
|
||||
|
||||
BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
|
||||
BAIL_IF_ERRPASS(!parseVolumeDescriptor(io, &rootpos, &len, &joliet), NULL);
|
||||
|
||||
if (!parseVolumeDescriptor(io, &rootpos, &len, &joliet, claimed))
|
||||
return NULL;
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
BAIL_IF_ERRPASS(!unpkarc, NULL);
|
||||
|
|
|
@ -53,7 +53,8 @@ static int mvlLoadEntries(PHYSFS_Io *io, const PHYSFS_uint32 count, void *arc)
|
|||
} /* mvlLoadEntries */
|
||||
|
||||
|
||||
static void *MVL_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
||||
static void *MVL_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
PHYSFS_uint8 buf[4];
|
||||
PHYSFS_uint32 count = 0;
|
||||
|
@ -63,8 +64,10 @@ static void *MVL_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
|||
BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, buf, 4), NULL);
|
||||
BAIL_IF(memcmp(buf, "DMVL", 4) != 0, PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof(count)), NULL);
|
||||
|
||||
*claimed = 1;
|
||||
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof(count)), NULL);
|
||||
count = PHYSFS_swapULE32(count);
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
|
|
|
@ -56,7 +56,8 @@ static int qpakLoadEntries(PHYSFS_Io *io, const PHYSFS_uint32 count, void *arc)
|
|||
} /* qpakLoadEntries */
|
||||
|
||||
|
||||
static void *QPAK_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
||||
static void *QPAK_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
PHYSFS_uint32 val = 0;
|
||||
PHYSFS_uint32 pos = 0;
|
||||
|
@ -71,6 +72,8 @@ static void *QPAK_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
|||
if (PHYSFS_swapULE32(val) != QPAK_SIG)
|
||||
BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
|
||||
*claimed = 1;
|
||||
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &val, 4), NULL);
|
||||
pos = PHYSFS_swapULE32(val); /* directory table offset. */
|
||||
|
||||
|
|
|
@ -59,7 +59,8 @@ static int slbLoadEntries(PHYSFS_Io *io, const PHYSFS_uint32 count, void *arc)
|
|||
} /* slbLoadEntries */
|
||||
|
||||
|
||||
static void *SLB_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
||||
static void *SLB_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
PHYSFS_uint32 version;
|
||||
PHYSFS_uint32 count;
|
||||
|
@ -102,6 +103,8 @@ static void *SLB_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
|||
return NULL;
|
||||
} /* if */
|
||||
|
||||
*claimed = 1; /* oh well. */
|
||||
|
||||
return unpkarc;
|
||||
} /* SLB_openArchive */
|
||||
|
||||
|
|
|
@ -91,7 +91,8 @@ static int vdfLoadEntries(PHYSFS_Io *io, const PHYSFS_uint32 count,
|
|||
} /* vdfLoadEntries */
|
||||
|
||||
|
||||
static void *VDF_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
||||
static void *VDF_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
PHYSFS_uint8 ignore[16];
|
||||
PHYSFS_uint8 sig[VDF_SIGNATURE_LENGTH];
|
||||
|
@ -106,6 +107,15 @@ static void *VDF_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
|||
BAIL_IF_ERRPASS(!io->seek(io, VDF_COMMENT_LENGTH), NULL);
|
||||
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, sig, sizeof (sig)), NULL);
|
||||
|
||||
if ((memcmp(sig, VDF_SIGNATURE_G1, VDF_SIGNATURE_LENGTH) != 0) &&
|
||||
(memcmp(sig, VDF_SIGNATURE_G2, VDF_SIGNATURE_LENGTH) != 0))
|
||||
{
|
||||
BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
} /* if */
|
||||
|
||||
*claimed = 1;
|
||||
|
||||
BAIL_IF_ERRPASS(!readui32(io, &count), NULL);
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, ignore, 4), NULL); /* numFiles */
|
||||
BAIL_IF_ERRPASS(!readui32(io, ×tamp), NULL);
|
||||
|
@ -115,12 +125,6 @@ static void *VDF_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
|||
|
||||
BAIL_IF(version != 0x50, PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
|
||||
if ((memcmp(sig, VDF_SIGNATURE_G1, VDF_SIGNATURE_LENGTH) != 0) &&
|
||||
(memcmp(sig, VDF_SIGNATURE_G2, VDF_SIGNATURE_LENGTH) != 0))
|
||||
{
|
||||
BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
} /* if */
|
||||
|
||||
BAIL_IF_ERRPASS(!io->seek(io, rootCatOffset), NULL);
|
||||
|
||||
unpkarc = UNPK_openArchive(io);
|
||||
|
|
|
@ -70,7 +70,8 @@ static int wadLoadEntries(PHYSFS_Io *io, const PHYSFS_uint32 count, void *arc)
|
|||
} /* wadLoadEntries */
|
||||
|
||||
|
||||
static void *WAD_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
||||
static void *WAD_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
PHYSFS_uint8 buf[4];
|
||||
PHYSFS_uint32 count;
|
||||
|
@ -84,6 +85,8 @@ static void *WAD_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
|||
if ((memcmp(buf, "IWAD", 4) != 0) && (memcmp(buf, "PWAD", 4) != 0))
|
||||
BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
|
||||
|
||||
*claimed = 1;
|
||||
|
||||
BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof (count)), NULL);
|
||||
count = PHYSFS_swapULE32(count);
|
||||
|
||||
|
|
|
@ -1451,7 +1451,8 @@ static void ZIP_closeArchive(void *opaque)
|
|||
} /* ZIP_closeArchive */
|
||||
|
||||
|
||||
static void *ZIP_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
||||
static void *ZIP_openArchive(PHYSFS_Io *io, const char *name,
|
||||
int forWriting, int *claimed)
|
||||
{
|
||||
ZIPinfo *info = NULL;
|
||||
ZIPentry *root = NULL;
|
||||
|
@ -1464,6 +1465,8 @@ static void *ZIP_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
|
|||
BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
|
||||
BAIL_IF_ERRPASS(!isZip(io), NULL);
|
||||
|
||||
*claimed = 1;
|
||||
|
||||
info = (ZIPinfo *) allocator.Malloc(sizeof (ZIPinfo));
|
||||
BAIL_IF(!info, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
|
||||
memset(info, '\0', sizeof (ZIPinfo));
|
||||
|
|
Loading…
Reference in New Issue