gems: initial version of fs_tool

The fs_tool component performs file operations according to its
configuration. This initial version implements only the operation
<remove-file> as needed for Sculpt CE.

Issue #3222
Issue #3193
This commit is contained in:
Norman Feske 2019-03-12 15:03:01 +01:00 committed by Christian Helmuth
parent 73f79ed5b1
commit cac3f3b24e
11 changed files with 293 additions and 0 deletions

View File

@ -0,0 +1 @@
Test for the fs_tool component

View File

@ -0,0 +1,8 @@
_/src/init
_/src/report_rom
_/src/sequence
_/src/dummy
_/src/fs_query
_/src/fs_tool
_/src/vfs
_/src/vfs_import

View File

@ -0,0 +1 @@
2019-03-12 6800bf66885ebc9a841c44ada90a59d4b7485082

View File

@ -0,0 +1,123 @@
<runtime ram="32M" caps="1000" binary="init">
<events>
<timeout meaning="failed" sec="10" />
<log meaning="succeeded">
[init -> report_rom] report 'fs_query -> listing'*
[init -> report_rom] &lt;listing>*
[init -> report_rom] &lt;dir path="/fs/items">*
[init -> report_rom] &lt;file name="1">first&lt;/file>*
[init -> report_rom] &lt;file name="2">second&lt;/file>*
[init -> report_rom] &lt;/dir>*
[init -> report_rom] &lt;/listing>*
[init -> test -> remove] Warning: file/items cannot be removed because it is a directory*
[init -> test -> remove] remove file /items/2*
[init -> test -> remove] Warning: file/3 cannot be removed because there is no such file*
[init -> test -> remove] remove file /4*
[init -> report_rom] report 'fs_query -> listing'*
[init -> report_rom] &lt;listing>*
[init -> report_rom] &lt;dir path="/fs/items">*
[init -> report_rom] &lt;file name="1">first&lt;/file>*
[init -> report_rom] &lt;/dir>*
[init -> report_rom] &lt;/listing>*
</log>
</events>
<content>
<rom label="ld.lib.so"/>
<rom label="report_rom"/>
<rom label="sequence"/>
<rom label="vfs"/>
<rom label="vfs.lib.so"/>
<rom label="vfs_import.lib.so"/>
<rom label="fs_query"/>
<rom label="fs_tool"/>
<rom label="dummy"/>
</content>
<config>
<parent-provides>
<service name="ROM"/>
<service name="LOG"/>
<service name="RM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="Timer"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<default caps="100"/>
<start name="report_rom">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config verbose="yes"/>
</start>
<start name="vfs">
<resource name="RAM" quantum="4M"/>
<provides><service name="File_system"/></provides>
<config>
<vfs>
<ram/>
<import>
<dir name="items">
<inline name="1">first</inline>
<inline name="2">second</inline>
</dir>
<inline name="4">fourth</inline>
</import>
</vfs>
<default-policy root="/" writeable="yes"/>
</config>
</start>
<start name="fs_query">
<resource name="RAM" quantum="1M"/>
<config>
<vfs> <dir name="fs"> <fs writeable="yes"/> </dir> </vfs>
<query path="/fs/items" content="yes"/>
</config>
</start>
<start name="test" caps="700">
<binary name="sequence"/>
<resource name="RAM" quantum="16M"/>
<config>
<start name="sleep" caps="100">
<resource name="RAM" quantum="4M"/>
<binary name="dummy"/>
<config>
<sleep ms="500"/>
<exit/>
</config>
</start>
<start name="remove" caps="500">
<binary name="fs_tool"/>
<config verbose="yes" exit="yes">
<vfs>
<fs writeable="yes"/>
</vfs>
<remove-file path="/items"/> <!-- is no file -->
<remove-file path="/items/2"/> <!-- should succeed -->
<remove-file path="/3"/> <!-- does not exist -->
<remove-file path="/4"/> <!-- should succeed -->
</config>
</start>
<start name="sleep" caps="100">
<resource name="RAM" quantum="4M"/>
<binary name="dummy"/>
<config>
<log string="sleep forever..."/>
</config>
</start>
</config>
</start>
</config>
</runtime>

View File

