| 105 | } |
| 106 | |
| 107 | bool IsSQLiteFile(const fs::path& path) |
| 108 | { |
| 109 | if (!fs::exists(path)) return false; |
| 110 | |
| 111 | // A SQLite Database file is at least 512 bytes. |
| 112 | std::error_code ec; |
| 113 | auto size = fs::file_size(path, ec); |
| 114 | if (ec) LogPrintf("%s: %s %s\n", __func__, ec.message(), fs::PathToString(path)); |
| 115 | if (size < 512) return false; |
| 116 | |
| 117 | std::ifstream file{path, std::ios::binary}; |
| 118 | if (!file.is_open()) return false; |
| 119 | |
| 120 | // Magic is at beginning and is 16 bytes long |
| 121 | char magic[16]; |
| 122 | file.read(magic, 16); |
| 123 | |
| 124 | // Application id is at offset 68 and 4 bytes long |
| 125 | file.seekg(68, std::ios::beg); |
| 126 | char app_id[4]; |
| 127 | file.read(app_id, 4); |
| 128 | |
| 129 | file.close(); |
| 130 | |
| 131 | // Check the magic, see https://sqlite.org/fileformat2.html |
| 132 | std::string magic_str(magic, 16); |
| 133 | if (magic_str != std::string("SQLite format 3", 16)) { |
| 134 | return false; |
| 135 | } |
| 136 | |
| 137 | // Check the application id matches our network magic |
| 138 | return memcmp(Params().MessageStart(), app_id, 4) == 0; |
| 139 | } |
| 140 | } // namespace wallet |