mirror of
https://github.com/FWGS/xash3d-fwgs
synced 2024-11-22 01:45:19 +01:00
utils: xar: add new utility called Xar that helps interacting with Xash3D FWGS archives using filesystem_stdio C API
The utility is not yet finalized, disable from wscript for now
This commit is contained in:
parent
4031f5cb01
commit
8905883225
20
utils/xar/wscript
Normal file
20
utils/xar/wscript
Normal file
@ -0,0 +1,20 @@
|
||||
#! /usr/bin/env python
|
||||
# encoding: utf-8
|
||||
# a1batross, mittorn, 2018
|
||||
|
||||
def options(opt):
|
||||
pass
|
||||
|
||||
def configure(conf):
|
||||
pass
|
||||
|
||||
def build(bld):
|
||||
bld(source = bld.path.ant_glob('*.c'),
|
||||
target = 'xar',
|
||||
features = 'c cprogram',
|
||||
includes = '.',
|
||||
use = 'public filesystem_includes',
|
||||
rpath = bld.env.DEFAULT_RPATH,
|
||||
install_path = bld.env.BINDIR,
|
||||
subsystem = bld.env.CONSOLE_SUBSYSTEM
|
||||
)
|
203
utils/xar/xar.c
Normal file
203
utils/xar/xar.c
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
xar.c -- Xash ARchives (XAR)
|
||||
Copyright (C) 2023 Alibek Omarov
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "port.h"
|
||||
#include "build.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include "filesystem.h"
|
||||
#if XASH_POSIX
|
||||
#include <sys/stat.h>
|
||||
#include <dlfcn.h>
|
||||
#define LoadLibrary( x ) dlopen( x, RTLD_NOW )
|
||||
#define GetProcAddress( x, y ) dlsym( x, y )
|
||||
#define FreeLibrary( x ) dlclose( x )
|
||||
#elif XASH_WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
static void *g_hModule;
|
||||
static FSAPI g_pfnGetFSAPI;
|
||||
static fs_api_t g_fs;
|
||||
static fs_globals_t *g_nullglobals;
|
||||
|
||||
static qboolean LoadFilesystem( void )
|
||||
{
|
||||
#if 0
|
||||
string cwd;
|
||||
|
||||
if( getcwd( cwd, sizeof( cwd )) == NULL )
|
||||
{
|
||||
printf( "getcwd() failed: %s\n", strerror( errno ));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
g_hModule = LoadLibrary( "filesystem_stdio." OS_LIB_EXT );
|
||||
if( !g_hModule )
|
||||
return false;
|
||||
|
||||
g_pfnGetFSAPI = (void*)GetProcAddress( g_hModule, GET_FS_API );
|
||||
if( !g_pfnGetFSAPI )
|
||||
return false;
|
||||
|
||||
if( !g_pfnGetFSAPI( FS_API_VERSION, &g_fs, &g_nullglobals, NULL ))
|
||||
return false;
|
||||
|
||||
// g_fs.InitStdio( true, cwd, );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void FS_CreatePath( char *path )
|
||||
{
|
||||
char *ofs, save;
|
||||
|
||||
for( ofs = path + 1; *ofs; ofs++ )
|
||||
{
|
||||
if( *ofs == '/' || *ofs == '\\' )
|
||||
{
|
||||
// create the directory
|
||||
save = *ofs;
|
||||
*ofs = 0;
|
||||
_mkdir( path );
|
||||
*ofs = save;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usage( const char *arg0 )
|
||||
{
|
||||
printf( "%s: <action> [option...] <file>\n", arg0 );
|
||||
puts( "XAR is a simple frontend to Xash3D FWGS's filesystem_stdio library" );
|
||||
puts( "that allows interacting with archive types supported by it" );
|
||||
puts( "Options:" );
|
||||
puts( "\tx\t\teXtract the archive" );
|
||||
puts( "\tt\t\tlisT the archive" );
|
||||
// TODO: make an interface for modifying
|
||||
// puts( "\tc\t\tCreate the archive" );
|
||||
// puts( "\tu\t\tUpdate the archive" );
|
||||
// puts( "\tr\t\tRemove from the archive" );
|
||||
|
||||
puts( "Extract and list options:" );
|
||||
puts( "\t-wads\tauto-mount WADs inside archives" );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
const char *filename;
|
||||
search_t *search;
|
||||
char action;
|
||||
int i, flags = FS_NOWRITE_PATH | FS_SKIP_ARCHIVED_WADS;
|
||||
|
||||
if( argc < 3 )
|
||||
usage( argv[0] );
|
||||
|
||||
if( !LoadFilesystem())
|
||||
{
|
||||
puts( "Can't load filesystem_stdio!" );
|
||||
return 2;
|
||||
}
|
||||
|
||||
action = argv[1][0];
|
||||
if( action != 'x' && action != 't' )
|
||||
{
|
||||
printf( "Unknown action: %c\n", action );
|
||||
usage( argv[0] );
|
||||
}
|
||||
|
||||
for( i = 2; i < argc - 1; i++ )
|
||||
{
|
||||
if( !strcmp( argv[i], "-wads" ))
|
||||
ClearBits( flags, FS_SKIP_ARCHIVED_WADS );
|
||||
else
|
||||
{
|
||||
printf( "Unknown option: %s\n", argv[i] );
|
||||
usage( argv[0] );
|
||||
}
|
||||
}
|
||||
|
||||
filename = argv[argc-1];
|
||||
|
||||
if( g_fs.MountArchive_Fullpath( filename, flags ) == NULL )
|
||||
{
|
||||
printf( "Can't mount %s\n", filename );
|
||||
return 3;
|
||||
}
|
||||
|
||||
// suboptimal, but that's what is available with current FS API
|
||||
search = g_fs.Search( "*", false, false );
|
||||
if( !search )
|
||||
{
|
||||
printf( "Can't find any files in %s\n", filename );
|
||||
return 4;
|
||||
}
|
||||
|
||||
if( action == 't' )
|
||||
{
|
||||
puts( "File list:" );
|
||||
for( i = 0; i < search->numfilenames; i++ )
|
||||
{
|
||||
printf( "\t%s\n", search->filenames[i] );
|
||||
}
|
||||
}
|
||||
else if( action == 'x' )
|
||||
{
|
||||
for( i = 0; i < search->numfilenames; i++ )
|
||||
{
|
||||
struct stat st;
|
||||
char *path = search->filenames[i];
|
||||
file_t *from;
|
||||
char buffer[4096];
|
||||
FILE *to;
|
||||
|
||||
if(( from = g_fs.Open( path, "rb", false )) == NULL )
|
||||
{
|
||||
printf( "Can't open %s in archive, skipping...\n", path );
|
||||
continue;
|
||||
}
|
||||
|
||||
FS_CreatePath( path );
|
||||
if( stat( path, &st ) == 0 )
|
||||
{
|
||||
printf( "Will not overwrite existing %s file\n", path );
|
||||
g_fs.Close( from );
|
||||
continue;
|
||||
}
|
||||
|
||||
if(( to = fopen( search->filenames[i], "wb" )) == NULL )
|
||||
{
|
||||
printf( "fopen() failed: %s\n", strerror( errno ));
|
||||
g_fs.Close( from );
|
||||
continue;
|
||||
}
|
||||
|
||||
printf( "Unpacking %s...\n", path );
|
||||
while( !g_fs.Eof( from ))
|
||||
{
|
||||
size_t len = g_fs.Read( from, buffer, sizeof( buffer ));
|
||||
fwrite( buffer, 1, len, to );
|
||||
}
|
||||
fclose( to );
|
||||
g_fs.Close( from );
|
||||
}
|
||||
}
|
||||
|
||||
free( search );
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user