Skip to content

Commit

Permalink
Lookup some files in homedir only.
Browse files Browse the repository at this point in the history
Some files that are written by engine, like savegames, should never be
loaded from base directory. Add FS_DIR_* family of flags to specify
whether to lookup file in basedir or homedir only.

Also simplify management of FS_PATH_* flags. Add default_lookup_flags()
to avoid manipulating searchpath flags in setup_game_paths().
  • Loading branch information
skullernet committed Sep 5, 2024
1 parent 93ab30d commit 17e38fd
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 45 deletions.
10 changes: 8 additions & 2 deletions inc/shared/files.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ typedef struct {
#define FS_BUF_NONE 0x0000000c // unbuffered
#define FS_BUF_MASK 0x0000000c

// where to open file from
// where to open file from (packfile vs disk)
#define FS_TYPE_ANY 0x00000000 // open from anywhere
#define FS_TYPE_REAL 0x00000010 // open from disk only
#define FS_TYPE_PAK 0x00000020 // open from pack only
#define FS_TYPE_MASK 0x00000030

// where to look for a file
// where to look for a file (baseq2 vs gamedir)
#define FS_PATH_ANY 0x00000000 // look in any search paths
#define FS_PATH_BASE 0x00000040 // look in base search paths
#define FS_PATH_GAME 0x00000080 // look in game search paths
Expand All @@ -67,3 +67,9 @@ typedef struct {
#define FS_FLAG_DEFLATE 0x00000800 // if compressed, read raw deflate data, fail otherwise
#define FS_FLAG_LOADFILE 0x00001000 // open non-unique handle, must be closed very quickly
#define FS_FLAG_MASK 0x0000ff00

// where to look for a file (basedir vs homedir)
#define FS_DIR_ANY 0x00000000 // look anywhere
#define FS_DIR_BASE 0x00010000 // look in basedir
#define FS_DIR_HOME 0x00020000 // look in homedir
#define FS_DIR_MASK 0x00030000
2 changes: 1 addition & 1 deletion src/client/ui/demos.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ static char *LoadCache(void **list)
if (Q_concat(buffer, sizeof(buffer), m_demos.browse, "/" COM_DEMOCACHE_NAME) >= sizeof(buffer)) {
return NULL;
}
len = FS_LoadFileEx(buffer, (void **)&cache, FS_TYPE_REAL | FS_PATH_GAME, TAG_FILESYSTEM);
len = FS_LoadFileEx(buffer, (void **)&cache, FS_TYPE_REAL | FS_PATH_GAME | FS_DIR_HOME, TAG_FILESYSTEM);
if (!cache) {
return NULL;
}
Expand Down
72 changes: 37 additions & 35 deletions src/common/files.c
Original file line number Diff line number Diff line change
Expand Up @@ -1333,10 +1333,9 @@ static int64_t open_file_read(file_t *file, const char *normalized, size_t namel

// search through the path, one element at a time
for (search = fs_searchpaths; search; search = search->next) {
if (file->mode & FS_PATH_MASK) {
if ((file->mode & search->mode & FS_PATH_MASK) == 0) {
continue;
}
if ((file->mode & search->mode & FS_PATH_MASK) == 0 ||
(file->mode & search->mode & FS_DIR_MASK ) == 0) {
continue;
}

// is the element a pak file?
Expand Down Expand Up @@ -1637,6 +1636,17 @@ int FS_Write(const void *buf, size_t len, qhandle_t f)
return len;
}

static unsigned default_lookup_flags(unsigned flags)
{
if (!(flags & FS_PATH_MASK) || !fs_game->string[0])
flags |= FS_PATH_MASK;

if (!(flags & FS_DIR_MASK) || !sys_homedir->string[0])
flags |= FS_DIR_MASK;

return flags;
}

/*
============
FS_OpenFile
Expand All @@ -1663,7 +1673,7 @@ int64_t FS_OpenFile(const char *name, qhandle_t *f, unsigned mode)
return Q_ERR(EMFILE);
}

file->mode = mode;
file->mode = default_lookup_flags(mode);

if ((mode & FS_MODE_MASK) == FS_MODE_READ) {
ret = expand_open_file_read(file, name);
Expand Down Expand Up @@ -1841,13 +1851,17 @@ int FS_LoadFileEx(const char *path, void **buffer, unsigned flags, memtag_t tag)
return Q_ERR(EAGAIN); // not yet initialized
}

if (flags & FS_MODE_MASK) {
return Q_ERR(EINVAL);
}

// allocate new file handle
file = alloc_handle(&f);
if (!file) {
return Q_ERR(EMFILE);
}

file->mode = (flags & ~FS_MODE_MASK) | FS_MODE_READ | FS_FLAG_LOADFILE;
file->mode = default_lookup_flags(flags) | FS_MODE_READ | FS_FLAG_LOADFILE;

// look for it in the filesystem or pack files
len = expand_open_file_read(file, path);
Expand Down Expand Up @@ -2756,6 +2770,10 @@ void **FS_ListFiles(const char *path, const char *filter, unsigned flags, int *c
*count_p = 0;
}

if (!fs_searchpaths) {
return NULL; // not yet initialized
}

if (!path) {
path = "";
pathlen = 0;
Expand All @@ -2774,11 +2792,12 @@ void **FS_ListFiles(const char *path, const char *filter, unsigned flags, int *c
return NULL;
}

flags = default_lookup_flags(flags);

for (search = fs_searchpaths; search; search = search->next) {
if (flags & FS_PATH_MASK) {
if ((flags & search->mode & FS_PATH_MASK) == 0) {
continue;
}
if ((flags & search->mode & FS_PATH_MASK) == 0 ||
(flags & search->mode & FS_DIR_MASK ) == 0) {
continue;
}
if (search->pack) {
if ((flags & FS_TYPE_MASK) == FS_TYPE_REAL) {
Expand Down Expand Up @@ -3509,7 +3528,7 @@ static void add_game_kpf(const char *dir)
return;

search = FS_Malloc(sizeof(*search));
search->mode = FS_PATH_BASE | FS_PATH_GAME;
search->mode = FS_PATH_BASE | FS_DIR_BASE;
search->filename[0] = 0;
search->pack = pack_get(pack);
search->next = fs_searchpaths;
Expand All @@ -3519,14 +3538,11 @@ static void add_game_kpf(const char *dir)

static void setup_base_paths(void)
{
// base paths have both BASE and GAME bits set by default
// the GAME bit will be removed once gamedir is set,
// and will be put back once gamedir is reset to basegame
add_game_kpf(sys_basedir->string);
add_game_dir(FS_PATH_BASE | FS_PATH_GAME, "%s/"BASEGAME, sys_basedir->string);
add_game_dir(FS_PATH_BASE | FS_DIR_BASE, "%s/"BASEGAME, sys_basedir->string);

if (sys_homedir->string[0]) {
add_game_dir(FS_PATH_BASE | FS_PATH_GAME, "%s/"BASEGAME, sys_homedir->string);
add_game_dir(FS_PATH_BASE | FS_DIR_HOME, "%s/"BASEGAME, sys_homedir->string);
}

fs_base_searchpaths = fs_searchpaths;
Expand All @@ -3535,33 +3551,19 @@ static void setup_base_paths(void)
// Sets the gamedir and path to a different directory.
static void setup_game_paths(void)
{
searchpath_t *path;

if (fs_game->string[0]) {
// add system path first
add_game_dir(FS_PATH_GAME, "%s/%s", sys_basedir->string, fs_game->string);
add_game_dir(FS_PATH_GAME | FS_DIR_BASE, "%s/%s", sys_basedir->string, fs_game->string);

// home paths override system paths
if (sys_homedir->string[0]) {
add_game_dir(FS_PATH_GAME, "%s/%s", sys_homedir->string, fs_game->string);
add_game_dir(FS_PATH_GAME | FS_DIR_HOME, "%s/%s", sys_homedir->string, fs_game->string);
}

// remove the game bit from base paths
for (path = fs_base_searchpaths; path; path = path->next) {
path->mode &= ~FS_PATH_GAME;
}

// this var is set for compatibility with server browsers, etc
Cvar_FullSet("gamedir", fs_game->string, CVAR_ROM | CVAR_SERVERINFO, FROM_CODE);
} else {
// add the game bit to base paths
for (path = fs_base_searchpaths; path; path = path->next) {
path->mode |= FS_PATH_GAME;
}

Cvar_FullSet("gamedir", "", CVAR_ROM, FROM_CODE);
}

// this var is set for compatibility with server browsers, etc
Cvar_FullSet("gamedir", fs_game->string, CVAR_ROM | CVAR_SERVERINFO, FROM_CODE);

// this var is used by the game library to find it's home directory
Cvar_FullSet("fs_gamedir", fs_gamedir, CVAR_ROM, FROM_CODE);
}
Expand Down
2 changes: 1 addition & 1 deletion src/common/prompt.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ void Prompt_LoadHistory(commandPrompt_t *prompt, const char *filename)
qhandle_t f;
unsigned i;

FS_OpenFile(filename, &f, FS_MODE_READ | FS_TYPE_REAL | FS_PATH_BASE);
FS_OpenFile(filename, &f, FS_MODE_READ | FS_TYPE_REAL | FS_PATH_BASE | FS_DIR_HOME);
if (!f) {
return;
}
Expand Down
15 changes: 9 additions & 6 deletions src/server/save.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define SAVE_CURRENT ".current"
#define SAVE_AUTO "save0"

// only load saves from home dir
#define SAVE_LOOKUP_FLAGS (FS_TYPE_REAL | FS_PATH_GAME | FS_DIR_HOME)

typedef enum {
SAVE_MANUAL, // manual save
SAVE_LEVEL_START, // autosave at level start
Expand Down Expand Up @@ -203,7 +206,7 @@ static int remove_file(const char *dir, const char *name)
static void **list_save_dir(const char *dir, int *count)
{
return FS_ListFiles(va("save/%s", dir), ".ssv;.sav;.sv2",
FS_TYPE_REAL | FS_PATH_GAME | FS_SEARCH_RECURSIVE, count);
SAVE_LOOKUP_FLAGS | FS_SEARCH_RECURSIVE, count);
}

static int wipe_save_dir(const char *dir)
Expand Down Expand Up @@ -241,7 +244,7 @@ static int read_binary_file(const char *name)
qhandle_t f;
int64_t len;

len = FS_OpenFile(name, &f, FS_MODE_READ | FS_TYPE_REAL | FS_PATH_GAME);
len = FS_OpenFile(name, &f, SAVE_LOOKUP_FLAGS | FS_MODE_READ);
if (!f)
return -1;

Expand Down Expand Up @@ -406,7 +409,7 @@ static int read_level_file(void)
if (Q_snprintf(name, MAX_QPATH, "save/" SAVE_CURRENT "/%s.sv2", sv.name) >= MAX_QPATH)
return -1;

len = FS_LoadFileEx(name, &data, FS_TYPE_REAL | FS_PATH_GAME, TAG_SERVER);
len = FS_LoadFileEx(name, &data, SAVE_LOOKUP_FLAGS, TAG_SERVER);
if (!data)
return -1;

Expand Down Expand Up @@ -592,7 +595,7 @@ void SV_CheckForEnhancedSavegames(void)
static void SV_Savegame_c(genctx_t *ctx, int argnum)
{
if (argnum == 1) {
FS_File_g("save", NULL, FS_SEARCH_DIRSONLY | FS_TYPE_REAL | FS_PATH_GAME, ctx);
FS_File_g("save", NULL, SAVE_LOOKUP_FLAGS | FS_SEARCH_DIRSONLY, ctx);
}
}

Expand All @@ -612,8 +615,8 @@ static void SV_Loadgame_f(void)
}

// make sure the server files exist
if (!FS_FileExistsEx(va("save/%s/server.ssv", dir), FS_TYPE_REAL | FS_PATH_GAME) ||
!FS_FileExistsEx(va("save/%s/game.ssv", dir), FS_TYPE_REAL | FS_PATH_GAME)) {
if (!FS_FileExistsEx(va("save/%s/server.ssv", dir), SAVE_LOOKUP_FLAGS) ||
!FS_FileExistsEx(va("save/%s/game.ssv", dir), SAVE_LOOKUP_FLAGS)) {
Com_Printf("No such savegame: %s\n", dir);
return;
}
Expand Down

0 comments on commit 17e38fd

Please sign in to comment.