Add logic to mark search path entries as required or optional.

Until 7.45 we supported adding non existent dirs to the search path,
8.00 bails out if it cannot at a dir. It turned out that some users
install the binary through their package management (SYSTEMWIDE is set),
but use local game data. This case was broken, because the SYSTEMDIR
doesn't exist. Fix this by marking the SYSTEMDIR as optional.

Closes #724.
This commit is contained in:
Yamagi 2021-06-20 18:20:16 +02:00
parent 21483dc1bd
commit c9f7faa7b1
4 changed files with 38 additions and 18 deletions

View file

@ -526,18 +526,21 @@ Sys_RemoveDir(const char *path)
}
}
void
qboolean
Sys_Realpath(const char *in, char *out, size_t size)
{
char *converted = realpath(in, NULL);
if (converted == NULL)
{
Com_Error(ERR_FATAL, "Couldn't get realpath for %s\n", in);
Com_Printf("Couldn't get realpath for %s\n", in);
return false;
}
Q_strlcpy(out, converted, size);
free(converted);
return true;
}
/* ================================================================ */

View file

@ -593,7 +593,7 @@ Sys_RemoveDir(const char *path)
RemoveDirectoryW(wpath);
}
void
qboolean
Sys_Realpath(const char *in, char *out, size_t size)
{
WCHAR win[MAX_OSPATH] = {0};
@ -604,10 +604,12 @@ Sys_Realpath(const char *in, char *out, size_t size)
if (wconverted == NULL)
{
Com_Error(ERR_FATAL, "Couldn't get realpath for %s\n", in);
Com_Printf("Couldn't get realpath for %s\n", in);
return false;
}
WideCharToMultiByte(CP_UTF8, 0, wconverted, -1, out, size, NULL, NULL);
return true
}
/* ======================================================================= */

View file

@ -1836,11 +1836,19 @@ const char* FS_GetFilenameForHandle(fileHandle_t f)
// --------
void FS_AddDirToRawPath (const char *rawdir, qboolean create) {
static void FS_AddDirToRawPath (const char *rawdir, qboolean create, qboolean required) {
char dir[MAX_OSPATH] = {0};
// Get the realpath.
Sys_Realpath(rawdir, dir, sizeof(dir));
if (!Sys_Realpath(rawdir, dir, sizeof(dir)))
{
if (required)
{
Com_Error(ERR_FATAL, "Couldn't add required directory %s to search path\n", rawdir);
}
return;
}
// Convert backslashes to forward slashes.
for (int i = 0; i < strlen(dir); i++)
@ -1883,36 +1891,43 @@ void FS_AddDirToRawPath (const char *rawdir, qboolean create) {
void FS_BuildRawPath(void) {
// Add $HOME/.yq2 (MUST be the last dir!)
// Add $HOME/.yq2, MUST be the last dir! Required,
// otherwise the config cannot be written.
if (!is_portable) {
const char *homedir = Sys_GetHomeDir();
if (homedir != NULL) {
FS_AddDirToRawPath(homedir, true);
FS_AddDirToRawPath(homedir, true, true);
}
}
// Add $binarydir
// Add binary dir. Required, because the renderer
// libraries are loaded from it.
const char *binarydir = Sys_GetBinaryDir();
if(binarydir[0] != '\0')
{
FS_AddDirToRawPath(binarydir, false);
FS_AddDirToRawPath(binarydir, false, true);
}
// Add $basedir/
FS_AddDirToRawPath(datadir, false);
// Add data dir. Required, when the user gives us
// a data dir he expects it in a working state.
FS_AddDirToRawPath(datadir, false, true);
// Add SYSTEMDIR
// Add SYSTEMDIR. Optional, the user may have a
// binary compiled with SYSTEMWIDE (installed from
// packages), but no systemwide game data.
#ifdef SYSTEMWIDE
FS_AddDirToRawPath(SYSTEMDIR, false);
FS_AddDirToRawPath(SYSTEMDIR, false, false);
#endif
// The CD must be the last directory of the path,
// otherwise we cannot be sure that the game won't
// stream the videos from the CD.
// stream the videos from the CD. Required, if the
// user sets a CD path, he expects data getting
// read from the CD.
if (fs_cddir->string[0] != '\0') {
FS_AddDirToRawPath(fs_cddir->string, false);
FS_AddDirToRawPath(fs_cddir->string, false, true);
}
}
@ -1977,4 +1992,4 @@ FS_ShutdownFilesystem(void)
fs_rawPath = FS_FreeRawPaths(fs_rawPath, NULL);
fs_baseSearchPaths = NULL;
}
}

View file

@ -825,7 +825,7 @@ void *Sys_GetGameAPI(void *parms);
void Sys_UnloadGame(void);
void Sys_GetWorkDir(char *buffer, size_t len);
qboolean Sys_SetWorkDir(char *path);
void Sys_Realpath(const char *in, char *out, size_t size);
qboolean Sys_Realpath(const char *in, char *out, size_t size);
// Windows only (system.c)
#ifdef _WIN32