//
#include "vfs.h"
+#include "globaldefs.h"
#include <stdio.h>
#include <stdlib.h>
#include "os/path.h"
#include "moduleobservers.h"
#include "filematch.h"
+#include "dpkdeps.h"
-#define VFS_MAXDIRS 64
+const int VFS_MAXDIRS = 64;
-#if defined( WIN32 )
+#if GDEF_OS_WINDOWS
#define PATH_MAX 260
#endif
entry.archive = table->m_pfnOpenArchive( filename );
entry.is_pakfile = true;
g_archives.push_back( entry );
- globalOutputStream() << " pak file: " << filename << "\n";
+ globalOutputStream() << "pak file: " << filename << "\n";
return entry.archive;
}
typedef std::set<CopiedString, PakLess> Archives;
-Archive* AddPk3Dir( const char* fullpath ){
+Archive* AddPakDir( const char* fullpath ){
if ( g_numDirs == VFS_MAXDIRS ) return 0;
+ globalOutputStream() << "pak directory: " << fullpath << "\n";
strncpy( g_strDirs[g_numDirs], fullpath, PATH_MAX );
g_strDirs[g_numDirs][PATH_MAX] = '\0';
g_numDirs++;
}
}
-// for Daemon DPK vfs
+// for Daemon DPK VFS
Archive* AddDpkDir( const char* fullpath ){
- return AddPk3Dir( fullpath );
+ return AddPakDir( fullpath );
}
struct pakfile_path_t
{
CopiedString fullpath; // full pak dir or pk3dir name
- bool is_pakfile; // defines is it .pk3dir or .pk3 file
+ bool is_pakfile; // tells it is .pk3dir or .pk3 file
};
typedef std::pair<CopiedString, pakfile_path_t> PakfilePathsKV;
g_pakfile_paths.insert( PakfilePathsKV( name, pakfile_path ) );
}
-// Comparaison function for version numbers
-// Implementation is based on dpkg's version comparison code (verrevcmp() and order())
-// http://anonscm.debian.org/gitweb/?p=dpkg/dpkg.git;a=blob;f=lib/dpkg/version.c;hb=74946af470550a3295e00cf57eca1747215b9311
-static int char_weight(char c){
- if (std::isdigit(c))
- return 0;
- else if (std::isalpha(c))
- return c;
- else if (c == '~')
- return -1;
- else if (c)
- return c + 256;
- else
- return 0;
-}
-
-static int VersionCmp(const char* a, const char* b){
- while (*a || *b) {
- int firstDiff = 0;
-
- while ((*a && !std::isdigit(*a)) || (*b && !std::isdigit(*b))) {
- int ac = char_weight(*a);
- int bc = char_weight(*b);
-
- if (ac != bc)
- return ac - bc;
-
- a++;
- b++;
- }
-
- while (*a == '0')
- a++;
- while (*b == '0')
- b++;
-
- while (std::isdigit(*a) && std::isdigit(*b)) {
- if (firstDiff == 0)
- firstDiff = *a - *b;
- a++;
- b++;
- }
-
- if (std::isdigit(*a))
- return 1;
- if (std::isdigit(*b))
- return -1;
- if (firstDiff)
- return firstDiff;
- }
-
- return false;
-}
-
// takes name without ext, returns without ext
static const char* GetLatestDpkPakVersion( const char* name ){
const char* maxversion = 0;
pakname = i->first.c_str();
if ( strncmp( pakname, name, namelen ) != 0 || pakname[namelen] != '_' ) continue;
pakversion = pakname + (namelen + 1);
- if ( maxversion == 0 || VersionCmp( pakversion, maxversion ) > 0 ){
+ if ( maxversion == 0 || DpkPakVersionCmp( pakversion, maxversion ) > 0 ){
maxversion = pakversion;
result = pakname;
}
// actual pak adding on initialise, deferred from InitDirectory
// Daemon DPK filesystem doesn't need load all paks it finds
static void LoadDpkPakWithDeps( const char* pakname ){
- const char* und = strrchr( pakname, '_' );
- if ( !und ) pakname = GetLatestDpkPakVersion( pakname );
- if ( !pakname || g_loaded_dpk_paks.find( pakname ) != g_loaded_dpk_paks.end() ) return;
-
- PakfilePaths::iterator i = g_pakfile_paths.find( pakname );
- if ( i == g_pakfile_paths.end() ) return;
-
Archive* arc;
- if ( i->second.is_pakfile ){
- arc = InitPakFile( FileSystemQ3API_getArchiveModules(), i->second.fullpath.c_str() );
+ ArchiveTextFile* depsFile;
+
+ if (pakname == NULL) {
+ // load DEPS from game pack
+ StringOutputStream baseDirectory( 256 );
+ const char* basegame = GlobalRadiant().getRequiredGameDescriptionKeyValue( "basegame" );
+ baseDirectory << GlobalRadiant().getGameToolsPath() << basegame << '/';
+ arc = AddDpkDir( baseDirectory.c_str() );
+ depsFile = arc->openTextFile( "DEPS" );
} else {
- arc = AddDpkDir( i->second.fullpath.c_str() );
+ const char* und = strrchr( pakname, '_' );
+ if ( !und ) {
+ pakname = GetLatestDpkPakVersion( pakname );
+ }
+ if ( !pakname || g_loaded_dpk_paks.find( pakname ) != g_loaded_dpk_paks.end() ) {
+ return;
+ }
+
+ PakfilePaths::iterator i = g_pakfile_paths.find( pakname );
+ if ( i == g_pakfile_paths.end() ) {
+ return;
+ }
+
+ if ( i->second.is_pakfile ){
+ arc = InitPakFile( FileSystemQ3API_getArchiveModules(), i->second.fullpath.c_str() );
+ } else {
+ arc = AddDpkDir( i->second.fullpath.c_str() );
+ }
+ g_loaded_dpk_paks.insert( pakname );
+
+ depsFile = arc->openTextFile( "DEPS" );
}
- g_loaded_dpk_paks.insert( pakname );
- ArchiveTextFile* depsFile = arc->openTextFile( "DEPS" );
- if ( !depsFile ) return;
+ if ( !depsFile ) {
+ return;
+ }
{
TextLinesInputStream<TextInputStream> istream = depsFile->getInputStream();
CopiedString line;
- const char* c;
- const char* p_name;
- const char* p_name_end;
- const char* p_version;
- const char* p_version_end;
+ char *p_name;
+ char *p_version;
while ( line = istream.readLine(), string_length( line.c_str() ) ) {
- c = line.c_str();
- while ( std::isspace( *c ) && *c != '\0' ) ++c;
- p_name = c;
- while ( !std::isspace( *c ) && *c != '\0' ) ++c;
- p_name_end = c;
- while ( std::isspace( *c ) && *c != '\0' ) ++c;
- p_version = c;
- while ( !std::isspace( *c ) && *c != '\0' ) ++c;
- p_version_end = c;
-
- if ( p_name_end - p_name == 0 ) continue;
- if ( p_version_end - p_version == 0 ) {
- const char* p_pakname;
- CopiedString name_final = CopiedString( StringRange( p_name, p_name_end ) );
- p_pakname = GetLatestDpkPakVersion( name_final.c_str() );
- if ( p_pakname != NULL ) {
- LoadDpkPakWithDeps( p_pakname );
- }
+ if ( !DpkReadDepsLine( line.c_str(), &p_name, &p_version ) ) continue;
+ if ( !p_version ) {
+ const char* p_latest = GetLatestDpkPakVersion( p_name );
+ if ( p_latest ) LoadDpkPakWithDeps( p_latest );
} else {
- int len = ( p_name_end - p_name ) + ( p_version_end - p_version ) + 1;
+ int len = string_length( p_name ) + string_length( p_version ) + 1;
char* p_pakname = string_new( len );
- strncpy( p_pakname, p_name, p_name_end - p_name );
- p_pakname[ p_name_end - p_name ] = '\0';
- strcat( p_pakname, "_" );
- strncat( p_pakname, p_version, p_version_end - p_version );
+ sprintf( p_pakname, "%s_%s", p_name, p_version );
LoadDpkPakWithDeps( p_pakname );
string_release( p_pakname, len );
}
+ string_release( p_name, string_length( p_name ) );
+ if ( p_version ) string_release( p_version, string_length( p_version ) );
}
}
g_numForbiddenDirs = 0;
StringTokeniser st( GlobalRadiant().getGameDescriptionKeyValue( "forbidden_paths" ), " " );
+
for ( j = 0; j < VFS_MAXDIRS; ++j )
{
const char *t = st.getToken();
}
g_free( dbuf );
}
+
if ( j < g_numForbiddenDirs ) {
printf( "Directory %s matched by forbidden dirs, removed\n", directory );
return;
GDir* dir = g_dir_open( path, 0, 0 );
- if ( dir != 0 ) {
+ if ( dir != NULL ) {
globalOutputStream() << "vfs directory: " << path << "\n";
Archives archives;
Archives archivesOverride;
const char* ignore_prefix = "";
const char* override_prefix = "";
- bool is_pk3_vfs, is_pk4_vfs, is_dpk_vfs;
+ bool is_wad_vfs, is_pak_vfs, is_pk3_vfs, is_pk4_vfs, is_dpk_vfs;
- is_pk3_vfs = GetArchiveTable( archiveModules, "pk3" );
- is_pk4_vfs = GetArchiveTable( archiveModules, "pk4" );
- is_dpk_vfs = GetArchiveTable( archiveModules, "dpk" );
+ is_wad_vfs = !!GetArchiveTable( archiveModules, "wad" );
+ is_pak_vfs = !!GetArchiveTable( archiveModules, "pak" );
+ is_pk3_vfs = !!GetArchiveTable( archiveModules, "pk3" );
+ is_pk4_vfs = !!GetArchiveTable( archiveModules, "pk4" );
+ is_dpk_vfs = !!GetArchiveTable( archiveModules, "dpk" );
- if ( !is_dpk_vfs ) {
+ if ( is_dpk_vfs ) {
// See if we are in "sp" or "mp" mapping mode
const char* gamemode = gamemode_get();
}
}
- for (;; )
+ while ( true )
{
const char* name = g_dir_read_name( dir );
- if ( name == 0 ) {
+
+ if ( name == nullptr ) {
break;
}
break;
}
}
+
if ( j < g_numForbiddenDirs ) {
continue;
}
const char *ext = strrchr( name, '.' );
- char tmppath[PATH_MAX];
+ char tmppath[PATH_MAX + 1];
- if ( is_dpk_vfs ) {
- if ( !!ext && !string_compare_nocase_upper( ext, ".dpkdir" ) ) {
+ if ( ext != nullptr ) {
+ if ( is_dpk_vfs && !string_compare_nocase_upper( ext, ".dpkdir" ) ) {
snprintf( tmppath, PATH_MAX, "%s%s/", path, name );
tmppath[PATH_MAX] = '\0';
FixDOSName( tmppath );
AddSlash( tmppath );
AddDpkPak( CopiedString( StringRange( name, ext ) ).c_str(), tmppath, false );
}
- }
- if ( is_pk3_vfs || is_pk4_vfs ) {
- if ( !!ext && ( !string_compare_nocase_upper( ext, ".pk3dir" )
- || !string_compare_nocase_upper( ext, ".pk4dir" ) ) ) {
+ else if ( ( is_wad_vfs && !string_compare_nocase_upper( ext, ".pakdir" ) )
+ || ( is_pk3_vfs && !string_compare_nocase_upper( ext, ".pk3dir" ) )
+ || ( is_pk4_vfs && !string_compare_nocase_upper( ext, ".pk4dir" ) ) ) {
snprintf( tmppath, PATH_MAX, "%s%s/", path, name );
tmppath[PATH_MAX] = '\0';
FixDOSName( tmppath );
AddSlash( tmppath );
- AddPk3Dir( tmppath );
+ AddPakDir( tmppath );
}
}
// GetArchiveTable() needs "pk3" if ext is ".pk3"
- if ( ( ext == 0 ) || *( ext + 1 ) == '\0' || GetArchiveTable( archiveModules, ext + 1 ) == 0 ) {
+ if ( ( ext == nullptr ) || *( ext + 1 ) == '\0' || GetArchiveTable( archiveModules, ext + 1 ) == 0 ) {
continue;
}
if ( !string_empty( ignore_prefix ) && strncmp( name, ignore_prefix, strlen( ignore_prefix ) ) == 0 ) {
continue;
}
+
if ( !string_empty( override_prefix ) && strncmp( name, override_prefix, strlen( override_prefix ) ) == 0 ) {
if ( !string_compare_nocase_upper( ext, ".dpk" ) ) {
if ( is_dpk_vfs ) {
archives.insert( name );
+ continue;
}
}
else {
archivesOverride.insert( name );
+ continue;
}
- continue;
}
archives.insert( name );
for ( Archives::iterator i = archives.begin(); i != archives.end(); ++i ) {
const char* name = i->c_str();
const char* ext = strrchr( name, '.' );
- if ( !string_compare_nocase_upper( ext, ".dpk" ) ) {
+ if ( !string_compare_nocase_upper( ext, ".dpk" ) )
+ {
CopiedString name_final = CopiedString( StringRange( name, ext ) );
fullpath = string_new_concat( path, name );
AddDpkPak( name_final.c_str(), fullpath, true );
}
}
}
- if ( is_pk3_vfs || is_pk4_vfs ) {
+ else
+ {
for ( Archives::iterator i = archivesOverride.begin(); i != archivesOverride.end(); ++i )
{
const char* name = i->c_str();
const char* ext = strrchr( name, '.' );
- if ( !string_compare_nocase_upper( ext, ".pk3" )
- || !string_compare_nocase_upper( ext, ".pk4" ) ) {
+ if ( ( is_wad_vfs && !string_compare_nocase_upper( ext, ".wad" ) )
+ || ( is_pak_vfs && !string_compare_nocase_upper( ext, ".pak" ) )
+ || ( is_pk3_vfs && !string_compare_nocase_upper( ext, ".pk3" ) )
+ || ( is_pk4_vfs && !string_compare_nocase_upper( ext, ".pk4" ) ) ) {
fullpath = string_new_concat( path, i->c_str() );
InitPakFile( archiveModules, fullpath );
string_release( fullpath, string_length( fullpath ) );
}
}
+
for ( Archives::iterator i = archives.begin(); i != archives.end(); ++i )
{
const char* name = i->c_str();
const char* ext = strrchr( name, '.' );
- if ( !string_compare_nocase_upper( ext, ".pk3" )
- || !string_compare_nocase_upper( ext, ".pk4" ) ) {
+ if ( ( is_wad_vfs && !string_compare_nocase_upper( ext, ".wad" ) )
+ || ( is_pak_vfs && !string_compare_nocase_upper( ext, ".pak" ) )
+ || ( is_pk3_vfs && !string_compare_nocase_upper( ext, ".pk3" ) )
+ || ( is_pk4_vfs && !string_compare_nocase_upper( ext, ".pk4" ) ) ) {
fullpath = string_new_concat( path, i->c_str() );
InitPakFile( archiveModules, fullpath );
string_release( fullpath, string_length( fullpath ) );
g_loaded_dpk_paks.clear();
}
-#define VFS_SEARCH_PAK 0x1
-#define VFS_SEARCH_DIR 0x2
+const int VFS_SEARCH_PAK = 0x1;
+const int VFS_SEARCH_DIR = 0x2;
int GetFileCount( const char *filename, int flag ){
int count = 0;
for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i )
{
- if ( ( *i ).is_pakfile && ( flag & VFS_SEARCH_PAK ) != 0
- || !( *i ).is_pakfile && ( flag & VFS_SEARCH_DIR ) != 0 ) {
+ if ( (( *i ).is_pakfile && ( flag & VFS_SEARCH_PAK ) != 0)
+ || (!( *i ).is_pakfile && ( flag & VFS_SEARCH_DIR ) != 0) ) {
if ( ( *i ).archive->containsFile( fixed ) ) {
++count;
}
InitDirectory( path, FileSystemQ3API_getArchiveModules() );
}
void initialise(){
+ load();
+ globalOutputStream() << "filesystem initialised\n";
+ g_observers.realise();
+}
+
+void load(){
ArchiveModules& archiveModules = FileSystemQ3API_getArchiveModules();
- bool is_dpk_vfs = GetArchiveTable( archiveModules, "dpk" );
+ bool is_dpk_vfs = !!GetArchiveTable( archiveModules, "dpk" );
if ( is_dpk_vfs ) {
const char* pakname;
g_loaded_dpk_paks.clear();
- pakname = GetLatestDpkPakVersion( "tex-common" );
- if (pakname != NULL) {
- LoadDpkPakWithDeps( pakname );
- }
+ // Load DEPS from game pack
+ LoadDpkPakWithDeps( NULL );
// prevent VFS double start, for MapName="" and MapName="unnamed.map"
if ( string_length( GlobalRadiant().getMapName() ) ){
g_pakfile_paths.clear();
g_loaded_dpk_paks.clear();
}
+}
- globalOutputStream() << "filesystem initialised\n";
- g_observers.realise();
+void clear() {
+ // like shutdown() but does not unrealise (keep map etc.)
+ Shutdown();
+}
+
+void refresh(){
+ // like initialise() but does not realise (keep map etc.)
+ load();
+ globalOutputStream() << "filesystem refreshed\n";
}
+
void shutdown(){
g_observers.unrealise();
globalOutputStream() << "filesystem shutdown\n";
if ( path_equal( ( *i ).name.c_str(), archiveName ) ) {
return ( *i ).archive;
}
+ else if ( path_equal( path_get_filename_start( ( *i ).name.c_str() ), archiveName ) ) {
+ return ( *i ).archive;
+ }
}
return 0;
}