XDG home directory support

This commit is contained in:
Tim Angus committed 2025-10-19 15:58:27 +01:00
1 parent da4f9bd13d
commit 0ebf1df742
18 files changed
+527 -143

No files matched your search

+6 -6
View File
@@ -205,7 +205,7 @@ void QDECL Com_Printf( const char *fmt, ... ) {
time( &aclock );
newtime = localtime( &aclock );
logfile = FS_FOpenFileWrite( "qconsole.log" );
logfile = FS_FOpenFileWrite_HomeData( "qconsole.log" );
if(logfile)
{
@@ -1921,8 +1921,8 @@ void Com_InitJournaling( void ) {
if ( com_journal->integer == 1 ) {
Com_Printf( "Journaling events\n");
com_journalFile = FS_FOpenFileWrite( "journal.dat" );
com_journalDataFile = FS_FOpenFileWrite( "journaldata.dat" );
com_journalFile = FS_FOpenFileWrite_HomeState( "journal.dat" );
com_journalDataFile = FS_FOpenFileWrite_HomeState( "journaldata.dat" );
} else if ( com_journal->integer == 2 ) {
Com_Printf( "Replaying journaled events\n");
FS_FOpenFileRead( "journal.dat", &com_journalFile, qtrue );
@@ -2547,7 +2547,7 @@ static void Com_WriteCDKey( const char *filename, const char *ikey ) {
#ifndef _WIN32
savedumask = umask(0077);
#endif
f = FS_BaseDir_FOpenFileWrite( fbuffer );
f = FS_BaseDir_FOpenFileWrite_HomeState( fbuffer );
if ( !f ) {
Com_Printf ("Couldn't write CD key to %s.\n", fbuffer );
goto out;
@@ -2921,7 +2921,7 @@ void Com_ReadFromPipe( void )
void Com_WriteConfigToFile( const char *filename ) {
fileHandle_t f;
f = FS_FOpenFileWrite( filename );
f = FS_FOpenFileWrite_HomeConfig( filename );
if ( !f ) {
Com_Printf ("Couldn't write %s.\n", filename );
return;
@@ -3293,7 +3293,7 @@ void Com_Shutdown (void) {
if( pipefile ) {
FS_FCloseFile( pipefile );
FS_HomeRemove( com_pipefile->string );
FS_Remove_HomeData( com_pipefile->string );
}
}
+99 -45
View File
@@ -246,7 +246,9 @@ typedef struct searchpath_s {
static char fs_gamedir[MAX_OSPATH]; // this will be a single file name with no separators
static cvar_t *fs_debug;
static cvar_t *fs_homepath;
static cvar_t *fs_homeconfigpath;
static cvar_t *fs_homedatapath;
static cvar_t *fs_homestatepath;
static cvar_t *fs_apppath;
static cvar_t *fs_steampath;
@@ -609,14 +611,14 @@ void FS_Remove( const char *osPath ) {
/*
===========
FS_HomeRemove
FS_Remove_HomeData
===========
*/
void FS_HomeRemove( const char *homePath ) {
void FS_Remove_HomeData( const char *homePath ) {
FS_CheckFilenameIsMutable( homePath, __func__ );
remove( FS_BuildOSPath( fs_homepath->string,
remove( FS_BuildOSPath( fs_homedatapath->string,
fs_gamedir, homePath ) );
}
@@ -644,7 +646,7 @@ qboolean FS_FileInPathExists(const char *testpath)
/*
================
FS_FileExists
FS_FileExists_HomeData
Tests if the file exists in the current gamedir, this DOES NOT
search the paths. This is to determine if opening a file to write
@@ -652,21 +654,21 @@ search the paths. This is to determine if opening a file to write
NOTE TTimo: this goes with FS_FOpenFileWrite for opening the file afterwards
================
*/
qboolean FS_FileExists(const char *file)
qboolean FS_FileExists_HomeData(const char *file)
{
return FS_FileInPathExists(FS_BuildOSPath(fs_homepath->string, fs_gamedir, file));
return FS_FileInPathExists(FS_BuildOSPath(fs_homedatapath->string, fs_gamedir, file));
}
/*
================
FS_BaseDir_FileExists
FS_BaseDir_FileExists_HomeData
Tests if the file exists
================
*/
qboolean FS_BaseDir_FileExists( const char *file )
static qboolean FS_BaseDir_FileExists_HomeData( const char *file )
{
return FS_FileInPathExists(FS_BaseDir_BuildOSPath(fs_homepath->string, file));
return FS_FileInPathExists(FS_BaseDir_BuildOSPath(fs_homedatapath->string, file));
}
@@ -708,13 +710,32 @@ static fileHandle_t FS_OSPath_FOpenFileWrite( const char *ospath, const char *fi
/*
===========
FS_BaseDir_FOpenFileWrite
FS_BaseDir_FOpenFileWrite_HomeConfig
===========
*/
fileHandle_t FS_BaseDir_FOpenFileWrite( const char *filename ) {
fileHandle_t FS_BaseDir_FOpenFileWrite_HomeConfig( const char *filename ) {
return FS_OSPath_FOpenFileWrite(
FS_BaseDir_BuildOSPath(fs_homepath->string, filename), filename);
FS_BaseDir_BuildOSPath(fs_homeconfigpath->string, filename), filename);
}
/*
===========
FS_BaseDir_FOpenFileWrite_HomeData
===========
*/
fileHandle_t FS_BaseDir_FOpenFileWrite_HomeData( const char *filename ) {
return FS_OSPath_FOpenFileWrite(
FS_BaseDir_BuildOSPath(fs_homedatapath->string, filename), filename);
}
/*
===========
FS_BaseDir_FOpenFileWrite_HomeState
===========
*/
fileHandle_t FS_BaseDir_FOpenFileWrite_HomeState( const char *filename ) {
return FS_OSPath_FOpenFileWrite(
FS_BaseDir_BuildOSPath(fs_homestatepath->string, filename), filename);
}
/*
@@ -776,11 +797,11 @@ long FS_BaseDir_FOpenFileRead(const char *filename, fileHandle_t *fp)
/*
===========
FS_BaseDir_Rename
FS_BaseDir_Rename_HomeData
===========
*/
void FS_BaseDir_Rename( const char *from, const char *to, qboolean safe ) {
void FS_BaseDir_Rename_HomeData( const char *from, const char *to, qboolean safe ) {
char *from_ospath, *to_ospath;
if ( !fs_searchpaths ) {
@@ -790,11 +811,11 @@ void FS_BaseDir_Rename( const char *from, const char *to, qboolean safe ) {
// don't let sound stutter
S_ClearSoundBuffer();
from_ospath = FS_BaseDir_BuildOSPath( fs_homepath->string, from );
to_ospath = FS_BaseDir_BuildOSPath( fs_homepath->string, to );
from_ospath = FS_BaseDir_BuildOSPath( fs_homedatapath->string, from );
to_ospath = FS_BaseDir_BuildOSPath( fs_homedatapath->string, to );
if ( fs_debug->integer ) {
Com_Printf( "FS_BaseDir_Rename: %s --> %s\n", from_ospath, to_ospath );
Com_Printf( "FS_BaseDir_Rename_HomeData: %s --> %s\n", from_ospath, to_ospath );
}
if ( safe ) {
@@ -837,22 +858,41 @@ void FS_FCloseFile( fileHandle_t f ) {
/*
===========
FS_FOpenFileWrite
FS_FOpenFileWrite_HomeConfig
===========
*/
fileHandle_t FS_FOpenFileWrite( const char *filename ) {
fileHandle_t FS_FOpenFileWrite_HomeConfig( const char *filename ) {
return FS_OSPath_FOpenFileWrite(
FS_BuildOSPath(fs_homepath->string, fs_gamedir, filename), filename);
FS_BuildOSPath(fs_homeconfigpath->string, fs_gamedir, filename), filename);
}
/*
===========
FS_FOpenFileAppend
FS_FOpenFileWrite_HomeData
===========
*/
fileHandle_t FS_FOpenFileWrite_HomeData( const char *filename ) {
return FS_OSPath_FOpenFileWrite(
FS_BuildOSPath(fs_homedatapath->string, fs_gamedir, filename), filename);
}
/*
===========
FS_FOpenFileWrite_HomeState
===========
*/
fileHandle_t FS_FOpenFileWrite_HomeState( const char *filename ) {
return FS_OSPath_FOpenFileWrite(
FS_BuildOSPath(fs_homestatepath->string, fs_gamedir, filename), filename);
}
/*
===========
FS_FOpenFileAppend_HomeData
===========
*/
fileHandle_t FS_FOpenFileAppend( const char *filename ) {
fileHandle_t FS_FOpenFileAppend_HomeData( const char *filename ) {
char *ospath;
fileHandle_t f;
@@ -868,10 +908,10 @@ fileHandle_t FS_FOpenFileAppend( const char *filename ) {
// don't let sound stutter
S_ClearSoundBuffer();
ospath = FS_BuildOSPath( fs_homepath->string, fs_gamedir, filename );
ospath = FS_BuildOSPath( fs_homedatapath->string, fs_gamedir, filename );
if ( fs_debug->integer ) {
Com_Printf( "FS_FOpenFileAppend: %s\n", ospath );
Com_Printf( "FS_FOpenFileAppend_HomeData: %s\n", ospath );
}
FS_CheckFilenameIsMutable( ospath, __func__ );
@@ -911,7 +951,7 @@ fileHandle_t FS_FCreateOpenPipeFile( const char *filename ) {
// don't let sound stutter
S_ClearSoundBuffer();
ospath = FS_BuildOSPath( fs_homepath->string, fs_gamedir, filename );
ospath = FS_BuildOSPath( fs_homedatapath->string, fs_gamedir, filename );
if ( fs_debug->integer ) {
Com_Printf( "FS_FCreateOpenPipeFile: %s\n", ospath );
@@ -1237,7 +1277,7 @@ long FS_FOpenFileReadDir(const char *filename, searchpath_t *search, fileHandle_
// if you are using FS_ReadFile to find out if a file exists,
// this test can make the search fail although the file is in the directory
// I had the problem on https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8
// turned out I used FS_FileExists instead
// turned out I used FS_FileExists_HomeData instead
if(!unpure && fs_numServerPaks)
{
if(!FS_IsExt(filename, ".cfg", len) && // for config files
@@ -1909,7 +1949,7 @@ void FS_WriteFile( const char *qpath, const void *buffer, int size ) {
Com_Error( ERR_FATAL, "FS_WriteFile: NULL parameter" );
}
f = FS_FOpenFileWrite( qpath );
f = FS_FOpenFileWrite_HomeData( qpath );
if ( !f ) {
Com_Printf( "Failed to open %s\n", qpath );
return;
@@ -3132,7 +3172,7 @@ qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring ) {
// Local name
Q_strcat( neededpaks, len, "@");
// Do we have one with the same name?
if ( FS_BaseDir_FileExists( va( "%s.pk3", fs_serverReferencedPakNames[i] ) ) )
if ( FS_BaseDir_FileExists_HomeData( va( "%s.pk3", fs_serverReferencedPakNames[i] ) ) )
{
char st[MAX_ZPATH];
// We already have one called this, we need to download it to another name
@@ -3159,7 +3199,7 @@ qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring ) {
Q_strcat( neededpaks, len, fs_serverReferencedPakNames[i] );
Q_strcat( neededpaks, len, ".pk3" );
// Do we have one with the same name?
if ( FS_BaseDir_FileExists( va( "%s.pk3", fs_serverReferencedPakNames[i] ) ) )
if ( FS_BaseDir_FileExists_HomeData( va( "%s.pk3", fs_serverReferencedPakNames[i] ) ) )
{
Q_strcat( neededpaks, len, " (local file exists with wrong checksum)");
}
@@ -3302,7 +3342,9 @@ FS_InitPathVars
static void FS_InitPathVars( void ) {
memset( fs_pathVars, 0, sizeof( fs_pathVars ) );
FS_AddPathVar( fs_homepath );
FS_AddPathVar( fs_homeconfigpath );
FS_AddPathVar( fs_homedatapath );
FS_AddPathVar( fs_homestatepath );
FS_AddPathVar( fs_basepath );
FS_AddPathVar( fs_apppath );
FS_AddPathVar( fs_steampath );
@@ -3317,7 +3359,18 @@ FS_Startup
*/
static void FS_Startup( const char *gameName )
{
const char *homePath;
cvar_t *fs_homepath = Cvar_Get("fs_homepath", "", CVAR_INIT|CVAR_PROTECTED);
const char *configPath = Sys_DefaultHomeConfigPath();
const char *dataPath = Sys_DefaultHomeDataPath();
const char *statePath = Sys_DefaultHomeStatePath();
if(*(fs_homepath)->string) {
// Setting fs_homepath manually overrides everything else
configPath = dataPath = statePath = fs_homepath->string;
} else if(!*configPath || !*dataPath || !*statePath) {
// #shouldneverhappen; just a sensible fallback
configPath = dataPath = statePath = Sys_DefaultInstallPath();
}
Com_Printf( "----- FS_Startup -----\n" );
@@ -3326,11 +3379,9 @@ static void FS_Startup( const char *gameName )
fs_debug = Cvar_Get( "fs_debug", "0", 0 );
fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultInstallPath(), CVAR_INIT|CVAR_PROTECTED );
fs_basegame = Cvar_Get ("fs_basegame", "", CVAR_INIT );
homePath = Sys_DefaultHomePath();
if (!homePath || !homePath[0]) {
homePath = fs_basepath->string;
}
fs_homepath = Cvar_Get ("fs_homepath", homePath, CVAR_INIT|CVAR_PROTECTED );
fs_homeconfigpath = Cvar_Get ("fs_homeconfigpath", configPath, CVAR_INIT|CVAR_PROTECTED );
fs_homedatapath = Cvar_Get ("fs_homedatapath", dataPath, CVAR_INIT|CVAR_PROTECTED );
fs_homestatepath = Cvar_Get ("fs_homestatepath", statePath, CVAR_INIT|CVAR_PROTECTED );
fs_gamedirvar = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
fs_steampath = Cvar_Get ("fs_steampath", Sys_SteamPath(), CVAR_INIT|CVAR_PROTECTED );
fs_gogpath = Cvar_Get ("fs_gogpath", Sys_GogPath(), CVAR_INIT|CVAR_PROTECTED );
@@ -3363,9 +3414,9 @@ static void FS_Startup( const char *gameName )
Com_Error( ERR_DROP, "Invalid fs_game '%s'", fs_gamedirvar->string );
}
if (fs_homepath->string[0] && Q_stricmp(fs_homepath->string, fs_basepath->string)) {
FS_CreatePath ( fs_homepath->string );
}
FS_CreatePath(fs_homeconfigpath->string);
FS_CreatePath(fs_homedatapath->string);
FS_CreatePath(fs_homestatepath->string);
FS_AddGameDirectories(gameName);
@@ -3639,7 +3690,7 @@ static void FS_CheckPak0( void )
#endif
if(installHome)
installPath = fs_homepath->string;
installPath = fs_homedatapath->string;
else
installPath = fs_basepath->string;
@@ -4059,6 +4110,9 @@ void FS_InitFilesystem( void ) {
// has already been initialized
Com_StartupVariable("fs_basepath");
Com_StartupVariable("fs_homepath");
Com_StartupVariable("fs_homeconfigpath");
Com_StartupVariable("fs_homedatapath");
Com_StartupVariable("fs_homestatepath");
Com_StartupVariable("fs_game");
if(!FS_FilenameCompare(Cvar_VariableString("fs_game"), com_basegame->string))
@@ -4201,7 +4255,7 @@ int FS_FOpenFileByMode( const char *qpath, fileHandle_t *f, fsMode_t mode ) {
r = FS_FOpenFileRead( qpath, f, qtrue );
break;
case FS_WRITE:
*f = FS_FOpenFileWrite( qpath );
*f = FS_FOpenFileWrite_HomeData( qpath );
r = 0;
if (*f == 0) {
r = -1;
@@ -4210,7 +4264,7 @@ int FS_FOpenFileByMode( const char *qpath, fileHandle_t *f, fsMode_t mode ) {
case FS_APPEND_SYNC:
sync = qtrue;
case FS_APPEND:
*f = FS_FOpenFileAppend( qpath );
*f = FS_FOpenFileAppend_HomeData( qpath );
r = 0;
if (*f == 0) {
r = -1;
+4 -6
View File
@@ -31,9 +31,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define BASEGAME "foobar"
#define CLIENT_WINDOW_TITLE "changeme"
#define CLIENT_WINDOW_MIN_TITLE "changeme2"
#define HOMEPATH_NAME_UNIX ".foo"
#define HOMEPATH_NAME_WIN "FooBar"
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
#define HOMEPATH_NAME_UNIX_LEGACY ".foo"
#define HOMEPATH_NAME "FooBar"
#define GAMENAME_FOR_MASTER "foobar" // must NOT contain whitespace
#define CINEMATICS_LOGO "foologo.roq"
#define CINEMATICS_INTRO "intro.roq"
@@ -45,9 +44,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define BASEGAME "baseq3"
#define CLIENT_WINDOW_TITLE "ioquake3"
#define CLIENT_WINDOW_MIN_TITLE "ioq3"
#define HOMEPATH_NAME_UNIX ".q3a"
#define HOMEPATH_NAME_WIN "Quake3"
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
#define HOMEPATH_NAME_UNIX_LEGACY ".q3a"
#define HOMEPATH_NAME "Quake3"
#define GAMENAME_FOR_MASTER "Quake3Arena"
#define CINEMATICS_LOGO "idlogo.RoQ"
#define CINEMATICS_INTRO "intro.RoQ"
+13 -7
View File
@@ -616,7 +616,7 @@ char **FS_ListFiles( const char *directory, const char *extension, int *numfiles
void FS_FreeFileList( char **list );
qboolean FS_FileExists( const char *file );
qboolean FS_FileExists_HomeData( const char *file );
qboolean FS_CreatePath (const char *OSPath);
@@ -633,14 +633,18 @@ int FS_GetModList( char *listbuf, int bufsize );
void FS_GetModDescription( const char *modDir, char *description, int descriptionLen );
fileHandle_t FS_FOpenFileWrite( const char *qpath );
fileHandle_t FS_FOpenFileAppend( const char *filename );
fileHandle_t FS_FOpenFileWrite_HomeConfig( const char *filename );
fileHandle_t FS_FOpenFileWrite_HomeData( const char *filename );
fileHandle_t FS_FOpenFileWrite_HomeState( const char *filename );
fileHandle_t FS_FOpenFileAppend_HomeData( const char *filename );
fileHandle_t FS_FCreateOpenPipeFile( const char *filename );
// will properly create any needed paths and deal with seperater character issues
fileHandle_t FS_BaseDir_FOpenFileWrite( const char *filename );
fileHandle_t FS_BaseDir_FOpenFileWrite_HomeConfig( const char *filename );
fileHandle_t FS_BaseDir_FOpenFileWrite_HomeData( const char *filename );
fileHandle_t FS_BaseDir_FOpenFileWrite_HomeState( const char *filename );
long FS_BaseDir_FOpenFileRead( const char *filename, fileHandle_t *fp );
void FS_BaseDir_Rename( const char *from, const char *to, qboolean safe );
void FS_BaseDir_Rename_HomeData( const char *from, const char *to, qboolean safe );
long FS_FOpenFileRead( const char *qpath, fileHandle_t *file, qboolean uniqueFILE );
// if uniqueFILE is true, then a new FILE will be fopened even if the file
// is found in an already open pak file. If uniqueFILE is false, you must call
@@ -725,7 +729,7 @@ qboolean FS_idPak(char *pak, char *base, int numPaks);
qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring );
void FS_Remove( const char *osPath );
void FS_HomeRemove( const char *homePath );
void FS_Remove_HomeData( const char *homePath );
void FS_FilenameCompletion( const char *dir, const char *ext, char *filter,
qboolean stripExt, void(*callback)(const char *s), qboolean allowNonPureFilesOnDisk );
@@ -1122,7 +1126,9 @@ char *Sys_MicrosoftStorePath(void);
char *Sys_DefaultAppPath(void);
#endif
char *Sys_DefaultHomePath(void);
char *Sys_DefaultHomeConfigPath(void);
char *Sys_DefaultHomeDataPath(void);
char *Sys_DefaultHomeStatePath(void);
const char *Sys_Dirname( char *path );
const char *Sys_Basename( char *path );
char *Sys_ConsoleInput(void);