X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=fs.c;h=40ec10a61ee94461039914bbca8505b57824fcf4;hb=2942e1d5fa49af36df6611b9d43f819d2de95ee5;hp=556384c0520f7421674811c2c03afc306c41a816;hpb=3e60d41ecefcd7296fbadfa3e2175dddd94023c3;p=xonotic%2Fdarkplaces.git diff --git a/fs.c b/fs.c index 556384c0..40ec10a6 100644 --- a/fs.c +++ b/fs.c @@ -40,6 +40,7 @@ #endif #include "fs.h" +#include "wad.h" // Win32 requires us to add O_BINARY, but the other OSes don't have it #ifndef O_BINARY @@ -273,11 +274,11 @@ char fs_gamedir[MAX_OSPATH]; char fs_basedir[MAX_OSPATH]; // list of active game directories (empty if not running a mod) -#define MAX_GAMEDIRS 16 int fs_numgamedirs = 0; char fs_gamedirs[MAX_GAMEDIRS][MAX_QPATH]; cvar_t scr_screenshot_name = {0, "scr_screenshot_name","dp", "prefix name for saved screenshots (changes based on -game commandline, as well as which game mode is running)"}; +cvar_t fs_empty_files_in_pack_mark_deletions = {0, "fs_empty_files_in_pack_mark_deletions", "0", "if enabled, empty files in a pak/pk3 count as not existing but cancel the search in further packs, effectively allowing patch pak/pk3 files to 'delete' files"}; /* @@ -961,35 +962,38 @@ then loads and adds pak1.pak pak2.pak ... */ void FS_AddGameDirectory (const char *dir) { - stringlist_t *list, *current; + int i; + stringlist_t list; searchpath_t *search; char pakfile[MAX_OSPATH]; strlcpy (fs_gamedir, dir, sizeof (fs_gamedir)); - list = listdirectory(dir); + stringlistinit(&list); + listdirectory(&list, dir); + stringlistsort(&list); // add any PAK package in the directory - for (current = list;current;current = current->next) + for (i = 0;i < list.numstrings;i++) { - if (!strcasecmp(FS_FileExtension(current->text), "pak")) + if (!strcasecmp(FS_FileExtension(list.strings[i]), "pak")) { - dpsnprintf (pakfile, sizeof (pakfile), "%s%s", dir, current->text); + dpsnprintf (pakfile, sizeof (pakfile), "%s%s", dir, list.strings[i]); FS_AddPack_Fullpath(pakfile, NULL, false); } } // add any PK3 package in the directory - for (current = list;current;current = current->next) + for (i = 0;i < list.numstrings;i++) { - if (!strcasecmp(FS_FileExtension(current->text), "pk3")) + if (!strcasecmp(FS_FileExtension(list.strings[i]), "pk3")) { - dpsnprintf (pakfile, sizeof (pakfile), "%s%s", dir, current->text); + dpsnprintf (pakfile, sizeof (pakfile), "%s%s", dir, list.strings[i]); FS_AddPack_Fullpath(pakfile, NULL, false); } } - freedirectory(list); + stringlistfreecontents(&list); // Add the directory to the search path // (unpacked files have the priority over packed files) @@ -1075,12 +1079,18 @@ FS_ClearSearchPath */ void FS_ClearSearchPath (void) { + // unload all packs and directory information, close all pack files + // (if a qfile is still reading a pack it won't be harmed because it used + // dup() to get its own handle already) while (fs_searchpaths) { searchpath_t *search = fs_searchpaths; fs_searchpaths = search->next; if (search->pack) { + // close the file + close(search->pack->handle); + // free any memory associated with it if (search->pack->files) Mem_Free(search->pack->files); Mem_Free(search->pack); @@ -1153,6 +1163,9 @@ void FS_Rescan (void) if (gamemode == GAME_NORMAL || gamemode == GAME_HIPNOTIC || gamemode == GAME_ROGUE) Con_Print("Playing registered version.\n"); } + + // unload all wads so that future queries will return the new data + W_UnloadAll(); } void FS_Rescan_f(void) @@ -1208,6 +1221,9 @@ qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean } } + // halt demo playback to close the file + CL_Disconnect(); + Host_SaveConfig_f(); fs_numgamedirs = numgamedirs; @@ -1220,8 +1236,8 @@ qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean // exec the new config Host_LoadConfig_f(); - // reinitialize the loaded sounds - S_Reload_f(); + // unload all sounds so they will be reloaded from the new files as needed + S_UnloadAllSounds_f(); // reinitialize renderer (this reloads hud/console background/etc) R_Modules_Restart(); @@ -1259,11 +1275,7 @@ void FS_GameDir_f (void) for (i = 0;i < numgamedirs;i++) strlcpy(gamedirs[i], Cmd_Argv(i+1), sizeof(gamedirs[i])); - // allow gamedir change during demo loop - if (cls.demoplayback) - CL_Disconnect(); - - if (cls.state == ca_connected || sv.active) + if ((cls.state == ca_connected && !cls.demoplayback) || sv.active) { // actually, changing during game would work fine, but would be stupid Con_Printf("Can not change gamedir while client is connected or server is running!\n"); @@ -1281,10 +1293,13 @@ FS_CheckGameDir */ qboolean FS_CheckGameDir(const char *gamedir) { - stringlist_t *list = listdirectory(va("%s%s/", fs_basedir, gamedir)); - if (list) - freedirectory(list); - return list != NULL; + qboolean success; + stringlist_t list; + stringlistinit(&list); + listdirectory(&list, va("%s%s/", fs_basedir, gamedir)); + success = list.numstrings > 0; + stringlistfreecontents(&list); + return success; } @@ -1373,6 +1388,7 @@ void FS_Init (void) void FS_Init_Commands(void) { Cvar_RegisterVariable (&scr_screenshot_name); + Cvar_RegisterVariable (&fs_empty_files_in_pack_mark_deletions); Cmd_AddCommand ("gamedir", FS_GameDir_f, "changes active gamedir list (can take multiple arguments), not including base directory (example usage: gamedir ctf)"); Cmd_AddCommand ("fs_rescan", FS_Rescan_f, "rescans filesystem for new pack archives and any other changes"); @@ -1388,6 +1404,10 @@ FS_Shutdown */ void FS_Shutdown (void) { + // close all pack files and such + // (hopefully there aren't any other open files, but they'll be cleaned up + // by the OS anyway) + FS_ClearSearchPath(); Mem_FreePool (&fs_mempool); } @@ -1666,6 +1686,17 @@ static searchpath_t *FS_FindFile (const char *name, int* index, qboolean quiet) // Found it if (!diff) { + if (fs_empty_files_in_pack_mark_deletions.integer && pak->files[middle].realsize == 0) + { + // yes, but the first one is empty so we treat it as not being there + if (!quiet && developer.integer >= 10) + Con_Printf("FS_FindFile: %s is marked as deleted\n", name); + + if (index != NULL) + *index = -1; + return NULL; + } + if (!quiet && developer.integer >= 10) Con_Printf("FS_FindFile: %s in %s\n", pak->files[middle].name, pak->filename); @@ -2423,8 +2454,9 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) fssearch_t *search; searchpath_t *searchpath; pack_t *pak; - int i, basepathlength, numfiles, numchars; - stringlist_t *dir, *dirfile, *liststart, *listcurrent, *listtemp; + int i, basepathlength, numfiles, numchars, resultlistindex, dirlistindex; + stringlist_t resultlist; + stringlist_t dirlist; const char *slash, *backslash, *colon, *separator; char *basepath; char netpath[MAX_OSPATH]; @@ -2439,10 +2471,9 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) return NULL; } + stringlistinit(&resultlist); + stringlistinit(&dirlist); search = NULL; - liststart = NULL; - listcurrent = NULL; - listtemp = NULL; slash = strrchr(pattern, '/'); backslash = strrchr(pattern, '\\'); colon = strrchr(pattern, ':'); @@ -2469,14 +2500,12 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) { if (matchpattern(temp, (char *)pattern, true)) { - for (listtemp = liststart;listtemp;listtemp = listtemp->next) - if (!strcmp(listtemp->text, temp)) + for (resultlistindex = 0;resultlistindex < resultlist.numstrings;resultlistindex++) + if (!strcmp(resultlist.strings[resultlistindex], temp)) break; - if (listtemp == NULL) + if (resultlistindex == resultlist.numstrings) { - listcurrent = stringlistappend(listcurrent, temp); - if (liststart == NULL) - liststart = listcurrent; + stringlistappend(&resultlist, temp); if (!quiet) Con_DPrintf("SearchPackFile: %s : %s\n", pak->filename, temp); } @@ -2501,59 +2530,52 @@ fssearch_t *FS_Search(const char *pattern, int caseinsensitive, int quiet) { // get a directory listing and look at each name dpsnprintf(netpath, sizeof (netpath), "%s%s", searchpath->filename, basepath); - if ((dir = listdirectory(netpath))) + stringlistinit(&dirlist); + listdirectory(&dirlist, netpath); + for (dirlistindex = 0;dirlistindex < dirlist.numstrings;dirlistindex++) { - for (dirfile = dir;dirfile;dirfile = dirfile->next) + dpsnprintf(temp, sizeof(temp), "%s%s", basepath, dirlist.strings[dirlistindex]); + if (matchpattern(temp, (char *)pattern, true)) { - dpsnprintf(temp, sizeof(temp), "%s%s", basepath, dirfile->text); - if (matchpattern(temp, (char *)pattern, true)) + for (resultlistindex = 0;resultlistindex < resultlist.numstrings;resultlistindex++) + if (!strcmp(resultlist.strings[resultlistindex], temp)) + break; + if (resultlistindex == resultlist.numstrings) { - for (listtemp = liststart;listtemp;listtemp = listtemp->next) - if (!strcmp(listtemp->text, temp)) - break; - if (listtemp == NULL) - { - listcurrent = stringlistappend(listcurrent, temp); - if (liststart == NULL) - liststart = listcurrent; - if (!quiet) - Con_DPrintf("SearchDirFile: %s\n", temp); - } + stringlistappend(&resultlist, temp); + if (!quiet) + Con_DPrintf("SearchDirFile: %s\n", temp); } } - freedirectory(dir); } + stringlistfreecontents(&dirlist); } } - if (liststart) + if (resultlist.numstrings) { - liststart = stringlistsort(liststart); - numfiles = 0; + stringlistsort(&resultlist); + numfiles = resultlist.numstrings; numchars = 0; - for (listtemp = liststart;listtemp;listtemp = listtemp->next) - { - numfiles++; - numchars += (int)strlen(listtemp->text) + 1; - } + for (resultlistindex = 0;resultlistindex < resultlist.numstrings;resultlistindex++) + numchars += (int)strlen(resultlist.strings[resultlistindex]) + 1; search = (fssearch_t *)Z_Malloc(sizeof(fssearch_t) + numchars + numfiles * sizeof(char *)); search->filenames = (char **)((char *)search + sizeof(fssearch_t)); search->filenamesbuffer = (char *)((char *)search + sizeof(fssearch_t) + numfiles * sizeof(char *)); search->numfilenames = (int)numfiles; numfiles = 0; numchars = 0; - for (listtemp = liststart;listtemp;listtemp = listtemp->next) + for (resultlistindex = 0;resultlistindex < resultlist.numstrings;resultlistindex++) { size_t textlen; search->filenames[numfiles] = search->filenamesbuffer + numchars; - textlen = strlen(listtemp->text) + 1; - memcpy(search->filenames[numfiles], listtemp->text, textlen); + textlen = strlen(resultlist.strings[resultlistindex]) + 1; + memcpy(search->filenames[numfiles], resultlist.strings[resultlistindex], textlen); numfiles++; numchars += (int)textlen; } - if (liststart) - stringlistfree(liststart); } + stringlistfreecontents(&resultlist); Mem_Free(basepath); return search;