From dc39e5057668e1face08c4fad82d1fce9a3d804e Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Sat, 6 Jul 2024 17:19:42 -0400 Subject: [PATCH 1/3] modding: Handle PHYSFS_mount failures --- src/modding.cpp | 42 +++++++++++++++++++++++++++--------------- src/modding.h | 3 ++- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/modding.cpp b/src/modding.cpp index 3d763562a51..7b932318b7c 100644 --- a/src/modding.cpp +++ b/src/modding.cpp @@ -44,7 +44,7 @@ static std::vector mod_names_list; static std::vector mod_hash_list; -static void addLoadedMod(std::string modname, std::string filename); +static void addLoadedMod(std::string modname, std::string filename, const std::string& fullRealPath); static inline std::vector split(std::string const &str, std::string const &sep) @@ -107,27 +107,38 @@ size_t addSubdirs(const char *basedir, const char *subdir, const bool appendToPa { size_t numAddedMods = 0; const WzString subdir_platformDependent = convertToPlatformDependentPath(subdir); + std::string tmpFullModRealPath; WZ_PHYSFS_enumerateFiles(subdir, [&](const char *i) -> bool { #ifdef DEBUG debug(LOG_NEVER, "Examining subdir: [%s]", i); #endif // DEBUG if (i[0] != '.' && (!checkList || std::find(checkList->begin(), checkList->end(), i) != checkList->end())) { - char tmpstr[PATH_MAX]; - snprintf(tmpstr, sizeof(tmpstr), "%s%s%s%s", basedir, subdir_platformDependent.toUtf8().c_str(), PHYSFS_getDirSeparator(), i); + // platform-dependent notation + tmpFullModRealPath = basedir; + tmpFullModRealPath += subdir_platformDependent.toUtf8(); + tmpFullModRealPath += PHYSFS_getDirSeparator(); + tmpFullModRealPath += i; #ifdef DEBUG - debug(LOG_NEVER, "Adding [%s] to search path", tmpstr); + debug(LOG_NEVER, "Adding [%s] to search path", tmpFullModRealPath.c_str()); #endif // DEBUG - if (addToModList) + if (PHYSFS_mount(tmpFullModRealPath.c_str(), NULL, appendToPath) != 0) // platform-dependent notation { - std::string filename = astringf("%s/%s", subdir, i); // platform-independent notation - addLoadedMod(i, std::move(filename)); - char buf[256]; - snprintf(buf, sizeof(buf), "mod: %s", i); - addDumpInfo(buf); + numAddedMods++; + if (addToModList) + { + std::string filename = astringf("%s/%s", subdir, i); // platform-independent notation + addLoadedMod(i, std::move(filename), tmpFullModRealPath); + char buf[256]; + snprintf(buf, sizeof(buf), "mod: %s", i); + addDumpInfo(buf); + } + } + else + { + // failed to mount mod + debug(LOG_WZ, "Failed to load mod from path: %s, %s", tmpFullModRealPath.c_str(), WZ_PHYSFS_getLastError()); } - PHYSFS_mount(tmpstr, NULL, appendToPath); // platform-dependent notation - numAddedMods++; } return true; // continue }); @@ -198,10 +209,10 @@ bool hasCampaignMods() return !campaign_mods.empty(); } -static void addLoadedMod(std::string modname, std::string filename) +static void addLoadedMod(std::string modname, std::string filename, const std::string& fullRealPath) { // Note, findHashOfFile won't work right now, since the search paths aren't set up until after all calls to addSubdirs, see rebuildSearchPath in init.cpp. - loaded_mods.emplace_back(std::move(modname), std::move(filename)); + loaded_mods.emplace_back(std::move(modname), std::move(filename), fullRealPath); mod_list.clear(); mod_names_list.clear(); mod_hash_list.clear(); @@ -252,9 +263,10 @@ std::vector const &getModNamesList() return mod_names_list; } -WzMods::LoadedMod::LoadedMod(const std::string& name, const std::string& filename) +WzMods::LoadedMod::LoadedMod(const std::string& name, const std::string& filename, const std::string& fullRealPath) : name(name) , filename(filename) +, fullRealPath(fullRealPath) { } Sha256& WzMods::LoadedMod::getHash() diff --git a/src/modding.h b/src/modding.h index 9b7d8b40f48..26cb43ff17e 100644 --- a/src/modding.h +++ b/src/modding.h @@ -45,8 +45,9 @@ struct LoadedMod { std::string name; std::string filename; + std::string fullRealPath; - LoadedMod(const std::string& name, const std::string& filename); + LoadedMod(const std::string& name, const std::string& filename, const std::string& fullRealPath); Sha256& getHash(); private: From 30b2ded344daaf134d7aef7e07316595e3fedb72 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Sat, 6 Jul 2024 17:36:00 -0400 Subject: [PATCH 2/3] modding: Additional sanity checks --- src/modding.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/modding.cpp b/src/modding.cpp index 7b932318b7c..4e8d76e620f 100644 --- a/src/modding.cpp +++ b/src/modding.cpp @@ -45,6 +45,7 @@ static std::vector mod_hash_list; static void addLoadedMod(std::string modname, std::string filename, const std::string& fullRealPath); +static bool hasLoadedModRealPath(const std::string& fullRealPath); static inline std::vector split(std::string const &str, std::string const &sep) @@ -122,6 +123,11 @@ size_t addSubdirs(const char *basedir, const char *subdir, const bool appendToPa #ifdef DEBUG debug(LOG_NEVER, "Adding [%s] to search path", tmpFullModRealPath.c_str()); #endif // DEBUG + if (hasLoadedModRealPath(tmpFullModRealPath)) + { + debug(LOG_INFO, "Already loaded: %s, skipping", tmpFullModRealPath.c_str()); + return true; // continue + } if (PHYSFS_mount(tmpFullModRealPath.c_str(), NULL, appendToPath) != 0) // platform-dependent notation { numAddedMods++; @@ -218,6 +224,13 @@ static void addLoadedMod(std::string modname, std::string filename, const std::s mod_hash_list.clear(); } +static bool hasLoadedModRealPath(const std::string& fullRealPath) +{ + return std::any_of(loaded_mods.begin(), loaded_mods.end(), [fullRealPath](const WzMods::LoadedMod& loadedMod) -> bool { + return loadedMod.fullRealPath == fullRealPath; + }); +} + void clearLoadedMods() { loaded_mods.clear(); From 1c469121d798cdae4267874a45913402f310d570 Mon Sep 17 00:00:00 2001 From: past-due <30942300+past-due@users.noreply.github.com> Date: Sat, 6 Jul 2024 17:58:09 -0400 Subject: [PATCH 3/3] modding: Adjust mod mount failure logging --- src/modding.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/modding.cpp b/src/modding.cpp index 4e8d76e620f..656b6915f93 100644 --- a/src/modding.cpp +++ b/src/modding.cpp @@ -143,7 +143,29 @@ size_t addSubdirs(const char *basedir, const char *subdir, const bool appendToPa else { // failed to mount mod - debug(LOG_WZ, "Failed to load mod from path: %s, %s", tmpFullModRealPath.c_str(), WZ_PHYSFS_getLastError()); + code_part log_level = LOG_WZ; +#if defined(WZ_PHYSFS_2_1_OR_GREATER) + auto errorCode = PHYSFS_getLastErrorCode(); + switch (errorCode) + { + case PHYSFS_ERR_CORRUPT: + log_level = LOG_ERROR; + break; + case PHYSFS_ERR_NOT_FOUND: + default: + log_level = LOG_WZ; + break; + } + const char* pErrStr = PHYSFS_getErrorByCode(errorCode); +#else + const char* pErrStr = WZ_PHYSFS_getLastError(); +#endif + if (!pErrStr) + { + pErrStr = ""; + } + debug(log_level, "Failed to load mod from path: %s, %s", tmpFullModRealPath.c_str(), pErrStr); + } } return true; // continue