mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-31 10:41:08 +00:00
Wallet/bdb: Safely and correctly list files only used by the single wallet
If any other files exist in the directory, we cannot assume the sharable files are exclusively for this wallet. But if they are, this also cleans up other log.* files
This commit is contained in:
parent
fa91ad3420
commit
7475d134f6
@ -16,6 +16,7 @@
|
||||
#include <util/strencodings.h>
|
||||
#include <util/translation.h>
|
||||
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <db_cxx.h>
|
||||
@ -340,6 +341,53 @@ bool BerkeleyDatabase::Verify(bilingual_str& errorStr)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<fs::path> BerkeleyDatabase::Files()
|
||||
{
|
||||
std::vector<fs::path> files;
|
||||
// If the wallet is the *only* file, clean up the entire BDB environment
|
||||
constexpr auto build_files_list = [](std::vector<fs::path>& files, const std::shared_ptr<BerkeleyEnvironment>& env, const fs::path& filename) {
|
||||
if (env->m_databases.size() != 1) return false;
|
||||
|
||||
const auto env_dir = env->Directory();
|
||||
const auto db_subdir = env_dir / "database";
|
||||
if (fs::exists(db_subdir)) {
|
||||
if (!fs::is_directory(db_subdir)) return false;
|
||||
for (const auto& entry : fs::directory_iterator(db_subdir)) {
|
||||
const auto& path = entry.path().filename();
|
||||
if (!fs::PathToString(path).starts_with("log.")) {
|
||||
return false;
|
||||
}
|
||||
files.emplace_back(entry.path());
|
||||
}
|
||||
}
|
||||
const std::set<fs::path> allowed_paths = {
|
||||
filename,
|
||||
"db.log",
|
||||
".walletlock",
|
||||
"database"
|
||||
};
|
||||
for (const auto& entry : fs::directory_iterator(env_dir)) {
|
||||
const auto& path = entry.path().filename();
|
||||
if (allowed_paths.contains(path)) {
|
||||
files.emplace_back(entry.path());
|
||||
} else if (fs::is_directory(entry.path())) {
|
||||
// Subdirectories can't possibly be using this db env, and is expected if this is a non-directory wallet
|
||||
// Do not include them in Files, but still allow the env cleanup
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
try {
|
||||
if (build_files_list(files, env, m_filename)) return files;
|
||||
} catch (...) {
|
||||
// Give up building the comprehensive file list if any error occurs
|
||||
}
|
||||
// Otherwise, it's only really safe to delete the one wallet file
|
||||
return {env->Directory() / m_filename};
|
||||
}
|
||||
|
||||
void BerkeleyEnvironment::CheckpointLSN(const std::string& strFile)
|
||||
{
|
||||
dbenv->txn_checkpoint(0, 0, 0);
|
||||
|
||||
@ -132,20 +132,7 @@ public:
|
||||
/** Return path to main database filename */
|
||||
std::string Filename() override { return fs::PathToString(env->Directory() / m_filename); }
|
||||
|
||||
std::vector<fs::path> Files() override
|
||||
{
|
||||
std::vector<fs::path> files;
|
||||
files.emplace_back(env->Directory() / m_filename);
|
||||
if (env->m_databases.size() == 1) {
|
||||
files.emplace_back(env->Directory() / "db.log");
|
||||
files.emplace_back(env->Directory() / ".walletlock");
|
||||
files.emplace_back(env->Directory() / "database" / "log.0000000001");
|
||||
files.emplace_back(env->Directory() / "database");
|
||||
// Note that this list is not exhaustive as BDB may create more log files, and possibly other ones too
|
||||
// However it should be good enough for the only calls to Files()
|
||||
}
|
||||
return files;
|
||||
}
|
||||
std::vector<fs::path> Files() override;
|
||||
|
||||
std::string Format() override { return "bdb"; }
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user