From 50643df49e46d0817fc1f57c83cdf5aa2f98dfea Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Mon, 8 Aug 2022 23:20:54 -0700 Subject: [PATCH] add PatchFileIndex --- src/PatchFileIndex.cc | 66 +++++++++++++++++++++++++++++++++++++++++++ src/PatchFileIndex.hh | 48 +++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 src/PatchFileIndex.cc create mode 100644 src/PatchFileIndex.hh diff --git a/src/PatchFileIndex.cc b/src/PatchFileIndex.cc new file mode 100644 index 00000000..eb43370b --- /dev/null +++ b/src/PatchFileIndex.cc @@ -0,0 +1,66 @@ +#include "PatchFileIndex.hh" + +#include +#include + +#include +#include +#include +#include +#include + +#include "Loggers.hh" + +using namespace std; + + + +void PatchFileIndex::File::load_data(const string& root_dir) { + string full_path = root_dir + '/' + join(this->path_directories, "/") + '/' + this->name; + auto f = fopen_unique(full_path, "rb"); + + this->size = 0; + this->crc32 = 0; + while (!feof(f.get())) { + auto& chunk = this->chunks.emplace_back(); + chunk.data = fread(f.get(), 0x4000); + this->size += chunk.data.size(); + this->crc32 = ::crc32(chunk.data.data(), chunk.data.size(), this->crc32); + } +} + +PatchFileIndex::PatchFileIndex(const string& root_dir) + : root_dir(root_dir) { + + vector path_directories; + function collect_dir = [&](const string& dir) -> void { + path_directories.emplace_back(dir); + + string full_dir_path = root_dir + '/' + join(path_directories, "/"); + patch_index_log.info("Listing directory %s", full_dir_path.c_str()); + + for (const auto& item : list_directory(full_dir_path)) { + // Skip invisible files (e.g. .DS_Store on macOS) + if (starts_with(item, ".")) { + continue; + } + + string full_item_path = full_dir_path + '/' + item; + if (isdir(full_item_path)) { + collect_dir(item); + } else if (isfile(full_item_path)) { + shared_ptr f(new File()); + f->path_directories = path_directories; + f->name = item; + f->load_data(root_dir); + this->files.emplace_back(f); + patch_index_log.info("Added file %s (%zu bytes; %zu chunks; %08" PRIX32 ")", + full_item_path.c_str(), f->size, f->chunks.size(), f->crc32); + } + } + + path_directories.pop_back(); + }; + + collect_dir("."); +} diff --git a/src/PatchFileIndex.hh b/src/PatchFileIndex.hh new file mode 100644 index 00000000..ef5ae912 --- /dev/null +++ b/src/PatchFileIndex.hh @@ -0,0 +1,48 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include + + + +struct PatchFileIndex { + explicit PatchFileIndex(const std::string& root_dir); + + struct File { + struct Chunk { + std::string data; + uint32_t crc32; + }; + std::vector path_directories; + std::string name; + std::vector chunks; + size_t size; + uint32_t crc32; + + File() : size(0), crc32(0) { } + void load_data(const std::string& root_dir); + }; + + std::vector> files; + std::string root_dir; +}; + +struct PatchFileChecksumRequest { + std::shared_ptr file; + uint32_t crc32; + uint32_t size; + bool response_received; + + explicit PatchFileChecksumRequest(std::shared_ptr file) + : file(file), crc32(0), size(0), response_received(false) { } + inline bool needs_update() const { + return !this->response_received || + (this->crc32 != this->file->crc32) || + (this->size != this->file->size); + } +};