Example #1
0
/**
 * @brief Recursively removes files matching a given pattern from homepath.
 * Useful for removing incomplete downloads and other garbage.
 * Files listed in the com_cleanWhitelist cvar are protected from deletion.
 */
void Cmd_CleanHomepath_f(void)
{
	int      i, j, numFiles = 0, delFiles = 0, totalNumFiles = 0;
	char     **pFiles = NULL, *tokens;
	char     path[MAX_OSPATH], whitelist[MAX_OSPATH];
	qboolean whitelisted;

	if (Cmd_Argc() < 3)
	{
		// basically files are downloaded again when required - but better print a warning for inexperienced users
		Com_Printf("usage: clean <mod> <pattern[1]> <pattern[n]>\nexample: clean all *tmp */zzz* etmain/etkey\nwarning: This command deletes files in fs_homepath. If you are not sure how to use this command do not play with fire!");
		return;
	}

	// avoid unreferenced pk3 runtime issues (not on HD but still referenced in game)
#ifndef DEDICATED
	if (cls.state != CA_DISCONNECTED)
	{
		Com_Printf("You are connected to a server - '/disconnect' to run '/clean'.\n");
		return;
	}
#else
	if (com_sv_running && com_sv_running->integer)
	{
		Com_Printf("Server is running - '/killserver'  to run '/clean'.\n");
		return;
	}
#endif // DEDICATED

	Cvar_VariableStringBuffer("fs_homepath", path, sizeof(path));

	// If the first argument is "all" or "*", search the whole homepath
	// FIXME: add more options ? see #53
	if (Q_stricmp(Cmd_Argv(1), "all") && Q_stricmp(Cmd_Argv(1), "*"))
	{
		Q_strcat(path, sizeof(path), va("%c%s", PATH_SEP, Cmd_Argv(1)));
	}

	for (i = 2; i < Cmd_Argc(); i++)
	{
		pFiles = Sys_ListFiles(path, NULL, Cmd_Argv(i), &numFiles, qtrue);

		Com_Printf("Found %i files matching the pattern \"%s\" under %s\n", numFiles, Cmd_Argv(i), path);

		// debug
		//for (j = 0; j < numFiles; j++)
		//{
		//	Com_Printf("FILE[%i]: %s - pattern: %s\n", j + 1, pFiles[j], Cmd_Argv(i));
		//}

		for (j = 0; j < numFiles; j++)
		{
			whitelisted = qfalse;
			totalNumFiles++;

			// FIXME: - don't let admins force this! - move to dat file?
			//        - optimize - don't do this each loop! -> strtok modifies the input string, which is undefined behaviour on a literal char[], at least in C99
			//          & print the whitelist files on top again

			Cvar_VariableStringBuffer("com_cleanwhitelist", whitelist, sizeof(whitelist));
			// Prevent clumsy users from deleting important files - keep leading space!
			Q_strcat(whitelist, sizeof(whitelist), " .txt .cfg .dat .gm .way .so .dll"); // *.so and *.dll are denied per default in FS_Remove but throw a Com_Error() -> game aborts

			//Com_DPrintf("Whitelist files/patterns: %s\n", whitelist);

			// Check if this file is in the whitelist
			tokens = strtok(whitelist, " ,;");

			while (tokens != NULL)
			{
				if (strstr(pFiles[j], tokens))
				{
					Com_Printf("- skipping file[%i]: %s%c%s - pattern: %s\n", j + 1, path, PATH_SEP, pFiles[j], tokens);
					whitelisted = qtrue;
					break;
				}
				tokens = strtok(NULL, " ,;");
			}

			if (whitelisted)
			{
				continue;
			}

			Com_Printf("- removing file[%i]: %s%c%s\n", j + 1, path, PATH_SEP, pFiles[j]);
			//remove(va("%s%c%s", path, PATH_SEP, pFiles[j])); // enable *.so & *.dll lib deletion - see whitelist
			FS_Remove(va("%s%c%s", path, PATH_SEP, pFiles[j]));
			delFiles++;
		}

		Sys_FreeFileList(pFiles);
		numFiles = 0;
	}
	Com_Printf("Path of fs_homepath cleaned - %i matches - %i files skipped - %i files deleted.\n", totalNumFiles, totalNumFiles - delFiles, delFiles);
}
/*
================
CreateResourceIDs_f
================
*/
void CreateResourceIDs_f( const idCmdArgs &args ) {
	int i, j;
	idStr path, fileName;
	idStrList resourceFiles;
	idLexer src;
	idToken token;
	idStrList dialogs;
	idStrList resources;
	idStrList bitmaps;
	idStrList icons;
	idStrList strings;
	idStrList controls;
	idStrList commands;

	if ( args.Argc() > 1 ) {
		path = args.Argv(1);
	} else {
		path = SOURCE_CODE_BASE_FOLDER"/";
		path.Append( __FILE__ );
		path.StripFilename();
		path.BackSlashesToSlashes();
	}

	common->Printf( "%s\n", path.c_str() );
	Sys_ListFiles( path, "_resource.h", resourceFiles );

	for ( i = 0; i < resourceFiles.Num(); i++ ) {

		fileName = path + "/" + resourceFiles[i];

		common->Printf( "creating IDs for %s...\n", fileName.c_str() );

		if ( !src.LoadFile( fileName, true ) ) {
			common->Warning( "couldn't load %s", fileName.c_str() );
			continue;
		}

		dialogs.Clear();
		resources.Clear();
		bitmaps.Clear();
		icons.Clear();
		strings.Clear();
		controls.Clear();
		commands.Clear();

		while( src.ReadToken( &token ) ) {
			if ( token == "#" ) {
				src.ExpectAnyToken( &token );
				if ( token == "ifdef" || token == "ifndef" ) {
					src.SkipRestOfLine();
				} else if ( token == "define" ) {
					src.ExpectTokenType( TT_NAME, 0, &token );

					if ( token.Icmpn( "_APS_", 5 ) == 0 ) {
						continue;
					}

					if ( token.Icmpn( "IDD_", 4 ) == 0 ) {
						dialogs.AddUnique( token );
					} else if ( token.Icmpn( "IDR_", 4 ) == 0 ) {
						resources.AddUnique( token );
					} else if ( token.Icmpn( "IDB_", 4 ) == 0 ) {
						bitmaps.AddUnique( token );
					} else if ( token.Icmpn( "IDI_", 4 ) == 0 ) {
						icons.AddUnique( token );
					} else if ( token.Icmpn( "IDS_", 4 ) == 0 ||
								token.Icmpn( "IDP_", 4 ) == 0 ) {
						strings.AddUnique( token );
					} else if ( token.Icmpn( "IDC_", 4 ) == 0 ) {
						controls.AddUnique( token );
					} else {
						commands.AddUnique( token );
					}
				}
			}
		}

		src.FreeSource();

		idFile *f;
		int curResource, curControl, curCommand;

		curResource = i ? i * 1000 : 100;
		curCommand = 20000 + i * 1000;
		curControl = i * 1000 + 200;

		f = fileSystem->OpenExplicitFileWrite( fileName );
		if ( !f ) {
			common->Warning( "couldn't write %s", fileName.c_str() );
			continue;
		}

		f->WriteFloatString(	"//{{NO_DEPENDENCIES}}\n"
								"// Microsoft Visual C++ generated include file.\n"
								"// Used by .rc\n"
								"//\n\n" );

		for ( j = 0; j < dialogs.Num(); j++ ) {
			f->WriteFloatString( "#define %-40s %d\n", dialogs[j].c_str(), curResource++ );
		}
		for ( j = 0; j < resources.Num(); j++ ) {
			f->WriteFloatString( "#define %-40s %d\n", resources[j].c_str(), curResource++ );
		}
		for ( j = 0; j < bitmaps.Num(); j++ ) {
			f->WriteFloatString( "#define %-40s %d\n", bitmaps[j].c_str(), curResource++ );
		}
		for ( j = 0; j < icons.Num(); j++ ) {
			f->WriteFloatString( "#define %-40s %d\n", icons[j].c_str(), curResource++ );
		}
		for ( j = 0; j < strings.Num(); j++ ) {
			f->WriteFloatString( "#define %-40s %d\n", strings[j].c_str(), curResource++ );
		}

		f->WriteFloatString( "\n" );

		for ( j = 0; j < controls.Num(); j++ ) {
			f->WriteFloatString( "#define %-40s %d\n", controls[j].c_str(), curControl++ );
		}

		f->WriteFloatString( "\n" );

		for ( j = 0; j < commands.Num(); j++ ) {

			// NOTE: special hack for Radiant
			if ( commands[j].Cmp( "ID_ENTITY_START" ) == 0 ) {
				f->WriteFloatString( "#define %-40s %d\n", commands[j].c_str(), 40000 );
				continue;
			}
			if ( commands[j].Cmp( "ID_ENTITY_END" ) == 0 ) {
				f->WriteFloatString( "#define %-40s %d\n", commands[j].c_str(), 45000 );
				continue;
			}

			f->WriteFloatString( "#define %-40s %d\n", commands[j].c_str(), curCommand++ );
		}


		f->WriteFloatString(	"\n// Next default values for new objects\n"
								"// \n"
								"#ifdef APSTUDIO_INVOKED\n"
								"#ifndef APSTUDIO_READONLY_SYMBOLS\n"
								"#define _APS_3D_CONTROLS                1\n"
								"#define _APS_NEXT_RESOURCE_VALUE        %d\n"
								"#define _APS_NEXT_COMMAND_VALUE         %d\n"
								"#define _APS_NEXT_CONTROL_VALUE         %d\n"
								"#define _APS_NEXT_SYMED_VALUE           %d\n"
								"#endif\n"
								"#endif\n", curResource, curCommand, curControl, curResource );

		fileSystem->CloseFile( f );
	}
}
Example #3
0
/**
 * @brief Recursively removes files matching a given pattern from homepath.
 *
 * Useful for removing incomplete downloads and other garbage.
 * Files listed in the com_cleanWhitelist cvar are protected from deletion.
 * Additionally, executable and configuration files are protected unless 'force'
 * argument is passed to this command.
 */
