Bitcoin ABC  0.29.1
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 <logging.h>
8 #include <util/system.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 
35 bool 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 
70 std::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 }
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:490
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: system.h:266
fs::path GetPathArg(std::string arg, const fs::path &default_value={}) const
Return path argument or default value.
Definition: system.cpp:396
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:206
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
ArgsManager gArgs
Definition: system.cpp:80
std::vector< fs::path > ListWalletDir()
Get wallets in wallet directory.
Definition: walletutil.cpp:70
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:13
bool IsBerkeleyBtree(const fs::path &path)
Check format of database file.
Definition: walletutil.cpp:35