4
4
5
5
#include < wallet/walletutil.h>
6
6
7
+ #include < util.h>
8
+
7
9
fs::path GetWalletDir ()
8
10
{
9
11
fs::path path;
@@ -25,3 +27,51 @@ fs::path GetWalletDir()
25
27
26
28
return path;
27
29
}
30
+
31
+ static bool IsBerkeleyBtree (const fs::path& path)
32
+ {
33
+ // A Berkeley DB Btree file has at least 4K.
34
+ // This check also prevents opening lock files.
35
+ boost::system::error_code ec;
36
+ if (fs::file_size (path, ec) < 4096 ) return false ;
37
+
38
+ fs::ifstream file (path.string (), std::ios::binary);
39
+ if (!file.is_open ()) return false ;
40
+
41
+ file.seekg (12 , std::ios::beg); // Magic bytes start at offset 12
42
+ uint32_t data = 0 ;
43
+ file.read ((char *) &data, sizeof (data)); // Read 4 bytes of file to compare against magic
44
+
45
+ // Berkeley DB Btree magic bytes, from:
46
+ // https://github.com/file/file/blob/5824af38469ec1ca9ac3ffd251e7afe9dc11e227/magic/Magdir/database#L74-L75
47
+ // - big endian systems - 00 05 31 62
48
+ // - little endian systems - 62 31 05 00
49
+ return data == 0x00053162 || data == 0x62310500 ;
50
+ }
51
+
52
+ std::vector<fs::path> ListWalletDir ()
53
+ {
54
+ const fs::path wallet_dir = GetWalletDir ();
55
+ std::vector<fs::path> paths;
56
+
57
+ for (auto it = fs::recursive_directory_iterator (wallet_dir); it != end (it); ++it) {
58
+ if (it->status ().type () == fs::directory_file && IsBerkeleyBtree (it->path () / " wallet.dat" )) {
59
+ // Found a directory which contains wallet.dat btree file, add it as a wallet.
60
+ paths.emplace_back (fs::relative (it->path (), wallet_dir));
61
+ } else if (it.level () == 0 && it->symlink_status ().type () == fs::regular_file && IsBerkeleyBtree (it->path ())) {
62
+ if (it->path ().filename () == " wallet.dat" ) {
63
+ // Found top-level wallet.dat btree file, add top level directory ""
64
+ // as a wallet.
65
+ paths.emplace_back ();
66
+ } else {
67
+ // Found top-level btree file not called wallet.dat. Current bitcoin
68
+ // software will never create these files but will allow them to be
69
+ // opened in a shared database environment for backwards compatibility.
70
+ // Add it to the list of available wallets.
71
+ paths.emplace_back (fs::relative (it->path (), wallet_dir));
72
+ }
73
+ }
74
+ }
75
+
76
+ return paths;
77
+ }
0 commit comments