X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=fs.c;h=74329aaf779185b2c82ce6e165fa21144e357592;hb=9e883a148a3370e139b78a19d2ee645fba8db8d1;hp=d11ea28eacf5db40d8dbd74fcc95a6a1f6d592e0;hpb=c8e869ff770f1a81f6e460185b541d2002846d2e;p=xonotic%2Fdarkplaces.git diff --git a/fs.c b/fs.c index d11ea28e..74329aaf 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 @@ -278,6 +279,7 @@ 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 +963,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) @@ -1153,6 +1158,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) @@ -1171,13 +1179,6 @@ qboolean FS_ChangeGameDirs(int numgamedirs, char gamedirs[][MAX_QPATH], qboolean { int i; - if (cls.state != ca_disconnected || sv.active) - { - if (complain) - Con_Printf("Can not change gamedir while client is connected or server is running!\n"); - return false; - } - if (fs_numgamedirs == numgamedirs) { for (i = 0;i < numgamedirs;i++) @@ -1270,7 +1271,7 @@ void FS_GameDir_f (void) if (cls.demoplayback) CL_Disconnect(); - if (cls.state != ca_disconnected || sv.active) + if (cls.state == ca_connected || 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"); @@ -1288,10 +1289,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; } @@ -1380,6 +1384,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"); @@ -1673,6 +1678,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); @@ -2430,8 +2446,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]; @@ -2446,10 +2463,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, ':'); @@ -2476,14 +2492,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); } @@ -2508,59 +2522,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; @@ -2729,3 +2736,24 @@ qboolean FS_IsRegisteredQuakePack(const char *name) return false; } + +int FS_CRCFile(const char *filename, size_t *filesizepointer) +{ + int crc = -1; + unsigned char *filedata; + fs_offset_t filesize; + if (filesizepointer) + *filesizepointer = 0; + if (!filename || !*filename) + return crc; + filedata = FS_LoadFile(filename, tempmempool, true, &filesize); + if (filedata) + { + if (filesizepointer) + *filesizepointer = filesize; + crc = CRC_Block(filedata, filesize); + Mem_Free(filedata); + } + return crc; +} +