From fce7698b444dfa7195da9a0832f4b7491c652286 Mon Sep 17 00:00:00 2001 From: kayomn Date: Mon, 27 Feb 2023 00:47:29 +0000 Subject: [PATCH] Further work on file bundling on oar. --- source/oar.cpp | 106 ++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/source/oar.cpp b/source/oar.cpp index b984a1f..ac7c456 100644 --- a/source/oar.cpp +++ b/source/oar.cpp @@ -220,69 +220,42 @@ export namespace oar { this->archive_path = archive_path; } - walk_result walk_files(path const & target_path, closure const & apply) override { - bool not_found {false}; - bool has_io_error {false}; - + /** + * See [fs::walk_files]. + */ + void walk_files(path const & target_path, closure const & then) override { this->backing_fs->read_file(this->archive_path, [&](file_reader & archive_reader) { entry archive_entry{&archive_reader}; - if (archive_entry.find(entry_kind::directory, target_path) != entry::find_result::ok) { - not_found = true; + if (archive_entry.find(entry_kind::directory, target_path) != entry::find_result::ok) return; - return; - } - - for (;;) { + then([&]() -> expected { constexpr usize path_size {sizeof(path)}; u8 path_buffer[path_size] {0}; - expected const data_read {archive_entry.read(path_buffer)}; - if (data_read.is_error()) { - has_io_error = true; + // Read verify integrity. + { + expected const data_read {archive_entry.read(path_buffer)}; - return; - } + if (data_read.is_error()) return walk_error::io_unavailable; - if (usize const data_read_value {*data_read.ok()}; data_read_value != path_size) { - if (data_read_value != 0) has_io_error = true; - - return; + switch (*data_read.ok()) { + case path_size: break; + case 0: return walk_error::end_of_walk; + default: return walk_error::io_unavailable; + } } // Verify existence of zero terminator in path. - if (!coral::find_last(path_buffer, 0).has_value()) { - has_io_error = true; + if (!coral::find_last(path_buffer, 0).has_value()) return walk_error::io_unavailable; - return; - } - - if (archive_entry.read(path_buffer).map(coral::equality_predicate(path_size)).ok_or(false)) - - if (!apply(*reinterpret_cast(path_buffer))) return; - } + return {*reinterpret_cast(path_buffer)}; + }); }); - - if (not_found) return walk_result::not_found; - - if (has_io_error) return walk_result::io_error; - - return walk_result::ok; } /** - * Queries the archive for the [fs::access_rules] and returns them. - */ - access_rules query_access() override { - return { - .can_read = true, - .can_write = false, - }; - } - - /** - * Attempts to open a readable context for reading from the archive file identified by `file_path`, doing - * nothing if the requested file could not be found. + * See [fs::read_file]. */ void read_file(path const & file_path, closure const & then) override { if ((this->backing_fs == nullptr) || (this->archive_path.byte_size() == 0)) return; @@ -317,17 +290,43 @@ export namespace oar { // Walk input dir to create blocks for all files needed. { - bool has_memory {true}; + bool has_io_error {false}; + bool is_out_of_memory {false}; - if (input_fs.walk_files(input_path, [&](path const & entry_path) -> bool { - has_memory = archive_blocks.push({.layout = {.path = entry_path}}) == coral::push_result::ok; + input_fs.walk_files(input_path, [&](fs::walker const & walk) { + coral::expected walked_path {walk()}; - return !has_memory; + while (walked_path.is_ok()) { + is_out_of_memory = archive_blocks.push({.layout = { + .path = *walked_path.ok() + }}) != coral::push_result::ok; - file_count += 1; - }) != fs::walk_result::ok) return bundle_result::io_error; + if (is_out_of_memory) return; - if (!has_memory) return bundle_result::out_of_memory; + file_count += 1; + walked_path = walk(); + } + + walked_path.error().and_then([&](fs::walk_error walk_error) { + switch (walk_error) { + case fs::walk_error::io_unavailable: { + has_io_error = true; + + return; + } + + case fs::walk_error::end_of_walk: { + has_io_error = true; + + return; + } + } + }); + }); + + if (has_io_error) return bundle_result::io_error; + + if (is_out_of_memory) return bundle_result::out_of_memory; if (file_count > coral::u32_max) return bundle_result::too_many_files; } @@ -341,6 +340,7 @@ export namespace oar { coral::copy(archive_header.layout.signature, signature_magic); + // This was safety-checked during the initial file tree walk step. archive_header.layout.entry_count = static_cast(file_count); if (!archive_writer.write(archive_header.bytes).map(header::is_sizeof).ok_or(false)) {