Skip to content

Commit

Permalink
wallet: Add ListWalletDir utility
Browse files Browse the repository at this point in the history
ListWalletDir returns all available wallets in the current wallet directory.

Based on MeshCollider work in pull bitcoin#11485.
  • Loading branch information
promag committed Oct 18, 2018
1 parent 920c090 commit fc4db35
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 2 deletions.
50 changes: 50 additions & 0 deletions src/wallet/walletutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include <wallet/walletutil.h>

#include <util.h>

fs::path GetWalletDir()
{
fs::path path;
Expand All @@ -25,3 +27,51 @@ fs::path GetWalletDir()

return path;
}

static bool IsBerkeleyBtree(const fs::path& path)
{
// A Berkeley DB Btree file has at least 4K.
// This check also prevents opening lock files.
boost::system::error_code ec;
if (fs::file_size(path, ec) < 4096) return false;

fs::ifstream file(path.string(), std::ios::binary);
if (!file.is_open()) return false;

file.seekg(12, std::ios::beg); // Magic bytes start at offset 12
uint32_t data = 0;
file.read((char*) &data, sizeof(data)); // Read 4 bytes of file to compare against magic

// Berkeley DB Btree magic bytes, from:
// https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
// - big endian systems - 00 05 31 62
// - little endian systems - 62 31 05 00
return data == 0x00053162 || data == 0x62310500;
}

std::vector<fs::path> ListWalletDir()
{
const fs::path wallet_dir = GetWalletDir();
std::vector<fs::path> paths;

for (auto it = fs::recursive_directory_iterator(wallet_dir); it != end(it); ++it) {
if (it->status().type() == fs::directory_file && IsBerkeleyBtree(it->path() / "wallet.dat")) {
// Found a directory which contains wallet.dat btree file, add it as a wallet.
paths.emplace_back(fs::relative(it->path(), wallet_dir));
} else if (it.level() == 0 && it->symlink_status().type() == fs::regular_file && IsBerkeleyBtree(it->path())) {
if (it->path().filename() == "wallet.dat") {
// Found top-level wallet.dat btree file, add top level directory ""
// as a wallet.
paths.emplace_back();
} else {
// Found top-level btree file not called wallet.dat. Current bitcoin
// software will never create these files but will allow them to be
// opened in a shared database environment for backwards compatibility.
// Add it to the list of available wallets.
paths.emplace_back(fs::relative(it->path(), wallet_dir));
}
}
}

return paths;
}
8 changes: 6 additions & 2 deletions src/wallet/walletutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@
#ifndef BITCOIN_WALLET_WALLETUTIL_H
#define BITCOIN_WALLET_WALLETUTIL_H

#include <chainparamsbase.h>
#include <util.h>
#include <fs.h>

#include <vector>

//! Get the path of the wallet directory.
fs::path GetWalletDir();

//! Get wallets in wallet directory.
std::vector<fs::path> ListWalletDir();

#endif // BITCOIN_WALLET_WALLETUTIL_H

0 comments on commit fc4db35

Please sign in to comment.