Detect data dirs at runtime

* Respecting the current platform
* Using them where appropiate
This commit is contained in:
Linus Dierheimer
2023-01-08 01:41:09 +01:00
parent bb57714ac9
commit 2a092de8d8
11 changed files with 225 additions and 191 deletions
+127 -106
View File
@@ -18,140 +18,160 @@
#include <signal.h>
#endif
static void initConfigDirs(FFstate* state)
#define FF_ENSURE_ONLY_ONCE_IN_LIST(list, element) \
if(ffListFirstIndexComp(list, element, (bool(*)(const void*, const void*))ffStrbufEqual) < list->length - 1) \
{ \
ffStrbufDestroy(ffListGet(list, list->length - 1)); \
--list->length; \
}
#ifdef _WIN32
void pathsAddKnownFolder(FFlist* dirs, REFKNOWNFOLDERID folderId)
{
ffListInit(&state->configDirs, sizeof(FFstrbuf));
#ifdef _WIN32
PWSTR pPath;
if(SUCCEEDED(SHGetKnownFolderPath(folderId, 0, NULL, &pPath)))
{
PWSTR pPath;
if(SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &pPath)))
{
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInit(buffer);
ffStrbufSetWS(buffer, pPath);
ffStrbufReplaceAllC(buffer, '\\', '/');
ffStrbufEnsureEndsWithC(buffer, '/');
}
CoTaskMemFree(pPath);
}
#elif defined(__APPLE__)
{
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInitS(buffer, state->passwd->pw_dir);
ffStrbufAppendS(buffer, "/Library/Preferences/");
}
#else
const char* xdgConfigHome = getenv("XDG_CONFIG_HOME");
if(ffStrSet(xdgConfigHome))
{
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, xdgConfigHome);
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs);
ffStrbufInit(buffer);
ffStrbufSetWS(buffer, pPath);
ffStrbufReplaceAllC(buffer, '\\', '/');
ffStrbufEnsureEndsWithC(buffer, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer);
}
CoTaskMemFree(pPath);
}
#endif
void pathsAddEnvSuffix(FFlist* dirs, const char* env, const char* suffix)
{
const char* value = getenv(env);
if(!ffStrSet(value))
return;
#define FF_ENSURE_ONLY_ONCE_IN_LIST(element) \
if(ffListFirstIndexComp(&state->configDirs, element, (bool(*)(const void*, const void*))ffStrbufEqual) < state->configDirs.length - 1) \
{ \
ffStrbufDestroy(ffListGet(&state->configDirs, state->configDirs.length - 1)); \
--state->configDirs.length; \
}
FFstrbuf* buffer = ffListAdd(dirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, value);
ffStrbufReplaceAllC(buffer, '\\', '/');
ffStrbufEnsureEndsWithC(buffer, '/');
ffStrbufAppendS(buffer, suffix);
ffStrbufEnsureEndsWithC(buffer, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer);
}
#endif
FFstrbuf* userConfigHome = ffListAdd(&state->configDirs);
ffStrbufInitA(userConfigHome, 64);
ffStrbufAppendS(userConfigHome, state->passwd->pw_dir);
ffStrbufAppendS(userConfigHome, "/.config/");
FF_ENSURE_ONLY_ONCE_IN_LIST(userConfigHome)
void pathsAddHome(FFlist* dirs, FFstate* state, const char* suffix)
{
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, state->passwd->pw_dir);
ffStrbufAppendS(buffer, suffix);
ffStrbufEnsureEndsWithC(buffer, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer);
}
FFstrbuf* userHome = ffListAdd(&state->configDirs);
ffStrbufInitA(userHome, 64);
ffStrbufAppendS(userHome, state->passwd->pw_dir);
ffStrbufEnsureEndsWithC(userHome, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(userHome)
void pathsAddAbsolute(FFlist* dirs, const char* path)
{
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(dirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, path);
ffStrbufEnsureEndsWithC(buffer, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(dirs, buffer);
}
#ifdef _WIN32
if(getenv("MSYSTEM") && getenv("HOME"))
{
// We are in MSYS2 / Git Bash
FFstrbuf* msysConfigHome = ffListAdd(&state->configDirs);
ffStrbufInitA(msysConfigHome, 64);
ffStrbufAppendS(msysConfigHome, getenv("HOME"));
ffStrbufReplaceAllC(msysConfigHome, '\\', '/');
ffStrbufEnsureEndsWithC(msysConfigHome, '/');
ffStrbufAppendS(msysConfigHome, ".config/");
FF_ENSURE_ONLY_ONCE_IN_LIST(msysConfigHome)
FFstrbuf* msysHome = ffListAdd(&state->configDirs);
ffStrbufInitA(msysHome, 64);
ffStrbufAppendS(msysHome, getenv("HOME"));
ffStrbufReplaceAllC(msysHome, '\\', '/');
ffStrbufEnsureEndsWithC(msysHome, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(msysHome)
}
#endif
#if !defined(_WIN32) && !defined(__APPLE__)
FFstrbuf xdgConfigDirs;
ffStrbufInitA(&xdgConfigDirs, 64);
ffStrbufAppendS(&xdgConfigDirs, getenv("XDG_CONFIG_DIRS"));
void pathsAddEnv(FFlist* dirs, const char* env)
{
FFstrbuf value;
ffStrbufInitA(&value, 64);
ffStrbufAppendS(&value, getenv(env));
uint32_t startIndex = 0;
while (startIndex < xdgConfigDirs.length)
while (startIndex < value.length)
{
uint32_t colonIndex = ffStrbufNextIndexC(&xdgConfigDirs, startIndex, ':');
xdgConfigDirs.chars[colonIndex] = '\0';
uint32_t colonIndex = ffStrbufNextIndexC(&value, startIndex, ':');
value.chars[colonIndex] = '\0';
if(!ffStrSet(xdgConfigDirs.chars + startIndex))
if(!ffStrSet(value.chars + startIndex))
{
startIndex = colonIndex + 1;
continue;
}
FFstrbuf* buffer = (FFstrbuf*) ffListAdd(&state->configDirs);
ffStrbufInitA(buffer, 64);
ffStrbufAppendS(buffer, xdgConfigDirs.chars + startIndex);
ffStrbufEnsureEndsWithC(buffer, '/');
FF_ENSURE_ONLY_ONCE_IN_LIST(buffer);
pathsAddAbsolute(dirs, value.chars + startIndex);
startIndex = colonIndex + 1;
}
ffStrbufDestroy(&xdgConfigDirs);
FFstrbuf* systemConfigHome = ffListAdd(&state->configDirs);
ffStrbufInitA(systemConfigHome, 64);
ffStrbufAppendS(systemConfigHome, FASTFETCH_TARGET_DIR_ETC"/xdg/");
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfigHome)
ffStrbufDestroy(&value);
}
static void initConfigDirs(FFstate* state)
{
ffListInit(&state->configDirs, sizeof(FFstrbuf));
#ifdef _WIN32
pathsAddKnownFolder(&state->configDirs, &FOLDERID_RoamingAppData);
pathsAddKnownFolder(&state->configDirs, &FOLDERID_LocalAppData);
#elif defined(__APPLE__)
pathsAddHome(&state->configDirs, state, "/Library/Preferences/");
#else
pathsAddEnv(&state->configDirs, "XDG_CONFIG_HOME");
#endif
#ifndef _WIN32
FFstrbuf* systemConfig = ffListAdd(&state->configDirs);
ffStrbufInitA(systemConfig, 64);
ffStrbufAppendS(systemConfig, FASTFETCH_TARGET_DIR_ETC"/");
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfig)
FFstrbuf* systemConfigInstall = ffListAdd(&state->configDirs);
ffStrbufInitA(systemConfigInstall, 64);
ffStrbufAppendS(systemConfigInstall, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/");
FF_ENSURE_ONLY_ONCE_IN_LIST(systemConfigInstall)
pathsAddHome(&state->configDirs, state, "/.config/");
pathsAddHome(&state->configDirs, state, "");
#ifdef _WIN32
if(getenv("MSYSTEM") && getenv("HOME"))
{
// We are in MSYS2 / Git Bash
pathsAddEnvSuffix(&state->configDirs, "HOME", ".config/");
pathsAddEnvSuffix(&state->configDirs, "HOME", "");
}
#endif
#undef FF_ENSURE_ONLY_ONCE_IN_LIST
#if !defined(_WIN32) && !defined(__APPLE__)
pathsAddEnv(&state->configDirs, "XDG_CONFIG_DIRS");
pathsAddAbsolute(&state->configDirs, FASTFETCH_TARGET_DIR_ETC"/xdg/");
#endif
#if !defined(_WIN32)
pathsAddAbsolute(&state->configDirs, FASTFETCH_TARGET_DIR_ETC"/");
pathsAddAbsolute(&state->configDirs, FASTFETCH_TARGET_DIR_INSTALL_SYSCONF"/");
#endif
}
static void initDataDirs(FFstate* state)
{
ffListInit(&state->dataDirs, sizeof(FFstrbuf));
#ifdef _WIN32
pathsAddKnownFolder(&state->dataDirs, &FOLDERID_RoamingAppData);
pathsAddKnownFolder(&state->dataDirs, &FOLDERID_LocalAppData);
#elif defined(__APPLE__)
pathsAddHome(&state->dataDirs, state, "/Library/Application Support/");
#else
pathsAddEnv(&state->dataDirs, "XDG_DATA_HOME");
#endif
pathsAddHome(&state->dataDirs, state, "/.local/share/");
pathsAddHome(&state->dataDirs, state, "");
#ifdef _WIN32
if(getenv("MSYSTEM") && getenv("HOME"))
{
// We are in MSYS2 / Git Bash
pathsAddEnvSuffix(&state->dataDirs, "HOME", ".local/share/");
pathsAddEnvSuffix(&state->dataDirs, "HOME", "");
}
#endif
#if !defined(_WIN32) && !defined(__APPLE__)
pathsAddEnv(&state->dataDirs, "XDG_DATA_DIRS");
#endif
#if !defined(_WIN32)
pathsAddAbsolute(&state->dataDirs, FASTFETCH_TARGET_DIR_USR"/local/share/");
pathsAddAbsolute(&state->dataDirs, FASTFETCH_TARGET_DIR_USR"/share/");
#endif
}
static void initState(FFstate* state)
@@ -172,6 +192,7 @@ static void initState(FFstate* state)
uname(&state->utsname);
initConfigDirs(state);
initDataDirs(state);
}
static void initModuleArg(FFModuleArgs* args)