From 04c5cd519f1c42e73fa0969d7307cd33e337c83d Mon Sep 17 00:00:00 2001 From: jolavillette Date: Mon, 25 May 2026 09:46:39 +0200 Subject: [PATCH 1/5] feature/relative-plugin-paths --- src/rsserver/rsinit.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/rsserver/rsinit.cc b/src/rsserver/rsinit.cc index 1629eb3c8c..4535ffa787 100644 --- a/src/rsserver/rsinit.cc +++ b/src/rsserver/rsinit.cc @@ -1306,6 +1306,20 @@ int RsServer::StartupRetroShare() #ifdef __APPLE__ plugins_directories.push_back(RsAccounts::systemDataDirectory()) ; #endif + + // Add dynamic paths relative to the running binary first, to prevent cross-version conflicts! + std::string exe_path = RsInit::executablePath(); + if (!exe_path.empty()) + { + std::string canonical_exe_path = RsDirUtil::removeSymLinks(exe_path); + std::string exe_dir = RsDirUtil::getDirectory(canonical_exe_path.empty() ? exe_path : canonical_exe_path); + if (!exe_dir.empty()) + { + plugins_directories.push_back(exe_dir + "/../lib/retroshare/extensions6/"); + plugins_directories.push_back(exe_dir + "/lib/retroshare/extensions6/"); + } + } + #if !defined(WINDOWS_SYS) && defined(PLUGIN_DIR) plugins_directories.push_back(std::string(PLUGIN_DIR)) ; #endif From 3c0e8e234df8f5b2a7b3b2e5929ae01b8e4a25ed Mon Sep 17 00:00:00 2001 From: jolavillette Date: Tue, 26 May 2026 03:55:07 +0200 Subject: [PATCH 2/5] Fix duplicate plugin loads by de-duplicating and canonicalizing search paths --- src/rsserver/rsinit.cc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/rsserver/rsinit.cc b/src/rsserver/rsinit.cc index 4535ffa787..82f11af43b 100644 --- a/src/rsserver/rsinit.cc +++ b/src/rsserver/rsinit.cc @@ -1326,6 +1326,33 @@ int RsServer::StartupRetroShare() std::string extensions_dir = RsAccounts::ConfigDirectory() + "/extensions6/" ; plugins_directories.push_back(extensions_dir) ; + // Canonicalize and de-duplicate directories to avoid double plugin loads and clean up listed paths + std::vector unique_directories; + for (size_t i = 0; i < plugins_directories.size(); ++i) + { + std::string clean_dir = RsDirUtil::removeSymLinks(plugins_directories[i]); + if (clean_dir.empty()) { + clean_dir = plugins_directories[i]; + } + if (!clean_dir.empty() && clean_dir.back() != '/' && clean_dir.back() != '\\') { + clean_dir += "/"; + } + bool already_exists = false; + for (size_t j = 0; j < unique_directories.size(); ++j) + { + if (unique_directories[j] == clean_dir) + { + already_exists = true; + break; + } + } + if (!already_exists) + { + unique_directories.push_back(clean_dir); + } + } + plugins_directories = unique_directories; + if(!RsDirUtil::checkCreateDirectory(extensions_dir)) std::cerr << "(EE) Cannot create extensions directory " << extensions_dir << ". This is not mandatory, but you probably have a permission problem." << std::endl; From 0a5781b564ea6627e580d4fda23b9b6a4d01688e Mon Sep 17 00:00:00 2001 From: jolavillette Date: Wed, 27 May 2026 03:06:18 +0200 Subject: [PATCH 3/5] Add PLUGINSDIR debug logs to trace plugin lookup --- src/rsserver/rsinit.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/rsserver/rsinit.cc b/src/rsserver/rsinit.cc index 82f11af43b..66eaa87e0b 100644 --- a/src/rsserver/rsinit.cc +++ b/src/rsserver/rsinit.cc @@ -1309,21 +1309,32 @@ int RsServer::StartupRetroShare() // Add dynamic paths relative to the running binary first, to prevent cross-version conflicts! std::string exe_path = RsInit::executablePath(); + RsInfo() << "PLUGINSDIR: Raw executable path from RsInit: " << exe_path; + if (!exe_path.empty()) { std::string canonical_exe_path = RsDirUtil::removeSymLinks(exe_path); + RsInfo() << "PLUGINSDIR: Canonicalized executable path: " << canonical_exe_path; + std::string exe_dir = RsDirUtil::getDirectory(canonical_exe_path.empty() ? exe_path : canonical_exe_path); + RsInfo() << "PLUGINSDIR: Extracted binary directory: " << exe_dir; + if (!exe_dir.empty()) { + RsInfo() << "PLUGINSDIR: Adding dynamic relative search path 1: " << exe_dir + "/../lib/retroshare/extensions6/"; plugins_directories.push_back(exe_dir + "/../lib/retroshare/extensions6/"); + + RsInfo() << "PLUGINSDIR: Adding dynamic relative search path 2: " << exe_dir + "/lib/retroshare/extensions6/"; plugins_directories.push_back(exe_dir + "/lib/retroshare/extensions6/"); } } #if !defined(WINDOWS_SYS) && defined(PLUGIN_DIR) + RsInfo() << "PLUGINSDIR: Adding compile-time hardcoded PLUGIN_DIR: " << PLUGIN_DIR; plugins_directories.push_back(std::string(PLUGIN_DIR)) ; #endif std::string extensions_dir = RsAccounts::ConfigDirectory() + "/extensions6/" ; + RsInfo() << "PLUGINSDIR: Adding user home extensions directory: " << extensions_dir; plugins_directories.push_back(extensions_dir) ; // Canonicalize and de-duplicate directories to avoid double plugin loads and clean up listed paths @@ -1353,6 +1364,12 @@ int RsServer::StartupRetroShare() } plugins_directories = unique_directories; + RsInfo() << "PLUGINSDIR: Final de-duplicated search directories:"; + for (size_t i = 0; i < plugins_directories.size(); ++i) + { + RsInfo() << "PLUGINSDIR: [" << i << "] -> " << plugins_directories[i]; + } + if(!RsDirUtil::checkCreateDirectory(extensions_dir)) std::cerr << "(EE) Cannot create extensions directory " << extensions_dir << ". This is not mandatory, but you probably have a permission problem." << std::endl; From d03a0199ec86ad6a2924f4faf084244575f0bd33 Mon Sep 17 00:00:00 2001 From: jolavillette Date: Wed, 27 May 2026 03:43:53 +0200 Subject: [PATCH 4/5] Resolve relative path components textually for non-existent search paths --- src/rsserver/rsinit.cc | 71 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/src/rsserver/rsinit.cc b/src/rsserver/rsinit.cc index 66eaa87e0b..74878e7de1 100644 --- a/src/rsserver/rsinit.cc +++ b/src/rsserver/rsinit.cc @@ -61,6 +61,70 @@ #include #include +#include + +namespace { +std::string resolvePathTextually(const std::string& path) +{ + if (path.empty()) return ""; + bool is_absolute = (path[0] == '/'); + bool has_drive = false; + std::string drive = ""; + std::string rest = path; + if (path.size() >= 2 && path[1] == ':') { + has_drive = true; + drive = path.substr(0, 2); + rest = path.substr(2); + if (rest.size() > 0 && (rest[0] == '/' || rest[0] == '\\')) { + drive += rest[0]; + rest = rest.substr(1); + } + } + + std::vector segments; + std::string segment; + for (size_t i = 0; i < rest.size(); ++i) { + char c = rest[i]; + if (c == '/' || c == '\\') { + if (!segment.empty()) { + if (segment == "..") { + if (!segments.empty()) { + segments.pop_back(); + } + } else if (segment != ".") { + segments.push_back(segment); + } + segment.clear(); + } + } else { + segment.push_back(c); + } + } + if (!segment.empty()) { + if (segment == "..") { + if (!segments.empty()) { + segments.pop_back(); + } + } else if (segment != ".") { + segments.push_back(segment); + } + } + + std::string result = has_drive ? drive : (is_absolute ? "/" : ""); + for (size_t i = 0; i < segments.size(); ++i) { + result += segments[i]; + if (i + 1 < segments.size()) { + result += "/"; + } + } + if (!path.empty() && (path.back() == '/' || path.back() == '\\')) { + if (result.empty() || (result.back() != '/' && result.back() != '\\')) { + result += "/"; + } + } + return result; +} +} // namespace #include #include @@ -1341,9 +1405,10 @@ int RsServer::StartupRetroShare() std::vector unique_directories; for (size_t i = 0; i < plugins_directories.size(); ++i) { - std::string clean_dir = RsDirUtil::removeSymLinks(plugins_directories[i]); - if (clean_dir.empty()) { - clean_dir = plugins_directories[i]; + std::string clean_dir = resolvePathTextually(plugins_directories[i]); + std::string sym_resolved = RsDirUtil::removeSymLinks(clean_dir); + if (!sym_resolved.empty()) { + clean_dir = sym_resolved; } if (!clean_dir.empty() && clean_dir.back() != '/' && clean_dir.back() != '\\') { clean_dir += "/"; From 8088acf2b82586b5a0943cd63930b7e794f28cec Mon Sep 17 00:00:00 2001 From: jolavillette Date: Wed, 27 May 2026 06:40:01 +0200 Subject: [PATCH 5/5] Add PLUGINSDIR debug log for successfully loaded plugins in memory --- src/plugins/pluginmanager.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/pluginmanager.cc b/src/plugins/pluginmanager.cc index 70371360ee..d357a3e444 100644 --- a/src/plugins/pluginmanager.cc +++ b/src/plugins/pluginmanager.cc @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -415,6 +416,9 @@ bool RsPluginManager::loadPlugin(const std::string& plugin_name,bool first_time) pinfo.info_string = "" ; _accepted_hashes.insert(pinfo.file_hash) ; // do it now, to avoid putting in list a plugin that might have crashed during the load. + RsInfo() << "PLUGINSDIR: Successfully loaded plugin in memory: " + << (p ? p->getPluginName() : "Unknown") + << " from path: " << plugin_name; return true; }