Bitcoin ABC 0.30.7
P2P Digital Currency
walletutil.cpp
Go to the documentation of this file.
1// Copyright (c) 2017 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <wallet/walletutil.h>
6
7#include <common/args.h>
8#include <logging.h>
9
10#include <exception>
11#include <fstream>
12
14 fs::path path;
15
16 if (gArgs.IsArgSet("-walletdir")) {
17 path = gArgs.GetPathArg("-walletdir");
18 if (!fs::is_directory(path)) {
19 // If the path specified doesn't exist, we return the deliberately
20 // invalid empty string.
21 path = "";
22 }
23 } else {
24 path = gArgs.GetDataDirNet();
25 // If a wallets directory exists, use that, otherwise default to
26 // GetDataDir
27 if (fs::is_directory(path / "wallets")) {
28 path /= "wallets";
29 }
30 }
31
32 return path;
33}
34
35bool IsBerkeleyBtree(const fs::path &path) {
36 if (!fs::exists(path)) {
37 return false;
38 }
39
40 // A Berkeley DB Btree file has at least 4K.
41 // This check also prevents opening lock files.
42 std::error_code ec;
43 auto size = fs::file_size(path, ec);
44 if (ec) {
45 LogPrintf("%s: %s %s\n", __func__, ec.message(),
46 fs::PathToString(path));
47 }
48 if (size < 4096) {
49 return false;
50 }
51
52 std::ifstream file{path, std::ios::binary};
53 if (!file.is_open()) {
54 return false;
55 }
56
57 // Magic bytes start at offset 12
58 file.seekg(12, std::ios::beg);
59 uint32_t data = 0;
60 // Read 4 bytes of file to compare against magic
61 file.read((char *)&data, sizeof(data));
62
63 // Berkeley DB Btree magic bytes, from:
64 // https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
65 // - big endian systems - 00 05 31 62
66 // - little endian systems - 62 31 05 00
67 return data == 0x00053162 || data == 0x62310500;
68}
69
70std::vector<fs::path> ListWalletDir() {
71 const fs::path wallet_dir = GetWalletDir();
72 const size_t offset = fs::PathToString(wallet_dir).size() + 1;
73 std::vector<fs::path> paths;
74 std::error_code ec;
75
76 for (auto it = fs::recursive_directory_iterator(wallet_dir, ec);
77 it != fs::recursive_directory_iterator(); it.increment(ec)) {
78 if (ec) {
79 LogPrintf("%s: %s %s\n", __func__, ec.message(),
80 fs::PathToString(it->path()));
81 continue;
82 }
83
84 try {
85 // Get wallet path relative to walletdir by removing walletdir from
86 // the wallet path. This can be replaced by
87 // boost::filesystem::lexically_relative once boost is bumped
88 // to 1.60.
89 const auto path_str = it->path().native().substr(offset);
90 const fs::path path{path_str.begin(), path_str.end()};
91
92 if (it->status().type() == fs::file_type::directory &&
93 IsBerkeleyBtree(it->path() / "wallet.dat")) {
94 // Found a directory which contains wallet.dat btree file, add
95 // it as a wallet.
96 paths.emplace_back(path);
97 } else if (it.depth() == 0 &&
98 it->symlink_status().type() == fs::file_type::regular &&
99 IsBerkeleyBtree(it->path())) {
100 if (it->path().filename() == "wallet.dat") {
101 // Found top-level wallet.dat btree file, add top level
102 // directory "" as a wallet.
103 paths.emplace_back();
104 } else {
105 // Found top-level btree file not called wallet.dat. Current
106 // bitcoin software will never create these files but will
107 // allow them to be opened in a shared database environment
108 // for backwards compatibility. Add it to the list of
109 // available wallets.
110 paths.emplace_back(path);
111 }
112 }
113 } catch (const std::exception &e) {
114 LogPrintf("%s: Error scanning %s: %s\n", __func__,
115 it->path().string(), e.what());
116 it.disable_recursion_pending();
117 }
118 }
119
120 return paths;
121}
ArgsManager gArgs
Definition: args.cpp:38
fs::path GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: args.h:215
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: args.cpp:381
fs::path GetPathArg(std::string arg, const fs::path &default_value={}) const
Return path argument or default value.
Definition: args.cpp:275
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
#define LogPrintf(...)
Definition: logging.h:227
static bool exists(const path &p)
Definition: fs.h:102
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:142
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
std::vector< fs::path > ListWalletDir()
Get wallets in wallet directory.
Definition: walletutil.cpp:70
bool IsBerkeleyBtree(const fs::path &path)
Check format of database file.
Definition: walletutil.cpp:35