summaryrefslogtreecommitdiff
path: root/src/qcommon/files.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/qcommon/files.c')
-rw-r--r--src/qcommon/files.c298
1 files changed, 167 insertions, 131 deletions
diff --git a/src/qcommon/files.c b/src/qcommon/files.c
index 302ce0fe..62617223 100644
--- a/src/qcommon/files.c
+++ b/src/qcommon/files.c
@@ -173,21 +173,6 @@ or configs will never get loaded from disk!
*/
-// every time a new demo pk3 file is built, this checksum must be updated.
-// the easiest way to get it is to just run the game and see what it spits out
-#define DEMO_PAK0_CHECKSUM 2985612116u
-static const unsigned pak_checksums[] = {
- 1566731103u,
- 298122907u,
- 412165236u,
- 2991495316u,
- 1197932710u,
- 4087071573u,
- 3709064859u,
- 908855077u,
- 977125798u
-};
-
// if this is defined, the executable positively won't work with any paks other
// than the demo pak, even if productid is present. This is only used for our
// last demo release to prevent the mac and linux users from using the demo
@@ -326,7 +311,7 @@ qboolean FS_PakIsPure( pack_t *pack ) {
for ( i = 0 ; i < fs_numServerPaks ; i++ ) {
// FIXME: also use hashed file names
// NOTE TTimo: a pk3 with same checksum but different name would be validated too
- // I don't see this as allowing for any exploit, it would only happen if the client does manips of it's file names 'not a bug'
+ // I don't see this as allowing for any exploit, it would only happen if the client does manips of its file names 'not a bug'
if ( pack->checksum == fs_serverPaks[i] ) {
return qtrue; // on the aproved list
}
@@ -538,57 +523,6 @@ static void FS_CheckFilenameIsNotExecutable( const char *filename,
}
}
-
-/*
-=================
-FS_CopyFile
-
-Copy a fully specified file from one place to another
-=================
-*/
-static void FS_CopyFile( char *fromOSPath, char *toOSPath ) {
- FILE *f;
- int len;
- byte *buf;
-
- Com_Printf( "copy %s to %s\n", fromOSPath, toOSPath );
-
- FS_CheckFilenameIsNotExecutable( toOSPath, __func__ );
-
- if (strstr(fromOSPath, "journal.dat") || strstr(fromOSPath, "journaldata.dat")) {
- Com_Printf( "Ignoring journal files\n");
- return;
- }
-
- f = fopen( fromOSPath, "rb" );
- if ( !f ) {
- return;
- }
- fseek (f, 0, SEEK_END);
- len = ftell (f);
- fseek (f, 0, SEEK_SET);
-
- // we are using direct malloc instead of Z_Malloc here, so it
- // probably won't work on a mac... Its only for developers anyway...
- buf = malloc( len );
- if (fread( buf, 1, len, f ) != len)
- Com_Error( ERR_FATAL, "Short read in FS_Copyfiles()\n" );
- fclose( f );
-
- if( FS_CreatePath( toOSPath ) ) {
- return;
- }
-
- f = fopen( toOSPath, "wb" );
- if ( !f ) {
- return;
- }
- if (fwrite( buf, 1, len, f ) != len)
- Com_Error( ERR_FATAL, "Short write in FS_Copyfiles()\n" );
- fclose( f );
- free( buf );
-}
-
/*
===========
FS_Remove
@@ -800,11 +734,7 @@ void FS_SV_Rename( const char *from, const char *to ) {
FS_CheckFilenameIsNotExecutable( to_ospath, __func__ );
- if (rename( from_ospath, to_ospath )) {
- // Failed, try copying it and deleting the original
- FS_CopyFile ( from_ospath, to_ospath );
- FS_Remove ( from_ospath );
- }
+ rename(from_ospath, to_ospath);
}
@@ -834,11 +764,7 @@ void FS_Rename( const char *from, const char *to ) {
FS_CheckFilenameIsNotExecutable( to_ospath, __func__ );
- if (rename( from_ospath, to_ospath )) {
- // Failed, try copying it and deleting the original
- FS_CopyFile ( from_ospath, to_ospath );
- FS_Remove ( from_ospath );
- }
+ rename(from_ospath, to_ospath);
}
/*
@@ -959,6 +885,52 @@ fileHandle_t FS_FOpenFileAppend( const char *filename ) {
/*
===========
+FS_FCreateOpenPipeFile
+
+===========
+*/
+fileHandle_t FS_FCreateOpenPipeFile( const char *filename ) {
+ char *ospath;
+ FILE *fifo;
+ fileHandle_t f;
+
+ if ( !fs_searchpaths ) {
+ Com_Error( ERR_FATAL, "Filesystem call made without initialization\n" );
+ }
+
+ f = FS_HandleForFile();
+ fsh[f].zipFile = qfalse;
+
+ Q_strncpyz( fsh[f].name, filename, sizeof( fsh[f].name ) );
+
+ // don't let sound stutter
+ S_ClearSoundBuffer();
+
+ ospath = FS_BuildOSPath( fs_homepath->string, fs_gamedir, filename );
+
+ if ( fs_debug->integer ) {
+ Com_Printf( "FS_FCreateOpenPipeFile: %s\n", ospath );
+ }
+
+ FS_CheckFilenameIsNotExecutable( ospath, __func__ );
+
+ fifo = Sys_Mkfifo( ospath );
+ if( fifo ) {
+ fsh[f].handleFiles.file.o = fifo;
+ fsh[f].handleSync = qfalse;
+ }
+ else
+ {
+ Com_Printf( S_COLOR_YELLOW "WARNING: Could not create new com_pipefile at %s. "
+ "com_pipefile will not be used.\n", ospath );
+ f = 0;
+ }
+
+ return f;
+}
+
+/*
+===========
FS_FilenameCompare
Ignore case and seprator char distinctions
@@ -995,6 +967,59 @@ qboolean FS_FilenameCompare( const char *s1, const char *s2 ) {
/*
===========
+FS_IsExt
+
+Return qtrue if ext matches file extension filename
+===========
+*/
+
+qboolean FS_IsExt(const char *filename, const char *ext, int namelen)
+{
+ int extlen;
+
+ extlen = strlen(ext);
+
+ if(extlen > namelen)
+ return qfalse;
+
+ filename += namelen - extlen;
+
+ return !Q_stricmp(filename, ext);
+}
+
+/*
+===========
+FS_IsDemoExt
+
+Return qtrue if filename has a demo extension
+===========
+*/
+
+qboolean FS_IsDemoExt(const char *filename, int namelen)
+{
+ char *ext_test;
+ int index, protocol;
+
+ ext_test = Q_strrchr(filename, '.');
+ if(ext_test && !Q_stricmpn(ext_test + 1, DEMOEXT, ARRAY_LEN(DEMOEXT) - 1))
+ {
+ protocol = atoi(ext_test + ARRAY_LEN(DEMOEXT));
+
+ if(protocol == PROTOCOL_VERSION)
+ return qtrue;
+
+ for(index = 0; demo_protocols[index]; index++)
+ {
+ if(demo_protocols[index] == protocol)
+ return qtrue;
+ }
+ }
+
+ return qfalse;
+}
+
+/*
+===========
FS_FOpenFileRead
Finds the file in the search path.
@@ -1014,7 +1039,6 @@ int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueF
long hash;
FILE *temp;
int l;
- char demoExt[16];
hash = 0;
@@ -1061,7 +1085,6 @@ int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueF
Com_Error( ERR_FATAL, "FS_FOpenFileRead: NULL 'filename' parameter passed\n" );
}
- Com_sprintf (demoExt, sizeof(demoExt), ".dm_%d",PROTOCOL_VERSION );
// qpaths are not supposed to have a leading slash
if ( filename[0] == '/' || filename[0] == '\\' ) {
filename++;
@@ -1106,16 +1129,19 @@ int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueF
// shaders, txt, arena files by themselves do not count as a reference as
// these are loaded from all pk3s
// from every pk3 file..
- l = strlen( filename );
- if ( !(pak->referenced & FS_GENERAL_REF)) {
- if ( Q_stricmp(filename + l - 7, ".shader") != 0 &&
- Q_stricmp(filename + l - 4, ".txt") != 0 &&
- Q_stricmp(filename + l - 4, ".cfg") != 0 &&
- Q_stricmp(filename + l - 7, ".config") != 0 &&
- strstr(filename, "levelshots") == NULL &&
- Q_stricmp(filename + l - 4, ".bot") != 0 &&
- Q_stricmp(filename + l - 6, ".arena") != 0 &&
- Q_stricmp(filename + l - 5, ".menu") != 0) {
+ l = strlen(filename);
+
+ if (!(pak->referenced & FS_GENERAL_REF))
+ {
+ if(!FS_IsExt(filename, ".shader", l) &&
+ !FS_IsExt(filename, ".txt", l) &&
+ !FS_IsExt(filename, ".cfg", l) &&
+ !FS_IsExt(filename, ".config", l) &&
+ !FS_IsExt(filename, ".bot", l) &&
+ !FS_IsExt(filename, ".arena", l) &&
+ !FS_IsExt(filename, ".menu", l) &&
+ !strstr(filename, "levelshots"))
+ {
pak->referenced |= FS_GENERAL_REF;
}
}
@@ -1166,13 +1192,14 @@ int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueF
// 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
- if ( fs_numServerPaks ) {
-
- if ( Q_stricmp( filename + l - 4, ".cfg" ) // for config files
- && Q_stricmp( filename + l - 5, ".menu" ) // menu files
- && Q_stricmp( filename + l - 5, ".game" ) // menu files
- && Q_stricmp( filename + l - strlen(demoExt), demoExt ) // menu files
- && Q_stricmp( filename + l - 4, ".dat" ) ) { // for journal files
+ if(fs_numServerPaks)
+ {
+ if(!FS_IsExt(filename, ".cfg", l) && // for config files
+ !FS_IsExt(filename, ".menu", l) && // menu files
+ !FS_IsExt(filename, ".game", l) && // menu files
+ !FS_IsExt(filename, ".cfg", l) && // for journal files
+ !FS_IsDemoExt(filename, l)) // demos
+ {
continue;
}
}
@@ -1206,6 +1233,32 @@ int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueF
}
+char *FS_FindDll( const char *filename ) {
+ searchpath_t *search;
+ directory_t *dir;
+
+ if ( !fs_searchpaths ) {
+ Com_Error( ERR_FATAL, "Filesystem call made without initialization\n" );
+ }
+
+ for ( search = fs_searchpaths ; search ; search = search->next ) {
+ if ( search->dir ) {
+ FILE *f;
+ char *netpath;
+
+ dir = search->dir;
+ netpath = FS_BuildOSPath( dir->path, dir->gamedir, filename );
+ f = fopen( netpath, "rb" );
+ if (f) {
+ fclose( f );
+ return netpath;
+ }
+ }
+ }
+
+ return NULL;
+}
+
/*
=================
FS_Read
@@ -1881,7 +1934,7 @@ Returns a uniqued list of files that match the given criteria
from all search paths
===============
*/
-char **FS_ListFilteredFiles( const char *path, const char *extension, char *filter, int *numfiles ) {
+char **FS_ListFilteredFiles( const char *path, const char *extension, char *filter, int *numfiles, qboolean allowNonPureFilesOnDisk ) {
int nfiles;
char **listCopy;
char *list[MAX_FOUND_FILES];
@@ -1977,7 +2030,7 @@ char **FS_ListFilteredFiles( const char *path, const char *extension, char *filt
char *name;
// don't scan directories for files if we are pure or restricted
- if ( fs_numServerPaks ) {
+ if ( fs_numServerPaks && !allowNonPureFilesOnDisk ) {
continue;
} else {
netpath = FS_BuildOSPath( search->dir->path, search->dir->gamedir, path );
@@ -2014,7 +2067,7 @@ FS_ListFiles
=================
*/
char **FS_ListFiles( const char *path, const char *extension, int *numfiles ) {
- return FS_ListFilteredFiles( path, extension, NULL, numfiles );
+ return FS_ListFilteredFiles( path, extension, NULL, numfiles, qfalse );
}
/*
@@ -2393,7 +2446,7 @@ void FS_NewDir_f( void ) {
Com_Printf( "---------------\n" );
- dirnames = FS_ListFilteredFiles( "", "", filter, &ndirs );
+ dirnames = FS_ListFilteredFiles( "", "", filter, &ndirs, qfalse );
FS_SortFileList(dirnames, ndirs);
@@ -2605,25 +2658,6 @@ void FS_AddGameDirectory( const char *path, const char *dir ) {
/*
================
-FS_idPak
-================
-*/
-qboolean FS_idPak( char *pak, char *base ) {
- int i;
-
- for (i = 0; i < NUM_ID_PAKS; i++) {
- if ( !FS_FilenameCompare(pak, va("%s/pak%d", base, i)) ) {
- break;
- }
- }
- if (i < NUM_ID_PAKS) {
- return qtrue;
- }
- return qfalse;
-}
-
-/*
-================
FS_CheckDirTraversal
Check whether the string contains stuff like "../" to prevent directory traversal bugs
@@ -2682,11 +2716,6 @@ qboolean FS_ComparePaks( char *neededpaks, int len, qboolean dlstring ) {
badchecksum = qfalse;
havepak = qfalse;
- // never autodownload any of the tremulous paks
- if ( FS_idPak(fs_serverReferencedPakNames[i], BASEGAME) ) {
- continue;
- }
-
// Make sure the server cannot make us write to non-quake3 directories.
if(FS_CheckDirTraversal(fs_serverReferencedPakNames[i]))
{
@@ -2863,13 +2892,13 @@ static void FS_Startup( const char *gameName )
fs_packFiles = 0;
fs_debug = Cvar_Get( "fs_debug", "0", 0 );
- fs_basepath = Cvar_Get ("fs_basepath", Sys_DefaultInstallPath(), CVAR_INIT );
+ 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 );
+ fs_homepath = Cvar_Get ("fs_homepath", homePath, CVAR_INIT|CVAR_PROTECTED );
fs_gamedirvar = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO );
// add search path elements in reverse priority order
@@ -2879,7 +2908,7 @@ static void FS_Startup( const char *gameName )
// fs_homepath is somewhat particular to *nix systems, only add if relevant
#ifdef MACOS_X
- fs_apppath = Cvar_Get ("fs_apppath", Sys_DefaultAppPath(), CVAR_INIT );
+ fs_apppath = Cvar_Get ("fs_apppath", Sys_DefaultAppPath(), CVAR_INIT|CVAR_PROTECTED );
// Make MacOSX also include the base path included with the .app bundle
if (fs_apppath->string[0])
FS_AddGameDirectory(fs_apppath->string, gameName);
@@ -2937,7 +2966,6 @@ static void FS_Startup( const char *gameName )
Com_Printf( "%d files in pk3 files\n", fs_packFiles );
}
-
/*
=====================
FS_GamePureChecksum
@@ -3256,7 +3284,7 @@ void FS_PureServerSetReferencedPaks( const char *pakSums, const char *pakNames )
fs_serverReferencedPaks[i] = atoi( Cmd_Argv( i ) );
}
- for (i = 0 ; i < sizeof(fs_serverReferencedPakNames) / sizeof(*fs_serverReferencedPakNames); i++)
+ for (i = 0 ; i < ARRAY_LEN(fs_serverReferencedPakNames); i++)
{
if(fs_serverReferencedPakNames[i])
Z_Free(fs_serverReferencedPakNames[i]);
@@ -3465,13 +3493,13 @@ void FS_Flush( fileHandle_t f ) {
}
void FS_FilenameCompletion( const char *dir, const char *ext,
- qboolean stripExt, void(*callback)(const char *s) ) {
+ qboolean stripExt, void(*callback)(const char *s), qboolean allowNonPureFilesOnDisk ) {
char **filenames;
int nfiles;
int i;
char filename[ MAX_STRING_CHARS ];
- filenames = FS_ListFilteredFiles( dir, ext, NULL, &nfiles );
+ filenames = FS_ListFilteredFiles( dir, ext, NULL, &nfiles, allowNonPureFilesOnDisk );
FS_SortFileList( filenames, nfiles );
@@ -3487,3 +3515,11 @@ void FS_FilenameCompletion( const char *dir, const char *ext,
}
FS_FreeFileList( filenames );
}
+
+const char *FS_GetCurrentGameDir(void)
+{
+ if(fs_gamedirvar->string[0])
+ return fs_gamedirvar->string;
+
+ return BASEGAME;
+}