From 2986d46fd3950f59ed42551ca9507b447b67ec3e Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 27 Jan 2023 17:33:41 +0100 Subject: [PATCH] fs_tool: add operation Related to issue #4744 --- repos/gems/src/app/fs_tool/main.cc | 75 ++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/repos/gems/src/app/fs_tool/main.cc b/repos/gems/src/app/fs_tool/main.cc index 83e566a620..4e82304651 100644 --- a/repos/gems/src/app/fs_tool/main.cc +++ b/repos/gems/src/app/fs_tool/main.cc @@ -21,10 +21,22 @@ namespace Fs_tool { using namespace Genode; + struct Byte_buffer; struct Main; } +struct Fs_tool::Byte_buffer : Byte_range_ptr +{ + Allocator &_alloc; + + Byte_buffer(Allocator &alloc, size_t size) + : Byte_range_ptr((char *)alloc.alloc(size), size), _alloc(alloc) { } + + ~Byte_buffer() { _alloc.free(start, num_bytes); } +}; + + struct Fs_tool::Main { Env &_env; @@ -46,9 +58,11 @@ struct Fs_tool::Main typedef Directory::Path Path; - void _remove_file(Xml_node); + void _copy_file(Path const &from, Path const &to, Byte_range_ptr const &); - void _new_file(Xml_node); + void _remove_file (Xml_node const &); + void _new_file (Xml_node const &); + void _copy_all_files (Xml_node const &); void _handle_config() { @@ -67,6 +81,9 @@ struct Fs_tool::Main if (operation.has_type("new-file")) _new_file(operation); + + if (operation.has_type("copy-all-files")) + _copy_all_files(operation); }); if (config.attribute_value("exit", false)) { @@ -83,7 +100,7 @@ struct Fs_tool::Main }; -void Fs_tool::Main::_remove_file(Xml_node operation) +void Fs_tool::Main::_remove_file(Xml_node const &operation) { Path const path = operation.attribute_value("path", Path()); @@ -108,7 +125,7 @@ void Fs_tool::Main::_remove_file(Xml_node operation) } -void Fs_tool::Main::_new_file(Xml_node operation) +void Fs_tool::Main::_new_file(Xml_node const &operation) { Path const path { operation.attribute_value("path", Path()) }; @@ -140,5 +157,55 @@ void Fs_tool::Main::_new_file(Xml_node operation) } +void Fs_tool::Main::_copy_file(Path const &from, Path const &to, + Byte_range_ptr const &buffer) +{ + try { + Readonly_file const src { _root_dir, from }; + New_file dst { _root_dir, to }; + + Readonly_file::At at { 0 }; + + for (;;) { + + size_t const read_bytes = src.read(at, buffer); + + dst.append(buffer.start, read_bytes); + + at.value += read_bytes; + + if (read_bytes < buffer.num_bytes) + break; + } + } + catch (...) { + error("failed to copy ", from, " to ", to); } +} + + +void Fs_tool::Main::_copy_all_files(Xml_node const &operation) +{ + Number_of_bytes const default_buffer { 1024*1024 }; + Byte_buffer buffer(_heap, operation.attribute_value("buffer", default_buffer)); + + Path const from = operation.attribute_value("from", Path()); + Path const to = operation.attribute_value("to", Path()); + + if (!_root_dir.directory_exists(from)) + return; + + Directory(_root_dir, from).for_each_entry([&] (Directory::Entry const &entry) { + + bool const continous_file = + (entry.type() == Vfs::Directory_service::Dirent_type::CONTINUOUS_FILE); + + if (continous_file) + _copy_file(Path(from, "/", entry.name()), + Path(to, "/", entry.name()), + buffer); + }); +} + + void Component::construct(Genode::Env &env) { static Fs_tool::Main main(env); }