Bitcoin ABC  0.26.2
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 
11  fs::path path;
12 
13  if (gArgs.IsArgSet("-walletdir")) {
14  path = fs::PathFromString(gArgs.GetArg("-walletdir", ""));
15  if (!fs::is_directory(path)) {
16  // If the path specified doesn't exist, we return the deliberately
17  // invalid empty string.
18  path = "";
19  }
20  } else {
21  path = gArgs.GetDataDirNet();
22  // If a wallets directory exists, use that, otherwise default to
23  // GetDataDir
24  if (fs::is_directory(path / "wallets")) {
25  path /= "wallets";
26  }
27  }
28 
29  return path;
30 }
31 
32 bool IsBerkeleyBtree(const fs::path &path) {
33  if (!fs::exists(path)) {
34  return false;
35  }
36 
37  // A Berkeley DB Btree file has at least 4K.
38  // This check also prevents opening lock files.
39  boost::system::error_code ec;
40  auto size = fs::file_size(path, ec);
41  if (ec) {
42  LogPrintf("%s: %s %s\n", __func__, ec.message(),
43  fs::PathToString(path));
44  }
45  if (size < 4096) {
46  return false;
47  }
48 
49  fsbridge::ifstream file(path, std::ios::binary);
50  if (!file.is_open()) {
51  return false;
52  }
53 
54  // Magic bytes start at offset 12
55  file.seekg(12, std::ios::beg);
56  uint32_t data = 0;
57  // Read 4 bytes of file to compare against magic
58  file.read((char *)&data, sizeof(data));
59 
60  // Berkeley DB Btree magic bytes, from:
61  // https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
62  // - big endian systems - 00 05 31 62
63  // - little endian systems - 62 31 05 00
64  return data == 0x00053162 || data == 0x62310500;
65 }
66 
67 std::vector<fs::path> ListWalletDir() {
68  const fs::path wallet_dir = GetWalletDir();
69  const size_t offset = fs::PathToString(wallet_dir).size() + 1;
70  std::vector<fs::path> paths;
71  boost::system::error_code ec;
72 
73  for (auto it = fs::recursive_directory_iterator(wallet_dir, ec);
74  it != fs::recursive_directory_iterator(); it.increment(ec)) {
75  if (ec) {
76  LogPrintf("%s: %s %s\n", __func__, ec.message(),
77  fs::PathToString(it->path()));
78  continue;
79  }
80 
81  // Get wallet path relative to walletdir by removing walletdir from the
82  // wallet path. This can be replaced by
83  // boost::filesystem::lexically_relative once boost is bumped to 1.60.
84  const auto path_str = it->path().native().substr(offset);
85  const fs::path path{path_str.begin(), path_str.end()};
86 
87  if (it->status().type() == fs::directory_file &&
88  IsBerkeleyBtree(it->path() / "wallet.dat")) {
89  // Found a directory which contains wallet.dat btree file, add it as
90  // a wallet.
91  paths.emplace_back(path);
92  } else if (it.level() == 0 &&
93  it->symlink_status().type() == fs::regular_file &&
94  IsBerkeleyBtree(it->path())) {
95  if (it->path().filename() == "wallet.dat") {
96  // Found top-level wallet.dat btree file, add top level
97  // directory "" as a wallet.
98  paths.emplace_back();
99  } else {
100  // Found top-level btree file not called wallet.dat. Current
101  // bitcoin software will never create these files but will allow
102  // them to be opened in a shared database environment for
103  // backwards compatibility. Add it to the list of available
104  // wallets.
105  paths.emplace_back(path);
106  }
107  }
108  }
109 
110  return paths;
111 }
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:484
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: system.h:258
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:584
Path class wrapper to prepare application code for transition from boost::filesystem library to std::...
Definition: fs.h:33
#define LogPrintf(...)
Definition: logging.h:201
static bool exists(const path &p)
Definition: fs.h:94
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:134
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:147
fs::ifstream ifstream
Definition: fs.h:246
ArgsManager gArgs
Definition: system.cpp:77
std::vector< fs::path > ListWalletDir()
Get wallets in wallet directory.
Definition: walletutil.cpp:67
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:10
bool IsBerkeleyBtree(const fs::path &path)
Check format of database file.
Definition: walletutil.cpp:32