2013-11-08 16:44:44 +01:00
|
|
|
/*
|
|
|
|
* \brief RAM file system
|
|
|
|
* \author Norman Feske
|
|
|
|
* \date 2012-04-11
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-01-16 17:04:28 +01:00
|
|
|
* Copyright (C) 2012-2017 Genode Labs GmbH
|
2013-11-08 16:44:44 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2013-11-08 16:44:44 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
2016-11-14 11:50:20 +01:00
|
|
|
#include <base/component.h>
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
#include <base/heap.h>
|
2016-11-14 11:50:20 +01:00
|
|
|
#include <base/attached_rom_dataspace.h>
|
|
|
|
#include <root/component.h>
|
2013-11-08 16:44:44 +01:00
|
|
|
#include <file_system_session/rpc_object.h>
|
|
|
|
#include <os/session_policy.h>
|
|
|
|
#include <util/xml_node.h>
|
|
|
|
|
|
|
|
/* local includes */
|
|
|
|
#include <directory.h>
|
2017-09-26 16:35:17 +02:00
|
|
|
#include <open_node.h>
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
namespace Lx_fs {
|
|
|
|
|
|
|
|
using namespace File_system;
|
|
|
|
using File_system::Packet_descriptor;
|
|
|
|
using File_system::Path;
|
|
|
|
|
2013-11-08 16:44:44 +01:00
|
|
|
struct Main;
|
|
|
|
struct Session_component;
|
|
|
|
struct Root;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
class Lx_fs::Session_component : public Session_rpc_object
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
typedef File_system::Open_node<Node> Open_node;
|
|
|
|
|
|
|
|
Genode::Env &_env;
|
|
|
|
Allocator &_md_alloc;
|
|
|
|
Directory &_root;
|
Follow practices suggested by "Effective C++"
The patch adjust the code of the base, base-<kernel>, and os repository.
To adapt existing components to fix violations of the best practices
suggested by "Effective C++" as reported by the -Weffc++ compiler
argument. The changes follow the patterns outlined below:
* A class with virtual functions can no longer publicly inherit base
classed without a vtable. The inherited object may either be moved
to a member variable, or inherited privately. The latter would be
used for classes that inherit 'List::Element' or 'Avl_node'. In order
to enable the 'List' and 'Avl_tree' to access the meta data, the
'List' must become a friend.
* Instead of adding a virtual destructor to abstract base classes,
we inherit the new 'Interface' class, which contains a virtual
destructor. This way, single-line abstract base classes can stay
as compact as they are now. The 'Interface' utility resides in
base/include/util/interface.h.
* With the new warnings enabled, all member variables must be explicitly
initialized. Basic types may be initialized with '='. All other types
are initialized with braces '{ ... }' or as class initializers. If
basic types and non-basic types appear in a row, it is nice to only
use the brace syntax (also for basic types) and align the braces.
* If a class contains pointers as members, it must now also provide a
copy constructor and assignment operator. In the most cases, one
would make them private, effectively disallowing the objects to be
copied. Unfortunately, this warning cannot be fixed be inheriting
our existing 'Noncopyable' class (the compiler fails to detect that
the inheriting class cannot be copied and still gives the error).
For now, we have to manually add declarations for both the copy
constructor and assignment operator as private class members. Those
declarations should be prepended with a comment like this:
/*
* Noncopyable
*/
Thread(Thread const &);
Thread &operator = (Thread const &);
In the future, we should revisit these places and try to replace
the pointers with references. In the presence of at least one
reference member, the compiler would no longer implicitly generate
a copy constructor. So we could remove the manual declaration.
Issue #465
2017-12-21 15:42:15 +01:00
|
|
|
Id_space<File_system::Node> _open_node_registry { };
|
2017-06-20 14:23:22 +02:00
|
|
|
bool _writable;
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2016-11-14 11:50:20 +01:00
|
|
|
Signal_handler<Session_component> _process_packet_dispatcher;
|
2013-11-08 16:44:44 +01:00
|
|
|
|
|
|
|
|
|
|
|
/******************************
|
|
|
|
** Packet-stream processing **
|
|
|
|
******************************/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Perform packet operation
|
|
|
|
*
|
|
|
|
* \return true on success, false on failure
|
|
|
|
*/
|
2017-06-20 14:23:22 +02:00
|
|
|
void _process_packet_op(Packet_descriptor &packet, Open_node &open_node)
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
|
|
|
size_t const length = packet.length();
|
|
|
|
|
|
|
|
/* resulting length */
|
|
|
|
size_t res_length = 0;
|
2018-02-13 15:13:06 +01:00
|
|
|
bool succeeded = false;
|
2013-11-08 16:44:44 +01:00
|
|
|
|
|
|
|
switch (packet.operation()) {
|
|
|
|
|
|
|
|
case Packet_descriptor::READ:
|
2018-11-25 11:58:58 +01:00
|
|
|
if (tx_sink()->packet_valid(packet) && (packet.length() <= packet.size())) {
|
|
|
|
res_length = open_node.node().read((char *)tx_sink()->packet_content(packet), length,
|
2018-02-13 15:13:06 +01:00
|
|
|
packet.position());
|
|
|
|
|
|
|
|
/* read data or EOF is a success */
|
|
|
|
succeeded = res_length || (packet.position() >= open_node.node().status().size);
|
|
|
|
}
|
2013-11-08 16:44:44 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case Packet_descriptor::WRITE:
|
2018-11-25 11:58:58 +01:00
|
|
|
if (tx_sink()->packet_valid(packet) && (packet.length() <= packet.size())) {
|
|
|
|
res_length = open_node.node().write((char const *)tx_sink()->packet_content(packet),
|
2018-02-13 15:13:06 +01:00
|
|
|
length,
|
|
|
|
packet.position());
|
|
|
|
|
|
|
|
/* File system session can't handle partial writes */
|
|
|
|
if (res_length != length) {
|
|
|
|
Genode::error("partial write detected ",
|
|
|
|
res_length, " vs ", length);
|
|
|
|
/* don't acknowledge */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
succeeded = true;
|
|
|
|
}
|
2013-11-08 16:44:44 +01:00
|
|
|
break;
|
2017-01-31 15:36:00 +01:00
|
|
|
|
2019-03-20 13:59:56 +01:00
|
|
|
case Packet_descriptor::WRITE_TIMESTAMP:
|
|
|
|
if (tx_sink()->packet_valid(packet) && (packet.length() <= packet.size())) {
|
|
|
|
|
|
|
|
packet.with_timestamp([&] (File_system::Timestamp const time) {
|
|
|
|
open_node.node().update_modification_time(time);
|
|
|
|
succeeded = true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2017-04-20 19:02:43 +02:00
|
|
|
case Packet_descriptor::CONTENT_CHANGED:
|
2017-06-20 14:23:22 +02:00
|
|
|
open_node.register_notify(*tx_sink());
|
2017-04-20 19:02:43 +02:00
|
|
|
/* notify_listeners may bounce the packet back*/
|
2017-06-20 14:23:22 +02:00
|
|
|
open_node.node().notify_listeners();
|
2017-04-20 19:02:43 +02:00
|
|
|
/* otherwise defer acknowledgement of this packet */
|
|
|
|
return;
|
|
|
|
|
2017-01-31 15:36:00 +01:00
|
|
|
case Packet_descriptor::READ_READY:
|
2018-02-13 15:13:06 +01:00
|
|
|
succeeded = true;
|
2017-01-31 15:36:00 +01:00
|
|
|
/* not supported */
|
|
|
|
break;
|
2017-08-15 20:51:53 +02:00
|
|
|
|
|
|
|
case Packet_descriptor::SYNC:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* We could call sync(2) here but for now we forward just the
|
|
|
|
* reminder because besides testing, there is currently no
|
|
|
|
* use-case.
|
|
|
|
*/
|
|
|
|
Genode::warning("SYNC not implemented!");
|
2018-02-13 15:13:06 +01:00
|
|
|
succeeded = true;
|
2017-08-15 20:51:53 +02:00
|
|
|
break;
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
packet.length(res_length);
|
2018-02-13 15:13:06 +01:00
|
|
|
packet.succeeded(succeeded);
|
2017-04-20 19:02:43 +02:00
|
|
|
tx_sink()->acknowledge_packet(packet);
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void _process_packet()
|
|
|
|
{
|
|
|
|
Packet_descriptor packet = tx_sink()->get_packet();
|
|
|
|
|
|
|
|
/* assume failure by default */
|
|
|
|
packet.succeeded(false);
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
auto process_packet_fn = [&] (Open_node &open_node) {
|
|
|
|
_process_packet_op(packet, open_node);
|
|
|
|
};
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
try {
|
|
|
|
_open_node_registry.apply<Open_node>(packet.handle(), process_packet_fn);
|
|
|
|
} catch (Id_space<File_system::Node>::Unknown_id const &) {
|
|
|
|
Genode::error("Invalid_handle");
|
|
|
|
tx_sink()->acknowledge_packet(packet);
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called by signal dispatcher, executed in the context of the main
|
|
|
|
* thread (not serialized with the RPC functions)
|
|
|
|
*/
|
2016-11-14 11:50:20 +01:00
|
|
|
void _process_packets()
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
|
|
|
while (tx_sink()->packet_avail()) {
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure that the '_process_packet' function does not
|
|
|
|
* block.
|
|
|
|
*
|
|
|
|
* If the acknowledgement queue is full, we defer packet
|
|
|
|
* processing until the client processed pending
|
|
|
|
* acknowledgements and thereby emitted a ready-to-ack
|
|
|
|
* signal. Otherwise, the call of 'acknowledge_packet()'
|
|
|
|
* in '_process_packet' would infinitely block the context
|
|
|
|
* of the main thread. The main thread is however needed
|
|
|
|
* for receiving any subsequent 'ready-to-ack' signals.
|
|
|
|
*/
|
|
|
|
if (!tx_sink()->ready_to_ack())
|
|
|
|
return;
|
|
|
|
|
|
|
|
_process_packet();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if string represents a valid path (must start with '/')
|
|
|
|
*/
|
|
|
|
static void _assert_valid_path(char const *path)
|
|
|
|
{
|
|
|
|
if (!path || path[0] != '/') {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::warning("malformed path '", path, "'");
|
2013-11-08 16:44:44 +01:00
|
|
|
throw Lookup_failed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructor
|
|
|
|
*/
|
2016-11-14 11:50:20 +01:00
|
|
|
Session_component(size_t tx_buf_size,
|
|
|
|
Genode::Env &env,
|
|
|
|
char const *root_dir,
|
|
|
|
bool writable,
|
|
|
|
Allocator &md_alloc)
|
2013-11-08 16:44:44 +01:00
|
|
|
:
|
2017-01-16 17:04:28 +01:00
|
|
|
Session_rpc_object(env.ram().alloc(tx_buf_size), env.rm(), env.ep().rpc_ep()),
|
2016-11-14 11:50:20 +01:00
|
|
|
_env(env),
|
2013-11-08 16:44:44 +01:00
|
|
|
_md_alloc(md_alloc),
|
|
|
|
_root(*new (&_md_alloc) Directory(_md_alloc, root_dir, false)),
|
|
|
|
_writable(writable),
|
2016-11-14 11:50:20 +01:00
|
|
|
_process_packet_dispatcher(env.ep(), *this, &Session_component::_process_packets)
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Register '_process_packets' dispatch function as signal
|
|
|
|
* handler for packet-avail and ready-to-ack signals.
|
|
|
|
*/
|
2014-01-10 11:42:31 +01:00
|
|
|
_tx.sigh_packet_avail(_process_packet_dispatcher);
|
|
|
|
_tx.sigh_ready_to_ack(_process_packet_dispatcher);
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destructor
|
|
|
|
*/
|
|
|
|
~Session_component()
|
|
|
|
{
|
|
|
|
Dataspace_capability ds = tx_sink()->dataspace();
|
2016-11-14 11:50:20 +01:00
|
|
|
_env.ram().free(static_cap_cast<Ram_dataspace>(ds));
|
2013-11-08 16:44:44 +01:00
|
|
|
destroy(&_md_alloc, &_root);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************
|
|
|
|
** File_system interface **
|
|
|
|
***************************/
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
File_handle file(Dir_handle dir_handle, Name const &name, Mode mode, bool create) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
|
|
|
if (!valid_name(name.string()))
|
|
|
|
throw Invalid_name();
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
auto file_fn = [&] (Open_node &open_node) {
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
Node &dir = open_node.node();
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
if (!_writable)
|
|
|
|
if (create || (mode != STAT_ONLY && mode != READ_ONLY))
|
|
|
|
throw Permission_denied();
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
File *file = dir.file(name.string(), mode, create);
|
|
|
|
|
|
|
|
Open_node *open_file =
|
|
|
|
new (_md_alloc) Open_node(*file, _open_node_registry);
|
|
|
|
|
|
|
|
return open_file->id();
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
return File_handle {
|
|
|
|
_open_node_registry.apply<Open_node>(dir_handle, file_fn).value
|
|
|
|
};
|
|
|
|
} catch (Id_space<File_system::Node>::Unknown_id const &) {
|
|
|
|
throw Invalid_handle();
|
|
|
|
}
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
Symlink_handle symlink(Dir_handle, Name const &, bool /* create */) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error(__func__, " not implemented");
|
2017-06-20 14:23:22 +02:00
|
|
|
throw Permission_denied();
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
Dir_handle dir(Path const &path, bool create) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
|
|
|
char const *path_str = path.string();
|
|
|
|
|
|
|
|
_assert_valid_path(path_str);
|
|
|
|
|
|
|
|
/* skip leading '/' */
|
|
|
|
path_str++;
|
|
|
|
|
|
|
|
if (!_writable && create)
|
|
|
|
throw Permission_denied();
|
|
|
|
|
2016-05-11 18:21:47 +02:00
|
|
|
if (!path.valid_string())
|
2013-11-08 16:44:44 +01:00
|
|
|
throw Name_too_long();
|
|
|
|
|
|
|
|
Directory *dir = _root.subdir(path_str, create);
|
2017-06-20 14:23:22 +02:00
|
|
|
|
|
|
|
Open_node *open_dir =
|
|
|
|
new (_md_alloc) Open_node(*dir, _open_node_registry);
|
|
|
|
|
|
|
|
return Dir_handle { open_dir->id().value };
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
Node_handle node(Path const &path) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
|
|
|
char const *path_str = path.string();
|
|
|
|
|
|
|
|
_assert_valid_path(path_str);
|
|
|
|
|
|
|
|
Node *node = _root.node(path_str + 1);
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
Open_node *open_node =
|
|
|
|
new (_md_alloc) Open_node(*node, _open_node_registry);
|
|
|
|
|
|
|
|
return open_node->id();
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void close(Node_handle handle) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
2017-06-20 14:23:22 +02:00
|
|
|
auto close_fn = [&] (Open_node &open_node) {
|
|
|
|
Node &node = open_node.node();
|
|
|
|
destroy(_md_alloc, &open_node);
|
|
|
|
destroy(_md_alloc, &node);
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
_open_node_registry.apply<Open_node>(handle, close_fn);
|
|
|
|
} catch (Id_space<File_system::Node>::Unknown_id const &) {
|
|
|
|
throw Invalid_handle();
|
|
|
|
}
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
Status status(Node_handle node_handle) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
2017-06-20 14:23:22 +02:00
|
|
|
auto status_fn = [&] (Open_node &open_node) {
|
|
|
|
return open_node.node().status();
|
|
|
|
};
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
try {
|
|
|
|
return _open_node_registry.apply<Open_node>(node_handle, status_fn);
|
|
|
|
} catch (Id_space<File_system::Node>::Unknown_id const &) {
|
|
|
|
throw Invalid_handle();
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void control(Node_handle, Control) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error(__func__, " not implemented");
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void unlink(Dir_handle, Name const &) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error(__func__, " not implemented");
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
void truncate(File_handle file_handle, file_size_t size) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
|
|
|
if (!_writable)
|
|
|
|
throw Permission_denied();
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
auto truncate_fn = [&] (Open_node &open_node) {
|
|
|
|
open_node.node().truncate(size);
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
_open_node_registry.apply<Open_node>(file_handle, truncate_fn);
|
|
|
|
} catch (Id_space<File_system::Node>::Unknown_id const &) {
|
|
|
|
throw Invalid_handle();
|
|
|
|
}
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
2019-01-31 15:04:22 +01:00
|
|
|
void move(Dir_handle dir_from, Name const & name_from,
|
|
|
|
Dir_handle dir_to, Name const & name_to) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
2019-01-31 15:04:22 +01:00
|
|
|
typedef File_system::Open_node<Directory> Dir_node;
|
|
|
|
|
|
|
|
Directory *to = 0;
|
|
|
|
|
|
|
|
auto to_fn = [&] (Dir_node &dir_node) {
|
|
|
|
to = &dir_node.node();
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
_open_node_registry.apply<Dir_node>(dir_to, to_fn);
|
|
|
|
} catch (Id_space<File_system::Node>::Unknown_id const &) {
|
|
|
|
throw Invalid_handle();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto move_fn = [&] (Dir_node &dir_node) {
|
|
|
|
dir_node.node().rename(*to, name_from.string(), name_to.string());
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
_open_node_registry.apply<Dir_node>(dir_from, move_fn);
|
|
|
|
} catch (Id_space<File_system::Node>::Unknown_id const &) {
|
|
|
|
throw Invalid_handle();
|
|
|
|
}
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
class Lx_fs::Root : public Root_component<Session_component>
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
2016-11-14 11:50:20 +01:00
|
|
|
Genode::Env &_env;
|
|
|
|
|
|
|
|
Genode::Attached_rom_dataspace _config { _env, "config" };
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2019-09-11 10:49:09 +02:00
|
|
|
static inline bool writeable_from_args(char const *args)
|
|
|
|
{
|
|
|
|
return { Arg_string::find_arg(args, "writeable").bool_value(true) };
|
|
|
|
}
|
|
|
|
|
2013-11-08 16:44:44 +01:00
|
|
|
protected:
|
|
|
|
|
2019-02-14 22:39:08 +01:00
|
|
|
Session_component *_create_session(const char *args) override
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Determine client-specific policy defined implicitly by
|
|
|
|
* the client's label.
|
|
|
|
*/
|
|
|
|
|
|
|
|
char const *root_dir = ".";
|
|
|
|
bool writeable = false;
|
|
|
|
|
|
|
|
enum { ROOT_MAX_LEN = 256 };
|
|
|
|
char root[ROOT_MAX_LEN];
|
|
|
|
root[0] = 0;
|
|
|
|
|
2016-01-12 14:11:58 +01:00
|
|
|
Session_label const label = label_from_args(args);
|
2013-11-08 16:44:44 +01:00
|
|
|
try {
|
2016-11-14 11:50:20 +01:00
|
|
|
Session_policy policy(label, _config.xml());
|
2013-11-08 16:44:44 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine directory that is used as root directory of
|
|
|
|
* the session.
|
|
|
|
*/
|
|
|
|
try {
|
|
|
|
policy.attribute("root").value(root, sizeof(root));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure the root path is specified with a
|
|
|
|
* leading path delimiter. For performing the
|
2014-09-22 00:05:09 +02:00
|
|
|
* lookup, we remove all leading slashes.
|
2013-11-08 16:44:44 +01:00
|
|
|
*/
|
2014-09-22 00:05:09 +02:00
|
|
|
if (root[0] != '/') {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("Root directory must start with / but is \"",
|
|
|
|
Genode::Cstring(root), "\"");
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
throw Service_denied();
|
2014-09-22 00:05:09 +02:00
|
|
|
}
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2014-09-22 00:05:09 +02:00
|
|
|
for (root_dir = root; *root_dir == '/'; ++root_dir) ;
|
|
|
|
|
|
|
|
/* sanitize possibly empty root_dir to current directory */
|
|
|
|
if (*root_dir == 0)
|
|
|
|
root_dir = ".";
|
2013-11-08 16:44:44 +01:00
|
|
|
} catch (Xml_node::Nonexistent_attribute) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("missing \"root\" attribute in policy definition");
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
throw Service_denied();
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Determine if write access is permitted for the session.
|
|
|
|
*/
|
2019-09-11 10:49:09 +02:00
|
|
|
writeable = policy.attribute_value("writeable", false) &&
|
|
|
|
writeable_from_args(args);
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
}
|
|
|
|
catch (Session_policy::No_policy_defined) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("invalid session request, no matching policy");
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
throw Genode::Service_denied();
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t ram_quota =
|
|
|
|
Arg_string::find_arg(args, "ram_quota" ).ulong_value(0);
|
|
|
|
size_t tx_buf_size =
|
|
|
|
Arg_string::find_arg(args, "tx_buf_size").ulong_value(0);
|
|
|
|
|
2015-05-20 16:13:31 +02:00
|
|
|
if (!tx_buf_size) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error(label, " requested a session with a zero length transmission buffer");
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
throw Genode::Service_denied();
|
2015-05-20 16:13:31 +02:00
|
|
|
}
|
|
|
|
|
2013-11-08 16:44:44 +01:00
|
|
|
/*
|
|
|
|
* Check if donated ram quota suffices for session data,
|
|
|
|
* and communication buffer.
|
|
|
|
*/
|
|
|
|
size_t session_size = sizeof(Session_component) + tx_buf_size;
|
|
|
|
if (max((size_t)4096, session_size) > ram_quota) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("insufficient 'ram_quota', "
|
|
|
|
"got ", ram_quota, ", need ", session_size);
|
2017-05-08 14:32:03 +02:00
|
|
|
throw Insufficient_ram_quota();
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
2014-09-22 00:05:09 +02:00
|
|
|
|
|
|
|
try {
|
|
|
|
return new (md_alloc())
|
2016-11-14 11:50:20 +01:00
|
|
|
Session_component(tx_buf_size, _env, root_dir, writeable, *md_alloc());
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
}
|
|
|
|
catch (Lookup_failed) {
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::error("session root directory \"", Genode::Cstring(root), "\" "
|
|
|
|
"does not exist");
|
Streamline exception types
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
2017-05-07 22:03:22 +02:00
|
|
|
throw Service_denied();
|
2014-09-22 00:05:09 +02:00
|
|
|
}
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2016-11-14 11:50:20 +01:00
|
|
|
Root(Genode::Env &env, Allocator &md_alloc)
|
2013-11-08 16:44:44 +01:00
|
|
|
:
|
2016-11-14 11:50:20 +01:00
|
|
|
Root_component<Session_component>(&env.ep().rpc_ep(), &md_alloc),
|
|
|
|
_env(env)
|
2013-11-08 16:44:44 +01:00
|
|
|
{ }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
struct Lx_fs::Main
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
2016-11-14 11:50:20 +01:00
|
|
|
Genode::Env &env;
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2016-11-14 11:50:20 +01:00
|
|
|
Genode::Sliced_heap sliced_heap { env.ram(), env.rm() };
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2016-11-14 11:50:20 +01:00
|
|
|
Root fs_root = { env, sliced_heap };
|
2013-11-08 16:44:44 +01:00
|
|
|
|
2016-11-14 11:50:20 +01:00
|
|
|
Main(Genode::Env &env) : env(env)
|
2013-11-08 16:44:44 +01:00
|
|
|
{
|
2016-11-14 11:50:20 +01:00
|
|
|
env.parent().announce(env.ep().manage(fs_root));
|
2013-11-08 16:44:44 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-06-20 14:23:22 +02:00
|
|
|
void Component::construct(Genode::Env &env) { static Lx_fs::Main inst(env); }
|