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