void recurse(const char *dir) { char **sysFiles, **dirFiles, *args[5]; int numSysFiles, i, len, numdirs; char altname[MAX_OSPATH]; char command1[MAX_OSPATH]; char command2[MAX_OSPATH]; dirFiles = Sys_ListFiles(dir, "/", &numdirs); if (numdirs > 2) { for (i=2;i<numdirs;i++) { sprintf(altname, "%s\\%s", dir, dirFiles[i]); // if (stricmp(altname,"q:\\send\\quake\\baseq3\\models\\players")) // dont recurse this dir { recurse(altname); } } } sprintf(command1, "-targa"); sprintf(command2, "-outfile"); sysFiles = Sys_ListFiles( dir, ".tga", &numSysFiles ); for(i=0; i<numSysFiles; i++) { char tgain[MAX_OSPATH]; sprintf(tgain,"%s\\%s", dir, sysFiles[i]); strcpy( altname, tgain ); len = strlen( altname ); altname[len-3] = 'j'; altname[len-2] = 'p'; altname[len-1] = 'g'; args[0] = "cjpeg"; args[1] = command2; args[2] = altname; args[3] = command1; args[4] = tgain; printf("%s", tgain); len = qmain(5, args); iNumberOf_FilesScanned++; if (!len) { iNumberOf_FilesConverted++; iSizeOf_JPGsWritten += scGetFileLen(altname); iSizeOf_TGAsDeleted += scGetFileLen(tgain); if (!gbNoTGADelete) { remove(tgain); printf(" nuked!"); } } printf("\n"); } Sys_FreeFileList( sysFiles ); Sys_FreeFileList( dirFiles ); }
/* ================ FS_GetFileList Returns a uniqued list of files that match the given criteria from all search paths ================ */ int FS_GetFileList( const char *path, const char *extension, char *listbuf, int bufsize ) { int nfiles = 0; int i; char *netpath; int numSysFiles; char **sysFiles; char *name; FS_CheckInit(); if ( !path ) { return 0; } if ( !extension ) { extension = ""; } // Prime the file list buffer listbuf[0] = '\0'; netpath = FS_BuildOSPath( path ); #ifdef _JK2MP sysFiles = Sys_ListFiles( netpath, extension, NULL, &numSysFiles, qfalse ); #else sysFiles = Sys_ListFiles( netpath, extension, &numSysFiles, qfalse ); #endif for ( i = 0 ; i < numSysFiles ; i++ ) { // unique the match name = sysFiles[i]; nfiles = FS_AddFileToListBuf( name, listbuf, bufsize, nfiles ); } Sys_FreeFileList( sysFiles ); return nfiles; }
/** * @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); }
// 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()); }
/** * @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); }
/** * @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; } }