scan for soundfonts relative to executable and config directory (#1869)

* scan for soundfonts relative to executable and config directory

* fix string concat

* explicitly track recursive calls of ScanDir()

* free() strings early

* track recursion in-function

* scan relative directories recursively only

* back to per-call recursion tracking

* do not traverse up out of the config directory
This commit is contained in:
Fabian Greffrath 2024-08-26 18:18:00 +02:00 committed by GitHub
parent 387c0deb03
commit af359bac43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -32,7 +32,8 @@ typedef long fluid_long_long_t;
typedef fluid_long_long_t fluid_int_t;
#endif
#include "d_iwad.h" // [FG] D_DoomExeDir()
#include "d_iwad.h"
#include "d_main.h"
#include "doomtype.h"
#include "i_glob.h"
#include "i_printf.h"
@ -99,44 +100,53 @@ static fluid_long_long_t FL_sftell(void *handle)
return mem_ftell((MEMFILE *)handle);
}
static void ScanDir(const char *dir)
static void ScanDir(const char *dir, boolean recursion)
{
const char usr_share[] = "/usr/share";
char *rel = NULL;
glob_t *glob;
// [FG] replace global "/usr/share" with user's "~/.local/share"
if (strncmp(dir, usr_share, strlen(usr_share)) == 0)
if (recursion == false)
{
char *home_dir = M_getenv("XDG_DATA_HOME");
if (home_dir == NULL)
// [FG] replace global "/usr/share" with user's "~/.local/share"
const char usr_share[] = "/usr/share";
if (strncmp(dir, usr_share, strlen(usr_share)) == 0)
{
home_dir = M_getenv("HOME");
}
char *home_dir = M_getenv("XDG_DATA_HOME");
if (home_dir)
{
char *local_share = M_StringJoin(home_dir, "/.local/share");
char *local_dir = M_StringReplace(dir, usr_share, local_share);
// [FG] do not trigger this code path again
if (strncmp(local_dir, usr_share, strlen(usr_share)) != 0)
if (home_dir == NULL)
{
ScanDir(local_dir);
home_dir = M_getenv("HOME");
}
free(local_dir);
free(local_share);
if (home_dir)
{
char *local_share = M_StringJoin(home_dir, "/.local/share");
char *local_dir = M_StringReplace(dir, usr_share, local_share);
free(local_share);
ScanDir(local_dir, true);
free(local_dir);
}
}
else if (dir[0] == '.')
{
// [FG] relative to the executable directory
char *rel = M_StringJoin(D_DoomExeDir(), DIR_SEPARATOR_S, dir);
ScanDir(rel, true);
free(rel);
// [FG] relative to the config directory (if different)
if (dir[1] != '.' && strcmp(D_DoomExeDir(), D_DoomPrefDir()) != 0)
{
rel = M_StringJoin(D_DoomPrefDir(), DIR_SEPARATOR_S, dir);
ScanDir(rel, true);
free(rel);
}
// [FG] never absolute path
return;
}
}
// [FG] relative to the executable directory
if (dir[0] == '.')
{
rel = M_StringJoin(D_DoomExeDir(), DIR_SEPARATOR_S, dir);
dir = rel;
}
I_Printf(VB_DEBUG, "Scanning for soundfonts in %s", dir);
glob = I_StartMultiGlob(dir, GLOB_FLAG_NOCASE | GLOB_FLAG_SORTED, "*.sf2",
"*.sf3");
@ -154,11 +164,6 @@ static void ScanDir(const char *dir)
}
I_EndGlob(glob);
if (rel)
{
free(rel);
}
}
static void GetSoundFonts(void)
@ -184,7 +189,7 @@ static void GetSoundFonts(void)
// as another soundfont dir
*p = '\0';
ScanDir(left);
ScanDir(left, false);
left = p + 1;
}
@ -194,7 +199,7 @@ static void GetSoundFonts(void)
}
}
ScanDir(left);
ScanDir(left, false);
free(dup_path);
}
@ -462,6 +467,7 @@ static void I_FL_BindVariables(void)
#if defined(_WIN32)
"soundfonts",
#else
"./soundfonts:"
// RedHat/Fedora/Arch
"/usr/share/soundfonts:"
// Debian/Ubuntu/OpenSUSE