Further work on file bundling on oar.
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
f43314cb53
commit
fce7698b44
106
source/oar.cpp
106
source/oar.cpp
@ -220,69 +220,42 @@ export namespace oar {
|
|||||||
this->archive_path = archive_path;
|
this->archive_path = archive_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
walk_result walk_files(path const & target_path, closure<bool(path const &)> const & apply) override {
|
/**
|
||||||
bool not_found {false};
|
* See [fs::walk_files].
|
||||||
bool has_io_error {false};
|
*/
|
||||||
|
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) {
|
this->backing_fs->read_file(this->archive_path, [&](file_reader & archive_reader) {
|
||||||
entry archive_entry{&archive_reader};
|
entry archive_entry{&archive_reader};
|
||||||
|
|
||||||
if (archive_entry.find(entry_kind::directory, target_path) != entry::find_result::ok) {
|
if (archive_entry.find(entry_kind::directory, target_path) != entry::find_result::ok) return;
|
||||||
not_found = true;
|
|
||||||
|
|
||||||
return;
|
then([&]() -> expected<path, walk_error> {
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
constexpr usize path_size {sizeof(path)};
|
constexpr usize path_size {sizeof(path)};
|
||||||
u8 path_buffer[path_size] {0};
|
u8 path_buffer[path_size] {0};
|
||||||
expected const data_read {archive_entry.read(path_buffer)};
|
|
||||||
|
|
||||||
if (data_read.is_error()) {
|
// Read verify integrity.
|
||||||
has_io_error = true;
|
{
|
||||||
|
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) {
|
switch (*data_read.ok()) {
|
||||||
if (data_read_value != 0) has_io_error = true;
|
case path_size: break;
|
||||||
|
case 0: return walk_error::end_of_walk;
|
||||||
return;
|
default: return walk_error::io_unavailable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify existence of zero terminator in path.
|
// Verify existence of zero terminator in path.
|
||||||
if (!coral::find_last(path_buffer, 0).has_value()) {
|
if (!coral::find_last(path_buffer, 0).has_value()) return walk_error::io_unavailable;
|
||||||
has_io_error = true;
|
|
||||||
|
|
||||||
return;
|
return {*reinterpret_cast<path const *>(path_buffer)};
|
||||||
}
|
});
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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.
|
* See [fs::read_file].
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
*/
|
||||||
void read_file(path const & file_path, closure<void(file_reader &)> const & then) override {
|
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;
|
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.
|
// 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 {
|
input_fs.walk_files(input_path, [&](fs::walker const & walk) {
|
||||||
has_memory = archive_blocks.push({.layout = {.path = entry_path}}) == coral::push_result::ok;
|
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;
|
if (is_out_of_memory) return;
|
||||||
}) != fs::walk_result::ok) return bundle_result::io_error;
|
|
||||||
|
|
||||||
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;
|
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);
|
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);
|
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)) {
|
if (!archive_writer.write(archive_header.bytes).map<bool>(header::is_sizeof).ok_or(false)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user