/* ================== Sys_Mkfifo ================== */ FILE *Sys_Mkfifo( const char *ospath ) { FILE *fifo; int result; int fn; struct stat buf; // if file already exists AND is a pipefile, remove it if( !stat( ospath, &buf ) && S_ISFIFO( buf.st_mode ) ) FS_Remove( ospath ); result = mkfifo( ospath, 0600 ); if( result != 0 ) return NULL; fn = open( ospath, O_RDWR | O_NONBLOCK ); if( fn == -1 ) return NULL; fifo = fdopen( fn, "w+" ); if( fifo == NULL ) close( fn ); return fifo; }
/********************************************************************* * * _DeleteFile */ static void * _DeleteFile (const char *sFilename) { char acAbsFilename[MAX_PATH]; _InitIfRequired(); // Perform automatic initialisation so that explicit call to FS_Init is not required _ConvertPath(sFilename, acAbsFilename, sizeof(acAbsFilename)); return (void*)FS_Remove(acAbsFilename); }
void screenshotJPEG(char *filename, qbyte *screendata, int screenwidth, int screenheight) //input is rgb NOT rgba { qbyte *buffer; vfsfile_t *outfile; jpeg_error_mgr_wrapper jerr; struct jpeg_compress_struct cinfo; JSAMPROW row_pointer[1]; if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY))) { FS_CreatePath (filename, FS_GAME); if (!(outfile = FS_OpenVFS(filename, "wb", FS_GAMEONLY))) { Con_Printf("Error opening %s\n", filename); return; } } cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = jpeg_error_exit; if (setjmp(jerr.setjmp_buffer)) { jpeg_destroy_compress(&cinfo); VFS_CLOSE(outfile); FS_Remove(filename, FS_GAME); Con_Printf("Failed to create jpeg\n"); return; } jpeg_create_compress(&cinfo); buffer = screendata; jpeg_mem_dest(&cinfo, outfile); cinfo.image_width = screenwidth; cinfo.image_height = screenheight; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); jpeg_set_quality (&cinfo, 75/*bound(0, (int) gl_image_jpeg_quality_level.value, 100)*/, true); jpeg_start_compress(&cinfo, true); while (cinfo.next_scanline < cinfo.image_height) { *row_pointer = &buffer[(cinfo.image_height - cinfo.next_scanline - 1) * cinfo.image_width * 3]; jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); VFS_CLOSE(outfile); jpeg_destroy_compress(&cinfo); }
/* ================== Sys_Mkfifo ================== */ FILE *Sys_Mkfifo( const char *ospath ) { FILE *fifo; int result; int fn; struct stat buf; // if file already exists AND is a pipefile, remove it if( !stat( ospath, &buf ) && S_ISFIFO( buf.st_mode ) ) FS_Remove( ospath ); result = mkfifo( ospath, 0600 ); if( result != 0 ) return NULL; fifo = fopen( ospath, "w+" ); if( fifo ) { fn = fileno( fifo ); fcntl( fn, F_SETFL, O_NONBLOCK ); } return fifo; }
/** * @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); }
/** * @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; } }