From 3f02ce767f77c364a1a70760c396279cf040dcb4 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 6 Sep 2010 02:50:29 -0400 Subject: [PATCH] Moved most the cut-and-paste between simple archivers to one file. --- CMakeLists.txt | 1 + src/archiver_grp.c | 376 ++++---------------------------------- src/archiver_hog.c | 388 ++++------------------------------------ src/archiver_mvl.c | 375 ++++---------------------------------- src/archiver_unpacked.c | 328 +++++++++++++++++++++++++++++++++ src/archiver_wad.c | 377 ++++---------------------------------- src/physfs_internal.h | 24 +++ 7 files changed, 478 insertions(+), 1391 deletions(-) create mode 100644 src/archiver_unpacked.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f910cb8..ee7fc22e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,7 @@ SET(PHYSFS_SRCS src/platform_macosx.c src/platform_windows.c src/archiver_dir.c + src/archiver_unpacked.c src/archiver_grp.c src/archiver_hog.c src/archiver_lzma.c diff --git a/src/archiver_grp.c b/src/archiver_grp.c index bbf5f10d..6c0cf9cf 100644 --- a/src/archiver_grp.c +++ b/src/archiver_grp.c @@ -34,188 +34,27 @@ #define __PHYSICSFS_INTERNAL__ #include "physfs_internal.h" -typedef struct -{ - char name[13]; - PHYSFS_uint32 startPos; - PHYSFS_uint32 size; -} GRPentry; - -typedef struct -{ - PHYSFS_Io *io; - PHYSFS_uint32 entryCount; - GRPentry *entries; -} GRPinfo; - -typedef struct -{ - PHYSFS_Io *io; - GRPentry *entry; - PHYSFS_uint32 curPos; -} GRPfileinfo; - - static inline int readAll(PHYSFS_Io *io, void *buf, const PHYSFS_uint64 len) { return (io->read(io, buf, len) == len); } /* readAll */ - -static void GRP_dirClose(dvoid *opaque) -{ - GRPinfo *info = ((GRPinfo *) opaque); - info->io->destroy(info->io); - allocator.Free(info->entries); - allocator.Free(info); -} /* GRP_dirClose */ - - -static PHYSFS_sint64 GRP_read(PHYSFS_Io *io, void *buffer, PHYSFS_uint64 len) -{ - GRPfileinfo *finfo = (GRPfileinfo *) io->opaque; - const GRPentry *entry = finfo->entry; - const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos); - PHYSFS_sint64 rc; - - if (bytesLeft < len) - len = bytesLeft; - - rc = finfo->io->read(finfo->io, buffer, len); - if (rc > 0) - finfo->curPos += (PHYSFS_uint32) rc; - - return rc; -} /* GRP_read */ - - -static PHYSFS_sint64 GRP_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, -1); -} /* GRP_write */ - - -static PHYSFS_sint64 GRP_tell(PHYSFS_Io *io) -{ - return ((GRPfileinfo *) io->opaque)->curPos; -} /* GRP_tell */ - - -static int GRP_seek(PHYSFS_Io *io, PHYSFS_uint64 offset) -{ - GRPfileinfo *finfo = (GRPfileinfo *) io->opaque; - const GRPentry *entry = finfo->entry; - int rc; - - BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0); - rc = finfo->io->seek(finfo->io, entry->startPos + offset); - if (rc) - finfo->curPos = (PHYSFS_uint32) offset; - - return rc; -} /* GRP_seek */ - - -static PHYSFS_sint64 GRP_length(PHYSFS_Io *io) -{ - const GRPfileinfo *finfo = (GRPfileinfo *) io->opaque; - return ((PHYSFS_sint64) finfo->entry->size); -} /* GRP_length */ - - -static PHYSFS_Io *GRP_duplicate(PHYSFS_Io *_io) -{ - GRPfileinfo *origfinfo = (GRPfileinfo *) _io->opaque; - PHYSFS_Io *io = NULL; - PHYSFS_Io *retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); - GRPfileinfo *finfo = (GRPfileinfo *) allocator.Malloc(sizeof (GRPfileinfo)); - GOTO_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, GRP_duplicate_failed); - GOTO_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, GRP_duplicate_failed); - - io = origfinfo->io->duplicate(origfinfo->io); - GOTO_IF_MACRO(io == NULL, NULL, GRP_duplicate_failed); - finfo->io = io; - finfo->entry = origfinfo->entry; - finfo->curPos = 0; - memcpy(retval, _io, sizeof (PHYSFS_Io)); - retval->opaque = finfo; - return retval; - -GRP_duplicate_failed: - if (finfo != NULL) allocator.Free(finfo); - if (retval != NULL) allocator.Free(retval); - if (io != NULL) io->destroy(io); - return NULL; -} /* GRP_duplicate */ - -static int GRP_flush(PHYSFS_Io *io) { return 1; /* no write support. */ } - -static void GRP_destroy(PHYSFS_Io *io) -{ - GRPfileinfo *finfo = (GRPfileinfo *) io->opaque; - finfo->io->destroy(finfo->io); - allocator.Free(finfo); - allocator.Free(io); -} /* GRP_destroy */ - - -static const PHYSFS_Io GRP_Io = -{ - GRP_read, - GRP_write, - GRP_seek, - GRP_tell, - GRP_length, - GRP_duplicate, - GRP_flush, - GRP_destroy, - NULL -}; - - - -static int grpEntryCmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two) -{ - if (one != two) - { - const GRPentry *a = (const GRPentry *) _a; - return __PHYSFS_stricmpASCII(a[one].name, a[two].name); - } /* if */ - - return 0; -} /* grpEntryCmp */ - - -static void grpEntrySwap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two) -{ - if (one != two) - { - GRPentry tmp; - GRPentry *first = &(((GRPentry *) _a)[one]); - GRPentry *second = &(((GRPentry *) _a)[two]); - memcpy(&tmp, first, sizeof (GRPentry)); - memcpy(first, second, sizeof (GRPentry)); - memcpy(second, &tmp, sizeof (GRPentry)); - } /* if */ -} /* grpEntrySwap */ - - -static int grp_load_entries(PHYSFS_Io *io, GRPinfo *info) +static UNPKentry *grpLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount) { - PHYSFS_uint32 fileCount = info->entryCount; PHYSFS_uint32 location = 16; /* sizeof sig. */ - GRPentry *entry; - char *ptr; + UNPKentry *entries = NULL; + UNPKentry *entry = NULL; + char *ptr = NULL; - info->entries = (GRPentry *) allocator.Malloc(sizeof(GRPentry)*fileCount); - BAIL_IF_MACRO(info->entries == NULL, ERR_OUT_OF_MEMORY, 0); + entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount); + BAIL_IF_MACRO(entries == NULL, ERR_OUT_OF_MEMORY, NULL); location += (16 * fileCount); - for (entry = info->entries; fileCount > 0; fileCount--, entry++) + for (entry = entries; fileCount > 0; fileCount--, entry++) { - BAIL_IF_MACRO(!readAll(io, &entry->name, 12), NULL, 0); - BAIL_IF_MACRO(!readAll(io, &entry->size, 4), NULL, 0); + GOTO_IF_MACRO(!readAll(io, &entry->name, 12), NULL, grpLoad_failed); + GOTO_IF_MACRO(!readAll(io, &entry->size, 4), NULL, grpLoad_failed); entry->name[12] = '\0'; /* name isn't null-terminated in file. */ if ((ptr = strchr(entry->name, ' ')) != NULL) *ptr = '\0'; /* trim extra spaces. */ @@ -225,16 +64,19 @@ static int grp_load_entries(PHYSFS_Io *io, GRPinfo *info) location += entry->size; } /* for */ - __PHYSFS_sort(info->entries, info->entryCount, grpEntryCmp, grpEntrySwap); - return 1; -} /* grp_load_entries */ + return entries; + +grpLoad_failed: + allocator.Free(entries); + return NULL; +} /* grpLoadEntries */ static void *GRP_openArchive(PHYSFS_Io *io, const char *name, int forWriting) { PHYSFS_uint8 buf[12]; - GRPinfo *info = NULL; - PHYSFS_uint32 val = 0; + PHYSFS_uint32 entryCount = 0; + UNPKentry *entries = NULL; assert(io != NULL); /* shouldn't ever happen. */ @@ -242,173 +84,17 @@ static void *GRP_openArchive(PHYSFS_Io *io, const char *name, int forWriting) BAIL_IF_MACRO(!readAll(io, buf, sizeof (buf)), NULL, NULL); if (memcmp(buf, "KenSilverman", sizeof (buf)) != 0) - GOTO_MACRO(ERR_NOT_AN_ARCHIVE, GRP_openArchive_failed); - - info = (GRPinfo *) allocator.Malloc(sizeof (GRPinfo)); - GOTO_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, GRP_openArchive_failed); - memset(info, '\0', sizeof (GRPinfo)); - info->io = io; - - GOTO_IF_MACRO(!readAll(io,&val,sizeof(val)), NULL, GRP_openArchive_failed); - info->entryCount = PHYSFS_swapULE32(val); + BAIL_MACRO(ERR_NOT_AN_ARCHIVE, NULL); - GOTO_IF_MACRO(!grp_load_entries(io, info), NULL, GRP_openArchive_failed); - - return info; - -GRP_openArchive_failed: - if (info != NULL) - { - if (info->entries != NULL) - allocator.Free(info->entries); - allocator.Free(info); - } /* if */ + BAIL_IF_MACRO(!readAll(io, &entryCount, sizeof (entryCount)), NULL, NULL); + entryCount = PHYSFS_swapULE32(entryCount); - return NULL; + entries = grpLoadEntries(io, entryCount); + BAIL_IF_MACRO(entries == NULL, NULL, NULL); + return UNPK_openArchive(io, entries, entryCount); } /* GRP_openArchive */ -static void GRP_enumerateFiles(dvoid *opaque, const char *dname, - int omitSymLinks, PHYSFS_EnumFilesCallback cb, - const char *origdir, void *callbackdata) -{ - /* no directories in GRP files. */ - if (*dname == '\0') - { - GRPinfo *info = (GRPinfo *) opaque; - GRPentry *entry = info->entries; - PHYSFS_uint32 max = info->entryCount; - PHYSFS_uint32 i; - - for (i = 0; i < max; i++, entry++) - cb(callbackdata, origdir, entry->name); - } /* if */ -} /* GRP_enumerateFiles */ - - -static GRPentry *grp_find_entry(const GRPinfo *info, const char *name) -{ - char *ptr = strchr(name, '.'); - GRPentry *a = info->entries; - PHYSFS_sint32 lo = 0; - PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1); - PHYSFS_sint32 middle; - int rc; - - /* - * Rule out filenames to avoid unneeded processing...no dirs, - * big filenames, or extensions > 3 chars. - */ - BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL); - BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL); - BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL); - - while (lo <= hi) - { - middle = lo + ((hi - lo) / 2); - rc = __PHYSFS_stricmpASCII(name, a[middle].name); - if (rc == 0) /* found it! */ - return &a[middle]; - else if (rc > 0) - lo = middle + 1; - else - hi = middle - 1; - } /* while */ - - BAIL_MACRO(ERR_NO_SUCH_FILE, NULL); -} /* grp_find_entry */ - - -static PHYSFS_Io *GRP_openRead(dvoid *opaque, const char *fnm, int *fileExists) -{ - PHYSFS_Io *retval = NULL; - GRPinfo *info = (GRPinfo *) opaque; - GRPfileinfo *finfo; - GRPentry *entry; - - entry = grp_find_entry(info, fnm); - *fileExists = (entry != NULL); - GOTO_IF_MACRO(entry == NULL, NULL, GRP_openRead_failed); - - retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); - GOTO_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, GRP_openRead_failed); - - finfo = (GRPfileinfo *) allocator.Malloc(sizeof (GRPfileinfo)); - GOTO_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, GRP_openRead_failed); - - finfo->io = info->io->duplicate(info->io); - GOTO_IF_MACRO(finfo->io == NULL, NULL, GRP_openRead_failed); - - if (!finfo->io->seek(finfo->io, entry->startPos)) - GOTO_MACRO(NULL, GRP_openRead_failed); - - finfo->curPos = 0; - finfo->entry = entry; - - memcpy(retval, &GRP_Io, sizeof (*retval)); - retval->opaque = finfo; - return retval; - -GRP_openRead_failed: - if (finfo != NULL) - { - if (finfo->io != NULL) - finfo->io->destroy(finfo->io); - allocator.Free(finfo); - } /* if */ - - if (retval != NULL) - allocator.Free(retval); - - return NULL; -} /* GRP_openRead */ - - -static PHYSFS_Io *GRP_openWrite(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, NULL); -} /* GRP_openWrite */ - - -static PHYSFS_Io *GRP_openAppend(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, NULL); -} /* GRP_openAppend */ - - -static int GRP_remove(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, 0); -} /* GRP_remove */ - - -static int GRP_mkdir(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, 0); -} /* GRP_mkdir */ - - -static int GRP_stat(dvoid *opaque, const char *filename, int *exists, - PHYSFS_Stat *stat) -{ - const GRPinfo *info = (const GRPinfo *) opaque; - const GRPentry *entry = grp_find_entry(info, filename); - - *exists = (entry != 0); - if (!entry) - return 0; - - stat->filesize = entry->size; - stat->filetype = PHYSFS_FILETYPE_REGULAR; - stat->modtime = -1; - stat->createtime = -1; - stat->accesstime = -1; - stat->readonly = 1; - - return 1; -} /* GRP_stat */ - - const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_GRP = { "GRP", @@ -422,14 +108,14 @@ const PHYSFS_Archiver __PHYSFS_Archiver_GRP = { &__PHYSFS_ArchiveInfo_GRP, GRP_openArchive, /* openArchive() method */ - GRP_enumerateFiles, /* enumerateFiles() method */ - GRP_openRead, /* openRead() method */ - GRP_openWrite, /* openWrite() method */ - GRP_openAppend, /* openAppend() method */ - GRP_remove, /* remove() method */ - GRP_mkdir, /* mkdir() method */ - GRP_dirClose, /* dirClose() method */ - GRP_stat /* stat() method */ + UNPK_enumerateFiles, /* enumerateFiles() method */ + UNPK_openRead, /* openRead() method */ + UNPK_openWrite, /* openWrite() method */ + UNPK_openAppend, /* openAppend() method */ + UNPK_remove, /* remove() method */ + UNPK_mkdir, /* mkdir() method */ + UNPK_dirClose, /* dirClose() method */ + UNPK_stat /* stat() method */ }; #endif /* defined PHYSFS_SUPPORTS_GRP */ diff --git a/src/archiver_hog.c b/src/archiver_hog.c index bebfad4c..49b297ca 100644 --- a/src/archiver_hog.c +++ b/src/archiver_hog.c @@ -39,392 +39,68 @@ #define __PHYSICSFS_INTERNAL__ #include "physfs_internal.h" -/* - * One HOGentry is kept for each file in an open HOG archive. - */ -typedef struct -{ - char name[13]; - PHYSFS_uint32 startPos; - PHYSFS_uint32 size; -} HOGentry; - -/* - * One HOGinfo is kept for each open HOG archive. - */ -typedef struct -{ - PHYSFS_Io *io; - PHYSFS_uint32 entryCount; - HOGentry *entries; -} HOGinfo; - -/* - * One HOGfileinfo is kept for each open file in a HOG archive. - */ -typedef struct -{ - PHYSFS_Io *io; - HOGentry *entry; - PHYSFS_uint32 curPos; -} HOGfileinfo; - - static inline int readAll(PHYSFS_Io *io, void *buf, const PHYSFS_uint64 len) { return (io->read(io, buf, len) == len); } /* readAll */ - -static void HOG_dirClose(dvoid *opaque) -{ - HOGinfo *info = ((HOGinfo *) opaque); - info->io->destroy(info->io); - allocator.Free(info->entries); - allocator.Free(info); -} /* HOG_dirClose */ - - -static PHYSFS_sint64 HOG_read(PHYSFS_Io *io, void *buffer, PHYSFS_uint64 len) -{ - HOGfileinfo *finfo = (HOGfileinfo *) io->opaque; - const HOGentry *entry = finfo->entry; - const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos); - PHYSFS_sint64 rc; - - if (bytesLeft < len) - len = bytesLeft; - - rc = finfo->io->read(finfo->io, buffer, len); - if (rc > 0) - finfo->curPos += (PHYSFS_uint32) rc; - - return rc; -} /* HOG_read */ - - -static PHYSFS_sint64 HOG_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, -1); -} /* HOG_write */ - - -static PHYSFS_sint64 HOG_tell(PHYSFS_Io *io) -{ - return ((HOGfileinfo *) io->opaque)->curPos; -} /* HOG_tell */ - - -static int HOG_seek(PHYSFS_Io *io, PHYSFS_uint64 offset) -{ - HOGfileinfo *finfo = (HOGfileinfo *) io->opaque; - const HOGentry *entry = finfo->entry; - int rc; - - BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0); - rc = finfo->io->seek(finfo->io, entry->startPos + offset); - if (rc) - finfo->curPos = (PHYSFS_uint32) offset; - - return rc; -} /* HOG_seek */ - - -static PHYSFS_sint64 HOG_length(PHYSFS_Io *io) -{ - const HOGfileinfo *finfo = (HOGfileinfo *) io->opaque; - return ((PHYSFS_sint64) finfo->entry->size); -} /* HOG_length */ - - -static PHYSFS_Io *HOG_duplicate(PHYSFS_Io *_io) -{ - HOGfileinfo *origfinfo = (HOGfileinfo *) _io->opaque; - PHYSFS_Io *io = NULL; - PHYSFS_Io *retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); - HOGfileinfo *finfo = (HOGfileinfo *) allocator.Malloc(sizeof (HOGfileinfo)); - GOTO_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, HOG_duplicate_failed); - GOTO_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, HOG_duplicate_failed); - - io = origfinfo->io->duplicate(origfinfo->io); - GOTO_IF_MACRO(io == NULL, NULL, HOG_duplicate_failed); - finfo->io = io; - finfo->entry = origfinfo->entry; - finfo->curPos = 0; - memcpy(retval, _io, sizeof (PHYSFS_Io)); - retval->opaque = finfo; - return retval; - -HOG_duplicate_failed: - if (finfo != NULL) allocator.Free(finfo); - if (retval != NULL) allocator.Free(retval); - if (io != NULL) io->destroy(io); - return NULL; -} /* HOG_duplicate */ - -static int HOG_flush(PHYSFS_Io *io) { return 1; /* no write support. */ } - -static void HOG_destroy(PHYSFS_Io *io) -{ - HOGfileinfo *finfo = (HOGfileinfo *) io->opaque; - finfo->io->destroy(finfo->io); - allocator.Free(finfo); - allocator.Free(io); -} /* HOG_destroy */ - - -static const PHYSFS_Io HOG_Io = -{ - HOG_read, - HOG_write, - HOG_seek, - HOG_tell, - HOG_length, - HOG_duplicate, - HOG_flush, - HOG_destroy, - NULL -}; - - - -static int hogEntryCmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two) -{ - if (one != two) - { - const HOGentry *a = (const HOGentry *) _a; - return __PHYSFS_stricmpASCII(a[one].name, a[two].name); - } /* if */ - - return 0; -} /* hogEntryCmp */ - - -static void hogEntrySwap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two) -{ - if (one != two) - { - HOGentry tmp; - HOGentry *first = &(((HOGentry *) _a)[one]); - HOGentry *second = &(((HOGentry *) _a)[two]); - memcpy(&tmp, first, sizeof (HOGentry)); - memcpy(first, second, sizeof (HOGentry)); - memcpy(second, &tmp, sizeof (HOGentry)); - } /* if */ -} /* hogEntrySwap */ - - -static int hog_load_entries(PHYSFS_Io *io, HOGinfo *info) +static UNPKentry *hogLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 *_entCount) { const PHYSFS_uint64 iolen = io->length(io); PHYSFS_uint32 entCount = 0; void *ptr = NULL; - HOGentry *entry = NULL; + UNPKentry *entries = NULL; + UNPKentry *entry = NULL; PHYSFS_uint32 size = 0; PHYSFS_uint32 pos = 3; while (pos < iolen) { entCount++; - ptr = allocator.Realloc(ptr, sizeof (HOGentry) * entCount); - BAIL_IF_MACRO(ptr == NULL, ERR_OUT_OF_MEMORY, 0); - info->entries = (HOGentry *) ptr; - entry = &info->entries[entCount-1]; + ptr = allocator.Realloc(ptr, sizeof (UNPKentry) * entCount); + GOTO_IF_MACRO(ptr == NULL, ERR_OUT_OF_MEMORY, hogLoad_failed); + entries = (UNPKentry *) ptr; + entry = &entries[entCount-1]; - BAIL_IF_MACRO(!readAll(io, &entry->name, 13), NULL, 0); + GOTO_IF_MACRO(!readAll(io, &entry->name, 13), NULL, hogLoad_failed); pos += 13; - BAIL_IF_MACRO(!readAll(io, &size, 4), NULL, 0); + GOTO_IF_MACRO(!readAll(io, &size, 4), NULL, hogLoad_failed); pos += 4; entry->size = PHYSFS_swapULE32(size); entry->startPos = pos; pos += size; - BAIL_IF_MACRO(!io->seek(io, pos), NULL, 0); /* skip over entry */ - } /* for */ + /* skip over entry */ + GOTO_IF_MACRO(!io->seek(io, pos), NULL, hogLoad_failed); + } /* while */ - info->entryCount = entCount; + *_entCount = entCount; + return entries; - __PHYSFS_sort(info->entries, entCount, hogEntryCmp, hogEntrySwap); - return 1; -} /* hog_load_entries */ +hogLoad_failed: + allocator.Free(entries); + return NULL; +} /* hogLoadEntries */ static void *HOG_openArchive(PHYSFS_Io *io, const char *name, int forWriting) { PHYSFS_uint8 buf[3]; - HOGinfo *info = NULL; + PHYSFS_uint32 entryCount = 0; + UNPKentry *entries = NULL; assert(io != NULL); /* shouldn't ever happen. */ - BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0); - BAIL_IF_MACRO(!readAll(io, buf, 3), NULL, 0); - if (memcmp(buf, "DHF", 3) != 0) - GOTO_MACRO(ERR_NOT_AN_ARCHIVE, HOG_openArchive_failed); - - info = (HOGinfo *) allocator.Malloc(sizeof (HOGinfo)); - GOTO_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, HOG_openArchive_failed); - memset(info, '\0', sizeof (HOGinfo)); - info->io = io; - - GOTO_IF_MACRO(!hog_load_entries(io, info), NULL, HOG_openArchive_failed); + BAIL_IF_MACRO(memcmp(buf, "DHF", 3) != 0, ERR_NOT_AN_ARCHIVE, NULL); - return info; - -HOG_openArchive_failed: - if (info != NULL) - { - if (info->entries != NULL) - allocator.Free(info->entries); - allocator.Free(info); - } /* if */ - - return NULL; + entries = hogLoadEntries(io, &entryCount); + BAIL_IF_MACRO(entries == NULL, NULL, NULL); + return UNPK_openArchive(io, entries, entryCount); } /* HOG_openArchive */ -static void HOG_enumerateFiles(dvoid *opaque, const char *dname, - int omitSymLinks, PHYSFS_EnumFilesCallback cb, - const char *origdir, void *callbackdata) -{ - /* no directories in HOG files. */ - if (*dname == '\0') - { - HOGinfo *info = (HOGinfo *) opaque; - HOGentry *entry = info->entries; - PHYSFS_uint32 max = info->entryCount; - PHYSFS_uint32 i; - - for (i = 0; i < max; i++, entry++) - cb(callbackdata, origdir, entry->name); - } /* if */ -} /* HOG_enumerateFiles */ - - -static HOGentry *hog_find_entry(const HOGinfo *info, const char *name) -{ - char *ptr = strchr(name, '.'); - HOGentry *a = info->entries; - PHYSFS_sint32 lo = 0; - PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1); - PHYSFS_sint32 middle; - int rc; - - /* - * Rule out filenames to avoid unneeded processing...no dirs, - * big filenames, or extensions > 3 chars. - */ - BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL); - BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL); - BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL); - - while (lo <= hi) - { - middle = lo + ((hi - lo) / 2); - rc = __PHYSFS_stricmpASCII(name, a[middle].name); - if (rc == 0) /* found it! */ - return &a[middle]; - else if (rc > 0) - lo = middle + 1; - else - hi = middle - 1; - } /* while */ - - BAIL_MACRO(ERR_NO_SUCH_FILE, NULL); -} /* hog_find_entry */ - - -static PHYSFS_Io *HOG_openRead(dvoid *opaque, const char *fnm, int *fileExists) -{ - PHYSFS_Io *retval = NULL; - HOGinfo *info = (HOGinfo *) opaque; - HOGfileinfo *finfo; - HOGentry *entry; - - entry = hog_find_entry(info, fnm); - *fileExists = (entry != NULL); - GOTO_IF_MACRO(entry == NULL, NULL, HOG_openRead_failed); - - retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); - GOTO_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, HOG_openRead_failed); - - finfo = (HOGfileinfo *) allocator.Malloc(sizeof (HOGfileinfo)); - GOTO_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, HOG_openRead_failed); - - finfo->io = info->io->duplicate(info->io); - GOTO_IF_MACRO(finfo->io == NULL, NULL, HOG_openRead_failed); - - if (!finfo->io->seek(finfo->io, entry->startPos)) - GOTO_MACRO(NULL, HOG_openRead_failed); - - finfo->curPos = 0; - finfo->entry = entry; - - memcpy(retval, &HOG_Io, sizeof (*retval)); - retval->opaque = finfo; - return retval; - -HOG_openRead_failed: - if (finfo != NULL) - { - if (finfo->io != NULL) - finfo->io->destroy(finfo->io); - allocator.Free(finfo); - } /* if */ - - if (retval != NULL) - allocator.Free(retval); - - return NULL; -} /* HOG_openRead */ - - -static PHYSFS_Io *HOG_openWrite(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, NULL); -} /* HOG_openWrite */ - - -static PHYSFS_Io *HOG_openAppend(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, NULL); -} /* HOG_openAppend */ - - -static int HOG_remove(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, 0); -} /* HOG_remove */ - - -static int HOG_mkdir(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, 0); -} /* HOG_mkdir */ - - -static int HOG_stat(dvoid *opaque, const char *filename, int *exists, - PHYSFS_Stat *stat) -{ - const HOGinfo *info = (const HOGinfo *) opaque; - const HOGentry *entry = hog_find_entry(info, filename); - - *exists = (entry != 0); - if (!entry) - return 0; - - stat->filesize = entry->size; - stat->filetype = PHYSFS_FILETYPE_REGULAR; - stat->modtime = -1; - stat->createtime = -1; - stat->accesstime = -1; - stat->readonly = 1; - - return 1; -} /* HOG_stat */ - - const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_HOG = { "HOG", @@ -438,14 +114,14 @@ const PHYSFS_Archiver __PHYSFS_Archiver_HOG = { &__PHYSFS_ArchiveInfo_HOG, HOG_openArchive, /* openArchive() method */ - HOG_enumerateFiles, /* enumerateFiles() method */ - HOG_openRead, /* openRead() method */ - HOG_openWrite, /* openWrite() method */ - HOG_openAppend, /* openAppend() method */ - HOG_remove, /* remove() method */ - HOG_mkdir, /* mkdir() method */ - HOG_dirClose, /* dirClose() method */ - HOG_stat /* stat() method */ + UNPK_enumerateFiles, /* enumerateFiles() method */ + UNPK_openRead, /* openRead() method */ + UNPK_openWrite, /* openWrite() method */ + UNPK_openAppend, /* openAppend() method */ + UNPK_remove, /* remove() method */ + UNPK_mkdir, /* mkdir() method */ + UNPK_dirClose, /* dirClose() method */ + UNPK_stat /* stat() method */ }; #endif /* defined PHYSFS_SUPPORTS_HOG */ diff --git a/src/archiver_mvl.c b/src/archiver_mvl.c index e91fa0f5..1d49a48e 100644 --- a/src/archiver_mvl.c +++ b/src/archiver_mvl.c @@ -37,27 +37,6 @@ #define __PHYSICSFS_INTERNAL__ #include "physfs_internal.h" -typedef struct -{ - char name[13]; - PHYSFS_uint32 startPos; - PHYSFS_uint32 size; -} MVLentry; - -typedef struct -{ - PHYSFS_Io *io; - PHYSFS_uint32 entryCount; - MVLentry *entries; -} MVLinfo; - -typedef struct -{ - PHYSFS_Io *io; - MVLentry *entry; - PHYSFS_uint32 curPos; -} MVLfileinfo; - static inline int readAll(PHYSFS_Io *io, void *buf, const PHYSFS_uint64 len) { @@ -65,347 +44,53 @@ static inline int readAll(PHYSFS_Io *io, void *buf, const PHYSFS_uint64 len) } /* readAll */ -static void MVL_dirClose(dvoid *opaque) -{ - MVLinfo *info = ((MVLinfo *) opaque); - info->io->destroy(info->io); - allocator.Free(info->entries); - allocator.Free(info); -} /* MVL_dirClose */ - - -static PHYSFS_sint64 MVL_read(PHYSFS_Io *io, void *buffer, PHYSFS_uint64 len) -{ - MVLfileinfo *finfo = (MVLfileinfo *) io->opaque; - const MVLentry *entry = finfo->entry; - const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos); - PHYSFS_sint64 rc; - - if (bytesLeft < len) - len = bytesLeft; - - rc = finfo->io->read(finfo->io, buffer, len); - if (rc > 0) - finfo->curPos += (PHYSFS_uint32) rc; - - return rc; -} /* MVL_read */ - - -static PHYSFS_sint64 MVL_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, -1); -} /* MVL_write */ - - -static PHYSFS_sint64 MVL_tell(PHYSFS_Io *io) -{ - return ((MVLfileinfo *) io->opaque)->curPos; -} /* MVL_tell */ - - -static int MVL_seek(PHYSFS_Io *io, PHYSFS_uint64 offset) -{ - MVLfileinfo *finfo = (MVLfileinfo *) io->opaque; - const MVLentry *entry = finfo->entry; - int rc; - - BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0); - rc = finfo->io->seek(finfo->io, entry->startPos + offset); - if (rc) - finfo->curPos = (PHYSFS_uint32) offset; - - return rc; -} /* MVL_seek */ - - -static PHYSFS_sint64 MVL_length(PHYSFS_Io *io) -{ - const MVLfileinfo *finfo = (MVLfileinfo *) io->opaque; - return ((PHYSFS_sint64) finfo->entry->size); -} /* MVL_length */ - - -static PHYSFS_Io *MVL_duplicate(PHYSFS_Io *_io) -{ - MVLfileinfo *origfinfo = (MVLfileinfo *) _io->opaque; - PHYSFS_Io *io = NULL; - PHYSFS_Io *retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); - MVLfileinfo *finfo = (MVLfileinfo *) allocator.Malloc(sizeof (MVLfileinfo)); - GOTO_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, MVL_duplicate_failed); - GOTO_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, MVL_duplicate_failed); - - io = origfinfo->io->duplicate(origfinfo->io); - GOTO_IF_MACRO(io == NULL, NULL, MVL_duplicate_failed); - finfo->io = io; - finfo->entry = origfinfo->entry; - finfo->curPos = 0; - memcpy(retval, _io, sizeof (PHYSFS_Io)); - retval->opaque = finfo; - return retval; - -MVL_duplicate_failed: - if (finfo != NULL) allocator.Free(finfo); - if (retval != NULL) allocator.Free(retval); - if (io != NULL) io->destroy(io); - return NULL; -} /* MVL_duplicate */ - -static int MVL_flush(PHYSFS_Io *io) { return 1; /* no write support. */ } - -static void MVL_destroy(PHYSFS_Io *io) -{ - MVLfileinfo *finfo = (MVLfileinfo *) io->opaque; - finfo->io->destroy(finfo->io); - allocator.Free(finfo); - allocator.Free(io); -} /* MVL_destroy */ - - -static const PHYSFS_Io MVL_Io = +static UNPKentry *mvlLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount) { - MVL_read, - MVL_write, - MVL_seek, - MVL_tell, - MVL_length, - MVL_duplicate, - MVL_flush, - MVL_destroy, - NULL -}; - - -static int mvlEntryCmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two) -{ - if (one != two) - { - const MVLentry *a = (const MVLentry *) _a; - return __PHYSFS_stricmpASCII(a[one].name, a[two].name); - } /* if */ - - return 0; -} /* mvlEntryCmp */ - - -static void mvlEntrySwap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two) -{ - if (one != two) - { - MVLentry tmp; - MVLentry *first = &(((MVLentry *) _a)[one]); - MVLentry *second = &(((MVLentry *) _a)[two]); - memcpy(&tmp, first, sizeof (MVLentry)); - memcpy(first, second, sizeof (MVLentry)); - memcpy(second, &tmp, sizeof (MVLentry)); - } /* if */ -} /* mvlEntrySwap */ - - -static int mvl_load_entries(PHYSFS_Io *io, MVLinfo *info) -{ - PHYSFS_uint32 fileCount = info->entryCount; PHYSFS_uint32 location = 8; /* sizeof sig. */ - MVLentry *entry; + UNPKentry *entries = NULL; + UNPKentry *entry = NULL; - info->entries = (MVLentry *) allocator.Malloc(sizeof(MVLentry)*fileCount); - BAIL_IF_MACRO(info->entries == NULL, ERR_OUT_OF_MEMORY, 0); + entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount); + BAIL_IF_MACRO(entries == NULL, ERR_OUT_OF_MEMORY, NULL); location += (17 * fileCount); - for (entry = info->entries; fileCount > 0; fileCount--, entry++) + for (entry = entries; fileCount > 0; fileCount--, entry++) { - BAIL_IF_MACRO(!readAll(io, &entry->name, 13), NULL, 0); - BAIL_IF_MACRO(!readAll(io, &entry->size, 4), NULL, 0); + GOTO_IF_MACRO(!readAll(io, &entry->name, 13), NULL, mvlLoad_failed); + GOTO_IF_MACRO(!readAll(io, &entry->size, 4), NULL, mvlLoad_failed); entry->size = PHYSFS_swapULE32(entry->size); entry->startPos = location; location += entry->size; } /* for */ - __PHYSFS_sort(info->entries, info->entryCount, mvlEntryCmp, mvlEntrySwap); - return 1; -} /* mvl_load_entries */ + return entries; + +mvlLoad_failed: + allocator.Free(entries); + return NULL; +} /* mvlLoadEntries */ static void *MVL_openArchive(PHYSFS_Io *io, const char *name, int forWriting) { PHYSFS_uint8 buf[4]; - MVLinfo *info = NULL; - PHYSFS_uint32 val = 0; + PHYSFS_uint32 entryCount = 0; + UNPKentry *entries = NULL; assert(io != NULL); /* shouldn't ever happen. */ - BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0); - BAIL_IF_MACRO(!readAll(io, buf, 4), NULL, NULL); - if (memcmp(buf, "DMVL", 4) != 0) - GOTO_MACRO(ERR_NOT_AN_ARCHIVE, MVL_openArchive_failed); - - info = (MVLinfo *) allocator.Malloc(sizeof (MVLinfo)); - GOTO_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, MVL_openArchive_failed); - memset(info, '\0', sizeof (MVLinfo)); - info->io = io; - - GOTO_IF_MACRO(!readAll(io,&val,sizeof(val)), NULL, MVL_openArchive_failed); - info->entryCount = PHYSFS_swapULE32(val); - - GOTO_IF_MACRO(!mvl_load_entries(io, info), NULL, MVL_openArchive_failed); - - return info; - -MVL_openArchive_failed: - if (info != NULL) - { - if (info->entries != NULL) - allocator.Free(info->entries); - allocator.Free(info); - } /* if */ + BAIL_IF_MACRO(memcmp(buf, "DMVL", 4) != 0, ERR_NOT_AN_ARCHIVE, NULL); + BAIL_IF_MACRO(!readAll(io, &entryCount, sizeof (entryCount)), NULL, NULL); - return NULL; + entryCount = PHYSFS_swapULE32(entryCount); + entries = mvlLoadEntries(io, entryCount); + BAIL_IF_MACRO(entries == NULL, NULL, NULL); + return UNPK_openArchive(io, entries, entryCount); } /* MVL_openArchive */ -static void MVL_enumerateFiles(dvoid *opaque, const char *dname, - int omitSymLinks, PHYSFS_EnumFilesCallback cb, - const char *origdir, void *callbackdata) -{ - /* no directories in MVL files. */ - if (*dname == '\0') - { - MVLinfo *info = ((MVLinfo *) opaque); - MVLentry *entry = info->entries; - PHYSFS_uint32 max = info->entryCount; - PHYSFS_uint32 i; - - for (i = 0; i < max; i++, entry++) - cb(callbackdata, origdir, entry->name); - } /* if */ -} /* MVL_enumerateFiles */ - - -static MVLentry *mvl_find_entry(const MVLinfo *info, const char *name) -{ - char *ptr = strchr(name, '.'); - MVLentry *a = info->entries; - PHYSFS_sint32 lo = 0; - PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1); - PHYSFS_sint32 middle; - int rc; - - /* - * Rule out filenames to avoid unneeded processing...no dirs, - * big filenames, or extensions > 3 chars. - */ - BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL); - BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL); - BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL); - - while (lo <= hi) - { - middle = lo + ((hi - lo) / 2); - rc = __PHYSFS_stricmpASCII(name, a[middle].name); - if (rc == 0) /* found it! */ - return &a[middle]; - else if (rc > 0) - lo = middle + 1; - else - hi = middle - 1; - } /* while */ - - BAIL_MACRO(ERR_NO_SUCH_FILE, NULL); -} /* mvl_find_entry */ - - -static PHYSFS_Io *MVL_openRead(dvoid *opaque, const char *fnm, int *fileExists) -{ - PHYSFS_Io *retval = NULL; - MVLinfo *info = (MVLinfo *) opaque; - MVLfileinfo *finfo; - MVLentry *entry; - - entry = mvl_find_entry(info, fnm); - *fileExists = (entry != NULL); - GOTO_IF_MACRO(entry == NULL, NULL, MVL_openRead_failed); - - retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); - GOTO_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, MVL_openRead_failed); - - finfo = (MVLfileinfo *) allocator.Malloc(sizeof (MVLfileinfo)); - GOTO_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, MVL_openRead_failed); - - finfo->io = info->io->duplicate(info->io); - GOTO_IF_MACRO(finfo->io == NULL, NULL, MVL_openRead_failed); - - if (!finfo->io->seek(finfo->io, entry->startPos)) - GOTO_MACRO(NULL, MVL_openRead_failed); - - finfo->curPos = 0; - finfo->entry = entry; - - memcpy(retval, &MVL_Io, sizeof (*retval)); - retval->opaque = finfo; - return retval; - -MVL_openRead_failed: - if (finfo != NULL) - { - if (finfo->io != NULL) - finfo->io->destroy(finfo->io); - allocator.Free(finfo); - } /* if */ - - if (retval != NULL) - allocator.Free(retval); - - return NULL; -} /* MVL_openRead */ - - -static PHYSFS_Io *MVL_openWrite(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, NULL); -} /* MVL_openWrite */ - - -static PHYSFS_Io *MVL_openAppend(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, NULL); -} /* MVL_openAppend */ - - -static int MVL_remove(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, 0); -} /* MVL_remove */ - - -static int MVL_mkdir(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, 0); -} /* MVL_mkdir */ - - -static int MVL_stat(dvoid *opaque, const char *filename, int *exists, - PHYSFS_Stat *stat) -{ - const MVLinfo *info = (const MVLinfo *) opaque; - const MVLentry *entry = mvl_find_entry(info, filename); - - *exists = (entry != 0); - if (!entry) - return 0; - - stat->filesize = entry->size; - stat->filetype = PHYSFS_FILETYPE_REGULAR; - stat->modtime = -1; - stat->createtime = -1; - stat->accesstime = -1; - stat->readonly = 1; - - return 1; -} /* MVL_stat */ - - const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_MVL = { "MVL", @@ -419,14 +104,14 @@ const PHYSFS_Archiver __PHYSFS_Archiver_MVL = { &__PHYSFS_ArchiveInfo_MVL, MVL_openArchive, /* openArchive() method */ - MVL_enumerateFiles, /* enumerateFiles() method */ - MVL_openRead, /* openRead() method */ - MVL_openWrite, /* openWrite() method */ - MVL_openAppend, /* openAppend() method */ - MVL_remove, /* remove() method */ - MVL_mkdir, /* mkdir() method */ - MVL_dirClose, /* dirClose() method */ - MVL_stat /* stat() method */ + UNPK_enumerateFiles, /* enumerateFiles() method */ + UNPK_openRead, /* openRead() method */ + UNPK_openWrite, /* openWrite() method */ + UNPK_openAppend, /* openAppend() method */ + UNPK_remove, /* remove() method */ + UNPK_mkdir, /* mkdir() method */ + UNPK_dirClose, /* dirClose() method */ + UNPK_stat /* stat() method */ }; #endif /* defined PHYSFS_SUPPORTS_MVL */ diff --git a/src/archiver_unpacked.c b/src/archiver_unpacked.c new file mode 100644 index 00000000..cc58cf50 --- /dev/null +++ b/src/archiver_unpacked.c @@ -0,0 +1,328 @@ +/* + * High-level PhysicsFS archiver for simple unpacked file formats. + * + * This is a framework that basic archivers build on top of. It's for simple + * formats that can just hand back a list of files and the offsets of their + * uncompressed data. There are an alarming number of formats like this. + * + * RULES: Archive entries must be uncompressed, must not have subdirs, + * must be case insensitive filenames < 32 chars. We can relax some of these + * rules as necessary. + * + * Please see the file LICENSE.txt in the source's root directory. + * + * This file written by Ryan C. Gordon. + */ + +#include +#include +#include +#include "physfs.h" + +#define __PHYSICSFS_INTERNAL__ +#include "physfs_internal.h" + +typedef struct +{ + PHYSFS_Io *io; + PHYSFS_uint32 entryCount; + UNPKentry *entries; +} UNPKinfo; + + +typedef struct +{ + PHYSFS_Io *io; + UNPKentry *entry; + PHYSFS_uint32 curPos; +} UNPKfileinfo; + + +void UNPK_dirClose(dvoid *opaque) +{ + UNPKinfo *info = ((UNPKinfo *) opaque); + info->io->destroy(info->io); + allocator.Free(info->entries); + allocator.Free(info); +} /* UNPK_dirClose */ + + +static PHYSFS_sint64 UNPK_read(PHYSFS_Io *io, void *buffer, PHYSFS_uint64 len) +{ + UNPKfileinfo *finfo = (UNPKfileinfo *) io->opaque; + const UNPKentry *entry = finfo->entry; + const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos); + PHYSFS_sint64 rc; + + if (bytesLeft < len) + len = bytesLeft; + + rc = finfo->io->read(finfo->io, buffer, len); + if (rc > 0) + finfo->curPos += (PHYSFS_uint32) rc; + + return rc; +} /* UNPK_read */ + + +static PHYSFS_sint64 UNPK_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len) +{ + BAIL_MACRO(ERR_NOT_SUPPORTED, -1); +} /* UNPK_write */ + + +static PHYSFS_sint64 UNPK_tell(PHYSFS_Io *io) +{ + return ((UNPKfileinfo *) io->opaque)->curPos; +} /* UNPK_tell */ + + +static int UNPK_seek(PHYSFS_Io *io, PHYSFS_uint64 offset) +{ + UNPKfileinfo *finfo = (UNPKfileinfo *) io->opaque; + const UNPKentry *entry = finfo->entry; + int rc; + + BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0); + rc = finfo->io->seek(finfo->io, entry->startPos + offset); + if (rc) + finfo->curPos = (PHYSFS_uint32) offset; + + return rc; +} /* UNPK_seek */ + + +static PHYSFS_sint64 UNPK_length(PHYSFS_Io *io) +{ + const UNPKfileinfo *finfo = (UNPKfileinfo *) io->opaque; + return ((PHYSFS_sint64) finfo->entry->size); +} /* UNPK_length */ + + +static PHYSFS_Io *UNPK_duplicate(PHYSFS_Io *_io) +{ + UNPKfileinfo *origfinfo = (UNPKfileinfo *) _io->opaque; + PHYSFS_Io *io = NULL; + PHYSFS_Io *retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); + UNPKfileinfo *finfo = (UNPKfileinfo *) allocator.Malloc(sizeof (UNPKfileinfo)); + GOTO_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, UNPK_duplicate_failed); + GOTO_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, UNPK_duplicate_failed); + + io = origfinfo->io->duplicate(origfinfo->io); + GOTO_IF_MACRO(io == NULL, NULL, UNPK_duplicate_failed); + finfo->io = io; + finfo->entry = origfinfo->entry; + finfo->curPos = 0; + memcpy(retval, _io, sizeof (PHYSFS_Io)); + retval->opaque = finfo; + return retval; + +UNPK_duplicate_failed: + if (finfo != NULL) allocator.Free(finfo); + if (retval != NULL) allocator.Free(retval); + if (io != NULL) io->destroy(io); + return NULL; +} /* UNPK_duplicate */ + +static int UNPK_flush(PHYSFS_Io *io) { return 1; /* no write support. */ } + +static void UNPK_destroy(PHYSFS_Io *io) +{ + UNPKfileinfo *finfo = (UNPKfileinfo *) io->opaque; + finfo->io->destroy(finfo->io); + allocator.Free(finfo); + allocator.Free(io); +} /* UNPK_destroy */ + + +static const PHYSFS_Io UNPK_Io = +{ + UNPK_read, + UNPK_write, + UNPK_seek, + UNPK_tell, + UNPK_length, + UNPK_duplicate, + UNPK_flush, + UNPK_destroy, + NULL +}; + + +static int entryCmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two) +{ + if (one != two) + { + const UNPKentry *a = (const UNPKentry *) _a; + return strcmp(a[one].name, a[two].name); + } /* if */ + + return 0; +} /* entryCmp */ + + +static void entrySwap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two) +{ + if (one != two) + { + UNPKentry tmp; + UNPKentry *first = &(((UNPKentry *) _a)[one]); + UNPKentry *second = &(((UNPKentry *) _a)[two]); + memcpy(&tmp, first, sizeof (UNPKentry)); + memcpy(first, second, sizeof (UNPKentry)); + memcpy(second, &tmp, sizeof (UNPKentry)); + } /* if */ +} /* entrySwap */ + + +void UNPK_enumerateFiles(dvoid *opaque, const char *dname, + int omitSymLinks, PHYSFS_EnumFilesCallback cb, + const char *origdir, void *callbackdata) +{ + /* no directories in UNPK files. */ + if (*dname == '\0') + { + UNPKinfo *info = (UNPKinfo *) opaque; + UNPKentry *entry = info->entries; + PHYSFS_uint32 max = info->entryCount; + PHYSFS_uint32 i; + + for (i = 0; i < max; i++, entry++) + cb(callbackdata, origdir, entry->name); + } /* if */ +} /* UNPK_enumerateFiles */ + + +static UNPKentry *findEntry(const UNPKinfo *info, const char *name) +{ + UNPKentry *a = info->entries; + PHYSFS_sint32 lo = 0; + PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1); + PHYSFS_sint32 middle; + int rc; + + while (lo <= hi) + { + middle = lo + ((hi - lo) / 2); + rc = __PHYSFS_utf8strcasecmp(name, a[middle].name); + if (rc == 0) /* found it! */ + return &a[middle]; + else if (rc > 0) + lo = middle + 1; + else + hi = middle - 1; + } /* while */ + + BAIL_MACRO(ERR_NO_SUCH_FILE, NULL); +} /* findEntry */ + + +PHYSFS_Io *UNPK_openRead(dvoid *opaque, const char *fnm, int *fileExists) +{ + PHYSFS_Io *retval = NULL; + UNPKinfo *info = (UNPKinfo *) opaque; + UNPKfileinfo *finfo; + UNPKentry *entry; + + entry = findEntry(info, fnm); + *fileExists = (entry != NULL); + GOTO_IF_MACRO(entry == NULL, NULL, UNPK_openRead_failed); + + retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); + GOTO_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, UNPK_openRead_failed); + + finfo = (UNPKfileinfo *) allocator.Malloc(sizeof (UNPKfileinfo)); + GOTO_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, UNPK_openRead_failed); + + finfo->io = info->io->duplicate(info->io); + GOTO_IF_MACRO(finfo->io == NULL, NULL, UNPK_openRead_failed); + + if (!finfo->io->seek(finfo->io, entry->startPos)) + GOTO_MACRO(NULL, UNPK_openRead_failed); + + finfo->curPos = 0; + finfo->entry = entry; + + memcpy(retval, &UNPK_Io, sizeof (*retval)); + retval->opaque = finfo; + return retval; + +UNPK_openRead_failed: + if (finfo != NULL) + { + if (finfo->io != NULL) + finfo->io->destroy(finfo->io); + allocator.Free(finfo); + } /* if */ + + if (retval != NULL) + allocator.Free(retval); + + return NULL; +} /* UNPK_openRead */ + + +PHYSFS_Io *UNPK_openWrite(dvoid *opaque, const char *name) +{ + BAIL_MACRO(ERR_NOT_SUPPORTED, NULL); +} /* UNPK_openWrite */ + + +PHYSFS_Io *UNPK_openAppend(dvoid *opaque, const char *name) +{ + BAIL_MACRO(ERR_NOT_SUPPORTED, NULL); +} /* UNPK_openAppend */ + + +int UNPK_remove(dvoid *opaque, const char *name) +{ + BAIL_MACRO(ERR_NOT_SUPPORTED, 0); +} /* UNPK_remove */ + + +int UNPK_mkdir(dvoid *opaque, const char *name) +{ + BAIL_MACRO(ERR_NOT_SUPPORTED, 0); +} /* UNPK_mkdir */ + + +int UNPK_stat(dvoid *opaque, const char *filename, int *exists, + PHYSFS_Stat *stat) +{ + const UNPKinfo *info = (const UNPKinfo *) opaque; + const UNPKentry *entry = findEntry(info, filename); + + *exists = (entry != 0); + if (!entry) + return 0; + + stat->filesize = entry->size; + stat->filetype = PHYSFS_FILETYPE_REGULAR; + stat->modtime = -1; + stat->createtime = -1; + stat->accesstime = -1; + stat->readonly = 1; + + return 1; +} /* UNPK_stat */ + + +dvoid *UNPK_openArchive(PHYSFS_Io *io, UNPKentry *e, const PHYSFS_uint32 num) +{ + UNPKinfo *info = (UNPKinfo *) allocator.Malloc(sizeof (UNPKinfo)); + if (info == NULL) + { + allocator.Free(e); + BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); + } /* if */ + + __PHYSFS_sort(e, num, entryCmp, entrySwap); + info->io = io; + info->entryCount = num; + info->entries = e; + + return info; +} /* UNPK_openArchive */ + +/* end of archiver_unpacked.c ... */ + diff --git a/src/archiver_wad.c b/src/archiver_wad.c index d41ff45f..179358da 100644 --- a/src/archiver_wad.c +++ b/src/archiver_wad.c @@ -52,380 +52,67 @@ #define __PHYSICSFS_INTERNAL__ #include "physfs_internal.h" -typedef struct -{ - char name[18]; - PHYSFS_uint32 startPos; - PHYSFS_uint32 size; -} WADentry; - -typedef struct -{ - PHYSFS_Io *io; - PHYSFS_uint32 entryCount; - WADentry *entries; -} WADinfo; - -typedef struct -{ - PHYSFS_Io *io; - WADentry *entry; - PHYSFS_uint32 curPos; -} WADfileinfo; - - static inline int readAll(PHYSFS_Io *io, void *buf, const PHYSFS_uint64 len) { return (io->read(io, buf, len) == len); } /* readAll */ -static void WAD_dirClose(dvoid *opaque) -{ - WADinfo *info = ((WADinfo *) opaque); - info->io->destroy(info->io); - allocator.Free(info->entries); - allocator.Free(info); -} /* WAD_dirClose */ - - -static PHYSFS_sint64 WAD_read(PHYSFS_Io *io, void *buffer, PHYSFS_uint64 len) -{ - WADfileinfo *finfo = (WADfileinfo *) io->opaque; - const WADentry *entry = finfo->entry; - const PHYSFS_uint64 bytesLeft = (PHYSFS_uint64)(entry->size-finfo->curPos); - PHYSFS_sint64 rc; - - if (bytesLeft < len) - len = bytesLeft; - - rc = finfo->io->read(finfo->io, buffer, len); - if (rc > 0) - finfo->curPos += (PHYSFS_uint32) rc; - - return rc; -} /* WAD_read */ - - -static PHYSFS_sint64 WAD_write(PHYSFS_Io *io, const void *b, PHYSFS_uint64 len) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, -1); -} /* WAD_write */ - - -static PHYSFS_sint64 WAD_tell(PHYSFS_Io *io) -{ - return ((WADfileinfo *) io->opaque)->curPos; -} /* WAD_tell */ - - -static int WAD_seek(PHYSFS_Io *io, PHYSFS_uint64 offset) -{ - WADfileinfo *finfo = (WADfileinfo *) io->opaque; - const WADentry *entry = finfo->entry; - int rc; - - BAIL_IF_MACRO(offset >= entry->size, ERR_PAST_EOF, 0); - rc = finfo->io->seek(finfo->io, entry->startPos + offset); - if (rc) - finfo->curPos = (PHYSFS_uint32) offset; - - return rc; -} /* WAD_seek */ - - -static PHYSFS_sint64 WAD_length(PHYSFS_Io *io) +static UNPKentry *wadLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount) { - const WADfileinfo *finfo = (WADfileinfo *) io->opaque; - return ((PHYSFS_sint64) finfo->entry->size); -} /* WAD_length */ - - -static PHYSFS_Io *WAD_duplicate(PHYSFS_Io *_io) -{ - WADfileinfo *origfinfo = (WADfileinfo *) _io->opaque; - PHYSFS_Io *io = NULL; - PHYSFS_Io *retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); - WADfileinfo *finfo = (WADfileinfo *) allocator.Malloc(sizeof (WADfileinfo)); - GOTO_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, WAD_duplicate_failed); - GOTO_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, WAD_duplicate_failed); - - io = origfinfo->io->duplicate(origfinfo->io); - GOTO_IF_MACRO(io == NULL, NULL, WAD_duplicate_failed); - finfo->io = io; - finfo->entry = origfinfo->entry; - finfo->curPos = 0; - memcpy(retval, _io, sizeof (PHYSFS_Io)); - retval->opaque = finfo; - return retval; - -WAD_duplicate_failed: - if (finfo != NULL) allocator.Free(finfo); - if (retval != NULL) allocator.Free(retval); - if (io != NULL) io->destroy(io); - return NULL; -} /* WAD_duplicate */ - -static int WAD_flush(PHYSFS_Io *io) { return 1; /* no write support. */ } - -static void WAD_destroy(PHYSFS_Io *io) -{ - WADfileinfo *finfo = (WADfileinfo *) io->opaque; - finfo->io->destroy(finfo->io); - allocator.Free(finfo); - allocator.Free(io); -} /* WAD_destroy */ - - -static const PHYSFS_Io WAD_Io = -{ - WAD_read, - WAD_write, - WAD_seek, - WAD_tell, - WAD_length, - WAD_duplicate, - WAD_flush, - WAD_destroy, - NULL -}; - - - -static int wadEntryCmp(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two) -{ - if (one != two) - { - const WADentry *a = (const WADentry *) _a; - return __PHYSFS_stricmpASCII(a[one].name, a[two].name); - } /* if */ - - return 0; -} /* wadEntryCmp */ - - -static void wadEntrySwap(void *_a, PHYSFS_uint32 one, PHYSFS_uint32 two) -{ - if (one != two) - { - WADentry tmp; - WADentry *first = &(((WADentry *) _a)[one]); - WADentry *second = &(((WADentry *) _a)[two]); - memcpy(&tmp, first, sizeof (WADentry)); - memcpy(first, second, sizeof (WADentry)); - memcpy(second, &tmp, sizeof (WADentry)); - } /* if */ -} /* wadEntrySwap */ - - -static int wad_load_entries(PHYSFS_Io *io, WADinfo *info) -{ - PHYSFS_uint32 fileCount = info->entryCount; PHYSFS_uint32 directoryOffset; - WADentry *entry; + UNPKentry *entries = NULL; + UNPKentry *entry = NULL; BAIL_IF_MACRO(!readAll(io, &directoryOffset, 4), NULL, 0); directoryOffset = PHYSFS_swapULE32(directoryOffset); - info->entries = (WADentry *) allocator.Malloc(sizeof(WADentry)*fileCount); - BAIL_IF_MACRO(info->entries == NULL, ERR_OUT_OF_MEMORY, 0); BAIL_IF_MACRO(!io->seek(io, directoryOffset), NULL, 0); - for (entry = info->entries; fileCount > 0; fileCount--, entry++) + entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount); + BAIL_IF_MACRO(entries == NULL, ERR_OUT_OF_MEMORY, NULL); + + for (entry = entries; fileCount > 0; fileCount--, entry++) { - BAIL_IF_MACRO(!readAll(io, &entry->startPos, 4), NULL, 0); - BAIL_IF_MACRO(!readAll(io, &entry->size, 4), NULL, 0); - BAIL_IF_MACRO(!readAll(io, &entry->name, 8), NULL, 0); + GOTO_IF_MACRO(!readAll(io, &entry->startPos, 4), NULL, wadLoad_failed); + GOTO_IF_MACRO(!readAll(io, &entry->size, 4), NULL, wadLoad_failed); + GOTO_IF_MACRO(!readAll(io, &entry->name, 8), NULL, wadLoad_failed); entry->name[8] = '\0'; /* name might not be null-terminated in file. */ entry->size = PHYSFS_swapULE32(entry->size); entry->startPos = PHYSFS_swapULE32(entry->startPos); } /* for */ - __PHYSFS_sort(info->entries, info->entryCount, wadEntryCmp, wadEntrySwap); - return 1; -} /* wad_load_entries */ + return entries; + +wadLoad_failed: + allocator.Free(entries); + return NULL; +} /* wadLoadEntries */ static void *WAD_openArchive(PHYSFS_Io *io, const char *name, int forWriting) { PHYSFS_uint8 buf[4]; - WADinfo *info = NULL; - PHYSFS_uint32 val = 0; + UNPKentry *entries = NULL; + PHYSFS_uint32 entryCount = 0; assert(io != NULL); /* shouldn't ever happen. */ BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0); - BAIL_IF_MACRO(!readAll(io, buf, sizeof (buf)), NULL, NULL); if ((memcmp(buf, "IWAD", 4) != 0) && (memcmp(buf, "PWAD", 4) != 0)) - GOTO_MACRO(ERR_NOT_AN_ARCHIVE, WAD_openArchive_failed); - - info = (WADinfo *) allocator.Malloc(sizeof (WADinfo)); - GOTO_IF_MACRO(info == NULL, ERR_OUT_OF_MEMORY, WAD_openArchive_failed); - memset(info, '\0', sizeof (WADinfo)); - info->io = io; - - GOTO_IF_MACRO(!readAll(io,&val,sizeof(val)), NULL, WAD_openArchive_failed); - info->entryCount = PHYSFS_swapULE32(val); - - GOTO_IF_MACRO(!wad_load_entries(io, info), NULL, WAD_openArchive_failed); - - return info; + BAIL_MACRO(ERR_NOT_AN_ARCHIVE, NULL); -WAD_openArchive_failed: - if (info != NULL) - { - if (info->entries != NULL) - allocator.Free(info->entries); - allocator.Free(info); - } /* if */ + BAIL_IF_MACRO(!readAll(io, &entryCount, sizeof (entryCount)), NULL, NULL); + entryCount = PHYSFS_swapULE32(entryCount); - return NULL; + entries = wadLoadEntries(io, entryCount); + BAIL_IF_MACRO(entries == NULL, NULL, NULL); + return UNPK_openArchive(io, entries, entryCount); } /* WAD_openArchive */ -static void WAD_enumerateFiles(dvoid *opaque, const char *dname, - int omitSymLinks, PHYSFS_EnumFilesCallback cb, - const char *origdir, void *callbackdata) -{ - /* no directories in WAD files. */ - if (*dname == '\0') - { - WADinfo *info = (WADinfo *) opaque; - WADentry *entry = info->entries; - PHYSFS_uint32 max = info->entryCount; - PHYSFS_uint32 i; - - for (i = 0; i < max; i++, entry++) - cb(callbackdata, origdir, entry->name); - } /* if */ -} /* WAD_enumerateFiles */ - - -static WADentry *wad_find_entry(const WADinfo *info, const char *name) -{ - char *ptr = strchr(name, '.'); - WADentry *a = info->entries; - PHYSFS_sint32 lo = 0; - PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1); - PHYSFS_sint32 middle; - int rc; - - /* - * Rule out filenames to avoid unneeded processing...no dirs, - * big filenames, or extensions. - */ - BAIL_IF_MACRO(ptr != NULL, ERR_NO_SUCH_FILE, NULL); - BAIL_IF_MACRO(strlen(name) > 8, ERR_NO_SUCH_FILE, NULL); - BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL); - - while (lo <= hi) - { - middle = lo + ((hi - lo) / 2); - rc = __PHYSFS_stricmpASCII(name, a[middle].name); - if (rc == 0) /* found it! */ - return &a[middle]; - else if (rc > 0) - lo = middle + 1; - else - hi = middle - 1; - } /* while */ - - BAIL_MACRO(ERR_NO_SUCH_FILE, NULL); -} /* wad_find_entry */ - - -static PHYSFS_Io *WAD_openRead(dvoid *opaque, const char *fnm, int *fileExists) -{ - PHYSFS_Io *retval = NULL; - WADinfo *info = (WADinfo *) opaque; - WADfileinfo *finfo; - WADentry *entry; - - entry = wad_find_entry(info, fnm); - *fileExists = (entry != NULL); - GOTO_IF_MACRO(entry == NULL, NULL, WAD_openRead_failed); - - retval = (PHYSFS_Io *) allocator.Malloc(sizeof (PHYSFS_Io)); - GOTO_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, WAD_openRead_failed); - - finfo = (WADfileinfo *) allocator.Malloc(sizeof (WADfileinfo)); - GOTO_IF_MACRO(finfo == NULL, ERR_OUT_OF_MEMORY, WAD_openRead_failed); - - finfo->io = info->io->duplicate(info->io); - GOTO_IF_MACRO(finfo->io == NULL, NULL, WAD_openRead_failed); - - if (!finfo->io->seek(finfo->io, entry->startPos)) - GOTO_MACRO(NULL, WAD_openRead_failed); - - finfo->curPos = 0; - finfo->entry = entry; - - memcpy(retval, &WAD_Io, sizeof (*retval)); - retval->opaque = finfo; - return retval; - -WAD_openRead_failed: - if (finfo != NULL) - { - if (finfo->io != NULL) - finfo->io->destroy(finfo->io); - allocator.Free(finfo); - } /* if */ - - if (retval != NULL) - allocator.Free(retval); - - return NULL; -} /* WAD_openRead */ - - -static PHYSFS_Io *WAD_openWrite(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, NULL); -} /* WAD_openWrite */ - - -static PHYSFS_Io *WAD_openAppend(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, NULL); -} /* WAD_openAppend */ - - -static int WAD_remove(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, 0); -} /* WAD_remove */ - - -static int WAD_mkdir(dvoid *opaque, const char *name) -{ - BAIL_MACRO(ERR_NOT_SUPPORTED, 0); -} /* WAD_mkdir */ - - -static int WAD_stat(dvoid *opaque, const char *filename, int *exists, - PHYSFS_Stat *stat) -{ - const WADinfo *info = (const WADinfo *) opaque; - const WADentry *entry = wad_find_entry(info, filename); - - *exists = (entry != 0); - if (!entry) - return 0; - - stat->filesize = entry->size; - stat->filetype = PHYSFS_FILETYPE_REGULAR; - stat->modtime = -1; - stat->createtime = -1; - stat->accesstime = -1; - stat->readonly = 1; - - return 1; -} /* WAD_stat */ - - const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_WAD = { "WAD", @@ -439,14 +126,14 @@ const PHYSFS_Archiver __PHYSFS_Archiver_WAD = { &__PHYSFS_ArchiveInfo_WAD, WAD_openArchive, /* openArchive() method */ - WAD_enumerateFiles, /* enumerateFiles() method */ - WAD_openRead, /* openRead() method */ - WAD_openWrite, /* openWrite() method */ - WAD_openAppend, /* openAppend() method */ - WAD_remove, /* remove() method */ - WAD_mkdir, /* mkdir() method */ - WAD_dirClose, /* dirClose() method */ - WAD_stat /* stat() method */ + UNPK_enumerateFiles, /* enumerateFiles() method */ + UNPK_openRead, /* openRead() method */ + UNPK_openWrite, /* openWrite() method */ + UNPK_openAppend, /* openAppend() method */ + UNPK_remove, /* remove() method */ + UNPK_mkdir, /* mkdir() method */ + UNPK_dirClose, /* dirClose() method */ + UNPK_stat /* stat() method */ }; #endif /* defined PHYSFS_SUPPORTS_WAD */ diff --git a/src/physfs_internal.h b/src/physfs_internal.h index 26850d0a..3379b1dd 100644 --- a/src/physfs_internal.h +++ b/src/physfs_internal.h @@ -1014,6 +1014,30 @@ PHYSFS_Io *__PHYSFS_createMemoryIo(const void *buf, PHYSFS_uint64 len, void (*destruct)(void *)); + + +/* These are shared between some archivers. */ + +typedef struct +{ + char name[32]; + PHYSFS_uint32 startPos; + PHYSFS_uint32 size; +} UNPKentry; + +void UNPK_dirClose(dvoid *opaque); +dvoid *UNPK_openArchive(PHYSFS_Io *io, UNPKentry *e, const PHYSFS_uint32 num); +void UNPK_enumerateFiles(dvoid *opaque, const char *dname, + int omitSymLinks, PHYSFS_EnumFilesCallback cb, + const char *origdir, void *callbackdata); +PHYSFS_Io *UNPK_openRead(dvoid *opaque, const char *fnm, int *fileExists); +PHYSFS_Io *UNPK_openWrite(dvoid *opaque, const char *name); +PHYSFS_Io *UNPK_openAppend(dvoid *opaque, const char *name); +int UNPK_remove(dvoid *opaque, const char *name); +int UNPK_mkdir(dvoid *opaque, const char *name); +int UNPK_stat(dvoid *opaque, const char *fn, int *exists, PHYSFS_Stat *stat); + + /*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/ /*------------ ----------------*/