void Cmd_CleanHomepath_f(void)
{
	int      i, j, patternFiles = 0, delFiles = 0, totalFiles = 0;
	char     path[MAX_OSPATH];
	qboolean force = qfalse, pretend = qfalse;

	// *.so and *.dll are denied per default in FS_Remove but throw a Com_Error() -> game aborts
	const char whitelist[] = ".txt .cfg .dat .gm .way .so .dll";

	if (Cmd_Argc() < 3)
	{
		// files in fs_homepath are downloaded again when required - but better print a warning for inexperienced users
		Com_Printf("usage: clean [force | pretend] [modname / all] [pattern 1] [pattern n]\n"
		           "example: clean all *tmp */zzz* etmain/etkey\n"
		           "Warning: This command deletes files in fs_homepath. If you are not sure how to use this command do not play with fire!\n");
		return;
	}

	// if home- and basepath are same better don't start to clean ...
	if (FS_IsSamePath(Cvar_VariableString("fs_homepath"), Cvar_VariableString("fs_basepath")))
	{
		Com_Printf("Invalid configuration to run clean cmd - 'fs_homepath' and 'fs_basepath' are equal.\n");
		return;
	}

	// avoid unreferenced pk3 runtime issues (not on HD but still referenced in game)
#ifndef DEDICATED
	if (cls.state != CA_DISCONNECTED)
	{
		Com_Printf("You are connected to a server - enter '/disconnect' to run '/clean'.\n");
		return;
	}
#else
	if (com_sv_running && com_sv_running->integer)
	{
		Com_Printf("Server is running - enter '/killserver' to run '/clean'.\n");
		return;
	}
#endif // DEDICATED

	Cvar_VariableStringBuffer("fs_homepath", path, sizeof(path));

	// if there are any command options, they must be at the very beginning
	for (i = 1; i < Cmd_Argc(); i++)
	{
		if (!Q_stricmp(Cmd_Argv(i), "force") || !Q_stricmp(Cmd_Argv(i), "f"))
		{
			force = qtrue;
			continue;
		}

		if (!Q_stricmp(Cmd_Argv(i), "pretend") || !Q_stricmp(Cmd_Argv(i), "p"))
		{
			pretend = qtrue;
			continue;
		}

		break;
	}

	// if the first argument is "all" or "*", search the whole homepath
	if (Q_stricmp(Cmd_Argv(i), "all") && Q_stricmp(Cmd_Argv(i), "*"))
	{
		Q_strcat(path, sizeof(path), va("%c%s", PATH_SEP, Cmd_Argv(i)));

		// check if it points to a valid directory
		if (FS_OSStatFile(path) != 1)
		{
			Com_Printf("Cannot commence cleaning, because \"%s\" is not a valid directory under fs_homepath (%s)\n", Cmd_Argv(i), path);
			return;
		}
	}

	for (i++; i < Cmd_Argc(); i++)
	{
		char **pFiles = NULL;

		pFiles = Sys_ListFiles(path, NULL, Cmd_Argv(i), &patternFiles, qtrue);

		Com_Printf("Found %i files matching the pattern \"%s\" under %s\n", patternFiles, Cmd_Argv(i), path);

		for (j = 0; j < patternFiles; j++)
		{
			char     *tokens;
			char     tmp_whitelist[MAX_OSPATH];
			qboolean whitelisted = qfalse;

			totalFiles++;

			Q_strncpyz(tmp_whitelist, (force ? Cvar_VariableString("com_cleanwhitelist") : va("%s %s", Cvar_VariableString("com_cleanwhitelist"), whitelist)), sizeof(tmp_whitelist));

			// Check if this file is in the whitelist
			tokens = strtok(tmp_whitelist, " ,;");

			while (tokens != NULL)
			{
				if (strstr(pFiles[j], tokens))
				{
					Com_Printf("- skipping file[%i]: %s%c%s (whitelisted by pattern: %s)\n", j + 1, path, PATH_SEP, pFiles[j], tokens);
					whitelisted = qtrue;
					break;
				}
				tokens = strtok(NULL, " ,;");
			}

			if (whitelisted)
			{
				continue;
			}

			if (!pretend)
			{
				Com_Printf("- removing file[%i]: %s%c%s\n", j + 1, path, PATH_SEP, pFiles[j]);

				if (force)
				{
					remove(va("%s%c%s", path, PATH_SEP, pFiles[j])); // enable *.so & *.dll lib deletion
				}
				else
				{
					FS_Remove(va("%s%c%s", path, PATH_SEP, pFiles[j]));
				}
				delFiles++;
			}
			else
			{
				Com_Printf("- pretending to remove file[%i]: %s%c%s\n", j + 1, path, PATH_SEP, pFiles[j]);
			}
		}

		Sys_FreeFileList(pFiles);
		patternFiles = 0;
	}
	Com_Printf("Path of fs_homepath cleaned - %i matches - %i files skipped - %i files deleted.\n", totalFiles, totalFiles - delFiles, delFiles);
}
Example #4
0
// returns true if at least one set of skin data was read, else false...
//
static bool Skins_Read(LPCSTR psModelFilename)
{
	LPCSTR psError = NULL;

	CWaitCursor;

	LPCSTR psSkinsPath = Skins_ModelNameToSkinPath(psModelFilename);	// eg "models/characters/skins"

	if (psSkinsPath)
	{
		string strThisModelBaseName(String_ToLower(Filename_WithoutExt(Filename_WithoutPath(psModelFilename))));

		char **ppsSkinFiles;
		int iSkinFiles;

		// scan for skin files...
		//
		ppsSkinFiles =	//ri.FS_ListFiles( "shaders", ".shader", &iSkinFiles );
						Sys_ListFiles(	va("%s%s",gamedir,psSkinsPath),// const char *directory, 
										".g2skin",	// const char *extension, 
										NULL,		// char *filter, 
										&iSkinFiles,// int *numfiles, 
										qfalse		// qboolean wantsubs 
										);

		if ( !ppsSkinFiles || !iSkinFiles )
		{
			CurrentSkins.clear();	
			CurrentSkinsSurfacePrefs.clear();
			return false;
		}

		if ( iSkinFiles > MAX_SKIN_FILES ) 
		{
			WarningBox(va("%d skin files found, capping to %d\n\n(tell me if this ever happens -Ste)", iSkinFiles, MAX_SKIN_FILES ));

			iSkinFiles = MAX_SKIN_FILES;
		}

		// load and parse skin files...
		//					
		// for now, I just scan each file and if it's out of date then I invalidate it's model-prefs info...
		//
		extern bool GetFileTime(LPCSTR psFileName, FILETIME &ft);
		for (int i=0; i<iSkinFiles; i++)
		{
			bool bReParseThisFile = false;

			char sFileName[MAX_QPATH];
			LPCSTR psFileName = ppsSkinFiles[i];
			Com_sprintf( sFileName, sizeof( sFileName ), "%s/%s", psSkinsPath, psFileName );
			psFileName = &sFileName[0];
											  
			// have a go at getting this time/date stamp if not already present...
			//
			if (!SkinFileTimeDates[psFileName].bValid)
			{
				FILETIME ft;
				if (GetFileTime(psFileName, ft))
				{
					SkinFileTimeDates[psFileName].ft = ft;
					SkinFileTimeDates[psFileName].bValid = true;
				}
			}

			// now see if there's a valid time-stamp, and use it if so, else give up and re-scan all files...
			//
			if (SkinFileTimeDates[psFileName].bValid)
			{
				FILETIME ft;
				if (GetFileTime(psFileName, ft))
				{
					LONG l = CompareFileTime( &SkinFileTimeDates[psFileName].ft, &ft);

					bReParseThisFile = (l<0);
				}
				else
				{
					bReParseThisFile = true;
				}
			}
			else
			{
				bReParseThisFile = true;
			}	
			
			if (bReParseThisFile)
			{
				G2SkinModelPrefs[sFileName].clear();
			}
		}		
		
		if (1)//bReParseSkinFiles || !CurrentSkins.size())
		{
			CurrentSkins.clear();	
			CurrentSkinsSurfacePrefs.clear();

			char *buffers[MAX_SKIN_FILES]={0};
//			long iTotalBytesLoaded = 0;
			for ( int i=0; i<iSkinFiles && !psError; i++ )
			{
				char sFileName[MAX_QPATH];

				string strThisSkinFile(ppsSkinFiles[i]);

				Com_sprintf( sFileName, sizeof( sFileName ), "%s/%s", psSkinsPath, strThisSkinFile.c_str() );
				StatusMessage( va("Scanning skin %d/%d: \"%s\"...",i+1,iSkinFiles,sFileName));

				//ri.Printf( PRINT_ALL, "...loading '%s'\n", sFileName );

				bool _bDiskLoadOccured = false;	// debug use only, but wtf?

#define LOAD_SKIN_FILE									\
/*iTotalBytesLoaded += */ ri.FS_ReadFile( sFileName, (void **)&buffers[i] );	\
if ( !buffers[i] )										\
{														\
	CurrentSkins.clear();								\
	CurrentSkinsSurfacePrefs.clear();					\
														\
	ri.Error( ERR_DROP, "Couldn't load %s", sFileName );\
}														\
_bDiskLoadOccured = true;


				// see if we should pay attention to the contents of this file...
				//
				CGPGroup	*pFileGroup			= NULL;
				CGPGroup *pParseGroup_Prefs	= NULL;
				CGenericParser2 SkinParser;
				//
				bool bParseThisFile = false;
				//
				// if we have any information about this skin file as regards what models it refers to, use the info...
				//
				if (G2SkinModelPrefs[sFileName].size())
				{
					map<string, int>::iterator it = G2SkinModelPrefs[sFileName].find( strThisModelBaseName );
					if (it != G2SkinModelPrefs[sFileName].end())
					{
						// this skin file contains this entry, so just check that we can setup the parse groups ok...
						//
						LOAD_SKIN_FILE;

						char *psDataPtr = buffers[i];
						if (SkinParser.Parse(&psDataPtr, true))
						{
							pFileGroup = SkinParser.GetBaseParseGroup();
							if (pFileGroup)
							{
								pParseGroup_Prefs = pFileGroup->FindSubGroup(sSKINKEYWORD_PREFS);//, true);
								if (pParseGroup_Prefs)
								{
									bParseThisFile = true;
								}
							}
						}
						else
						{
							ErrorBox(va("{} - Brace mismatch error in file \"%s\"!",sFileName));
						}
					}
				}
				else
				{
					// no size info for this file, so check it manually...
					//
					LOAD_SKIN_FILE;

					if (Skins_ParseThisFile(SkinParser, buffers[i], strThisModelBaseName, pFileGroup, pParseGroup_Prefs, 
											sFileName, G2SkinModelPrefs)
						)
					{
						bParseThisFile = true;
					}
				}

				if (bParseThisFile)
				{
					psError = Skins_Parse( strThisSkinFile, pFileGroup, pParseGroup_Prefs);
					if (psError)
					{
						ErrorBox(va("Skins_Read(): Error reading file \"%s\"!\n\n( Skins will be ignored for this model )\n\nError was:\n\n",sFileName,psError));
					}
				}
				else
				{
					//OutputDebugString(va("Skipping parse of file \"%s\" %s\n",sFileName, _bDiskLoadOccured?"":"( and no load! )"));
				}
			}
			//
			// free loaded skin files...
			//
			for ( i=0; i<iSkinFiles; i++ )
			{
				if (buffers[i])
				{
					ri.FS_FreeFile( buffers[i] );
				}
			}
		}

		StatusMessage(NULL);
		Sys_FreeFileList( ppsSkinFiles );
	}
	else
	{
		CurrentSkins.clear();	
		CurrentSkinsSurfacePrefs.clear();
	}

	if (psError)
	{
		return false;
	}

	return !!(CurrentSkins.size());
}
Example #5
0
/**
 * @brief Recursively removes files matching a given pattern from homepath.
 * Useful for removing incomplete downloads and other garbage.
 * Files listed in the com_cleanWhitelist cvar are protected from deletion.
 */
