diff --git a/es-core/src/utils/FileSystemUtil.cpp b/es-core/src/utils/FileSystemUtil.cpp index 5b56ad1e4..66bbaf729 100644 --- a/es-core/src/utils/FileSystemUtil.cpp +++ b/es-core/src/utils/FileSystemUtil.cpp @@ -20,6 +20,7 @@ #include "utils/FileSystemUtil.h" #include "Log.h" +#include "utils/PlatformUtil.h" #include "utils/StringUtil.h" #include @@ -256,15 +257,44 @@ namespace Utils return ""; #else #if defined(FLATPAK_BUILD) - // Ugly hack for the Flatpak build to find emulators installed as Flatpaks and Snaps. - // Note that due to limitations of this package format anything installed under /usr - // and similar system directories will not be possible to launch as they are shadowed - // by the Flatpak sandbox directories. Therefore they are excluded here. - std::string pathVariable { - "/var/lib/flatpak/exports/bin:/snap/bin:/var/lib/snapd/snap/bin"}; + // Ugly hack to compensate for the Flatpak sandbox restrictions. We traverse + // this hardcoded list of paths and use the "which" command to check outside the + // sandbox if the emulator binary exists. + std::string pathVariable {"/var/lib/flatpak/exports/bin:/usr/bin:/usr/local/" + "bin:/usr/local/sbin:/usr/sbin:/sbin:/bin:/usr/games:/usr/" + "local/games:/snap/bin:/var/lib/snapd/snap/bin"}; + + std::vector pathList { + Utils::String::delimitedStringToVector(pathVariable, ":")}; + + // Using a temporary file is the only viable solution I've found to communicate + // between the sandbox and the outside world. + std::string tempFile {Utils::FileSystem::getHomePath() + "/.emulationstation/" + + ".flatpak_emulator_binary_path.tmp"}; + + std::string emulatorPath; + + for (auto it = pathList.cbegin(); it != pathList.cend(); ++it) { + Utils::Platform::runSystemCommand("flatpak-spawn --host which " + *it + "/" + + executable + " > " + tempFile); + std::ifstream tempFileStream; + tempFileStream.open(tempFile); + getline(tempFileStream, emulatorPath); + tempFileStream.close(); + + if (emulatorPath != "") { + emulatorPath = getParent(emulatorPath); + break; + } + } + + if (exists(tempFile)) + removeFile(tempFile); + + return emulatorPath; #else std::string pathVariable {std::string(getenv("PATH"))}; -#endif + std::vector pathList { Utils::String::delimitedStringToVector(pathVariable, ":")}; @@ -277,6 +307,7 @@ namespace Utils return it->c_str(); } return ""; +#endif #endif }