fs_tool: add <copy-all-files> operation

Related to issue #4744
This commit is contained in:
Norman Feske 2023-01-27 17:33:41 +01:00 committed by Christian Helmuth
parent 7ada79b5ca
commit 2986d46fd3

View File

@ -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); }