bool CBitcoinAddrDb::Read(CAddrMan& addr) { boost::filesystem::path pathAddr = GetDataDir() / m_addrFileName; // open input file, and associate with CAutoFile FILE *file = fopen(pathAddr.string().c_str(), "rb"); CAutoFile filein = CAutoFile(file, SER_DISK, BITCOIN_CLIENT_VERSION); if (!filein) { return false; } // use file size to size memory buffer int fileSize = GetFilesize(filein); int dataSize = fileSize - sizeof(uint256); //Don't try to resize to a negative number if file is small if ( dataSize < 0 ) dataSize = 0; vector<unsigned char> vchData; vchData.resize(dataSize); uint256 hashIn; // read data and checksum from file try { filein.read((char *)&vchData[0], dataSize); filein >> hashIn; } catch (std::exception &e) { return false; } filein.fclose(); CDataStream ssPeers(vchData, SER_DISK, BITCOIN_CLIENT_VERSION); // verify stored checksum matches input data uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); if (hashIn != hashTmp) { return false; } unsigned char pchMsgTmp[4]; try { // de-serialize file header (network specific magic number) and .. ssPeers >> FLATDATA(pchMsgTmp); // ... verify the network matches ours if (memcmp(pchMsgTmp, BitcoinMessageStart, sizeof(pchMsgTmp))) { return false; } // de-serialize address data into one CAddrMan object ssPeers >> addr; } catch (std::exception &e) { return false; } return true; }
bool CAddrDB::Read(CAddrMan& addr) { // open input file, and associate with CAutoFile FILE *file = fopen(pathAddr.string().c_str(), "rb"); CAutoFile filein(file, SER_DISK, CLIENT_VERSION); if (filein.IsNull()) return error("%s: Failed to open file %s", __func__, pathAddr.string()); // use file size to size memory buffer uint64_t fileSize = boost::filesystem::file_size(pathAddr); uint64_t dataSize = 0; // Don't try to resize to a negative number if file is small if (fileSize >= sizeof(uint256)) dataSize = fileSize - sizeof(uint256); std::vector<unsigned char> vchData; vchData.resize(dataSize); uint256 hashIn; // read data and checksum from file try { filein.read((char *)&vchData[0], dataSize); filein >> hashIn; } catch (const std::exception& e) { return error("%s: Deserialize or I/O error - %s", __func__, e.what()); } filein.fclose(); CDataStream ssPeers(vchData, SER_DISK, CLIENT_VERSION); // verify stored checksum matches input data uint256 hashTmp = Hash(ssPeers.begin(), ssPeers.end()); if (hashIn != hashTmp) return error("%s: Checksum mismatch, data corrupted", __func__); return Read(addr, ssPeers); }
bool CAddrDB::Write(const CAddrMan& addr) { // Generate random temporary filename unsigned short randv = 0; GetRandBytes((unsigned char*)&randv, sizeof(randv)); std::string tmpfn = strprintf("peers.dat.%04x", randv); // serialize addresses, checksum data up to that point, then append csum CDataStream ssPeers(SER_DISK, CLIENT_VERSION); ssPeers << FLATDATA(Params().MessageStart()); ssPeers << addr; uint256 hash = Hash(ssPeers.begin(), ssPeers.end()); ssPeers << hash; // open temp output file, and associate with CAutoFile boost::filesystem::path pathTmp = GetDataDir() / tmpfn; FILE *file = fopen(pathTmp.string().c_str(), "wb"); CAutoFile fileout(file, SER_DISK, CLIENT_VERSION); if (fileout.IsNull()) return error("%s: Failed to open file %s", __func__, pathTmp.string()); // Write and commit header, data try { fileout << ssPeers; } catch (const std::exception& e) { return error("%s: Serialize or I/O error - %s", __func__, e.what()); } FileCommit(fileout.Get()); fileout.fclose(); // replace existing peers.dat, if any, with new peers.dat.XXXX if (!RenameOver(pathTmp, pathAddr)) return error("%s: Rename-into-place failed", __func__); return true; }