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)
+4 -19
View File
@@ -144,11 +144,6 @@ done:
return true;
}
bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}});
}
bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
FFstrbuf absolutePath;
@@ -164,22 +159,17 @@ bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeF
return result;
}
bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
bool foundAFile = false;
FFstrbuf baseDir;
ffStrbufInitA(&baseDir, 64);
for(uint32_t i = 0; i < instance->state.configDirs.length; i++)
for(uint32_t i = 0; i < list->length; i++)
{
//We need to copy the config dir each time, because it used by multiple threads, so we can't directly write to it.
ffStrbufSet(&baseDir, ffListGet(&instance->state.configDirs, i));
//We need to copy the dir each time, because it used by multiple threads, so we can't directly write to it.
ffStrbufSet(&baseDir, ffListGet(list, i));
ffStrbufAppendS(&baseDir, relativeFile);
if(ffParsePropFileValues(baseDir.chars, numQueries, queries))
@@ -203,8 +193,3 @@ bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativ
return foundAFile;
}
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
+36 -4
View File
@@ -14,10 +14,42 @@ typedef struct FFpropquery
bool ffParsePropLine(const char* line, const char* start, FFstrbuf* buffer);
bool ffParsePropLines(const char* lines, const char* start, FFstrbuf* buffer);
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries);
bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer);
bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
bool ffParsePropFileListValues(const FFlist* list, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
static inline bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}});
}
static inline bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
static inline bool ffParsePropFileList(const FFlist* list, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileListValues(list, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
static inline bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
return ffParsePropFileListValues(&instance->state.configDirs, relativeFile, numQueries, queries);
}
static inline bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
static inline bool ffParsePropFileDataValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
{
return ffParsePropFileListValues(&instance->state.dataDirs, relativeFile, numQueries, queries);
}
static inline bool ffParsePropFileData(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
{
return ffParsePropFileDataValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
}
#endif