void Cmd_CleanHomepath_f(void)
{
	int      i, j, k, numFiles = 0;
	char     **pFiles = NULL, *tokens;
	char     path[MAX_OSPATH], whitelist[MAX_OSPATH];
	qboolean whitelisted;

	if (Cmd_Argc() < 3)
	{
		Com_Printf("usage: clean <mod> <pattern[s]>\n");
		Com_Printf("example: clean all *tmp zzz* etmain/etkey\n");
		return;
	}

	Cvar_VariableStringBuffer("fs_homepath", path, sizeof(path));

	Cvar_VariableStringBuffer("com_cleanwhitelist", whitelist, sizeof(whitelist));

	// Prevent clumsy users from deleting important files
	Q_strcat(whitelist, sizeof(whitelist), " .txt .cfg .dat .gm .way omnibot_et.so omnibot_et.dll");

	Com_DPrintf("Whitelist: %s\n", whitelist);

	// If the first argument is "all" or "*", search the whole homepath
	if (Q_stricmp(Cmd_Argv(1), "all") && Q_stricmp(Cmd_Argv(1), "*"))
	{
		Q_strcat(path, sizeof(path), va("%c%s", PATH_SEP, Cmd_Argv(1)));
	}

	for (i = 2; i < Cmd_Argc(); i++)
	{
		pFiles = Sys_ListFiles(path, NULL, Cmd_Argv(i), &numFiles, qtrue);

		Com_Printf("Found %i files matching the pattern \"%s\" under %s\n", numFiles, Cmd_Argv(i), path);

		for (j = 0; j < numFiles; j++)
		{
			for (k = 0; k < ARRAY_LEN(whitelist); k++)
			{
				whitelisted = qfalse;

				// Check if this file is in the whitelist
				tokens = strtok(whitelist, " ,;");
				while (tokens != NULL)
				{
					if (strstr(pFiles[j], tokens))
					{
						Com_Printf("- skipping whitelisted file %s\n", pFiles[j]);
						whitelisted = qtrue;
						break;
					}
					tokens = strtok(NULL, " ,;");
				}

				if (whitelisted)
				{
					break;
				}

				if (k == STRARRAY_LEN(whitelist))
				{
					Com_Printf("- removing %s\n", pFiles[j]);
					FS_Remove(va("%s%c%s", path, PATH_SEP, pFiles[j]));
				}
			}
		}

		Sys_FreeFileList(pFiles);
		numFiles = 0;
	}
}