Updated hpfs hash verification with file mode checks. (#257)

* Added file mode to hpfs responses.

* Parse file mode on hpfs response read.

* Apply file/dir mode.

* Fixed mode apply logic.

* Fixed code review comments.

* Additional fix.
This commit is contained in:
Ravin Perera
2021-02-24 11:13:28 +05:30
committed by GitHub
parent 363116fc2a
commit 5b56d9c1b3
13 changed files with 201 additions and 80 deletions

View File

@@ -181,10 +181,10 @@ namespace conf
std::string hpfs_exe_path; // hpfs executable file path.
std::string contract_dir; // Contract base directory full path.
std::string contract_hpfs_dir; // Contract hpfs metdata dir (The location of hpfs log file).
std::string contract_hpfs_dir; // Contract hpfs metadata dir (The location of hpfs log file).
std::string contract_hpfs_mount_dir; // Contract hpfs fuse file system mount path.
std::string contract_hpfs_rw_dir; // Contract hpfs read/write fs session path.
std::string ledger_hpfs_dir; // Ledger hpfs metdata dir (The location of hpfs log file).
std::string ledger_hpfs_dir; // Ledger hpfs metadata dir (The location of hpfs log file).
std::string ledger_hpfs_mount_dir; // Ledger hpfs fuse file system mount path.
std::string ledger_hpfs_rw_dir; // Ledger hpfs read/write fs session path.
std::string log_dir; // HotPocket log dir full path.

View File

@@ -115,7 +115,7 @@ namespace crypto
* @param data_length hash data length.
* @return The blake3 hash of the pointed buffer.
*/
const std::string get_hash(const unsigned char *data, size_t data_length)
const std::string get_hash(const void *data, const size_t data_length)
{
std::string hash;
hash.resize(BLAKE3_OUT_LEN);

View File

@@ -25,7 +25,7 @@ namespace crypto
const std::string get_hash(std::string_view data);
const std::string get_hash(const unsigned char *data, size_t data_length);
const std::string get_hash(const void *data, const size_t data_length);
const std::string get_hash(std::string_view s1, std::string_view s2);

View File

@@ -161,8 +161,9 @@ namespace hpfs
if (hr.is_file)
{
std::vector<util::h32> block_hashes;
std::size_t file_length = 0;
const int result = get_data_block_hashes(block_hashes, file_length, hr.parent_path, hr.expected_hash);
size_t file_length = 0;
mode_t file_mode = 0;
const int result = get_data_block_hashes(block_hashes, file_length, file_mode, hr.parent_path, hr.expected_hash);
if (result == -1)
{
@@ -173,7 +174,7 @@ namespace hpfs
{
p2pmsg::create_msg_from_filehashmap_response(
fbuf, hr.parent_path, fs_mount->mount_id, block_hashes,
file_length, hr.expected_hash);
file_length, file_mode, hr.expected_hash);
return 1; // Success.
}
}
@@ -191,8 +192,17 @@ namespace hpfs
}
else if (result == 1)
{
// Get dir mode.
const std::string dir_path = fs_mount->rw_dir + hr.parent_path.data();
struct stat st;
if (stat(dir_path.data(), &st) == -1)
{
LOG_ERROR << errno << ": Error in getting dir metadata: " << hr.parent_path;
return -1;
}
p2pmsg::create_msg_from_fsentry_response(
fbuf, hr.parent_path, fs_mount->mount_id, child_hash_nodes, hr.expected_hash);
fbuf, hr.parent_path, fs_mount->mount_id, st.st_mode, child_hash_nodes, hr.expected_hash);
return 1; // Success.
}
}
@@ -283,7 +293,7 @@ namespace hpfs
* Retrieves the specified file block hashes if expected hash matches.
* @return 1 if block hashes were successfuly fetched. 0 if vpath does not exist. -1 on error.
*/
int hpfs_serve::get_data_block_hashes(std::vector<util::h32> &hashes, size_t &file_length,
int hpfs_serve::get_data_block_hashes(std::vector<util::h32> &hashes, size_t &file_length, mode_t &file_mode,
const std::string_view vpath, const util::h32 expected_hash)
{
// Check whether the existing file hash matches expected hash.
@@ -303,15 +313,16 @@ namespace hpfs
}
else
{
// Get actual file length.
// Get actual file metadata.
const std::string file_path = fs_mount->rw_dir + vpath.data();
struct stat st;
if (stat(file_path.c_str(), &st) == -1)
{
LOG_ERROR << errno << ": Stat failed when getting file length. " << file_path;
LOG_ERROR << errno << ": Stat failed when getting file metadata. " << file_path;
result = -1;
}
file_length = st.st_size;
file_mode = st.st_mode;
result = 1; // Success.
}
}

