Skip to content

Commit

Permalink
POSIX GNU tar read support
Browse files Browse the repository at this point in the history
- supporting tared csm.bin of Chasm: The Rift Remastered at https://store.steampowered.com/app/2061230/Chasm_The_Rift/
- Thanks to @sezero for OS/2 and Windows fixes
  • Loading branch information
Jon Daniel committed Aug 11, 2023
1 parent 7931b9b commit 341e13d
Show file tree
Hide file tree
Showing 6 changed files with 352 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ set(PHYSFS_SRCS
src/physfs_archiver_qpak.c
src/physfs_archiver_wad.c
src/physfs_archiver_csm.c
src/physfs_archiver_tar.c
src/physfs_archiver_zip.c
src/physfs_archiver_slb.c
src/physfs_archiver_iso9660.c
Expand Down Expand Up @@ -130,6 +131,11 @@ if(NOT PHYSFS_ARCHIVE_CSM)
add_definitions(-DPHYSFS_SUPPORTS_CSM=0)
endif()

option(PHYSFS_ARCHIVE_TAR "Enable POSIX TAR / Chasm: The Rift [Demo] Remastered csm.bin support" TRUE)
if(NOT PHYSFS_ARCHIVE_TAR)
add_definitions(-DPHYSFS_SUPPORTS_TAR=0)
endif()

option(PHYSFS_ARCHIVE_HOG "Enable Descent I/II HOG support" TRUE)
if(NOT PHYSFS_ARCHIVE_HOG)
add_definitions(-DPHYSFS_SUPPORTS_HOG=0)
Expand Down Expand Up @@ -325,6 +331,7 @@ message_bool_option("7zip support" PHYSFS_ARCHIVE_7Z)
message_bool_option("GRP support" PHYSFS_ARCHIVE_GRP)
message_bool_option("WAD support" PHYSFS_ARCHIVE_WAD)
message_bool_option("CSM support" PHYSFS_ARCHIVE_CSM)
message_bool_option("TAR support" PHYSFS_ARCHIVE_TAR)
message_bool_option("HOG support" PHYSFS_ARCHIVE_HOG)
message_bool_option("MVL support" PHYSFS_ARCHIVE_MVL)
message_bool_option("QPAK support" PHYSFS_ARCHIVE_QPAK)
Expand Down
1 change: 1 addition & 0 deletions src/Makefile.os2
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ SRCS = physfs.c &
physfs_archiver_slb.c &
physfs_archiver_iso9660.c &
physfs_archiver_csm.c &
physfs_archiver_tar.c &
physfs_archiver_vdf.c


Expand Down
3 changes: 3 additions & 0 deletions src/physfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1191,6 +1191,9 @@ static int initStaticArchivers(void)
#if PHYSFS_SUPPORTS_CSM
REGISTER_STATIC_ARCHIVER(CSM);
#endif
#if PHYSFS_SUPPORTS_TAR
REGISTER_STATIC_ARCHIVER(TAR);
#endif
#if PHYSFS_SUPPORTS_SLB
REGISTER_STATIC_ARCHIVER(SLB);
#endif
Expand Down
109 changes: 109 additions & 0 deletions src/physfs_archiver_tar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* tar support routines for PhysicsFS.
*
* Please see the file LICENSE.txt in the source's root directory.
*
* based on code by Uli Köhler: https://techoverflow.net/2013/03/29/reading-tar-files-in-c/
*/

#define __PHYSICSFS_INTERNAL__
#include "physfs_internal.h"

#if PHYSFS_SUPPORTS_TAR
#include "physfs_tar.h"

static bool TAR_loadEntries(PHYSFS_Io *io, void *arc)
{
union block zero_block;
union block current_block;
PHYSFS_uint64 count = 0;
bool long_name = false;

memset(zero_block.buffer, 0, sizeof(BLOCKSIZE));
memset(current_block.buffer, 0, sizeof(BLOCKSIZE));

/* read header block until zero-only terminated block */
for(; __PHYSFS_readAll(io, current_block.buffer, BLOCKSIZE); count++)
{
if( memcmp(current_block.buffer, zero_block.buffer, BLOCKSIZE) == 0 )
return true;

/* verify magic */
switch(TAR_magic(&current_block))
{
case POSIX_FORMAT:
TAR_posix_block(io, arc, &current_block, &count, &long_name);
break;
case OLDGNU_FORMAT:
break;
case GNU_FORMAT:
break;
case V7_FORMAT:
break;
case USTAR_FORMAT:
break;
case STAR_FORMAT:
break;
default:
break;
}
}

return false;
}

static void *TAR_openArchive(PHYSFS_Io *io, const char *name,
int forWriting, int *claimed)
{
void *unpkarc = NULL;
union block first;
enum archive_format format;

assert(io != NULL); /* shouldn't ever happen. */

BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);

BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, first.buffer, BLOCKSIZE), NULL);
format = TAR_magic(&first);
io->seek(io, 0);
*claimed = format == DEFAULT_FORMAT ? 0 : 1;

unpkarc = UNPK_openArchive(io, 0, 1);
BAIL_IF_ERRPASS(!unpkarc, NULL);

if (!TAR_loadEntries(io, unpkarc))
{
UNPK_abandonArchive(unpkarc);
return NULL;
} /* if */


return unpkarc;
} /* TAR_openArchive */


const PHYSFS_Archiver __PHYSFS_Archiver_TAR =
{
CURRENT_PHYSFS_ARCHIVER_API_VERSION,
{
"TAR",
"POSIX tar archives / Chasm: the Rift Remastered",
"Jon Daniel <[email protected]>",
"http://www.gnu.org/software/tar/",
0,
},
TAR_openArchive,
UNPK_enumerate,
UNPK_openRead,
UNPK_openWrite,
UNPK_openAppend,
UNPK_remove,
UNPK_mkdir,
UNPK_stat,
UNPK_closeArchive
};

#endif /* defined PHYSFS_SUPPORTS_TAR */

/* end of physfs_archiver_tar.c ... */

4 changes: 4 additions & 0 deletions src/physfs_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ extern const PHYSFS_Archiver __PHYSFS_Archiver_HOG;
extern const PHYSFS_Archiver __PHYSFS_Archiver_MVL;
extern const PHYSFS_Archiver __PHYSFS_Archiver_WAD;
extern const PHYSFS_Archiver __PHYSFS_Archiver_CSM;
extern const PHYSFS_Archiver __PHYSFS_Archiver_TAR;
extern const PHYSFS_Archiver __PHYSFS_Archiver_SLB;
extern const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660;
extern const PHYSFS_Archiver __PHYSFS_Archiver_VDF;
Expand Down Expand Up @@ -204,6 +205,9 @@ void __PHYSFS_smallFree(void *ptr);
#ifndef PHYSFS_SUPPORTS_CSM
#define PHYSFS_SUPPORTS_CSM PHYSFS_SUPPORTS_DEFAULT
#endif
#ifndef PHYSFS_SUPPORTS_TAR
#define PHYSFS_SUPPORTS_TAR PHYSFS_SUPPORTS_DEFAULT
#endif
#ifndef PHYSFS_SUPPORTS_QPAK
#define PHYSFS_SUPPORTS_QPAK PHYSFS_SUPPORTS_DEFAULT
#endif
Expand Down
Loading

0 comments on commit 341e13d

Please sign in to comment.