diff --git a/include/Startup.h b/include/Startup.h index 55809b8..232036f 100644 --- a/include/Startup.h +++ b/include/Startup.h @@ -13,6 +13,7 @@ void InitLauncher(); beammp_fs_string GetEP(const beammp_fs_char* P = nullptr); +std::filesystem::path GetBP(const beammp_fs_char* P = nullptr); std::filesystem::path GetGamePath(); std::string GetVer(); std::string GetPatch(); diff --git a/include/Utils.h b/include/Utils.h index 3c8381e..c0f4e21 100644 --- a/include/Utils.h +++ b/include/Utils.h @@ -236,7 +236,7 @@ namespace Utils { for (size_t i = 0; i < sha256_len; i++) { char buf[3]; sprintf(buf, "%02x", sha256_value[i]); - buf[2] = NULL; + buf[2] = '\0'; result += buf; } return result; @@ -280,7 +280,7 @@ namespace Utils { for (size_t i = 0; i < sha256_len; i++) { char buf[3]; sprintf(buf, "%02x", sha256_value[i]); - buf[2] = NULL; + buf[2] = '\0'; result += buf; } return result; diff --git a/src/Startup.cpp b/src/Startup.cpp index 0335877..5cfcb6d 100644 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -14,7 +14,10 @@ #if defined(_WIN32) #elif defined(__linux__) #include -#endif +#elif defined (__APPLE__) +#include +#include +#endif // __APPLE__ #include "Http.h" #include "Logger.h" #include "Network/network.hpp" @@ -94,6 +97,34 @@ beammp_fs_string GetEP(const beammp_fs_char* P) { }(); return Ret; } + +fs::path GetBP(const beammp_fs_char* P) { + fs::path fspath = {}; +#if defined(_WIN32) + beammp_fs_char path[256]; + GetModuleFileNameW(nullptr, path, sizeof(path)); + fspath = path; +#elif defined(__linux__) + fspath = fs::canonical("/proc/self/exe"); +#elif defined(__APPLE__) + pid_t pid = getpid(); + char path[PROC_PIDPATHINFO_MAXSIZE]; + // While this is fine for a raw executable, + // an application bundle is read-only and these files + // should instead be placed in Application Support. + proc_pidpath(pid, path, sizeof(path)); + fspath = std::string(path); + #else + fspath = beammp_fs_string(P); +#endif + fspath = fs::weakly_canonical(fspath.string() + "/.."); +#if defined(_WIN32) + return fspath.wstring(); +#else + return fspath.string(); +#endif +} + #if defined(_WIN32) void ReLaunch() { std::wstring Arg; @@ -103,7 +134,7 @@ void ReLaunch() { } info("Relaunch!"); system("cls"); - ShellExecuteW(nullptr, L"runas", (GetEP() + GetEN()).c_str(), Arg.c_str(), nullptr, SW_SHOWNORMAL); + ShellExecuteW(nullptr, L"runas", (GetBP() / GetEN()).c_str(), Arg.c_str(), nullptr, SW_SHOWNORMAL); ShowWindow(GetConsoleWindow(), 0); std::this_thread::sleep_for(std::chrono::seconds(1)); exit(1); @@ -114,7 +145,7 @@ void URelaunch() { Arg += Utils::ToWString(options.argv[c - 1]); Arg += L" "; } - ShellExecuteW(nullptr, L"open", (GetEP() + GetEN()).c_str(), Arg.c_str(), nullptr, SW_SHOWNORMAL); + ShellExecuteW(nullptr, L"open", (GetBP() / GetEN()).c_str(), Arg.c_str(), nullptr, SW_SHOWNORMAL); ShowWindow(GetConsoleWindow(), 0); std::this_thread::sleep_for(std::chrono::seconds(1)); exit(1); @@ -128,7 +159,7 @@ void ReLaunch() { } info("Relaunch!"); system("clear"); - int ret = execv(options.executable_name.c_str(), const_cast(options.argv)); + int ret = execv((GetBP() / GetEN()).c_str(), const_cast(options.argv)); if (ret < 0) { error(std::string("execv() failed with: ") + strerror(errno) + ". Failed to relaunch"); exit(1); @@ -137,7 +168,7 @@ void ReLaunch() { exit(1); } void URelaunch() { - int ret = execv(options.executable_name.c_str(), const_cast(options.argv)); + int ret = execv((GetBP() / GetEN()).c_str(), const_cast(options.argv)); if (ret < 0) { error(std::string("execv() failed with: ") + strerror(errno) + ". Failed to relaunch"); exit(1); @@ -169,9 +200,9 @@ void CheckForUpdates(const std::string& CV) { "https://backend.beammp.com/version/launcher?branch=" + Branch + "&pk=" + PublicKey); transform(LatestHash.begin(), LatestHash.end(), LatestHash.begin(), ::tolower); - beammp_fs_string EP(GetEP() + GetEN()), Back(GetEP() + beammp_wide("BeamMP-Launcher.back")); + beammp_fs_string BP(GetBP() / GetEN()), Back(GetBP() / beammp_wide("BeamMP-Launcher.back")); - std::string FileHash = Utils::GetSha256HashReallyFastFile(EP); + std::string FileHash = Utils::GetSha256HashReallyFastFile(BP); if (FileHash != LatestHash && IsOutdated(Version(VersionStrToInts(GetVer() + GetPatch())), Version(VersionStrToInts(LatestVersion)))) { if (!options.no_update) { @@ -184,16 +215,16 @@ void CheckForUpdates(const std::string& CV) { "https://backend.beammp.com/builds/launcher?download=true" "&pk=" + PublicKey + "&branch=" + Branch, - beammp_wide("new_") + EP, LatestHash); + beammp_wide("new_") + BP, LatestHash); std::error_code ec; fs::remove(Back, ec); if (ec == std::errc::permission_denied) { error("Failed to remove old backup file: " + ec.message() + ". Using alternative name."); - fs::rename(EP, Back + beammp_wide(".") + Utils::ToWString(FileHash.substr(0, 8))); + fs::rename(BP, Back + beammp_wide(".") + Utils::ToWString(FileHash.substr(0, 8))); } else { - fs::rename(EP, Back); + fs::rename(BP, Back); } - fs::rename(beammp_wide("new_") + EP, EP); + fs::rename(beammp_wide("new_") + BP, BP); URelaunch(); #endif } else { @@ -254,8 +285,8 @@ void InitLauncher() { } #endif -size_t DirCount(const std::filesystem::path& path) { - return (size_t)std::distance(std::filesystem::directory_iterator { path }, std::filesystem::directory_iterator {}); +size_t DirCount(const fs::path& path) { + return (size_t)std::distance(fs::directory_iterator { path }, fs::directory_iterator {}); } void CheckMP(const beammp_fs_string& Path) {