Bitcoin ABC  0.24.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 <logging.h>
8 #include <util/system.h>
9 
10 fs::path GetWalletDir() {
11  fs::path path;
12 
13  if (gArgs.IsArgSet("-walletdir")) {
14  path = 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 = GetDataDir();
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(), path.string());
43  }
44  if (size < 4096) {
45  return false;
46  }
47 
48  fsbridge::ifstream file(path, std::ios::binary);
49  if (!file.is_open()) {
50  return false;
51  }
52 
53  // Magic bytes start at offset 12
54  file.seekg(12, std::ios::beg);
55  uint32_t data = 0;
56  // Read 4 bytes of file to compare against magic
57  file.read((char *)&data, sizeof(data));
58 
59  // Berkeley DB Btree magic bytes, from:
60  // https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
61  // - big endian systems - 00 05 31 62
62  // - little endian systems - 62 31 05 00
63  return data == 0x00053162 || data == 0x62310500;
64 }
65 
66 std::vector<fs::path> ListWalletDir() {
67  const fs::path wallet_dir = GetWalletDir();
68  const size_t offset = wallet_dir.string().size() + 1;
69  std::vector<fs::path> paths;
70  boost::system::error_code ec;
71 
72  for (auto it = fs::recursive_directory_iterator(wallet_dir, ec);
73  it != fs::recursive_directory_iterator(); it.increment(ec)) {
74  if (ec) {
75  LogPrintf("%s: %s %s\n", __func__, ec.message(),
76  it->path().string());
77  continue;
78  }
79 
80  // Get wallet path relative to walletdir by removing walletdir from the
81  // wallet path. This can be replaced by
82  // boost::filesystem::lexically_relative once boost is bumped to 1.60.
83  const fs::path path = it->path().string().substr(offset);
84 
85  if (it->status().type() == fs::directory_file &&
86  IsBerkeleyBtree(it->path() / "wallet.dat")) {
87  // Found a directory which contains wallet.dat btree file, add it as
88  // a wallet.
89  paths.emplace_back(path);
90  } else if (it.level() == 0 &&
91  it->symlink_status().type() == fs::regular_file &&
92  IsBerkeleyBtree(it->path())) {
93  if (it->path().filename() == "wallet.dat") {
94  // Found top-level wallet.dat btree file, add top level
95  // directory "" as a wallet.
96  paths.emplace_back();
97  } else {
98  // Found top-level btree file not called wallet.dat. Current
99  // bitcoin software will never create these files but will allow
100  // them to be opened in a shared database environment for
101  // backwards compatibility. Add it to the list of available
102  // wallets.
103  paths.emplace_back(path);
104  }
105  }
106  }
107 
108  return paths;
109 }
fsbridge::ifstream
fs::ifstream ifstream
Definition: fs.h:98
GetDataDir
const fs::path & GetDataDir(bool fNetSpecific)
Definition: system.cpp:779
ArgsManager::IsArgSet
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: system.cpp:400
ListWalletDir
std::vector< fs::path > ListWalletDir()
Get wallets in wallet directory.
Definition: walletutil.cpp:66
walletutil.h
IsBerkeleyBtree
bool IsBerkeleyBtree(const fs::path &path)
Check format of database file.
Definition: walletutil.cpp:32
ArgsManager::GetArg
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:498
system.h
gArgs
ArgsManager gArgs
Definition: system.cpp:75
logging.h
GetWalletDir
fs::path GetWalletDir()
Get the path of the wallet directory.
Definition: walletutil.cpp:10
LogPrintf
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:175