/* * 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 ); }
/* * ML_InitFromMaps * Fills map list array from each map file. Very slow * and should only be called if cache doesnt exist */ static void ML_InitFromMaps( void ) { int i, j, total, len; char maps[2048]; char *filename; if( ml_initialized ) return; total = FS_GetFileList( "maps", ".bsp", NULL, 0, 0, 0 ); if( !total ) return; i = 0; while( i < total ) { memset( maps, 0, sizeof( maps ) ); j = FS_GetFileList( "maps", ".bsp", maps, sizeof( maps ), i, total ); // no maps returned, map name is too big or end of list? if( !j ) { i++; continue; } i += j; // split the maps up and find their fullnames len = 0; while( j-- ) { filename = maps + len; if( !*filename ) continue; len += strlen( filename ) + 1; COM_SanitizeFilePath( filename ); COM_StripExtension( filename ); ML_AddMap( filename, NULL ); } } }
/* * ML_FilenameExists * Checks to see if a filename is present in the map list */ static bool ML_FilenameExistsExt( const char *filename, bool quick ) { mapinfo_t *map; char *filepath; if( !ml_initialized ) return false; filepath = va( "maps/%s.bsp", filename ); COM_SanitizeFilePath( filepath ); if( !ML_ValidateFilename( filename ) ) return false; if( Trie_Find( mlist_filenames_trie, filename, TRIE_EXACT_MATCH, (void **)&map ) == TRIE_OK ) { if( quick || FS_FOpenFile( filepath, NULL, FS_READ ) != -1 ) return true; } return false; }
/* * 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_StartDemoRecord */ void TV_Upstream_StartDemoRecord( upstream_t *upstream, const char *demoname, qboolean silent ) { char *servername, *temp; size_t name_size; assert( upstream ); assert( demoname ); if( upstream->demo.playing ) { if( !silent ) Com_Printf( "You can't record from another demo.\n" ); return; } if( upstream->demo.recording ) { if( !silent ) Com_Printf( "Already recording.\n" ); return; } // strip the port number from servername servername = TempCopyString( upstream->servername ); temp = strstr( servername, ":" ); if( temp ) *temp = '\0'; // store the name name_size = sizeof( char ) * ( strlen( "demos/tvserver" ) + 1 + strlen( servername ) + 1 + strlen( demoname ) + strlen( APP_DEMO_EXTENSION_STR ) + 1 ); upstream->demo.filename = Mem_ZoneMalloc( name_size ); Q_snprintfz( upstream->demo.filename, name_size, "demos/tvserver/%s/%s", servername, demoname ); COM_SanitizeFilePath( upstream->demo.filename ); COM_DefaultExtension( upstream->demo.filename, APP_DEMO_EXTENSION_STR, name_size ); Mem_TempFree( servername ); if( !COM_ValidateRelativeFilename( upstream->demo.filename ) ) { if( !silent ) Com_Printf( "Invalid filename.\n" ); Mem_ZoneFree( upstream->demo.filename ); return; } // temp name name_size = sizeof( char ) * ( strlen( upstream->demo.filename ) + strlen( ".rec" ) + 1 ); upstream->demo.tempname = Mem_ZoneMalloc( name_size ); Q_snprintfz( upstream->demo.tempname, name_size, "%s.rec", upstream->demo.filename ); // open the demo file if( FS_FOpenFile( upstream->demo.tempname, &upstream->demo.filehandle, FS_WRITE|SNAP_DEMO_GZ ) == -1 ) { Com_Printf( "Error: Couldn't create the demo file.\n" ); Mem_ZoneFree( upstream->demo.tempname ); upstream->demo.tempname = NULL; Mem_ZoneFree( upstream->demo.filename ); upstream->demo.filename = NULL; return; } if( !silent ) Com_Printf( "Recording demo: %s\n", upstream->demo.filename ); upstream->demo.recording = qtrue; upstream->demo.localtime = 0; upstream->demo.basetime = upstream->demo.duration = 0; // don't start saving messages until a non-delta compressed message is received TV_Upstream_AddReliableCommand( upstream, "nodelta" ); // request non delta compressed frame from server upstream->demo.waiting = qtrue; // the rest of the demo file will be individual frames }
/* * S_ReadPlaylistFile */ static bgTrack_t *S_ReadPlaylistFile( const char *filename, bool shuffle, bool loop ) { int filenum, length; char *tmpname = 0; size_t tmpname_size = 0; char *data, *line, *entry; playlistItem_t items[MAX_PLAYLIST_ITEMS]; int i, numItems = 0; length = trap_FS_FOpenFile( filename, &filenum, FS_READ ); if( length < 0 ) return NULL; // load the playlist into memory data = S_Malloc( length + 1 ); trap_FS_Read( data, length, filenum ); trap_FS_FCloseFile( filenum ); srand( time( NULL ) ); while( *data ) { size_t s; entry = data; // read the whole line for( line = data; *line != '\0' && *line != '\n'; line++ ); // continue reading from the next character, if possible data = (*line == '\0' ? line : line + 1); *line = '\0'; // trim whitespaces, tabs, etc entry = Q_trim( entry ); // special M3U entry or comment if( !*entry || *entry == '#' ) continue; if( trap_FS_IsUrl( entry ) ) { items[numItems].track = S_AllocTrack( entry ); } else { // append the entry name to playlist path s = strlen( filename ) + 1 + strlen( entry ) + 1; if( s > tmpname_size ) { if( tmpname ) S_Free( tmpname ); tmpname_size = s; tmpname = S_Malloc( tmpname_size ); } Q_strncpyz( tmpname, filename, tmpname_size ); COM_StripFilename( tmpname ); Q_strncatz( tmpname, "/", tmpname_size ); Q_strncatz( tmpname, entry, tmpname_size ); COM_SanitizeFilePath( tmpname ); items[numItems].track = S_AllocTrack( tmpname ); } if( ++numItems == MAX_PLAYLIST_ITEMS ) break; } if( tmpname ) { S_Free( tmpname ); tmpname = NULL; } if( !numItems ) return NULL; // set the playing order for( i = 0; i < numItems; i++ ) items[i].order = (shuffle ? (rand() % numItems) : i); // sort the playlist R_SortPlaylistItems( numItems, items ); // link the playlist for( i = 1; i < numItems; i++ ) { items[i-1].track->next = items[i].track; items[i].track->prev = items[i-1].track; items[i].track->loop = loop; } items[numItems-1].track->next = items[0].track; items[0].track->prev = items[numItems-1].track; items[0].track->loop = loop; return items[0].track; }
/* * SV_Demo_Start_f * * Begins server demo recording. */ void SV_Demo_Start_f( void ) { int demofilename_size, i; if( Cmd_Argc() < 2 ) { Com_Printf( "Usage: serverrecord <demoname>\n" ); return; } if( svs.demo.file ) { Com_Printf( "Already recording\n" ); return; } if( sv.state != ss_game ) { Com_Printf( "Must be in a level to record\n" ); return; } for( i = 0; i < sv_maxclients->integer; i++ ) { if( svs.clients[i].state >= CS_SPAWNED && svs.clients[i].edict && !( svs.clients[i].edict->r.svflags & SVF_NOCLIENT ) ) break; } if( i == sv_maxclients->integer ) { Com_Printf( "No players in game, can't record a demo\n" ); return; } // // open the demo file // // real name demofilename_size = sizeof( char ) * ( strlen( SV_DEMO_DIR ) + 1 + strlen( Cmd_Args() ) + strlen( APP_DEMO_EXTENSION_STR ) + 1 ); svs.demo.filename = Mem_ZoneMalloc( demofilename_size ); Q_snprintfz( svs.demo.filename, demofilename_size, "%s/%s", SV_DEMO_DIR, Cmd_Args() ); COM_SanitizeFilePath( svs.demo.filename ); if( !COM_ValidateRelativeFilename( svs.demo.filename ) ) { Mem_ZoneFree( svs.demo.filename ); svs.demo.filename = NULL; Com_Printf( "Invalid filename.\n" ); return; } COM_DefaultExtension( svs.demo.filename, APP_DEMO_EXTENSION_STR, demofilename_size ); // temp name demofilename_size = sizeof( char ) * ( strlen( svs.demo.filename ) + strlen( ".rec" ) + 1 ); svs.demo.tempname = Mem_ZoneMalloc( demofilename_size ); Q_snprintfz( svs.demo.tempname, demofilename_size, "%s.rec", svs.demo.filename ); // open it if( FS_FOpenFile( svs.demo.tempname, &svs.demo.file, FS_WRITE|SNAP_DEMO_GZ ) == -1 ) { Com_Printf( "Error: Couldn't open file: %s\n", svs.demo.tempname ); Mem_ZoneFree( svs.demo.filename ); svs.demo.filename = NULL; Mem_ZoneFree( svs.demo.tempname ); svs.demo.tempname = NULL; return; } Com_Printf( "Recording server demo: %s\n", svs.demo.filename ); SV_Demo_InitClient(); // write serverdata, configstrings and baselines svs.demo.duration = 0; svs.demo.basetime = svs.gametime; svs.demo.localtime = time( NULL ); SV_Demo_WriteStartMessages(); // write one nodelta frame svs.demo.client.nodelta = true; SV_Demo_WriteSnap(); svs.demo.client.nodelta = false; }
/* * 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 ); }