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 2545ef4 commit 212f3a5
Show file tree
Hide file tree
Showing 6 changed files with 351 additions and 1 deletion.
8 changes: 8 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 @@ -125,11 +126,17 @@ if(NOT PHYSFS_ARCHIVE_WAD)
add_definitions(-DPHYSFS_SUPPORTS_WAD=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_CSM "Enable Chasm: The Rift CSM.BIN support" TRUE)
if(NOT PHYSFS_ARCHIVE_CSM)
add_definitions(-DPHYSFS_SUPPORTS_CSM=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 +332,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
2 changes: 2 additions & 0 deletions src/Makefile.os2
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ SRCS = physfs.c &
physfs_archiver_zip.c &
physfs_archiver_slb.c &
physfs_archiver_iso9660.c &
physfs_archiver_csm.c &
physfs_archiver_tar.c &
physfs_archiver_vdf.c


Expand Down
5 changes: 4 additions & 1 deletion src/physfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ static PHYSFS_Io *memoryIo_duplicate(PHYSFS_Io *io)
BAIL(PHYSFS_ERR_OUT_OF_MEMORY, NULL);
} /* if */

__PHYSFS_ATOMIC_INCR(&info->refcount);
(void) __PHYSFS_ATOMIC_INCR(&info->refcount);

memset(newinfo, '\0', sizeof (*info));
newinfo->buf = info->buf;
Expand Down Expand Up @@ -1188,6 +1188,9 @@ static int initStaticArchivers(void)
#if PHYSFS_SUPPORTS_WAD
REGISTER_STATIC_ARCHIVER(WAD);
#endif
#if PHYSFS_SUPPORTS_TAR
REGISTER_STATIC_ARCHIVER(TAR);
#endif
#if PHYSFS_SUPPORTS_CSM
REGISTER_STATIC_ARCHIVER(CSM);
#endif
Expand Down
105 changes: 105 additions & 0 deletions src/physfs_archiver_tar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* 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 int TAR_loadEntries(PHYSFS_Io *io, void *arc)
{
union block zero_block = { 0 };
union block current_block = { 0 };
PHYSFS_uint64 count = 0;
bool long_name = false;

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

/* 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 0;
}

static void *TAR_openArchive(PHYSFS_Io *io, const char *name,
int forWriting, int *claimed)
{
void *unpkarc = NULL;
char buf[BLOCKSIZE] = { '\0' };

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

BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
BAIL_IF_ERRPASS(__PHYSFS_readAll(io, buf, sizeof (buf)) == 0, 0);
if ((memcmp(&buf[TMAGOFF], TMAGIC, TMAGLEN - 1) != 0) != 0)
BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);

*claimed = 1;

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

if (TAR_loadEntries(io, unpkarc) == 0)
{
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 <jondaniel879@gmail.com>",
"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 @@ -88,6 +88,7 @@ extern const PHYSFS_Archiver __PHYSFS_Archiver_QPAK;
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_TAR;
extern const PHYSFS_Archiver __PHYSFS_Archiver_CSM;
extern const PHYSFS_Archiver __PHYSFS_Archiver_SLB;
extern const PHYSFS_Archiver __PHYSFS_Archiver_ISO9660;
Expand Down Expand Up @@ -201,6 +202,9 @@ void __PHYSFS_smallFree(void *ptr);
#ifndef PHYSFS_SUPPORTS_WAD
#define PHYSFS_SUPPORTS_WAD PHYSFS_SUPPORTS_DEFAULT
#endif
#ifndef PHYSFS_SUPPORTS_TAR
#define PHYSFS_SUPPORTS_TAR PHYSFS_SUPPORTS_DEFAULT
#endif
#ifndef PHYSFS_SUPPORTS_CSM
#define PHYSFS_SUPPORTS_CSM PHYSFS_SUPPORTS_DEFAULT
#endif
Expand Down
Loading

0 comments on commit 212f3a5

Please sign in to comment.