From 7456daf65f1855549c4fe3cd959efa27b3da1593 Mon Sep 17 00:00:00 2001 From: Yamagi Burmeister Date: Sun, 25 Oct 2015 16:42:33 +0100 Subject: [PATCH] Do not display baseq2 savegames in mods / addons The savegame list is generated by calling FS_FOpenFile() for each possible savegame name. When a file handle is returned the savegame exists, otherwise the savegame slot is empty. But FS_FOpenFile() searches in every directory known to the VFS. If a savegame file isn't found in $moddir but in baseq2, the file in baseq2 is opened and a baseq2 savegame is displayed in the mods / addons savegame menu. The fix is compromise between a clean solution and invasiveness: - Refactor FS_FOpenFile() to include FS_FOpenFileRead(). FS_FOpenFile() was used only to open read only files, limit its's possibilities to do exactly that. - Introduce a new flag "gamedir_only" to FS_FOpenFile(). When true only the gamedir directories are searched and not other directories like baseq2. - Change all callers to FS_FOpenFile()s new signature. - Use the new gamedir_only flag to limit the searchpath for savegames to the gamedir. --- src/client/cl_cin.c | 2 +- src/client/menu/menu.c | 2 +- src/common/filesystem.c | 268 ++++++++++++++++--------------------- src/common/header/common.h | 2 +- src/server/sv_save.c | 10 +- src/server/sv_user.c | 6 +- 6 files changed, 130 insertions(+), 160 deletions(-) diff --git a/src/client/cl_cin.c b/src/client/cl_cin.c index 9a8e03c7..1ef6acf3 100644 --- a/src/client/cl_cin.c +++ b/src/client/cl_cin.c @@ -612,7 +612,7 @@ SCR_PlayCinematic(char *arg) } Com_sprintf(name, sizeof(name), "video/%s", arg); - FS_FOpenFile(name, &cl.cinematic_file, FS_READ); + FS_FOpenFile(name, &cl.cinematic_file, false); if (!cl.cinematic_file) { diff --git a/src/client/menu/menu.c b/src/client/menu/menu.c index c1393773..c73f5c53 100644 --- a/src/client/menu/menu.c +++ b/src/client/menu/menu.c @@ -2226,7 +2226,7 @@ Create_Savestrings(void) for (i = 0; i < MAX_SAVESLOTS; i++) { Com_sprintf(name, sizeof(name), "save/save%i/server.ssv", m_loadsave_page * MAX_SAVESLOTS + i); - FS_FOpenFile(name, &f, FS_READ); + FS_FOpenFile(name, &f, true); if (!f) { diff --git a/src/common/filesystem.c b/src/common/filesystem.c index f076298e..580c82cd 100644 --- a/src/common/filesystem.c +++ b/src/common/filesystem.c @@ -367,134 +367,6 @@ FS_FOpenFileWrite(fsHandle_t *handle) return -1; } -/* - * Returns file size or -1 if not found. Can open separate files as well as - * files inside pack files (both PAK and PK3). - */ -int -FS_FOpenFileRead(fsHandle_t *handle) -{ - char path[MAX_OSPATH]; - int i; - fsSearchPath_t *search; - fsPack_t *pack; - - file_from_pak = 0; -#ifdef ZIP - file_from_pk3 = 0; -#endif - - /* Search through the path, one element at a time. */ - for (search = fs_searchPaths; search; search = search->next) - { - /* Search inside a pack file. */ - if (search->pack) - { - pack = search->pack; - - for (i = 0; i < pack->numFiles; i++) - { - if (Q_stricmp(pack->files[i].name, handle->name) == 0) - { - /* Found it! */ - Com_FilePath(pack->name, fs_fileInPath, - sizeof(fs_fileInPath)); - fs_fileInPack = true; - - if (fs_debug->value) - { - Com_Printf("FS_FOpenFileRead: '%s' (found in '%s').\n", - handle->name, pack->name); - } - - if (pack->pak) - { - /* PAK */ - file_from_pak = 1; - handle->file = fopen(pack->name, "rb"); - - if (handle->file) - { - fseek(handle->file, pack->files[i].offset, SEEK_SET); - return pack->files[i].size; - } - } -#ifdef ZIP - else if (pack->pk3) - { - /* PK3 */ - file_from_pk3 = 1; - Q_strlcpy(file_from_pk3_name, strrchr(pack->name, - '/') + 1, sizeof(file_from_pk3_name)); - handle->zip = unzOpen(pack->name); - - if (handle->zip) - { - if (unzLocateFile(handle->zip, handle->name, - 2) == UNZ_OK) - { - if (unzOpenCurrentFile(handle->zip) == UNZ_OK) - { - return pack->files[i].size; - } - } - - unzClose(handle->zip); - } - } -#endif - - Com_Error(ERR_FATAL, "Couldn't reopen '%s'", pack->name); - } - } - } - else - { - /* Search in a directory tree. */ - Com_sprintf(path, sizeof(path), "%s/%s", search->path, handle->name); - - handle->file = fopen(path, "rb"); - - if (!handle->file) - { - Q_strlwr(path); - handle->file = fopen(path, "rb"); - } - - if (!handle->file) - { - continue; - } - - if (handle->file) - { - /* Found it! */ - Q_strlcpy(fs_fileInPath, search->path, sizeof(fs_fileInPath)); - fs_fileInPack = false; - - if (fs_debug->value) - { - Com_Printf("FS_FOpenFileRead: '%s' (found in '%s').\n", - handle->name, search->path); - } - - return FS_FileLength(handle->file); - } - } - } - - /* Not found! */ - fs_fileInPath[0] = 0; - fs_fileInPack = false; - - if (fs_debug->value) - { - Com_Printf("FS_FOpenFileRead: couldn't find '%s'.\n", handle->name); - } - - return -1; -} - /* * Other dll's can't just call fclose() on files returned by FS_FOpenFile. */ @@ -546,41 +418,139 @@ Developer_searchpath(int who) * for streaming data out of either a pak file or a seperate file. */ int -FS_FOpenFile(const char *name, fileHandle_t *f, fsMode_t mode) +FS_FOpenFile(const char *name, fileHandle_t *f, qboolean gamedir_only) { - int size = 0; + char path[MAX_OSPATH]; fsHandle_t *handle; + fsPack_t *pack; + fsSearchPath_t *search; + int i; + + file_from_pak = 0; +#ifdef ZIP + file_from_pk3 = 0; +#endif handle = FS_HandleForFile(name, f); - Q_strlcpy(handle->name, name, sizeof(handle->name)); - handle->mode = mode; + handle->mode = FS_READ; - switch (mode) + /* Search through the path, one element at a time. */ + for (search = fs_searchPaths; search; search = search->next) { - case FS_READ: - size = FS_FOpenFileRead(handle); - break; - case FS_WRITE: - size = FS_FOpenFileWrite(handle); - break; - case FS_APPEND: - size = FS_FOpenFileAppend(handle); - break; - default: - Com_Error(ERR_FATAL, "FS_FOpenFile: bad mode (%i)", mode); - break; + if (gamedir_only) + { + if (strstr(search->path, FS_Gamedir()) == NULL) + { + break; + } + } + + /* Search inside a pack file. */ + if (search->pack) + { + pack = search->pack; + + for (i = 0; i < pack->numFiles; i++) + { + if (Q_stricmp(pack->files[i].name, handle->name) == 0) + { + /* Found it! */ + Com_FilePath(pack->name, fs_fileInPath, sizeof(fs_fileInPath)); + fs_fileInPack = true; + + if (fs_debug->value) + { + Com_Printf("FS_FOpenFile: '%s' (found in '%s').\n", + handle->name, pack->name); + } + + if (pack->pak) + { + /* PAK */ + file_from_pak = 1; + handle->file = fopen(pack->name, "rb"); + + if (handle->file) + { + fseek(handle->file, pack->files[i].offset, SEEK_SET); + return pack->files[i].size; + } + } +#ifdef ZIP + else if (pack->pk3) + { + /* PK3 */ + file_from_pk3 = 1; + Q_strlcpy(file_from_pk3_name, strrchr(pack->name, '/') + 1, sizeof(file_from_pk3_name)); + handle->zip = unzOpen(pack->name); + + if (handle->zip) + { + if (unzLocateFile(handle->zip, handle->name, 2) == UNZ_OK) + { + if (unzOpenCurrentFile(handle->zip) == UNZ_OK) + { + return pack->files[i].size; + } + } + + unzClose(handle->zip); + } + } +#endif + + Com_Error(ERR_FATAL, "Couldn't reopen '%s'", pack->name); + } + } + } + else + { + /* Search in a directory tree. */ + Com_sprintf(path, sizeof(path), "%s/%s", search->path, handle->name); + + handle->file = fopen(path, "rb"); + + if (!handle->file) + { + Q_strlwr(path); + handle->file = fopen(path, "rb"); + } + + if (!handle->file) + { + continue; + } + + if (handle->file) + { + /* Found it! */ + Q_strlcpy(fs_fileInPath, search->path, sizeof(fs_fileInPath)); + fs_fileInPack = false; + + if (fs_debug->value) + { + Com_Printf("FS_FOpenFile: '%s' (found in '%s').\n", + handle->name, search->path); + } + + return FS_FileLength(handle->file); + } + } } - if (size != -1) + /* Not found! */ + fs_fileInPath[0] = 0; + fs_fileInPack = false; + + if (fs_debug->value) { - return size; + Com_Printf("FS_FOpenFile: couldn't find '%s'.\n", handle->name); } /* Couldn't open, so free the handle. */ memset(handle, 0, sizeof(*handle)); *f = 0; - return -1; } @@ -732,7 +702,7 @@ FS_LoadFile(char *path, void **buffer) fileHandle_t f; /* File handle. */ buf = NULL; - size = FS_FOpenFile(path, &f, FS_READ); + size = FS_FOpenFile(path, &f, false); if (size <= 0) { diff --git a/src/common/header/common.h b/src/common/header/common.h index 07d6d47b..1241bd6e 100644 --- a/src/common/header/common.h +++ b/src/common/header/common.h @@ -686,7 +686,7 @@ typedef enum } fsSearchType_t; void FS_DPrintf(const char *format, ...); -int FS_FOpenFile(const char *name, fileHandle_t *f, fsMode_t mode); +int FS_FOpenFile(const char *name, fileHandle_t *f, qboolean gamedir_only); void FS_FCloseFile(fileHandle_t f); int FS_Read(void *buffer, int size, fileHandle_t f); int FS_FRead(void *buffer, int size, int count, fileHandle_t f); diff --git a/src/server/sv_save.c b/src/server/sv_save.c index fabd9f4a..004efb44 100644 --- a/src/server/sv_save.c +++ b/src/server/sv_save.c @@ -41,12 +41,12 @@ SV_WipeSavegame(char *savename) Com_sprintf(name, sizeof(name), "%s/save/%s/server.ssv", FS_Gamedir(), savename); - + remove(name); Com_sprintf(name, sizeof(name), "%s/save/%s/game.ssv", FS_Gamedir(), savename); - + remove(name); Com_sprintf(name, sizeof(name), "%s/save/%s/*.sav", FS_Gamedir(), savename); @@ -194,7 +194,7 @@ SV_ReadLevelFile(void) Com_DPrintf("SV_ReadLevelFile()\n"); Com_sprintf(name, sizeof(name), "save/current/%s.sv2", sv.name); - FS_FOpenFile(name, &f, FS_READ); + FS_FOpenFile(name, &f, true); if (!f) { @@ -300,7 +300,7 @@ SV_ReadServerFile(void) Com_DPrintf("SV_ReadServerFile()\n"); Com_sprintf(name, sizeof(name), "save/current/server.ssv"); - FS_FOpenFile(name, &f, FS_READ); + FS_FOpenFile(name, &f, true); if (!f) { @@ -315,7 +315,7 @@ SV_ReadServerFile(void) FS_Read(mapcmd, sizeof(mapcmd), f); /* read all CVAR_LATCH cvars - these will be things like + these will be things like coop, skill, deathmatch, etc */ while (1) { diff --git a/src/server/sv_user.c b/src/server/sv_user.c index 45cc6a94..12336c14 100644 --- a/src/server/sv_user.c +++ b/src/server/sv_user.c @@ -36,7 +36,7 @@ SV_BeginDemoserver(void) char name[MAX_OSPATH]; Com_sprintf(name, sizeof(name), "demos/%s", sv.name); - FS_FOpenFile(name, &sv.demofile, FS_READ); + FS_FOpenFile(name, &sv.demofile, false); if (!sv.demofile) { @@ -135,7 +135,7 @@ SV_Configstrings_f(void) start = (int)strtol(Cmd_Argv(2), (char **)NULL, 10); /* write a packet full of data */ - while (sv_client->netchan.message.cursize < MAX_MSGLEN / 2 && + while (sv_client->netchan.message.cursize < MAX_MSGLEN / 2 && start < MAX_CONFIGSTRINGS) { if (sv.configstrings[start][0]) @@ -387,7 +387,7 @@ SV_Nextserver(void) const char *v; if ((sv.state == ss_game) || - ((sv.state == ss_pic) && + ((sv.state == ss_pic) && !Cvar_VariableValue("coop"))) { return; /* can't nextserver while playing a normal game */