diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -94,7 +94,6 @@ jobs: liblzo2-dev \ libsdl1.2-dev \ libsdl2-dev \ - libxdg-basedir-dev \ zlib1g-dev \ # EOF echo "::endgroup::" diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,7 +122,6 @@ if(NOT WIN32) find_package(Fluidsynth) find_package(Fontconfig) find_package(ICU OPTIONAL_COMPONENTS i18n lx) - find_package(XDG_basedir) else() find_package(Iconv) @@ -208,7 +207,6 @@ link_package(PNG TARGET PNG::PNG ENCOURA link_package(ZLIB TARGET ZLIB::ZLIB ENCOURAGED) link_package(LIBLZMA TARGET LibLZMA::LibLZMA ENCOURAGED) link_package(LZO) -link_package(XDG_basedir) if(NOT OPTION_DEDICATED) link_package(Fluidsynth) diff --git a/cmake/FindXDG_basedir.cmake b/cmake/FindXDG_basedir.cmake deleted file mode 100644 --- a/cmake/FindXDG_basedir.cmake +++ /dev/null @@ -1,65 +0,0 @@ -#[=======================================================================[.rst: -FindXDG_basedir -------- - -Finds the xdg-basedir library. - -Result Variables -^^^^^^^^^^^^^^^^ - -This will define the following variables: - -``XDG_basedir_FOUND`` - True if the system has the xdg-basedir library. -``XDG_basedir_INCLUDE_DIRS`` - Include directories needed to use xdg-basedir. -``XDG_basedir_LIBRARIES`` - Libraries needed to link to xdg-basedir. -``XDG_basedir_VERSION`` - The version of the xdg-basedir library which was found. - -Cache Variables -^^^^^^^^^^^^^^^ - -The following cache variables may also be set: - -``XDG_basedir_INCLUDE_DIR`` - The directory containing ``xdg-basedir.h``. -``XDG_basedir_LIBRARY`` - The path to the xdg-basedir library. - -#]=======================================================================] - -find_package(PkgConfig QUIET) -pkg_check_modules(PC_XDG_basedir QUIET libxdg-basedir) - -find_path(XDG_basedir_INCLUDE_DIR - NAMES basedir.h - PATHS ${PC_XDG_basedir_INCLUDE_DIRS} -) - -find_library(XDG_basedir_LIBRARY - NAMES xdg-basedir - PATHS ${PC_XDG_basedir_LIBRARY_DIRS} -) - -set(XDG_basedir_VERSION ${PC_XDG_basedir_VERSION}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(XDG_basedir - FOUND_VAR XDG_basedir_FOUND - REQUIRED_VARS - XDG_basedir_LIBRARY - XDG_basedir_INCLUDE_DIR - VERSION_VAR XDG_basedir_VERSION -) - -if(XDG_basedir_FOUND) - set(XDG_basedir_LIBRARIES ${XDG_basedir_LIBRARY}) - set(XDG_basedir_INCLUDE_DIRS ${XDG_basedir_INCLUDE_DIR}) -endif() - -mark_as_advanced( - XDG_basedir_INCLUDE_DIR - XDG_basedir_LIBRARY -) diff --git a/src/fileio.cpp b/src/fileio.cpp --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -28,10 +28,6 @@ #include #include -#ifdef WITH_XDG_BASEDIR -#include -#endif - #include "safeguards.h" /** Size of the #Fio data buffer. */ @@ -978,54 +974,65 @@ bool DoScanWorkingDirectory() } /** + * Gets the home directory of the user. + * May return an empty string in the unlikely scenario that the home directory cannot be found. + * @return User's home directory + */ +static std::string GetHomeDir() +{ +#ifdef __HAIKU__ + BPath path; + find_directory(B_USER_SETTINGS_DIRECTORY, &path); + return std::string(path.Path()); +#else + const char *home_env = getenv("HOME"); // Stack var, shouldn't be freed + if (home_env != nullptr) return std::string(home_env); + + const struct passwd *pw = getpwuid(getuid()); + if (pw != nullptr) return std::string(pw->pw_dir); +#endif + return {}; +} + +/** * Determine the base (personal dir and game data dir) paths * @param exe the path to the executable */ void DetermineBasePaths(const char *exe) { std::string tmp; -#if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) - const char *xdg_data_home = xdgDataHome(nullptr); - tmp = xdg_data_home; - tmp += PATHSEP; - tmp += PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR; - free(xdg_data_home); + const std::string homedir = GetHomeDir(); +#ifdef USE_XDG + const char *xdg_data_home = getenv("XDG_DATA_HOME"); + if (xdg_data_home != nullptr) { + tmp = xdg_data_home; + tmp += PATHSEP; + tmp += PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR; + AppendPathSeparator(tmp); - AppendPathSeparator(tmp); - _searchpaths[SP_PERSONAL_DIR_XDG] = tmp; + _searchpaths[SP_PERSONAL_DIR_XDG] = tmp; + } else if (!homedir.empty()) { + tmp = homedir; + tmp += PATHSEP ".local" PATHSEP "share" PATHSEP; + tmp += PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR; + AppendPathSeparator(tmp); + + _searchpaths[SP_PERSONAL_DIR_XDG] = tmp; + } else { + _searchpaths[SP_PERSONAL_DIR_XDG].clear(); + } #endif + #if defined(OS2) || !defined(WITH_PERSONAL_DIR) _searchpaths[SP_PERSONAL_DIR].clear(); #else -#ifdef __HAIKU__ - BPath path; - find_directory(B_USER_SETTINGS_DIRECTORY, &path); - const char *homedir = stredup(path.Path()); -#else - /* getenv is highly unsafe; duplicate it as soon as possible, - * or at least before something else touches the environment - * variables in any way. It can also contain all kinds of - * unvalidated data we rather not want internally. */ - const char *homedir = getenv("HOME"); - if (homedir != nullptr) { - homedir = stredup(homedir); - } - - if (homedir == nullptr) { - const struct passwd *pw = getpwuid(getuid()); - homedir = (pw == nullptr) ? nullptr : stredup(pw->pw_dir); - } -#endif - - if (homedir != nullptr) { - ValidateString(homedir); + if (!homedir.empty()) { tmp = homedir; tmp += PATHSEP; tmp += PERSONAL_DIR; AppendPathSeparator(tmp); _searchpaths[SP_PERSONAL_DIR] = tmp; - free(homedir); } else { _searchpaths[SP_PERSONAL_DIR].clear(); } @@ -1111,13 +1118,20 @@ void DeterminePaths(const char *exe) { DetermineBasePaths(exe); -#if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) - const char *xdg_config_home = xdgConfigHome(nullptr); - std::string config_home(xdg_config_home); - config_home += PATHSEP; - config_home += PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR; - free(xdg_config_home); - +#ifdef USE_XDG + std::string config_home; + const std::string homedir = GetHomeDir(); + const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); + if (xdg_config_home != nullptr) { + config_home = xdg_config_home; + config_home += PATHSEP; + config_home += PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR; + } else if (!homedir.empty()) { + /* Defaults to ~/.config */ + config_home = homedir; + config_home += PATHSEP ".config" PATHSEP; + config_home += PERSONAL_DIR[0] == '.' ? &PERSONAL_DIR[1] : PERSONAL_DIR; + } AppendPathSeparator(config_home); #endif @@ -1137,7 +1151,7 @@ void DeterminePaths(const char *exe) if (end != std::string::npos) personal_dir.erase(end + 1); config_dir = personal_dir; } else { -#if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) +#ifdef USE_XDG /* No previous configuration file found. Use the configuration folder from XDG. */ config_dir = config_home; #else @@ -1165,7 +1179,7 @@ void DeterminePaths(const char *exe) extern std::string _windows_file; _windows_file = config_dir + "windows.cfg"; -#if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) +#ifdef USE_XDG if (config_dir == config_home) { /* We are using the XDG configuration home for the config file, * then store the rest in the XDG data home folder. */ diff --git a/src/fileio_type.h b/src/fileio_type.h --- a/src/fileio_type.h +++ b/src/fileio_type.h @@ -131,7 +131,7 @@ enum Subdirectory { enum Searchpath : unsigned { SP_FIRST_DIR, SP_WORKING_DIR = SP_FIRST_DIR, ///< Search in the working directory -#if defined(WITH_XDG_BASEDIR) && defined(WITH_PERSONAL_DIR) +#ifdef USE_XDG SP_PERSONAL_DIR_XDG, ///< Search in the personal directory from the XDG specification #endif SP_PERSONAL_DIR, ///< Search in the personal directory diff --git a/src/stdafx.h b/src/stdafx.h --- a/src/stdafx.h +++ b/src/stdafx.h @@ -348,6 +348,11 @@ typedef unsigned char byte; # define PERSONAL_DIR "" #endif +/* Define the the platforms that use XDG */ +#if defined(WITH_PERSONAL_DIR) && defined(UNIX) && !defined(__APPLE__) +# define USE_XDG +#endif + /* Check if the types have the bitsizes like we are using them */ static_assert(sizeof(uint64) == 8); static_assert(sizeof(uint32) == 4);