View File

@@ -16,6 +16,13 @@ namespace hpfs
hpfs::hpfs_mount *fs_mount = NULL;
std::string_view name;
void hpfs_serve_loop();
int create_hpfs_response(flatbuffers::FlatBufferBuilder &fbuf, const p2p::hpfs_request &hr);
int get_data_block(std::vector<uint8_t> &block, const std::string_view vpath,
const uint32_t block_id, const util::h32 expected_hash);
int get_data_block_hashes(std::vector<util::h32> &hashes, size_t &file_length, mode_t &file_mode,
const std::string_view vpath, const util::h32 expected_hash);
int get_fs_entry_hashes(std::vector<hpfs::child_hash_node> &hash_nodes,
const std::string_view vpath, const util::h32 expected_hash);
protected:
std::list<std::pair<std::string, p2p::hpfs_request>> hpfs_requests;
@@ -26,17 +33,6 @@ namespace hpfs
int init(std::string_view server_name, hpfs::hpfs_mount *fs_mount_ptr);
void deinit();
int create_hpfs_response(flatbuffers::FlatBufferBuilder &fbuf, const p2p::hpfs_request &hr);
int get_data_block(std::vector<uint8_t> &block, const std::string_view vpath,
const uint32_t block_id, const util::h32 expected_hash);
int get_data_block_hashes(std::vector<util::h32> &hashes, size_t &file_length,
const std::string_view vpath, const util::h32 expected_hash);
int get_fs_entry_hashes(std::vector<hpfs::child_hash_node> &hash_nodes,
const std::string_view vpath, const util::h32 expected_hash);
};
} // namespace hpfs

View File

