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.
This commit is contained in:
Yamagi Burmeister 2015-10-25 16:42:33 +01:00 committed by Daniel Gibson
parent 2e82fe85fd
commit 7456daf65f
6 changed files with 130 additions and 160 deletions

View file

@ -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)
{

View file

@ -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)
{

View file

@ -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)
{

View file

@ -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);

View file

@ -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)
{

View file

@ -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 */