@ -0,0 +1,10 @@
SRC_DIR := src/app/fs_tool
include $(GENODE_DIR)/repos/base/recipes/src/content.inc
MIRROR_FROM_REP_DIR := include/gems/vfs.h
content: $(MIRROR_FROM_REP_DIR)
$(MIRROR_FROM_REP_DIR):
$(mirror_from_rep_dir)

View File

@ -0,0 +1 @@
2019-03-12 c9d57e9f88f69a73e394f8a415044c1f6979b87c

View File

@ -0,0 +1,3 @@
base
os
vfs

View File

@ -665,6 +665,7 @@ set default_test_pkgs {
test-fs_rom_update test-fs_rom_update
test-fs_rom_update_fs test-fs_rom_update_fs
test-fs_rom_update_ram test-fs_rom_update_ram
test-fs_tool
test-gnatio test-gnatio
test-init test-init
test-init_loop test-init_loop

View File

@ -0,0 +1,13 @@
The fs_tool component performs a sequence of file operations on a locally
configured VFS. The file operations are given the configuration as follows:
! <config exit="yes">
! <vfs>
! ...
! </vfs>
! <remove-file path="/path/to/file" />
! </config>
The 'exit="yes"' attribute instructs the component to exit after completing
the sequence. Otherwise, the component keeps responding to configuration
changes by executing the operations found in the updated configurations.

View File

@ -0,0 +1,129 @@
/*
* \brief Tool for performing a sequence of file operations
* \author Norman Feske
* \date 2019-03-12
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <base/component.h>
#include <base/sleep.h>
#include <base/attached_rom_dataspace.h>
#include <base/heap.h>
#include <gems/vfs.h>
namespace Fs_tool {
using namespace Genode;
struct Main;
}
struct Fs_tool::Main
{
Env &_env;
Heap _heap { _env.ram(), _env.rm() };
Attached_rom_dataspace _config { _env, "config" };
Vfs::Global_file_system_factory _fs_factory { _heap };
struct Vfs_env : Vfs::Env
{
Main &_main;
struct Io_response_dummy : Vfs::Io_response_handler {
void handle_io_response(Vfs::Vfs_handle::Context*) override { }
} _io_dummy { };
struct Watch_response_dummy: Vfs::Watch_response_handler {
void handle_watch_response(Vfs::Vfs_watch_handle::Context*) override { }
} _watch_dummy { };
Vfs_env(Main &main) : _main(main) { }
Genode::Env &env() override { return _main._env; }
Allocator &alloc() override { return _main._heap; }
Vfs::File_system &root_dir() override { return _main._root_dir_fs; }
Vfs::Io_response_handler &io_handler() override { return _io_dummy; }
Vfs::Watch_response_handler &watch_handler() override { return _watch_dummy; }
} _vfs_env { *this };
Vfs::Dir_file_system _root_dir_fs {
_vfs_env, _config.xml().sub_node("vfs"), _fs_factory };
Directory _root_dir { _vfs_env };
Signal_handler<Main> _config_handler {
_env.ep(), *this, &Main::_handle_config };
bool _verbose = false;
typedef Directory::Path Path;
void _remove_file(Xml_node);
void _handle_config()
{
_config.update();
Xml_node const config = _config.xml();
_verbose = config.attribute_value("verbose", false);
_root_dir_fs.apply_config(config.sub_node("vfs"));
config.for_each_sub_node([&] (Xml_node operation) {
if (operation.has_type("remove-file")) {
_remove_file(operation);
}
});
if (config.attribute_value("exit", false)) {
_env.parent().exit(0);
sleep_forever();
}
}
Main(Env &env) : _env(env)
{
_config.sigh(_config_handler);
_handle_config();
}
};
void Fs_tool::Main::_remove_file(Xml_node operation)
{
Path const path = operation.attribute_value("path", Path());
if (!_root_dir.file_exists(path)) {
if (_verbose) {
if (_root_dir.directory_exists(path))
warning("file", path, " cannot be removed because it is a directory");
else
warning("file", path, " cannot be removed because there is no such file");
}
return;
}
if (_verbose)
log("remove file ", path);
_root_dir.unlink(path);
if (_verbose && _root_dir.file_exists(path))
warning("failed to remove file ", path);
}
void Component::construct(Genode::Env &env) { static Fs_tool::Main main(env); }

View File

@ -0,0 +1,3 @@
TARGET = fs_tool
SRC_CC = main.cc
LIBS += base vfs