/* * R_Bloom_InitTextures */ static void R_Bloom_InitTextures( void ) { qbyte *data; int size; if( glConfig.ext.texture_non_power_of_two ) { screen_texture_width = glState.width; screen_texture_height = glState.height; } else { // find closer power of 2 to screen size for (screen_texture_width = 1;screen_texture_width < glState.width;screen_texture_width <<= 1); for (screen_texture_height = 1;screen_texture_height < glState.height;screen_texture_height <<= 1); } // disable blooms if we can't handle a texture of that size if( screen_texture_width > glConfig.maxTextureSize || screen_texture_height > glConfig.maxTextureSize ) { screen_texture_width = screen_texture_height = 0; Cvar_ForceSet( "r_bloom", "0" ); Com_Printf( S_COLOR_YELLOW "WARNING: 'R_InitBloomScreenTexture' too high resolution for light bloom, effect disabled\n" ); return; } // init the screen texture size = screen_texture_width * screen_texture_height * 4; data = Mem_TempMalloc( size ); memset( data, 255, size ); r_bloomscreentexture = R_LoadPic( "***r_bloomscreentexture***", &data, screen_texture_width, screen_texture_height, IT_CLAMP|IT_NOMIPMAP|IT_NOCOMPRESS|IT_NOPICMIP, 3 ); Mem_TempFree( data ); // validate bloom size and init the bloom effect texture R_Bloom_InitEffectTexture(); // if screensize is more than 2x the bloom effect texture, set up for stepped downsampling r_bloomdownsamplingtexture = NULL; r_screendownsamplingtexture_size = 0; if( (glState.width > (BLOOM_SIZE * 2) || glState.height > (BLOOM_SIZE * 2)) && !r_bloom_fast_sample->integer ) { r_screendownsamplingtexture_size = (int)( BLOOM_SIZE * 2 ); data = Mem_TempMalloc( r_screendownsamplingtexture_size * r_screendownsamplingtexture_size * 4 ); memset( data, 0, r_screendownsamplingtexture_size * r_screendownsamplingtexture_size * 4 ); r_bloomdownsamplingtexture = R_LoadPic( "***r_bloomdownsamplingtexture***", &data, r_screendownsamplingtexture_size, r_screendownsamplingtexture_size, IT_CLAMP|IT_NOMIPMAP|IT_NOCOMPRESS|IT_NOPICMIP, 3 ); Mem_TempFree( data ); } // init the screen backup texture if( r_screendownsamplingtexture_size ) R_Bloom_InitBackUpTexture( r_screendownsamplingtexture_size, r_screendownsamplingtexture_size ); else R_Bloom_InitBackUpTexture( BLOOM_SIZE, BLOOM_SIZE ); }
/* * Con_Dump_f * * Save the console contents out to a file */ static void Con_Dump_f( void ) { int file; size_t buffer_size; char *buffer; size_t name_size; char *name; const char *newline = "\r\n"; if( !con_initialized ) return; if( Cmd_Argc() != 2 ) { Com_Printf( "usage: condump <filename>\n" ); return; } name_size = sizeof( char ) * ( strlen( Cmd_Argv( 1 ) ) + strlen( ".txt" ) + 1 ); name = Mem_TempMalloc( name_size ); Q_strncpyz( name, Cmd_Argv( 1 ), name_size ); COM_DefaultExtension( name, ".txt", name_size ); COM_SanitizeFilePath( name ); if( !COM_ValidateRelativeFilename( name ) ) { Com_Printf( "Invalid filename.\n" ); Mem_TempFree( name ); return; } if( FS_FOpenFile( name, &file, FS_WRITE ) == -1 ) { Com_Printf( "Couldn't open: %s\n", name ); Mem_TempFree( name ); return; } buffer_size = Con_BufferText( NULL, newline ) + 1; buffer = Mem_TempMalloc( buffer_size ); Con_BufferText( buffer, newline ); FS_Write( buffer, buffer_size - 1, file ); FS_FCloseFile( file ); Mem_TempFree( buffer ); Com_Printf( "Dumped console text: %s\n", name ); Mem_TempFree( name ); }
/* * Com_LoadScriptLibrary */ static void *Com_LoadScriptLibrary( const char *basename, void *parms ) { size_t file_size; char *file; void *( *GetAngelwrapAPI )(void *); dllfunc_t funcs[2]; if( script_library ) Com_Error( ERR_FATAL, "Com_LoadScriptLibrary without Com_UnloadScriptLibrary" ); file_size = strlen( LIB_DIRECTORY "/" ) + strlen( basename ) + 1 + strlen( ARCH ) + strlen( LIB_SUFFIX ) + 1; file = Mem_TempMalloc( file_size ); Q_snprintfz( file, file_size, LIB_DIRECTORY "/%s_" ARCH LIB_SUFFIX, basename ); funcs[0].name = "GetAngelwrapAPI"; funcs[0].funcPointer = ( void ** )&GetAngelwrapAPI; funcs[1].name = NULL; script_library = Com_LoadLibrary( file, funcs ); Mem_TempFree( file ); if( script_library ) return GetAngelwrapAPI( parms ); return NULL; }
/* * R_Bloom_InitEffectTexture */ static void R_Bloom_InitEffectTexture( void ) { qbyte *data; int limit; if( r_bloom_sample_size->integer < 32 ) Cvar_ForceSet( "r_bloom_sample_size", "32" ); // make sure bloom size doesn't have stupid values limit = min( r_bloom_sample_size->integer, min( screen_texture_width, screen_texture_height ) ); if( glConfig.ext.texture_non_power_of_two ) BLOOM_SIZE = limit; else // make sure bloom size is a power of 2 for( BLOOM_SIZE = 32; (BLOOM_SIZE<<1) <= limit; BLOOM_SIZE <<= 1 ); if( BLOOM_SIZE != r_bloom_sample_size->integer ) Cvar_ForceSet( "r_bloom_sample_size", va( "%i", BLOOM_SIZE ) ); data = Mem_TempMalloc( BLOOM_SIZE * BLOOM_SIZE * 4 ); memset( data, 0, BLOOM_SIZE * BLOOM_SIZE * 4 ); r_bloomeffecttexture = R_LoadPic( "***r_bloomeffecttexture***", &data, BLOOM_SIZE, BLOOM_SIZE, IT_CLAMP|IT_NOMIPMAP|IT_NOCOMPRESS|IT_NOPICMIP, 3 ); Mem_TempFree( data ); }
/* * CL_SetSoundExtension */ static char *CL_SetSoundExtension( const char *name ) { unsigned int i; char *finalname; size_t finalname_size, maxlen; const char *extension; assert( name ); if( COM_FileExtension( name ) ) return TempCopyString( name ); maxlen = 0; for( i = 0; i < NUM_SOUND_EXTENSIONS; i++ ) { if( strlen( SOUND_EXTENSIONS[i] ) > maxlen ) maxlen = strlen( SOUND_EXTENSIONS[i] ); } finalname_size = strlen( name ) + maxlen + 1; finalname = Mem_TempMalloc( finalname_size ); Q_strncpyz( finalname, name, finalname_size ); extension = FS_FirstExtension( finalname, SOUND_EXTENSIONS, NUM_SOUND_EXTENSIONS ); if( extension ) Q_strncatz( finalname, extension, finalname_size ); // if not found, we just pass it without the extension return finalname; }
/* * ML_Update */ bool ML_Update( void ) { int i, len, total, newpaks; size_t size; char *map, *maps, *filename; newpaks = FS_Rescan(); if( !newpaks ) return false; total = FS_GetFileListExt( "maps", ".bsp", NULL, &size, 0, 0 ); if( size ) { maps = ( char* )Mem_TempMalloc( size ); FS_GetFileList( "maps", ".bsp", maps, size, 0, 0 ); for( i = 0, len = 0; i < total; i++ ) { map = maps + len; len += strlen( map ) + 1; filename = ( char * )COM_FileBase( map ); COM_StripExtension( filename ); // don't check for existance of each file itself, as we've just got the fresh list if( !ML_FilenameExistsExt( filename, true ) ) ML_AddMap( filename, MLIST_UNKNOWN_MAPNAME ); } Mem_TempFree( maps ); } return true; }
/* * ML_GetFilename * Returns the filename for the map with the corresponding fullname */ const char *ML_GetFilenameExt( const char *fullname, bool recursive ) { mapinfo_t *map; trie_error_t err; char *fullname2; if( !ml_initialized ) return MLIST_NULL; if( !ML_ValidateFullname( fullname ) ) return MLIST_NULL; fullname2 = ( char* )Mem_TempMalloc( strlen( fullname ) + 1 ); strcpy( fullname2, fullname ); Q_strlwr( fullname2 ); err = Trie_Find( mlist_fullnames_trie, fullname2, TRIE_EXACT_MATCH, (void **)&map ); Mem_Free( fullname2 ); if( err == TRIE_OK ) return map->filename; // we should technically never get here, but // maybe the mapper has changed the fullname of the map // or the user has tampered with the mapcache // we need to reload the whole cache from file if we get here /* if( !recursive ) { ML_Restart( true ); return ML_GetFilenameExt( fullname, true ); } */ return MLIST_NULL; }
// callback for scandir int evdev_filter( const struct dirent *de ) { char *filename; int fd; // check that we have character file if( de->d_type != DT_CHR ) return 0; filename = Mem_TempMalloc( strlen( EVDEV_DIR ) + strlen( de->d_name ) + 1 ); strcpy( filename, EVDEV_DIR ); strcat( filename, de->d_name ); // open the file and see if we have a mouse fd = open( filename, O_RDONLY ); Mem_TempFree( filename ); if( fd != -1 ) { if( evdev_ismouse( fd ) ) { close( fd ); return 1; } close( fd ); } return 0; }
/* * CL_ReadServerCache */ void CL_ReadServerCache( void ) { int filelen, filehandle; qbyte *buf = NULL; char *ptr, *token; netadr_t adr; char adrString[64]; qboolean favorite = qfalse; filelen = FS_FOpenFile( SERVERSFILE, &filehandle, FS_READ ); if( !filehandle || filelen < 1 ) { FS_FCloseFile( filehandle ); } else { buf = Mem_TempMalloc( filelen + 1 ); filelen = FS_Read( buf, filelen, filehandle ); FS_FCloseFile( filehandle ); } if( !buf ) return; ptr = ( char * )buf; while( ptr ) { token = COM_ParseExt( &ptr, qtrue ); if( !token[0] ) break; if( !Q_stricmp( token, "master" ) ) { favorite = qfalse; continue; } if( !Q_stricmp( token, "favorites" ) ) { favorite = qtrue; continue; } if( NET_StringToAddress( token, &adr ) ) { Q_strncpyz( adrString, token, sizeof( adrString ) ); token = COM_ParseExt( &ptr, qfalse ); if( !token[0] ) continue; if( favorite ) CL_AddServerToList( &favoritesList, adrString, (unsigned int)atoi( token ) ); else CL_AddServerToList( &masterList, adrString, (unsigned int)atoi( token ) ); } } Mem_TempFree( buf ); }
/* * CL_SoundModule_Load * * Helper function to try loading sound module with certain name */ static bool CL_SoundModule_Load( const char *name, sound_import_t *import, bool verbose ) { int apiversion; size_t file_size; char *file; void *( *GetSoundAPI )(void *); dllfunc_t funcs[2]; if( verbose ) Com_Printf( "Loading sound module: %s\n", name ); file_size = strlen( LIB_DIRECTORY "/" LIB_PREFIX "snd_" ) + strlen( name ) + 1 + strlen( ARCH ) + strlen( LIB_SUFFIX ) + 1; file = Mem_TempMalloc( file_size ); Q_snprintfz( file, file_size, LIB_DIRECTORY "/" LIB_PREFIX "snd_%s_" ARCH LIB_SUFFIX, name ); funcs[0].name = "GetSoundAPI"; funcs[0].funcPointer = ( void ** )&GetSoundAPI; funcs[1].name = NULL; sound_library = Com_LoadLibrary( file, funcs ); Mem_TempFree( file ); if( !sound_library ) { Com_Printf( "Loading %s failed\n", name ); return false; } s_loaded = true; se = ( sound_export_t * )GetSoundAPI( import ); apiversion = se->API(); if( apiversion != SOUND_API_VERSION ) { CL_SoundModule_Shutdown( verbose ); Com_Printf( "Wrong module version for %s: %i, not %i\n", name, apiversion, SOUND_API_VERSION ); return false; } if( !se->Init( VID_GetWindowHandle(), MAX_EDICTS, verbose ) ) { CL_SoundModule_Shutdown( verbose ); Com_Printf( "Initialization of %s failed\n", name ); return false; } if( verbose ) Com_Printf( "Initialization of %s succesful\n", name ); return true; }
/* * SV_ReloadPureList */ static void SV_ReloadPureList( void ) { char **paks; int i, numpaks; Com_FreePureList( &svs.purelist ); // game modules if( sv_pure_forcemodulepk3->string[0] ) { if( Q_strnicmp( COM_FileBase( sv_pure_forcemodulepk3->string ), "modules", strlen( "modules" ) ) || !FS_IsPakValid( sv_pure_forcemodulepk3->string, NULL ) ) { Com_Printf( "Warning: Invalid value for sv_pure_forcemodulepk3, disabling\n" ); Cvar_ForceSet( "sv_pure_forcemodulepk3", "" ); } else { SV_AddPurePak( sv_pure_forcemodulepk3->string ); } } if( !sv_pure_forcemodulepk3->string[0] ) { char *libname; int libname_size; libname_size = strlen( LIB_PREFIX ) + 5 + strlen( ARCH ) + strlen( LIB_SUFFIX ) + 1; libname = Mem_TempMalloc( libname_size ); Q_snprintfz( libname, libname_size, LIB_PREFIX "game_" ARCH LIB_SUFFIX ); if( !FS_PakNameForFile( libname ) ) { if( sv_pure->integer ) { Com_Printf( "Warning: Game module not in pk3, disabling pure mode\n" ); Com_Printf( "sv_pure_forcemodulepk3 can be used to force the pure system to use a different module\n" ); Cvar_ForceSet( "sv_pure", "0" ); } } else { SV_AddPureFile( libname ); } Mem_TempFree( libname ); libname = NULL; } // *pure.(pk3|pak) paks = NULL; numpaks = FS_GetExplicitPurePakList( &paks ); if( numpaks ) { for( i = 0; i < numpaks; i++ ) { SV_AddPurePak( paks[i] ); Mem_ZoneFree( paks[i] ); } Mem_ZoneFree( paks ); } }
/* * R_Bloom_InitBackUpTexture */ static void R_Bloom_InitBackUpTexture( int width, int height ) { qbyte *data; data = Mem_TempMalloc( width * height * 4 ); memset( data, 0, width * height * 4 ); r_screenbackuptexture_width = width; r_screenbackuptexture_height = height; r_bloombackuptexture = R_LoadPic( "***r_bloombackuptexture***", &data, width, height, IT_CLAMP|IT_NOMIPMAP|IT_NOCOMPRESS|IT_NOPICMIP, 3 ); Mem_TempFree( data ); }
/* * Sys_FS_FindNext */ const char *Sys_FS_FindNext( unsigned musthave, unsigned canhave ) { struct dirent64 *d; assert( fdir ); assert( findbase && findpattern ); if( !fdir ) return NULL; while( ( d = readdir64( fdir ) ) != NULL ) { if( !CompareAttributes( d, findbase, musthave, canhave ) ) continue; if( fdots > 0 ) { // . and .. never match const char *base = COM_FileBase( d->d_name ); if( !strcmp( base, "." ) || !strcmp( base, ".." ) ) { fdots--; continue; } } if( !*findpattern || Com_GlobMatch( findpattern, d->d_name, 0 ) ) { const char *dname = d->d_name; size_t dname_len = strlen( dname ); size_t size = sizeof( char ) * ( findbase_size + dname_len + 1 + 1 ); if( findpath_size < size ) { if( findpath ) Mem_TempFree( findpath ); findpath_size = size * 2; // extra size to reduce reallocs findpath = Mem_TempMalloc( findpath_size ); } Q_snprintfz( findpath, findpath_size, "%s/%s%s", findbase, dname, dname[dname_len-1] != '/' && FS_DirentIsDir( d, findbase ) ? "/" : "" ); if( CompareAttributesForPath( d, findpath, musthave, canhave ) ) return findpath; } } return NULL; }
static int wswcurl_debug_callback( CURL *curl, curl_infotype infotype, char *buf, size_t buf_size, void *userp ) { char *temp; if( infotype != CURLINFO_TEXT ) { return 0; } temp = Mem_TempMalloc( buf_size + 1 ); memcpy( temp, buf, buf_size ); Com_Printf( "%s\n", temp ); Mem_TempFree( temp ); return 0; }
int evdev_scandevices( void ) { struct dirent **de; // list of pointers char *filename; char deviceName[256]; int n; if( m_evdev_fds ) { free( m_evdev_fds ); m_evdev_fds = 0; } m_evdev_num = 0; n = scandir( EVDEV_DIR, &de, evdev_filter, NULL ); if( n > 0 ) { m_evdev_fds = calloc( n, sizeof( *m_evdev_fds ) ); m_evdev_num = n; while( n-- ) { filename = Mem_TempMalloc( strlen( EVDEV_DIR ) + strlen( de[n]->d_name ) + 1 ); strcpy( filename, EVDEV_DIR ); strcat( filename, de[n]->d_name ); m_evdev_fds[n] = open( filename, O_RDONLY | O_NONBLOCK ); // some nice information about the device if( ioctl( m_evdev_fds[n], EVIOCGNAME(sizeof(deviceName)-1), deviceName) < 0 ) deviceName[0] = '\0'; Com_Printf( "Evdev: Found %s (%s)\n", deviceName, filename ); Mem_TempFree( filename ); free( de[n] ); } free( de ); } return m_evdev_num; }
/* * Sys_FS_FindFirst */ const char *Sys_FS_FindFirst( const char *path, unsigned musthave, unsigned canhave ) { char *p; assert( path ); assert( !fdir ); assert( fdfd == -1 ); assert( !findbase && !findpattern && !findpath && !findpath_size ); if( fdir ) Sys_Error( "Sys_BeginFind without close" ); findbase_size = strlen( path ); assert( findbase_size ); findbase_size += 1; findbase = Mem_TempMalloc( sizeof( char ) * findbase_size ); Q_strncpyz( findbase, path, sizeof( char ) * findbase_size ); if( ( p = strrchr( findbase, '/' ) ) ) { *p = 0; if( !strcmp( p+1, "*.*" ) ) // *.* to * *( p+2 ) = 0; findpattern = p+1; } else { findpattern = "*"; } if( !( fdir = opendir( findbase ) ) ) return NULL; fdfd = dirfd( fdir ); if( fdfd == -1 ) return NULL; fdots = 2; // . and .. return Sys_FS_FindNext( musthave, canhave ); }
/* * SV_AutoUpdateFromWeb */ void SV_AutoUpdateFromWeb( qboolean checkOnly ) { static const char *autoUpdateBaseUrl = APP_UPDATE_URL APP_SERVER_UPDATE_DIRECTORY; char checksumString1[32], checksumString2[32]; unsigned int checksum; qboolean success; int length, filenum; qbyte *data; const char *token, *ptr; char path[MAX_QPATH]; int downloadCount = 0, downloadFailed = 0; char newVersionTag[MAX_QPATH]; qboolean newVersion = qfalse; if( !dedicated->integer ) return; assert( svs.mapcmd[0] ); if( !checkOnly ) SV_UpdateActivity(); Com_Printf( "\n" ); Com_Printf( "========== Starting Auto Update ===========\n" ); Com_Printf( "Checking for updates\n" ); // download the update file list success = SV_WebDownload( autoUpdateBaseUrl, APP_SERVER_UPDATE_FILE, qtrue, qtrue ); // set as last updated today if( !checkOnly ) Cvar_ForceSet( "sv_lastAutoUpdate", va( "%i", (int)Com_DaysSince1900() ) ); if( !success ) // no update to do goto done; // read the file list if( ( length = FS_FOpenBaseFile( APP_SERVER_UPDATE_FILE, &filenum, FS_READ ) ) == -1 ) { Com_Printf( "WARNING: Couldn't find %s\n", path ); goto done; } if( !length ) { FS_FCloseFile( filenum ); goto done; } data = Mem_TempMalloc( length + 1 ); FS_Read( data, length, filenum ); FS_FCloseFile( filenum ); FS_RemoveBaseFile( APP_SERVER_UPDATE_FILE ); ptr = (const char *)data; // first token is always the current release version token = COM_ParseExt( &ptr, qtrue ); if( !token[0] ) goto cancel; // compare versions Q_strncpyz( newVersionTag, token, sizeof( newVersionTag ) ); if( atof( newVersionTag ) > atof( va( "%4.3f", APP_VERSION ) ) ) newVersion = qtrue; while( ptr ) { // we got what should be a checksum token = COM_ParseExt( &ptr, qtrue ); if( !token[0] ) goto cancel; // copy checksum reported by server Q_strncpyz( checksumString1, token, sizeof( checksumString1 ) ); // get filename token = COM_ParseExt( &ptr, qtrue ); if( !token[0] ) goto cancel; // filename should never begin with a slash if( token[0] == '/' ) token++; Q_strncpyz( path, token, sizeof( path ) ); // we got what should be a file path if( !COM_ValidateRelativeFilename( path ) ) { Com_Printf( "WARNING: Invalid filename %s\n", path ); continue; } checksum = FS_ChecksumBaseFile( path ); Q_snprintfz( checksumString2, sizeof( checksumString2 ), "%u", checksum ); // if same checksum no need to update if( !strcmp( checksumString1, checksumString2 ) ) continue; // if it's a pack file and the file exists it can't be replaced, so skip if( FS_CheckPakExtension( path ) && checksum ) { Com_Printf( "WARNING: Purity check failed for: %s\n", path ); Com_Printf( "WARNING: This file has been locally modified. It is highly \n" ); Com_Printf( "WARNING: recommended to restore the original file.\n" ); Com_Printf( "WARNING: Reinstalling \""APPLICATION"\" might be convenient.\n" ); continue; } if( checkOnly ) { Com_Printf( "File update available : %s\n", path ); continue; } if( developer->integer ) Com_Printf( "Downloading update of %s (checksum %s local checksum %s)\n", path, checksumString1, checksumString2 ); else Com_Printf( "Updating %s\n", path ); if( !SV_WebDownload( autoUpdateBaseUrl, path, qtrue, qtrue ) ) { Com_Printf( "Failed to update %s\n", path ); downloadFailed++; } downloadCount++; } cancel: Mem_TempFree( data ); done: if( newVersion ) { if( downloadCount ) { if( downloadFailed ) Com_Printf( "This version of "APPLICATION" was updated incompletely\n" ); else Com_Printf( "This version of "APPLICATION" was updated successfully\n\n" ); } Com_Printf( "****** Version %s of "APPLICATION" is available. ******\n", newVersionTag ); Com_Printf( "****** Please download the new version at "APP_URL" ******\n" ); } else if( downloadCount ) { if( downloadFailed ) Com_Printf( APPLICATION" was updated incompletely\n" ); else Com_Printf( APPLICATION" was updated successfully\n" ); } else if( !checkOnly ) { if( downloadFailed ) Com_Printf( "At least one file failed to update\n" ); else Com_Printf( APPLICATION" is up to date\n" ); } Com_Printf( "========== Auto Update Finished ===========\n" ); Com_Printf( "\n" ); // update the map list, which also does a filesystem rescan ML_Update(); // if there are any new filesystem entries, restart if( FS_GetNotifications() & FS_NOTIFT_NEWPAKS ) { if( sv.state != ss_dead ) { // restart the current map, SV_Map also rescans the filesystem Com_Printf( "The server will now restart...\n\n" ); // start the default map if current map isn't available Cbuf_ExecuteText( EXEC_APPEND, va( "map %s\n", svs.mapcmd[0] ? svs.mapcmd : sv_defaultmap->string ) ); } } }
/* * SV_WebDownload */ static qboolean SV_WebDownload( const char *baseUrl, const char *filepath, qboolean overwrite, qboolean silent ) { qboolean success; int alloc_size; char *temppath, *writepath, *url; if( developer->integer ) silent = qfalse; if( !baseUrl || !baseUrl[0] || !filepath ) return qfalse; if( !strrchr( baseUrl, '/' ) ) { if( !silent ) Com_Printf( "SV_WebDownload: Invalid URL\n" ); return qfalse; } if( filepath[0] == '/' ) // filepath should never begin with a slash filepath++; if( !COM_ValidateRelativeFilename( filepath ) ) { if( !silent ) Com_Printf( "SV_WebDownload: Invalid filename\n" ); return qfalse; } if( !COM_FileExtension( filepath ) ) { if( !silent ) Com_Printf( "SV_WebDownload: no file extension\n" ); return qfalse; } // full url (baseurl + path) alloc_size = strlen( baseUrl ) + 1 + strlen( filepath ) + 1; url = Mem_TempMalloc( alloc_size ); if( baseUrl[ strlen( baseUrl ) - 1 ] == '/' ) // url includes last slash Q_snprintfz( url, alloc_size, "%s%s", baseUrl, filepath ); else Q_snprintfz( url, alloc_size, "%s/%s", baseUrl, filepath ); // add .tmp (relative + .tmp) alloc_size = strlen( filepath ) + strlen( ".tmp" ) + 1; temppath = Mem_TempMalloc( alloc_size ); Q_snprintfz( temppath, alloc_size, "%s.tmp", filepath ); // full write path for curl alloc_size = strlen( FS_WriteDirectory() ) + 1 + strlen( temppath ) + 1; writepath = Mem_TempMalloc( alloc_size ); Q_snprintfz( writepath, alloc_size, "%s/%s", FS_WriteDirectory(), temppath ); webDownloadPercentPrint = 0; webDownloadPercentStarted = qfalse; success = Web_Get( url, NULL, writepath, qtrue, 60 * 30, 60, SV_WebDownloadProgress, qfalse ); if( webDownloadPercentStarted ) Com_Printf( "\n" ); if( !success ) { if( !silent ) Com_Printf( "Failed to download remote file.\n" ); goto failed; } // rename the downloaded file if( !FS_MoveBaseFile( temppath, filepath ) ) { if( !overwrite ) { if( !silent ) Com_Printf( "Failed to rename temporary file.\n" ); goto failed; } // check if it failed because there already exists a file with the same name // and in this case remove this file if( FS_FOpenBaseFile( filepath, NULL, FS_READ ) != -1 ) { char *backfile; alloc_size = strlen( filepath ) + strlen( ".bak" ) + 1; backfile = Mem_TempMalloc( alloc_size ); Q_snprintfz( backfile, alloc_size, "%s.bak", filepath ); // if there is already a .bak file, destroy it if( FS_FOpenBaseFile( backfile, NULL, FS_READ ) != -1 ) FS_RemoveBaseFile( backfile ); // move the current file into .bak file if( !FS_MoveBaseFile( filepath, backfile ) ) { Mem_TempFree( backfile ); if( !silent ) Com_Printf( "Failed to backup destination file.\n" ); goto failed; } // now try renaming the downloaded file again if( !FS_MoveBaseFile( temppath, filepath ) ) { // didn't work, so restore the backup file if( FS_MoveBaseFile( backfile, filepath ) ) { if( !silent ) Com_Printf( "Failed to rename temporary file, restoring from backup.\n" ); } else { if( !silent ) Com_Printf( "Failed to rename temporary file and restore from backup.\n" ); } Mem_TempFree( backfile ); goto failed; } Mem_TempFree( backfile ); } } Mem_TempFree( temppath ); Mem_TempFree( writepath ); Mem_TempFree( url ); return qtrue; failed: if( !silent ) Com_Printf( "Removing temporary file: %s\n", writepath ); FS_RemoveAbsoluteFile( writepath ); Mem_TempFree( temppath ); Mem_TempFree( writepath ); Mem_TempFree( url ); return qfalse; }
/* * CM_LoadMapMessage */ char *CM_LoadMapMessage( char *name, char *message, int size ) { int file, len; qbyte h_v[8]; char *data, *entitystring; lump_t l; qboolean isworld; char key[MAX_KEY], value[MAX_VALUE], *token; const modelFormatDescr_t *descr; const bspFormatDesc_t *bspFormat = NULL; *message = '\0'; len = FS_FOpenFile( name, &file, FS_READ ); if( !file || len < 1 ) { if( file ) FS_FCloseFile( file ); return message; } FS_Read( h_v, 4 + sizeof( int ), file ); descr = Q_FindFormatDescriptor( cm_supportedformats, h_v, &bspFormat ); if( !descr ) { Com_Printf( "CM_LoadMapMessage: %s: unknown bsp format\n", name ); FS_FCloseFile( file ); return message; } FS_Seek( file, descr->headerLen + sizeof( int ) + sizeof( lump_t ) * bspFormat->entityLumpNum, FS_SEEK_SET ); FS_Read( &l.fileofs, sizeof( l.fileofs ), file ); l.fileofs = LittleLong( l.fileofs ); FS_Read( &l.filelen, sizeof( l.filelen ), file ); l.filelen = LittleLong( l.filelen ); if( !l.filelen ) { FS_FCloseFile( file ); return message; } FS_Seek( file, l.fileofs, FS_SEEK_SET ); entitystring = Mem_TempMalloc( l.filelen ); FS_Read( entitystring, l.filelen, file ); FS_FCloseFile( file ); for( data = entitystring; ( token = COM_Parse( &data ) ) && token[0] == '{'; ) { isworld = qtrue; while( 1 ) { token = COM_Parse( &data ); if( !token[0] || token[0] == '}' ) break; // end of entity Q_strncpyz( key, token, sizeof( key ) ); while( key[strlen( key )-1] == ' ' ) // remove trailing spaces key[strlen( key )-1] = 0; token = COM_Parse( &data ); if( !token[0] ) break; // error Q_strncpyz( value, token, sizeof( value ) ); // now that we have the key pair worked out... if( !strcmp( key, "classname" ) ) { if( strcmp( value, "worldspawn" ) ) isworld = qfalse; } else if( !strcmp( key, "message" ) ) { Q_strncpyz( message, token, size ); break; } } if( isworld ) break; } Mem_Free( entitystring ); return message; }
/* * CM_LoadMap * Loads in the map and all submodels * * for spawning a server with no map at all, call like this: * CM_LoadMap( "", qfalse, &checksum ); // no real map */ cmodel_t *CM_LoadMap( cmodel_state_t *cms, const char *name, qboolean clientload, unsigned *checksum ) { int length; unsigned *buf; char *header; const modelFormatDescr_t *descr; bspFormatDesc_t *bspFormat = NULL; assert( cms ); assert( name && strlen( name ) < MAX_CONFIGSTRING_CHARS ); assert( checksum ); cms->map_clientload = clientload; if( !strcmp( cms->map_name, name ) && ( clientload || !Cvar_Value( "flushmap" ) ) ) { *checksum = cms->checksum; if( !clientload ) { memset( cms->map_areaportals, 0, cms->numareas * cms->numareas * sizeof( *cms->map_areaportals ) ); CM_FloodAreaConnections( cms ); } return cms->map_cmodels; // still have the right version } CM_Clear( cms ); if( !name || !name[0] ) { cms->numleafs = 1; cms->numcmodels = 2; *checksum = 0; return cms->map_cmodels; // cinematic servers won't have anything at all } // // load the file // length = FS_LoadFile( name, ( void ** )&buf, NULL, 0 ); if( !buf ) Com_Error( ERR_DROP, "Couldn't load %s", name ); cms->checksum = Com_MD5Digest32( ( const qbyte * )buf, length ); *checksum = cms->checksum; // call the apropriate loader descr = Q_FindFormatDescriptor( cm_supportedformats, ( const qbyte * )buf, (const bspFormatDesc_t **)&bspFormat ); if( !descr ) Com_Error( ERR_DROP, "CM_LoadMap: unknown fileid for %s", name ); if( !bspFormat ) Com_Error( ERR_DROP, "CM_LoadMap: %s: unknown bsp format" ); // copy header into temp variable to be saveed in a cvar header = Mem_TempMalloc( descr->headerLen + 1 ); memcpy( header, buf, descr->headerLen ); header[descr->headerLen] = '\0'; // store map format description in cvars Cvar_ForceSet( "cm_mapHeader", header ); Cvar_ForceSet( "cm_mapVersion", va( "%i", LittleLong( *((int *)((qbyte *)buf + descr->headerLen)) ) ) ); Mem_TempFree( header ); descr->loader( cms, NULL, buf, bspFormat ); CM_InitBoxHull( cms ); CM_InitOctagonHull( cms ); if( cms->numareas ) { cms->map_areas = Mem_Alloc( cms->mempool, cms->numareas * sizeof( *cms->map_areas ) ); cms->map_areaportals = Mem_Alloc( cms->mempool, cms->numareas * cms->numareas * sizeof( *cms->map_areaportals ) ); memset( cms->map_areaportals, 0, cms->numareas * cms->numareas * sizeof( *cms->map_areaportals ) ); CM_FloodAreaConnections( cms ); } memset( cms->nullrow, 255, MAX_CM_LEAFS / 8 ); Q_strncpyz( cms->map_name, name, sizeof( cms->map_name ) ); return cms->map_cmodels; }
/* * ML_InitFromCache * Fills map list array from cache, much faster */ static void ML_InitFromCache( void ) { int count, i, total, len; size_t size = 0; char *buffer, *chr, *current, *curend; char *temp, *maps, *map; mapdir_t *dir, *curmap, *prev; if( ml_initialized ) return; total = FS_GetFileListExt( "maps", ".bsp", NULL, &size, 0, 0 ); if( !total ) return; // load maps from directory reading into a list maps = temp = ( char* )Mem_TempMalloc( size + sizeof( mapdir_t ) * total ); temp += size; FS_GetFileList( "maps", ".bsp", maps, size, 0, 0 ); len = 0; prev = NULL; dir = NULL; for( i = 0; i < total; i++ ) { map = maps + len; len += strlen( map ) + 1; curmap = ( mapdir_t * )temp; temp += sizeof( mapdir_t ); COM_StripExtension( map ); if( !i ) dir = curmap; else { prev->next = curmap; curmap->prev = prev; } curmap->filename = map; prev = curmap; } FS_LoadCacheFile( MLIST_CACHE, (void **)&buffer, NULL, 0 ); if( !buffer ) { Mem_TempFree( maps ); return; } current = curend = buffer; count = 0; for( chr = buffer; *chr; chr++ ) { // current character is a delimiter if( *chr == '\n' ) { if( *(chr-1) == '\r' ) *(chr-1) = '\0'; // clear the CR too *chr = '\0'; // clear the LF // if we have got both params if( !( ++count & 1 ) ) { // check if its in the maps directory for( curmap = dir; curmap; curmap = curmap->next ) { if( !Q_stricmp( curmap->filename, current ) ) { if( curmap->prev ) curmap->prev->next = curmap->next; else dir = curmap->next; if( curmap->next ) curmap->next->prev = curmap->prev; break; } } // if we found it in the maps directory if( curmap ) { COM_SanitizeFilePath( current ); // well, if we've got a map with an unknown fullname, load it from map if( !strcmp( curend + 1, MLIST_UNKNOWN_MAPNAME ) ) ML_AddMap( current, NULL ); else ML_AddMap( current, curend + 1 ); } current = chr + 1; } else curend = chr; } } // we've now loaded the mapcache, but there may be files which // have been added to maps directory, and the mapcache isnt aware // these will be left over in our directory list for( curmap = dir; curmap; curmap = curmap->next ) ML_AddMap( curmap->filename, NULL ); Mem_TempFree( maps ); FS_FreeFile( buffer ); }
/* * TV_Upstream_NextDemo */ void TV_Upstream_NextDemo( const char *demoname, const char *curdemo, qboolean randomize, char **name, char **filepath ) { int i, j, total; size_t bufsize, len, dir_size; char *file, *buf, **match, *dir; const char *extension, *pattern, *p; *name = *filepath = NULL; assert( demoname ); assert( *demoname ); buf = NULL; bufsize = 0; total = 0; // check if user specified a demo pattern (e.g. "tutorials/*.wd10") or a demolist filename extension = COM_FileExtension( demoname ); if( extension && !Q_stricmp( extension, APP_DEMO_EXTENSION_STR ) ) pattern = demoname; else pattern = ""; dir_size = strlen( "demos" ) + strlen( pattern ) + 1; dir = Mem_TempMalloc( dir_size ); strcpy( dir, "demos" ); if( *pattern ) { // find first character that looks like a wildcard const char *last_slash = NULL; p = pattern; do { if( *p == '/' ) last_slash = p; else if( *p == '?' || *p == '*' || *p == '[' ) break; } while( *++p ); // append the path part of wildcard to dir and shift the pattern if( last_slash ) { Q_strncatz( dir, "/", dir_size ); Q_strncatz( dir, pattern, strlen( dir ) + (last_slash - pattern) + 1 ); pattern = last_slash + 1; } bufsize = 0; total = FS_GetFileListExt( dir, APP_DEMO_EXTENSION_STR, NULL, &bufsize, 0, 0 ); if( !total ) bufsize = 0; if( bufsize ) { buf = Mem_TempMalloc( bufsize ); FS_GetFileList( dir, APP_DEMO_EXTENSION_STR, buf, bufsize, 0, 0 ); } } else { // load demolist file and pick next available demo int filehandle = 0, filelen = -1; // load list from file filelen = FS_FOpenFile( demoname, &filehandle, FS_READ ); if( filehandle && filelen > 0 ) { bufsize = (size_t)(filelen + 1); buf = Mem_TempMalloc( bufsize ); FS_Read( buf, filelen, filehandle ); FS_FCloseFile( filehandle ); } // parse the list stripping CRLF characters if( buf ) { p = strtok( buf, "\r\n" ); if( p ) { char *newbuf; size_t newbufsize; newbufsize = 0; newbuf = Mem_TempMalloc( bufsize ); while( p != NULL ) { total++; Q_strncpyz( newbuf + newbufsize, p, bufsize - newbufsize ); newbufsize += strlen( p ) + 1; p = strtok( NULL, "\r\n" ); } Mem_TempFree( buf ); buf = newbuf; } } } if( buf ) { int next; // get the list of demo files match = Mem_TempMalloc( total * sizeof( char * ) ); total = 0; next = (randomize ? -1 : 0); for( len = 0; buf[len]; ) { file = buf + len; len += strlen( file ) + 1; if( *pattern ) { if( !Com_GlobMatch( pattern, file, qfalse ) ) continue; } // avoid replays if( curdemo && !Q_stricmp( file, curdemo ) ) { // if ordered, schedule the next map if( !randomize ) next = total; continue; } match[total++] = file; } // pick a new random demo if possible or otherwise try the old one if( total ) { if( next < 0 ) next = rand() % total; // walk the list until we find an existing file // in case of pattern match, the check is not necessary though for( i = 0; i < total; i++ ) { j = (i + next) % total; if( !*pattern ) { extension = COM_FileExtension( match[j] ); if( FS_FOpenFile( va( "demos/%s%s", match[j], (extension ? "" : APP_DEMO_EXTENSION_STR) ), NULL, FS_READ ) == -1 ) continue; } *name = TempCopyString( match[j] ); break; } } // fallback to current demo if( !*name && curdemo ) *name = TempCopyString( curdemo ); Mem_TempFree( match ); // append the dir to filename, sigh.. if( *name ) { size_t filepath_size; filepath_size = strlen( dir ) + strlen( "/" ) + strlen( *name ) + strlen( APP_DEMO_EXTENSION_STR ) + 1; *filepath = Mem_TempMalloc( filepath_size ); strcpy( *filepath, dir ); strcat( *filepath, "/" ); strcat( *filepath, *name ); COM_DefaultExtension( *filepath, APP_DEMO_EXTENSION_STR, filepath_size ); } Mem_TempFree( buf ); } Mem_TempFree( dir ); }
/* * Com_LoadGameLibrary */ void *Com_LoadGameLibrary( const char *basename, const char *apifuncname, void **handle, void *parms, bool pure, char *manifest ) { static int randomizer = 0; // random part of tempmodules dir, always the same for one launch of Warsow static int64_t randomizer_time; const char *temppath; char *tempname, *libname; int libname_size; void *( *APIfunc )(void *); gamelib_t *gamelib; *handle = 0; if( !randomizer ) { randomizer_time = time( NULL ); srand( randomizer_time ); randomizer = brandom( 1, 9999 ); } gamelib = ( gamelib_t* )Mem_ZoneMalloc( sizeof( gamelib_t ) ); gamelib->lib = NULL; gamelib->fullname = NULL; libname_size = strlen( LIB_PREFIX ) + strlen( basename ) + 1 + strlen( ARCH ) + strlen( LIB_SUFFIX ) + 1; libname = ( char* )Mem_TempMalloc( libname_size ); Q_snprintfz( libname, libname_size, LIB_PREFIX "%s_" ARCH LIB_SUFFIX, basename ); // it exists? if( FS_FOpenFile( libname, NULL, FS_READ ) == -1 ) { Com_Printf( "LoadLibrary (%s):(File not found)\n", libname ); Mem_TempFree( libname ); Mem_ZoneFree( gamelib ); return NULL; } // pure check if( pure && !FS_IsPureFile( libname ) ) { Com_Printf( "LoadLibrary (%s):(Unpure file)\n", libname ); Mem_TempFree( libname ); Mem_ZoneFree( gamelib ); return NULL; } temppath = Sys_Library_GetGameLibPath( libname, randomizer_time, randomizer ); tempname = ( char * )Mem_ZoneMalloc( strlen( temppath ) + 1 ); strcpy( tempname, temppath ); if( FS_FOpenFile( tempname, NULL, FS_READ ) == -1 ) { if( !FS_ExtractFile( libname, tempname ) ) { Com_Printf( "LoadLibrary (%s):(FS_ExtractFile failed)\n", libname ); Mem_TempFree( libname ); Mem_ZoneFree( tempname ); Mem_ZoneFree( gamelib ); return NULL; } } gamelib->fullname = COM_SanitizeFilePath( tempname ); gamelib->lib = Sys_Library_Open( gamelib->fullname ); gamelib->next = gamelibs; gamelibs = gamelib; if( !( gamelib->lib ) ) { Com_Printf( "LoadLibrary (%s):(%s)\n", tempname, Sys_Library_ErrorString() ); Mem_TempFree( libname ); Com_UnloadGameLibrary( (void **)&gamelib ); return NULL; } APIfunc = ( void* ( * )( void* ) )Sys_Library_ProcAddress( gamelib->lib, apifuncname ); if( !APIfunc ) { Com_Printf( "LoadLibrary (%s):(%s)\n", tempname, Sys_Library_ErrorString() ); Mem_TempFree( libname ); Com_UnloadGameLibrary( (void **)&gamelib ); return NULL; } *handle = gamelib; if( manifest ) Com_LoadGameLibraryManifest( libname, manifest ); Mem_TempFree( libname ); return APIfunc( parms ); }
/* * Com_Printf * * Both client and server can use this, and it will output * to the apropriate place. */ void Com_Printf( const char *format, ... ) { va_list argptr; char msg[MAX_PRINTMSG]; time_t timestamp; char timestamp_str[MAX_PRINTMSG]; struct tm *timestampptr; timestamp = time( NULL ); timestampptr = gmtime( ×tamp ); strftime( timestamp_str, MAX_PRINTMSG, "%Y-%m-%dT%H:%M:%SZ ", timestampptr ); va_start( argptr, format ); Q_vsnprintfz( msg, sizeof( msg ), format, argptr ); va_end( argptr ); if( rd_target ) { if( (int)( strlen( msg ) + strlen( rd_buffer ) ) > ( rd_buffersize - 1 ) ) { rd_flush( rd_target, rd_buffer, rd_extra ); *rd_buffer = 0; } strcat( rd_buffer, msg ); return; } QMutex_Lock( com_print_mutex ); Con_Print( msg ); // also echo to debugging console Sys_ConsoleOutput( msg ); // logconsole if( logconsole && logconsole->modified ) { logconsole->modified = qfalse; if( log_file ) { FS_FCloseFile( log_file ); log_file = 0; } if( logconsole->string && logconsole->string[0] ) { size_t name_size; char *name; name_size = strlen( logconsole->string ) + strlen( ".log" ) + 1; name = ( char* )Mem_TempMalloc( name_size ); Q_strncpyz( name, logconsole->string, name_size ); COM_DefaultExtension( name, ".log", name_size ); if( FS_FOpenFile( name, &log_file, ( logconsole_append && logconsole_append->integer ? FS_APPEND : FS_WRITE ) ) == -1 ) { log_file = 0; Com_Printf( "Couldn't open: %s\n", name ); } Mem_TempFree( name ); } } if( log_file ) { if( logconsole_timestamp && logconsole_timestamp->integer ) FS_Printf( log_file, "%s", timestamp_str ); FS_Printf( log_file, "%s", msg ); if( logconsole_flush && logconsole_flush->integer ) FS_Flush( log_file ); // force it to save every time } QMutex_Unlock( com_print_mutex ); }
/* * SV_BeginDownload_f * Responds to reliable download packet with reliable initdownload packet */ static void SV_BeginDownload_f( client_t *client ) { const char *requestname; const char *uploadname; size_t alloc_size; unsigned checksum; char *url; const char *errormsg = NULL; qboolean allow, requestpak; qboolean local_http = SV_Web_Running() && sv_uploads_http->integer != 0; requestpak = ( atoi( Cmd_Argv( 1 ) ) == 1 ); requestname = Cmd_Argv( 2 ); if( !requestname[0] || !COM_ValidateRelativeFilename( requestname ) ) { SV_DenyDownload( client, "Invalid filename" ); return; } if( !SV_FilenameForDownloadRequest( requestname, requestpak, &uploadname, &errormsg ) ) { assert( errormsg != NULL ); SV_DenyDownload( client, errormsg ); return; } if( FS_CheckPakExtension( uploadname ) ) { allow = qfalse; // allow downloading paks from the pure list, if not spawned if( client->state < CS_SPAWNED ) { purelist_t *purefile; purefile = svs.purelist; while( purefile ) { if( !strcmp( uploadname, purefile->filename ) ) { allow = qtrue; break; } purefile = purefile->next; } } // game module has a change to allow extra downloads if( !allow && !SV_GameAllowDownload( client, requestname, uploadname ) ) { SV_DenyDownload( client, "Downloading of this file is not allowed" ); return; } } else { if( !SV_GameAllowDownload( client, requestname, uploadname ) ) { SV_DenyDownload( client, "Downloading of this file is not allowed" ); return; } } // we will just overwrite old download, if any if( client->download.name ) { if( client->download.data ) { FS_FreeBaseFile( client->download.data ); client->download.data = NULL; } Mem_ZoneFree( client->download.name ); client->download.name = NULL; client->download.size = 0; client->download.timeout = 0; } client->download.size = FS_LoadBaseFile( uploadname, NULL, NULL, 0 ); if( client->download.size == -1 ) { Com_Printf( "Error getting size of %s for uploading\n", uploadname ); client->download.size = 0; SV_DenyDownload( client, "Error getting file size" ); return; } checksum = FS_ChecksumBaseFile( uploadname ); client->download.timeout = svs.realtime + 1000 * 60 * 60; // this is web download timeout alloc_size = sizeof( char ) * ( strlen( uploadname ) + 1 ); client->download.name = Mem_ZoneMalloc( alloc_size ); Q_strncpyz( client->download.name, uploadname, alloc_size ); Com_Printf( "Offering %s to %s\n", client->download.name, client->name ); if( FS_CheckPakExtension( uploadname ) && ( local_http || sv_uploads_baseurl->string[0] != 0 ) ) { // .pk3 and .pak download from the web if( local_http ) { url = TempCopyString( va( "files/%s", uploadname ) ); } else { alloc_size = sizeof( char ) * ( strlen( sv_uploads_baseurl->string ) + 1 ); url = Mem_TempMalloc( alloc_size ); Q_snprintfz( url, alloc_size, "%s/", sv_uploads_baseurl->string ); } } else if( SV_IsDemoDownloadRequest( requestname ) && ( local_http || sv_uploads_demos_baseurl->string[0] != 0 ) ) { // demo file download from the web if( local_http ) { url = TempCopyString( va( "files/%s", uploadname ) ); } else { alloc_size = sizeof( char ) * ( strlen( sv_uploads_demos_baseurl->string ) + 1 ); url = Mem_TempMalloc( alloc_size ); Q_snprintfz( url, alloc_size, "%s/", sv_uploads_demos_baseurl->string ); } } else { url = NULL; } // start the download SV_InitClientMessage( client, &tmpMessage, NULL, 0 ); SV_SendServerCommand( client, "initdownload \"%s\" %i %u %i \"%s\"", client->download.name, client->download.size, checksum, local_http ? 1 : 0, ( url ? url : "" ) ); SV_AddReliableCommandsToMessage( client, &tmpMessage ); SV_SendMessageToClient( client, &tmpMessage ); if( url ) { Mem_TempFree( url ); url = NULL; } }
/* * TV_Upstream_ParseConfigstringCommand_f */ static void TV_Upstream_HandleConfigstring( upstream_t *upstream, int index, const char *val ) { char hostname[MAX_CONFIGSTRING_CHARS]; msg_t msg; qbyte msgbuf[MAX_MSGLEN]; if( !val || !val[0] ) return; if( index < 0 || index >= MAX_CONFIGSTRINGS ) TV_Upstream_Error( upstream, "configstring > MAX_CONFIGSTRINGS" ); Q_strncpyz( upstream->configstrings[index], val, sizeof( upstream->configstrings[index] ) ); if( index == CS_AUTORECORDSTATE ) { // don't do a thing until we receive a "precache" command if( upstream->precacheDone ) TV_Upstream_AutoRecordAction( upstream, upstream->configstrings[CS_AUTORECORDSTATE] ); return; } if( index != CS_HOSTNAME ) return; if( !upstream->demo.playing ) { TV_Upstream_SetName( upstream, val ); return; } // demos often come with generic hostnames, attempt to workaround that if( !Q_stricmp( val, APPLICATION " server" ) ) { char *temp; size_t temp_size; const char *filebase; filebase = COM_FileBase( upstream->demo.filename ); temp_size = strlen( filebase ) + strlen( APP_DEMO_EXTENSION_STR ) + 1; temp = Mem_TempMalloc( temp_size ); Q_strncpyz( temp, filebase, temp_size ); COM_ReplaceExtension( temp, APP_DEMO_EXTENSION_STR, temp_size ); if( Com_GlobMatch( "*_auto[0-9][0-9][0-9][0-9]" APP_DEMO_EXTENSION_STR, temp, qfalse ) || Com_GlobMatch( "*_mvd" APP_DEMO_EXTENSION_STR, temp, qfalse ) ) temp[strrchr( temp, '_' ) - temp] = '\0'; else COM_StripExtension( temp ); Q_strncpyz( hostname, va( S_COLOR_ORANGE "R: " S_COLOR_WHITE "%s", temp ), sizeof( hostname ) ); Mem_TempFree( temp ); } else { Q_strncpyz( hostname, va( S_COLOR_ORANGE "R: " S_COLOR_WHITE "%s", val ), sizeof( hostname ) ); } TV_Upstream_SetName( upstream, hostname ); // override CS_HOSTNAME in next packet MSG_Init( &msg, msgbuf, sizeof( msgbuf ) ); MSG_WriteByte( &msg, svc_servercs ); MSG_WriteString( &msg, va( "cs %i \"%s\"", CS_HOSTNAME, hostname ) ); TV_Upstream_SavePacket( upstream, &msg, 0 ); }
/* * SV_Demo_Purge_f * * Removes the server demo files */ void SV_Demo_Purge_f( void ) { char *buffer; char *p, *s, num[8]; char path[256]; size_t extlen, length, bufSize; unsigned int i, numdemos, numautodemos, maxautodemos; if( Cmd_Argc() > 2 ) { Com_Printf( "Usage: serverrecordpurge [maxautodemos]\n" ); return; } maxautodemos = 0; if( Cmd_Argc() == 2 ) maxautodemos = atoi( Cmd_Argv( 1 ) ); numdemos = FS_GetFileListExt( SV_DEMO_DIR, APP_DEMO_EXTENSION_STR, NULL, &bufSize, 0, 0 ); if( !numdemos ) return; extlen = strlen( APP_DEMO_EXTENSION_STR ); buffer = Mem_TempMalloc( bufSize ); FS_GetFileList( SV_DEMO_DIR, APP_DEMO_EXTENSION_STR, buffer, bufSize, 0, 0 ); numautodemos = 0; s = buffer; for( i = 0; i < numdemos; i++, s += length + 1 ) { length = strlen( s ); if( length < strlen( "_auto9999" ) + extlen ) continue; p = s + length - strlen( "_auto9999" ) - extlen; if( strncmp( p, "_auto", strlen( "_auto" ) ) ) continue; p += strlen( "_auto" ); Q_snprintfz( num, sizeof( num ), "%04i", atoi( p ) ); if( strncmp( p, num, 4 ) ) continue; numautodemos++; } if( numautodemos <= maxautodemos ) { Mem_TempFree( buffer ); return; } s = buffer; for( i = 0; i < numdemos; i++, s += length + 1 ) { length = strlen( s ); if( length < strlen( "_auto9999" ) + extlen ) continue; p = s + length - strlen( "_auto9999" ) - extlen; if( strncmp( p, "_auto", strlen( "_auto" ) ) ) continue; p += strlen( "_auto" ); Q_snprintfz( num, sizeof( num ), "%04i", atoi( p ) ); if( strncmp( p, num, 4 ) ) continue; Q_snprintfz( path, sizeof( path ), "%s/%s", SV_DEMO_DIR, s ); Com_Printf( "Removing old autorecord demo: %s\n", path ); if( !FS_RemoveFile( path ) ) { Com_Printf( "Error, couldn't remove file: %s\n", path ); continue; } if( --numautodemos == maxautodemos ) break; } Mem_TempFree( buffer ); }
static mufont_t *SCR_LoadMUFont( const char *name, size_t len ) { size_t filename_size; char *filename; qbyte *buf; char *ptr, *token, *start; int filenum; int length; mufont_t *font; struct shader_s *shader; int numchar; int x, y, w, h; filename_size = strlen( "fonts/" ) + len + strlen( ".tga" ) + 1; filename = Mem_TempMalloc( filename_size ); Q_snprintfz( filename, filename_size, "fonts/%s", name ); // load the shader COM_ReplaceExtension( filename, ".tga", filename_size ); shader = R_RegisterPic( filename ); if( !shader ) { Mem_TempFree( filename ); return NULL; } // load the font description COM_ReplaceExtension( filename, ".wfd", filename_size ); // load the file length = FS_FOpenFile( filename, &filenum, FS_READ ); if( length == -1 ) { Mem_TempFree( filename ); return NULL; } Mem_TempFree( filename ); buf = Mem_TempMalloc( length + 1 ); length = FS_Read( buf, length, filenum ); FS_FCloseFile( filenum ); if( !length ) { Mem_TempFree( buf ); return NULL; } // seems to be valid. Allocate it font = (mufont_t *)Font_Alloc( sizeof( mufont_t ) ); font->shader = shader; font->name = Font_Alloc( len + 1 ); Q_strncpyz( font->name, name, len + 1 ); // proceed ptr = ( char * )buf; // get texture width and height token = COM_Parse( &ptr ); if( !token[0] ) goto error; font->imagewidth = atoi( token ); token = COM_Parse( &ptr ); if( !token[0] ) goto error; font->imageheight = atoi( token ); font->numchars = MIN_FONT_CHARS; // get the number of chars start = ptr; while( ptr ) { // "<char>" "<x>" "<y>" "<width>" "<height>" token = COM_Parse( &ptr ); if( !token[0] ) break; numchar = atoi( token ); if( numchar <= 0 ) break; x = atoi( COM_Parse( &ptr ) ), y = atoi( COM_Parse( &ptr ) ); w = atoi( COM_Parse( &ptr ) ), h = atoi( COM_Parse( &ptr ) ); if( numchar < 32 || numchar >= MAX_FONT_CHARS ) continue; if( ( unsigned int )( numchar + 1 ) > font->numchars ) font->numchars = ( unsigned int )numchar + 1; } if( !font->numchars ) goto error; font->chars = Font_Alloc( font->numchars * sizeof( muchar_t ) ); // get the chars ptr = start; while( ptr ) { token = COM_Parse( &ptr ); if( !token[0] ) break; numchar = atoi( token ); if( numchar <= 0 ) break; x = atoi( COM_Parse( &ptr ) ), y = atoi( COM_Parse( &ptr ) ); w = atoi( COM_Parse( &ptr ) ), h = atoi( COM_Parse( &ptr ) ); if( numchar < 32 || ( unsigned int )numchar >= font->numchars ) continue; font->chars[numchar].x = x; font->chars[numchar].y = y; font->chars[numchar].width = w; font->chars[numchar].height = h; // create the texture coordinates font->chars[numchar].s1 = ( (float)x )/(float)font->imagewidth; font->chars[numchar].s2 = ( (float)( x + w ) )/(float)font->imagewidth; font->chars[numchar].t1 = ( (float)y )/(float)font->imageheight; font->chars[numchar].t2 = ( (float)( y + h ) )/(float)font->imageheight; } // mudFont is not always giving a proper size to the space character font->chars[' '].width = font->chars['-'].width; // height is the same for every character font->fontheight = font->chars['a'].height; // if REPLACEMENT_CHAR is not present in this font, copy '?' to that position if( !( font->chars[REPLACEMENT_CHAR].height ) ) font->chars[REPLACEMENT_CHAR] = font->chars['?']; Mem_TempFree( buf ); return font; error: if( font->chars ) Font_Free( font->chars ); if( font->name ) Font_Free( font->name ); Font_Free( font ); Mem_TempFree( buf ); return NULL; }