Further work on file bundling on oar.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
kayomn 2023-02-27 00:47:29 +00:00
parent f43314cb53
commit fce7698b44

View File

@ -220,69 +220,42 @@ export namespace oar {
this->archive_path = archive_path;
}
walk_result walk_files(path const & target_path, closure<bool(path const &)> const & apply) override {
bool not_found {false};
bool has_io_error {false};
/**
* See [fs::walk_files].
*/
void walk_files(path const & target_path, closure<void(walker const &)> 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<path, walk_error> {
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<bool>(coral::equality_predicate(path_size)).ok_or(false))
if (!apply(*reinterpret_cast<path const *>(path_buffer))) return;
}
return {*reinterpret_cast<path const *>(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<void(file_reader &)> 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<coral::u32>(file_count);
if (!archive_writer.write(archive_header.bytes).map<bool>(header::is_sizeof).ok_or(false)) {