@@ -266,33 +266,31 @@ namespace hpfs
std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> peer_fs_entry_map;
p2pmsg::flatbuf_hpfsfshashentry_to_hpfsfshashentry(peer_fs_entry_map, fs_resp.entries());
// Commented for now. Need to change the way the hash is calculated once the flatbuffer re-architecture finishes.
// Validate received fs data against the hash.
// if (!validate_fs_entry_hash(vpath, hash, peer_fs_entry_map))
// {
// LOG_INFO << "Hpfs " << name << " sync: Skipping hpfs response due to fs entry hash mismatch.";
// continue;
// }
if (!validate_fs_entry_hash(vpath, hash, fs_resp.dir_mode(), peer_fs_entry_map))
{
LOG_INFO << "Hpfs " << name << " sync: Skipping hpfs response due to fs entry hash mismatch.";
continue;
}
handle_fs_entry_response(vpath, peer_fs_entry_map);
handle_fs_entry_response(vpath, fs_resp.dir_mode(), peer_fs_entry_map);
}
else if (msg_type == p2pmsg::HpfsResponse_HpfsFileHashMapResponse)
{
const p2pmsg::HpfsFileHashMapResponse &file_resp = *resp_msg.content_as_HpfsFileHashMapResponse();
// File block hashes we received from the peer.
const util::h32 *peer_hashes = reinterpret_cast<const util::h32 *>(file_resp.hash_map()->data());
const size_t peer_hash_count = file_resp.hash_map()->size() / sizeof(util::h32);
const util::h32 *block_hashes = reinterpret_cast<const util::h32 *>(file_resp.hash_map()->data());
const size_t block_hash_count = file_resp.hash_map()->size() / sizeof(util::h32);
// Commented for now. Need to change the way the hash is calculated once the flatbuffer re-architecture finishes.
// Validate received hashmap against the hash.
// if (!validate_file_hashmap_hash(vpath, hash, peer_hashes, peer_hash_count))
// {
// LOG_INFO << "Hpfs " << name << " sync: Skipping hpfs response due to file hashmap hash mismatch.";
// continue;
// }
if (!validate_file_hashmap_hash(vpath, hash, file_resp.file_mode(), block_hashes, block_hash_count))
{
LOG_INFO << "Hpfs " << name << " sync: Skipping hpfs response due to file hashmap hash mismatch.";
continue;
}
handle_file_hashmap_response(vpath, peer_hashes, peer_hash_count, file_resp.file_length());
handle_file_hashmap_response(vpath, file_resp.file_mode(), block_hashes, block_hash_count, file_resp.file_length());
}
else if (msg_type == p2pmsg::HpfsResponse_HpfsBlockResponse)
{
@@ -302,13 +300,12 @@ namespace hpfs
const uint32_t block_id = block_resp.block_id();
std::string_view buf = msg::fbuf::flatbuf_bytes_to_sv(block_resp.data());
// Commented for now. Need to change the way the hash is calculated once the flatbuffer re-architecture finishes.
// Validate received block data against the hash.
// if (!validate_file_block_hash(hash, block_id, buf))
// {
// LOG_INFO << "Hpfs " << name << " sync: Skipping hpfs response due to file block hash mismatch.";
// continue;
// }
if (!validate_file_block_hash(hash, block_id, buf))
{
LOG_INFO << "Hpfs " << name << " sync: Skipping hpfs response due to file block hash mismatch.";
continue;
}
handle_file_block_response(vpath, block_id, buf);
}
@@ -394,18 +391,24 @@ namespace hpfs
* Vadidated the received hash against the received fs entry map.
* @param vpath Virtual path of the fs.
* @param hash Received hash.
* @param dir_mode Metadata 'mode' of the directory containing the fs entries.
* @param fs_entry_map Received fs entry map.
* @returns true if hash is valid, otherwise false.
*/
bool hpfs_sync::validate_fs_entry_hash(std::string_view vpath, std::string_view hash, const std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map)
bool hpfs_sync::validate_fs_entry_hash(std::string_view vpath, std::string_view hash, const mode_t dir_mode,
const std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map)
{
util::h32 content_hash;
const std::string vpath_name = util::get_name(vpath);
// Initilal hash is vpath hash.
// Initilal hash is vpath hash + mode hash.
content_hash = crypto::get_hash(vpath_name);
uint8_t mode_bytes[4];
util::uint32_to_bytes(mode_bytes, dir_mode);
content_hash ^= crypto::get_hash(mode_bytes, sizeof(mode_bytes));
// Then XOR the file hashes to the initial hash.
for (const auto &[name, fs_entry] : fs_entry_map)
{
@@ -419,19 +422,25 @@ namespace hpfs
* Vadidated the received hash against the received file hash map.
* @param vpath Virtual path of the file.
* @param hash Received hash.
* @param file_mode Metadata 'mode' of the file.
* @param hashes Received block hashes.
* @param hash_count Size of the hash list.
* @returns true if hash is valid, otherwise false.
*/
bool hpfs_sync::validate_file_hashmap_hash(std::string_view vpath, std::string_view hash, const util::h32 *hashes, const size_t hash_count)
bool hpfs_sync::validate_file_hashmap_hash(std::string_view vpath, std::string_view hash, const mode_t file_mode,
const util::h32 *hashes, const size_t hash_count)
{
util::h32 content_hash = util::h32_empty;
const std::string vpath_name = util::get_name(vpath);
// Initilal hash is vpath hash.
// Initilal hash is vpath hash + mode hash.
content_hash = crypto::get_hash(vpath_name);
uint8_t mode_bytes[4];
util::uint32_to_bytes(mode_bytes, file_mode);
content_hash ^= crypto::get_hash(mode_bytes, sizeof(mode_bytes));
// Then XOR the block hashes to the initial hash.
for (int32_t block_id = 0; block_id < hash_count; block_id++)
{
@@ -452,7 +461,9 @@ namespace hpfs
{
// Calculate block offset of this block.
const off_t block_offset = block_id * hpfs::BLOCK_SIZE;
std::string_view offset = std::string_view(reinterpret_cast<const char *>(&block_offset), sizeof(off_t));
uint8_t bytes[8];
util::uint64_to_bytes(bytes, block_offset);
std::string_view offset = std::string_view(reinterpret_cast<const char *>(bytes), sizeof(bytes));
return crypto::get_hash(offset, buf) == hash;
}
@@ -514,10 +525,11 @@ namespace hpfs
/**
* Process dir children response.
* @param vpath Virtual path of the fs.
* @param dir_mode Metadata 'mode' of dir.
* @param fs_entry_map Received fs entry map.
* @returns 0 on success, otherwise -1.
*/
int hpfs_sync::handle_fs_entry_response(std::string_view vpath, std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map)
int hpfs_sync::handle_fs_entry_response(std::string_view vpath, const mode_t dir_mode, std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map)
{
// Get the parent path of the fs entries we have received.
LOG_DEBUG << "Hpfs " << name << " sync: Processing fs entries response for " << vpath;
@@ -527,6 +539,10 @@ namespace hpfs
if (util::create_dir_tree_recursive(parent_physical_path) == -1)
return -1;
// Apply physical dir mode if received mode is different from our side.
if (apply_metadata_mode(parent_physical_path, dir_mode, true) == -1)
return -1;
// Get the children hash entries and compare with what we got from peer.
std::vector<hpfs::child_hash_node> existing_fs_entries;
if (fs_mount->get_dir_children_hashes(existing_fs_entries, hpfs::RW_SESSION_NAME, vpath) == -1)
@@ -589,12 +605,13 @@ namespace hpfs
/**
* Process file block hash map response.
* @param vpath Virtual path of the file.
* @param hash Received hash.
* @param file_mode Received metadata mode of the file.
* @param hashes Received block hashes.
* @param hash_count No. of received block hashes.
* @param file_length Size of the file.
* @returns 0 on success, otherwise -1.
*/
int hpfs_sync::handle_file_hashmap_response(std::string_view vpath, const util::h32 *hashes, const size_t hash_count, const uint64_t file_length)
int hpfs_sync::handle_file_hashmap_response(std::string_view vpath, const mode_t file_mode, const util::h32 *hashes, const size_t hash_count, const uint64_t file_length)
{
// Get the file path of the block hashes we have received.
LOG_DEBUG << "Hpfs " << name << " sync: Processing file block hashes response for " << vpath;
@@ -623,6 +640,11 @@ namespace hpfs
return -1;
}
// Apply physical file mode if received mode is different from our side.
const std::string physical_path = fs_mount->rw_dir + vpath.data();
if (apply_metadata_mode(physical_path, file_mode, false) == -1)
return -1;
return 0;
}
@@ -659,6 +681,49 @@ namespace hpfs
return 0;
}
/**
* Applies the specified to local file/dir if different. If it's a file, this will create the file
* if not exist.
* @returns 0 on success, otherwise -1.
*/
int hpfs_sync::apply_metadata_mode(std::string_view physical_path, const mode_t mode, const bool is_dir)
{
// Overlay the file/dir type flags to the permission bits.
const mode_t full_mode = (is_dir ? S_IFDIR : S_IFREG) | mode;
struct stat st;
if (stat(physical_path.data(), &st) == -1)
{
if (!is_dir && errno == ENOENT) // File does not exist. So we must create it with the given 'mode'.
{
if (mknod(physical_path.data(), full_mode, 0) == -1)
{
LOG_ERROR << errno << ": Error in creating file node. " << physical_path;
return -1;
}
else
{
return 0;
}
}
LOG_ERROR << errno << "," << ENOENT << ": Error in stat when applying file/dir mode. " << physical_path;
return -1;
}
// Reaching here means file/dir already exists. So we must apply the specified mode if it's different from current value.
if (st.st_mode != full_mode)
{
if (chmod(physical_path.data(), mode) == -1)
{
LOG_ERROR << errno << ": Error in applying file/dir mode. " << physical_path;
return -1;
}
}
return 0;
}
/**
* This method can be used to invoke mount specific custom logic (after overriding this method) to be executed after
* a sync target is acheived.

View File

@@ -70,6 +70,29 @@ namespace hpfs
int start_syncing_next_target();
bool validate_fs_entry_hash(std::string_view vpath, std::string_view hash, const mode_t dir_mode,
const std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map);
bool validate_file_hashmap_hash(std::string_view vpath, std::string_view hash, const mode_t file_mode,
const util::h32 *hashes, const size_t hash_count);
bool validate_file_block_hash(std::string_view hash, const uint32_t block_id, std::string_view buf);
bool should_stop_request_loop(const util::h32 &current_target_hash);
void request_state_from_peer(const std::string &path, const bool is_file, const int32_t block_id,
const util::h32 expected_hash, std::string &target_pubkey);
void submit_request(const backlog_item &request);
int handle_fs_entry_response(std::string_view vpath, const mode_t dir_mode, std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map);
int handle_file_hashmap_response(std::string_view vpath, const mode_t file_mode, const util::h32 *hashes, const size_t hash_count, const uint64_t file_length);
int handle_file_block_response(std::string_view vpath, const uint32_t block_id, std::string_view buf);
int apply_metadata_mode(std::string_view physical_path, const mode_t mode, const bool is_dir);
protected:
// List of sender pubkeys and hpfs responses(flatbuffer messages) to be processed.
std::list<std::pair<std::string, std::string>> candidate_hpfs_responses;
@@ -95,27 +118,8 @@ namespace hpfs
void set_target(const std::list<sync_target> &sync_target_list);
void set_target_push_front(const sync_target &target);
void set_target_push_back(const sync_target &target);
bool validate_fs_entry_hash(std::string_view vpath, std::string_view hash, const std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map);
bool validate_file_hashmap_hash(std::string_view vpath, std::string_view hash, const util::h32 *hashes, const size_t hash_count);
bool validate_file_block_hash(std::string_view hash, const uint32_t block_id, std::string_view buf);
bool should_stop_request_loop(const util::h32 &current_target_hash);
void request_state_from_peer(const std::string &path, const bool is_file, const int32_t block_id,
const util::h32 expected_hash, std::string &target_pubkey);
void submit_request(const backlog_item &request);
int handle_fs_entry_response(std::string_view vpath, std::unordered_map<std::string, p2p::hpfs_fs_hash_entry> &fs_entry_map);
int handle_file_hashmap_response(std::string_view vpath, const util::h32 *hashes, const size_t hash_count, const uint64_t file_length);
int handle_file_block_response(std::string_view vpath, const uint32_t block_id, std::string_view buf);
};
} // namespace hpfs

View File

@@ -100,11 +100,13 @@ table HpfsResponseMsg{
}
table HpfsFsEntryResponse{
dir_mode:uint32;
entries: [HpfsFSHashEntry];
}
table HpfsFileHashMapResponse{
file_length:uint64;
file_mode:uint32;
hash_map:[ubyte];
}

View File

@@ -380,11 +380,12 @@ namespace msg::fbuf::p2pmsg
}
void create_msg_from_fsentry_response(
flatbuffers::FlatBufferBuilder &builder, const std::string_view path, const uint32_t mount_id,
std::vector<hpfs::child_hash_node> &hash_nodes, util::h32 expected_hash)
flatbuffers::FlatBufferBuilder &builder, const std::string_view path, const uint32_t mount_id, const mode_t dir_mode,
std::vector<hpfs::child_hash_node> &hash_nodes, const util::h32 &expected_hash)
{
const auto child_msg = CreateHpfsFsEntryResponse(
builder,
dir_mode,
hpfsfshashentry_to_flatbuf_hpfsfshashentry(builder, hash_nodes));
const auto msg = CreateHpfsResponseMsg(
@@ -400,13 +401,14 @@ namespace msg::fbuf::p2pmsg
void create_msg_from_filehashmap_response(
flatbuffers::FlatBufferBuilder &builder, std::string_view path, const uint32_t mount_id,
std::vector<util::h32> &hashmap, std::size_t file_length, util::h32 expected_hash)
std::vector<util::h32> &hashmap, const std::size_t file_length, const mode_t file_mode, const util::h32 &expected_hash)
{
std::string_view hashmap_sv(reinterpret_cast<const char *>(hashmap.data()), hashmap.size() * sizeof(util::h32));
const auto child_msg = CreateHpfsFileHashMapResponse(
builder,
file_length,
file_mode,
sv_to_flatbuf_bytes(builder, hashmap_sv));
const auto msg = CreateHpfsResponseMsg(

View File

@@ -70,12 +70,12 @@ namespace msg::fbuf::p2pmsg
void create_msg_from_hpfs_request(flatbuffers::FlatBufferBuilder &builder, const p2p::hpfs_request &hr);
void create_msg_from_fsentry_response(
flatbuffers::FlatBufferBuilder &builder, const std::string_view path, const uint32_t mount_id,
std::vector<hpfs::child_hash_node> &hash_nodes, util::h32 expected_hash);
flatbuffers::FlatBufferBuilder &builder, const std::string_view path, const uint32_t mount_id, const mode_t dir_mode,
std::vector<hpfs::child_hash_node> &hash_nodes, const util::h32 &expected_hash);
void create_msg_from_filehashmap_response(
flatbuffers::FlatBufferBuilder &builder, std::string_view path, const uint32_t mount_id,
std::vector<util::h32> &hashmap, std::size_t file_length, util::h32 expected_hash);
std::vector<util::h32> &hashmap, const std::size_t file_length, const mode_t file_mode, const util::h32 &expected_hash);
void create_msg_from_block_response(flatbuffers::FlatBufferBuilder &builder, p2p::block_response &block_resp, const uint32_t mount_id);

View File

@@ -1439,8 +1439,15 @@ inline flatbuffers::Offset<HpfsResponseMsg> CreateHpfsResponseMsgDirect(
struct HpfsFsEntryResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef HpfsFsEntryResponseBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_ENTRIES = 4
VT_DIR_MODE = 4,
VT_ENTRIES = 6
};
uint32_t dir_mode() const {
return GetField<uint32_t>(VT_DIR_MODE, 0);
}
bool mutate_dir_mode(uint32_t _dir_mode) {
return SetField<uint32_t>(VT_DIR_MODE, _dir_mode, 0);
}
const flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::p2pmsg::HpfsFSHashEntry>> *entries() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::p2pmsg::HpfsFSHashEntry>> *>(VT_ENTRIES);
}
@@ -1449,6 +1456,7 @@ struct HpfsFsEntryResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint32_t>(verifier, VT_DIR_MODE) &&
VerifyOffset(verifier, VT_ENTRIES) &&
verifier.VerifyVector(entries()) &&
verifier.VerifyVectorOfTables(entries()) &&
@@ -1460,6 +1468,9 @@ struct HpfsFsEntryResponseBuilder {
typedef HpfsFsEntryResponse Table;
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_dir_mode(uint32_t dir_mode) {
fbb_.AddElement<uint32_t>(HpfsFsEntryResponse::VT_DIR_MODE, dir_mode, 0);
}
void add_entries(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::p2pmsg::HpfsFSHashEntry>>> entries) {
fbb_.AddOffset(HpfsFsEntryResponse::VT_ENTRIES, entries);
}
@@ -1477,18 +1488,22 @@ struct HpfsFsEntryResponseBuilder {
inline flatbuffers::Offset<HpfsFsEntryResponse> CreateHpfsFsEntryResponse(
flatbuffers::FlatBufferBuilder &_fbb,
uint32_t dir_mode = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::p2pmsg::HpfsFSHashEntry>>> entries = 0) {
HpfsFsEntryResponseBuilder builder_(_fbb);
builder_.add_entries(entries);
builder_.add_dir_mode(dir_mode);
return builder_.Finish();
}
inline flatbuffers::Offset<HpfsFsEntryResponse> CreateHpfsFsEntryResponseDirect(
flatbuffers::FlatBufferBuilder &_fbb,
uint32_t dir_mode = 0,
const std::vector<flatbuffers::Offset<msg::fbuf::p2pmsg::HpfsFSHashEntry>> *entries = nullptr) {
auto entries__ = entries ? _fbb.CreateVector<flatbuffers::Offset<msg::fbuf::p2pmsg::HpfsFSHashEntry>>(*entries) : 0;
return msg::fbuf::p2pmsg::CreateHpfsFsEntryResponse(
_fbb,
dir_mode,
entries__);
}
@@ -1496,7 +1511,8 @@ struct HpfsFileHashMapResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Ta
typedef HpfsFileHashMapResponseBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_FILE_LENGTH = 4,
VT_HASH_MAP = 6
VT_FILE_MODE = 6,
VT_HASH_MAP = 8
};
uint64_t file_length() const {
return GetField<uint64_t>(VT_FILE_LENGTH, 0);
@@ -1504,6 +1520,12 @@ struct HpfsFileHashMapResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Ta
bool mutate_file_length(uint64_t _file_length) {
return SetField<uint64_t>(VT_FILE_LENGTH, _file_length, 0);
}
uint32_t file_mode() const {
return GetField<uint32_t>(VT_FILE_MODE, 0);
}
bool mutate_file_mode(uint32_t _file_mode) {
return SetField<uint32_t>(VT_FILE_MODE, _file_mode, 0);
}
const flatbuffers::Vector<uint8_t> *hash_map() const {
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_HASH_MAP);
}
@@ -1513,6 +1535,7 @@ struct HpfsFileHashMapResponse FLATBUFFERS_FINAL_CLASS : private flatbuffers::Ta
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint64_t>(verifier, VT_FILE_LENGTH) &&
VerifyField<uint32_t>(verifier, VT_FILE_MODE) &&
VerifyOffset(verifier, VT_HASH_MAP) &&
verifier.VerifyVector(hash_map()) &&
verifier.EndTable();
@@ -1526,6 +1549,9 @@ struct HpfsFileHashMapResponseBuilder {
void add_file_length(uint64_t file_length) {
fbb_.AddElement<uint64_t>(HpfsFileHashMapResponse::VT_FILE_LENGTH, file_length, 0);
}
void add_file_mode(uint32_t file_mode) {
fbb_.AddElement<uint32_t>(HpfsFileHashMapResponse::VT_FILE_MODE, file_mode, 0);
}
void add_hash_map(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> hash_map) {
fbb_.AddOffset(HpfsFileHashMapResponse::VT_HASH_MAP, hash_map);
}
@@ -1544,21 +1570,25 @@ struct HpfsFileHashMapResponseBuilder {
inline flatbuffers::Offset<HpfsFileHashMapResponse> CreateHpfsFileHashMapResponse(
flatbuffers::FlatBufferBuilder &_fbb,
uint64_t file_length = 0,
uint32_t file_mode = 0,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> hash_map = 0) {
HpfsFileHashMapResponseBuilder builder_(_fbb);
builder_.add_file_length(file_length);
builder_.add_hash_map(hash_map);
builder_.add_file_mode(file_mode);
return builder_.Finish();
}
inline flatbuffers::Offset<HpfsFileHashMapResponse> CreateHpfsFileHashMapResponseDirect(
flatbuffers::FlatBufferBuilder &_fbb,
uint64_t file_length = 0,
uint32_t file_mode = 0,
const std::vector<uint8_t> *hash_map = nullptr) {
auto hash_map__ = hash_map ? _fbb.CreateVector<uint8_t>(*hash_map) : 0;
return msg::fbuf::p2pmsg::CreateHpfsFileHashMapResponse(
_fbb,
file_length,
file_mode,
hash_map__);
}

View File

@@ -40,6 +40,16 @@ namespace util
return *this;
}
void h32::operator^=(std::string_view sv)
{
const uint64_t *rhs = (uint64_t *)sv.data();
this->data[0] ^= rhs[0];
this->data[1] ^= rhs[1];
this->data[2] ^= rhs[2];
this->data[3] ^= rhs[3];
}
// Comparison operator for std::map key support.
bool h32::operator<(const h32 rhs) const
{

View File

@@ -17,6 +17,7 @@ namespace util
void operator^=(const h32 rhs);
std::string_view to_string_view() const;
h32 &operator=(std::string_view sv);
void operator^=(std::string_view sv);
bool operator<(const h32 rhs) const;
h32()