fix(util): use the POSIX daemon binary name, scan versions off-thread
The installed-daemon lookup built the binary path from the Windows
resource key "dragonxd.exe", which never exists on Linux or macOS, so
the installed full node was never found there. The version scan also
read the whole binary, now around 200 MB, into memory on the UI thread.
- A new DAEMON_BINARY_NAME gives the daemon's file name on this platform
("dragonxd" on POSIX, "dragonxd.exe" on Windows); the old resource
constant stays only as the embedded-table key. The installed daemon is
now found on POSIX.
- The version-stamp scan streams the file in 4 MiB chunks with bounded
memory, carrying bytes across each boundary so a stamp straddling it is
neither cut short nor missed, and stops at the first match. The result
is cached by path, size and mtime, so only a changed binary is
rescanned.
- Settings stats the binary on the UI thread but runs the streamed scan
on a worker, guarded so a new scan is not started while one is still
running (the future blocks in its destructor), and the version fills
in when it lands.
Tests: the POSIX path and binary name, a version stamp in a small file,
a stamp straddling the 4 MiB chunk boundary, and a file with no stamp.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2951,6 +2951,49 @@ void testSecureVaultWellFormed()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
void testInstalledDaemonInfoPosix()
|
||||
{
|
||||
const char* oldHome = std::getenv("HOME");
|
||||
const std::string savedHome = oldHome ? oldHome : "";
|
||||
const char* oldXdg = std::getenv("XDG_CONFIG_HOME");
|
||||
const bool hadXdg = oldXdg != nullptr;
|
||||
const std::string savedXdg = hadXdg ? oldXdg : "";
|
||||
const fs::path tmp = makeTempDir();
|
||||
setenv("HOME", tmp.string().c_str(), 1);
|
||||
setenv("XDG_CONFIG_HOME", (tmp / ".config").string().c_str(), 1);
|
||||
{
|
||||
const fs::path dir = fs::path(dragonx::resources::getDaemonDirectory());
|
||||
std::error_code ec;
|
||||
fs::create_directories(dir, ec);
|
||||
EXPECT_TRUE(dir.string().rfind(tmp.string(), 0) == 0); // never the real config dir
|
||||
auto info0 = dragonx::resources::getInstalledDaemonInfo(false);
|
||||
EXPECT_FALSE(info0.exists); // nothing installed yet
|
||||
{ // a stamp in a small file
|
||||
std::ofstream o(dir / "dragonxd", std::ios::binary);
|
||||
o << "garbage v9 x v1.3.0-0123abcdef trailing";
|
||||
}
|
||||
auto info1 = dragonx::resources::getInstalledDaemonInfo(true);
|
||||
EXPECT_TRUE(info1.exists);
|
||||
EXPECT_EQ(info1.version, std::string("v1.3.0-0123abcdef"));
|
||||
{ // a stamp straddling the 4 MiB chunk boundary
|
||||
std::string blob(4u * 1024 * 1024 - 7, 'x');
|
||||
blob += "v1.4.2-deadbeef12"; blob += std::string(100, 'y');
|
||||
std::ofstream o(dir / "dragonxd", std::ios::binary | std::ios::trunc); o << blob;
|
||||
}
|
||||
EXPECT_EQ(dragonx::resources::getInstalledDaemonInfo(true).version, std::string("v1.4.2-deadbeef12"));
|
||||
{ // no stamp => ""
|
||||
std::ofstream o(dir / "dragonxd", std::ios::binary | std::ios::trunc); o << std::string(5000, 'z');
|
||||
}
|
||||
EXPECT_TRUE(dragonx::resources::getInstalledDaemonInfo(true).version.empty());
|
||||
EXPECT_EQ(std::string(dragonx::resources::DAEMON_BINARY_NAME), std::string("dragonxd"));
|
||||
}
|
||||
if (!savedHome.empty()) setenv("HOME", savedHome.c_str(), 1); else unsetenv("HOME");
|
||||
if (hadXdg) setenv("XDG_CONFIG_HOME", savedXdg.c_str(), 1); else unsetenv("XDG_CONFIG_HOME");
|
||||
removeTree(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
void testWalletSecurityController()
|
||||
{
|
||||
using dragonx::services::WalletSecurityController;
|
||||
@@ -17652,6 +17695,7 @@ int main()
|
||||
testPinVaultPolicy();
|
||||
#ifndef _WIN32
|
||||
testSecureVaultWellFormed();
|
||||
testInstalledDaemonInfoPosix();
|
||||
#endif
|
||||
testWalletSecurityController();
|
||||
testWalletSecurityWorkflow();
|
||||
|
||||
Reference in New Issue
Block a user