diff --git a/doc/components.txt b/doc/components.txt
index 0dbc8ecb4..3fb7b3a5d 100644
--- a/doc/components.txt
+++ b/doc/components.txt
@@ -367,9 +367,6 @@ Separate components:
Provides each file of an ISO9660 file system accessed via a block session as
separate ROM session.
-:'os/src/server/ram_fs':
- A file-system implementation that keeps all data in memory.
-
:'dde_rump/src/server/rump_fs':
A file-system server that contains various file-systems ported from the
NetBSD kernel.
diff --git a/repos/os/recipes/src/ram_fs/content.mk b/repos/os/recipes/src/ram_fs/content.mk
deleted file mode 100644
index 74257c0c0..000000000
--- a/repos/os/recipes/src/ram_fs/content.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-SRC_DIR = include/file_system include/ram_fs src/server/ram_fs
-include $(GENODE_DIR)/repos/base/recipes/src/content.inc
diff --git a/repos/os/recipes/src/ram_fs/hash b/repos/os/recipes/src/ram_fs/hash
deleted file mode 100644
index fabe9451f..000000000
--- a/repos/os/recipes/src/ram_fs/hash
+++ /dev/null
@@ -1 +0,0 @@
-2020-04-16 2f7198daac115b393af5a3d71475a7014500c60b
diff --git a/repos/os/recipes/src/ram_fs/used_apis b/repos/os/recipes/src/ram_fs/used_apis
deleted file mode 100644
index b462f992d..000000000
--- a/repos/os/recipes/src/ram_fs/used_apis
+++ /dev/null
@@ -1,3 +0,0 @@
-base
-os
-file_system_session
diff --git a/repos/os/src/server/ram_fs/README b/repos/os/src/server/ram_fs/README
deleted file mode 100644
index d2f441eb8..000000000
--- a/repos/os/src/server/ram_fs/README
+++ /dev/null
@@ -1,57 +0,0 @@
-This directory contains an in-memory file-system implementation.
-
-Configuration
-~~~~~~~~~~~~~
-
-Access to the file system can be tailored for each session depending on the
-session's label. By default, no permissions are granted to any session.
-To selectively permit access to (a part of) the file system, at least one
-ram_fs policy must be defined.
-
-The following configuration illustates the way of how to express policy.
-
-!
-!
-!
-!
-!
-!
-!
-!
-!
-! set hidden
-!
-!
-!
-!
-!
-!
-!
-!
-!
-
-The '' sub node of the '' node provides a way to pre-populate
-the file system with directories and files. Note that '' nodes can be
-arbitrarily nested. Files can be loaded from the ROM service. By adding the
-optional 'at' attribute to a rom node, the file name can be defined
-independently from the ROM module name. In addition to creating files from
-ROM modules, files can be created from data specified directly as part of the
-configuration using '' nodes. The content of such nodes is used as
-file content as is.
-
-Session-specific access-control policy is expressed via one or more ''
-nodes. At session-creation time, each policy node is matched against the label
-of the new session. If the label of a policy node matches, the defined policy
-is applied. If multiple policies match, the one with the longest 'label'
-attribute (the most specific one) is selected.
-
-A policy node may contain the following attributes. The mandatory 'root'
-attribute defines the viewport of the session onto the file system. The
-optional 'writeable' attribute grants the permission to modify the file system.
-
-
-Example
-~~~~~~~
-
-To illustrate the use of ram_fs, refer to the 'libports/run/libc_fs.run'
-script.
diff --git a/repos/os/src/server/ram_fs/directory.h b/repos/os/src/server/ram_fs/directory.h
deleted file mode 100644
index 8b4919b92..000000000
--- a/repos/os/src/server/ram_fs/directory.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * \brief File-system directory node
- * \author Norman Feske
- * \date 2012-04-11
- */
-
-/*
- * Copyright (C) 2012-2017 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.
- */
-
-#ifndef _INCLUDE__RAM_FS__DIRECTORY_H_
-#define _INCLUDE__RAM_FS__DIRECTORY_H_
-
-/* Genode includes */
-#include
-
-/* local includes */
-#include "node.h"
-#include "file.h"
-#include "symlink.h"
-
-namespace Ram_fs { class Directory; }
-
-
-class Ram_fs::Directory : public Node
-{
- private:
-
- List _entries { };
- size_t _num_entries = 0;
-
- Node *_entry_unsynchronized(size_t index)
- {
- Node *node = _entries.first();
- for (unsigned i = 0; i < index && node; node = node->next(), i++);
- return node;
- }
-
- public:
-
- Directory(char const *name) { Node::name(name); }
-
- bool has_sub_node_unsynchronized(char const *name) const override
- {
- Node const *sub_node = _entries.first();
- for (; sub_node; sub_node = sub_node->next())
- if (strcmp(sub_node->name(), name) == 0)
- return true;
-
- return false;
- }
-
- void adopt_unsynchronized(Node *node) override
- {
- /*
- * XXX inc ref counter
- */
- _entries.insert(node);
- _num_entries++;
-
- mark_as_updated();
- notify_listeners();
- }
-
- void discard(Node *node) override
- {
- _entries.remove(node);
- _num_entries--;
-
- mark_as_updated();
- notify_listeners();
- }
-
- Node *lookup(char const *path, bool return_parent = false) override
- {
- if (strcmp(path, "") == 0) {
- return this;
- }
-
- if (!path || path[0] == '/')
- throw File_system::Lookup_failed();
-
- /* find first path delimiter */
- unsigned i = 0;
- for (; path[i] && path[i] != '/'; i++);
-
- /*
- * If no path delimiter was found, we are the parent of the
- * specified path.
- */
- if (path[i] == 0 && return_parent) {
- return this;
- }
-
- /*
- * The offset 'i' corresponds to the end of the first path
- * element, which can be either the end of the string or the
- * first '/' character.
- */
-
- /* try to find entry that matches the first path element */
- Node *sub_node = _entries.first();
- for (; sub_node; sub_node = sub_node->next())
- if ((strlen(sub_node->name()) == i) &&
- (strcmp(sub_node->name(), path, i) == 0))
- break;
-
- if (!sub_node)
- throw File_system::Lookup_failed();
-
- if (!File_system::contains_path_delimiter(path)) {
-
- /*
- * Because 'path' is a basename that corresponds to an
- * existing sub_node, we have found what we were looking
- * for.
- */
- return sub_node;
- }
-
- /*
- * As 'path' contains one or more path delimiters, traverse
- * into the sub directory names after the first path element.
- */
-
- /*
- * We cannot traverse into anything other than a directory.
- *
- * XXX we might follow symlinks here
- */
- Directory *sub_dir = dynamic_cast(sub_node);
- if (!sub_dir)
- throw File_system::Lookup_failed();
-
- return sub_dir->lookup(path + i + 1, return_parent);
- }
-
- Directory *lookup_dir(char const *path)
- {
- Node *node = lookup(path);
-
- Directory *dir = dynamic_cast(node);
- if (dir)
- return dir;
-
- throw File_system::Lookup_failed();
- }
-
- File *lookup_file(char const *path) override
- {
- Node *node = lookup(path);
-
- File *file = dynamic_cast(node);
- if (file)
- return file;
-
- throw File_system::Lookup_failed();
- }
-
- Symlink *lookup_symlink(char const *path) override
- {
- Node *node = lookup(path);
-
- Symlink *symlink = dynamic_cast(node);
- if (symlink)
- return symlink;
-
- throw File_system::Lookup_failed();
- }
-
- /**
- * Lookup parent directory of the specified path
- *
- * \throw File_system::Lookup_failed
- */
- Directory *lookup_parent(char const *path)
- {
- return static_cast(lookup(path, true));
- }
-
- size_t read(char *dst, size_t len, seek_off_t seek_offset,
- Session_writeable writeable) override
- {
- using File_system::Directory_entry;
-
- if (len < sizeof(Directory_entry)) {
- Genode::error("read buffer too small for directory entry");
- return 0;
- }
-
- seek_off_t index = seek_offset / sizeof(Directory_entry);
-
- if (seek_offset % sizeof(Directory_entry)) {
- Genode::error("seek offset not alighed to sizeof(Directory_entry)");
- return 0;
- }
-
- Node *node = _entry_unsynchronized(index);
-
- /* index out of range */
- if (!node)
- return 0;
-
- auto type = [&] ()
- {
- using Node_type = File_system::Node_type;
-
- if (dynamic_cast(node)) return Node_type::DIRECTORY;
- if (dynamic_cast(node)) return Node_type::SYMLINK;
- return Node_type::CONTINUOUS_FILE;
- };
-
- Directory_entry &e = *(Directory_entry *)(dst);
-
- e = {
- .inode = node->inode(),
- .type = type(),
- .rwx = { .readable = true,
- .writeable = writeable == Session_writeable::WRITEABLE,
- .executable = true },
- .name = { node->name() }
- };
-
- return sizeof(Directory_entry);
- }
-
- size_t write(char const *, size_t, seek_off_t) override
- {
- /* writing to directory nodes is not supported */
- return 0;
- }
-
- Status status(Session_writeable writeable) override
- {
- return {
- .size = _num_entries * sizeof(File_system::Directory_entry),
- .type = File_system::Node_type::DIRECTORY,
- .rwx = { .readable = true,
- .writeable = (writeable == Session_writeable::WRITEABLE),
- .executable = true },
- .inode = inode(),
- .modification_time = modification_time()
- };
- }
-};
-
-#endif /* _INCLUDE__RAM_FS__DIRECTORY_H_ */
diff --git a/repos/os/src/server/ram_fs/file.h b/repos/os/src/server/ram_fs/file.h
deleted file mode 100644
index 507be0eec..000000000
--- a/repos/os/src/server/ram_fs/file.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * \brief File node
- * \author Norman Feske
- * \date 2012-04-11
- */
-
-/*
- * Copyright (C) 2012-2017 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.
- */
-
-#ifndef _INCLUDE__RAM_FS__FILE_H_
-#define _INCLUDE__RAM_FS__FILE_H_
-
-/* Genode includes */
-#include
-#include
-
-/* local includes */
-#include
-#include
-#include "node.h"
-
-namespace Ram_fs
-{
- using File_system::Chunk;
- using File_system::Chunk_index;
- using File_system::file_size_t;
- using File_system::SEEK_TAIL;
- class File;
-}
-
-
-class Ram_fs::File : public Node
-{
- private:
-
- typedef Chunk Chunk_level_3;
- typedef Chunk_index Chunk_level_2;
- typedef Chunk_index Chunk_level_1;
- typedef Chunk_index Chunk_level_0;
-
- Chunk_level_0 _chunk;
-
- file_size_t _length;
-
- public:
-
- File(Allocator &alloc, char const *name)
- : _chunk(alloc, 0), _length(0) { Node::name(name); }
-
- size_t read(char *dst, size_t len, seek_off_t seek_offset, Session_writeable) override
- {
- file_size_t const chunk_used_size = _chunk.used_size();
-
- if (seek_offset == SEEK_TAIL)
- seek_offset = (len < _length) ? (_length - len) : 0;
- else if (seek_offset >= _length)
- return 0;
-
- /*
- * Constrain read transaction to available chunk data
- *
- * Note that 'chunk_used_size' may be lower than '_length'
- * because 'Chunk' may have truncated tailing zeros.
- */
- if (seek_offset + len >= _length)
- len = _length - seek_offset;
-
- file_size_t read_len = len;
-
- if (seek_offset + read_len > chunk_used_size) {
- if (chunk_used_size >= seek_offset)
- read_len = chunk_used_size - seek_offset;
- else
- read_len = 0;
- }
-
- _chunk.read(dst, read_len, seek_offset);
-
- /* add zero padding if needed */
- if (read_len < len)
- memset(dst + read_len, 0, len - read_len);
-
- return len;
- }
-
- size_t write(char const *src, size_t len, seek_off_t seek_offset) override
- {
- if (seek_offset == SEEK_TAIL)
- seek_offset = _length;
-
- if (seek_offset + len >= Chunk_level_0::SIZE) {
- len = (Chunk_level_0::SIZE-1) - seek_offset;
- Genode::error(name(), ": size limit ", (long)Chunk_level_0::SIZE, " reached");
- }
-
- _chunk.write(src, len, (size_t)seek_offset);
-
- /*
- * Keep track of file length. We cannot use 'chunk.used_size()'
- * as file length because trailing zeros may by represented
- * by zero chunks, which do not contribute to 'used_size()'.
- */
- _length = max(_length, seek_offset + len);
-
- mark_as_updated();
- return len;
- }
-
- Status status(Session_writeable writeable) override
- {
- return {
- .size = _length,
- .type = File_system::Node_type::CONTINUOUS_FILE,
- .rwx = { .readable = true,
- .writeable = (writeable == Session_writeable::WRITEABLE),
- .executable = true },
- .inode = inode(),
- .modification_time = modification_time()
- };
- }
-
- void truncate(file_size_t size) override
- {
- if (size < _chunk.used_size())
- _chunk.truncate(size);
-
- _length = size;
-
- mark_as_updated();
- }
-};
-
-#endif /* _INCLUDE__RAM_FS__FILE_H_ */
diff --git a/repos/os/src/server/ram_fs/main.cc b/repos/os/src/server/ram_fs/main.cc
deleted file mode 100644
index a4e479ef8..000000000
--- a/repos/os/src/server/ram_fs/main.cc
+++ /dev/null
@@ -1,777 +0,0 @@
-/*
- * \brief RAM file system
- * \author Norman Feske
- * \date 2012-04-11
- */
-
-/*
- * Copyright (C) 2012-2017 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
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* local includes */
-#include "directory.h"
-
-
-/*************************
- ** File-system service **
- *************************/
-
-namespace Ram_fs {
-
- using namespace File_system;
- using File_system::Packet_descriptor;
- using File_system::Path;
-
- class Session_component;
- class Root;
- class Main;
-};
-
-
-class Ram_fs::Session_component : public File_system::Session_rpc_object
-{
- private:
-
- typedef File_system::Open_node Open_node;
-
- Genode::Entrypoint &_ep;
- Genode::Ram_allocator &_ram;
- Genode::Allocator &_alloc;
- Directory &_root;
- Id_space _open_node_registry { };
- Session_writeable const _writeable;
-
- Signal_handler _process_packet_handler;
-
-
- /******************************
- ** Packet-stream processing **
- ******************************/
-
- /**
- * Perform packet operation
- *
- * \return true on success, false on failure
- */
- void _process_packet_op(Packet_descriptor &packet, Open_node &open_node)
- {
- size_t const length = packet.length();
-
- /* resulting length */
- size_t res_length = 0;
- bool succeeded = false;
-
- switch (packet.operation()) {
-
- case Packet_descriptor::READ:
- if (packet.length() <= packet.size()) {
- Locked_ptr node { open_node.node() };
- if (!node.valid())
- break;
- res_length = node->read((char *)tx_sink()->packet_content(packet),
- length, packet.position(), _writeable);
-
- /* read data or EOF is a success */
- succeeded = res_length || (packet.position() >= node->status(_writeable).size);
- }
- break;
-
- case Packet_descriptor::WRITE:
- if (packet.length() <= packet.size()) {
- Locked_ptr node { open_node.node() };
- if (!node.valid())
- break;
-
- if (_writeable == Session_writeable::READ_ONLY)
- break;
-
- res_length = node->write((char const *)tx_sink()->packet_content(packet),
- 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;
- }
- open_node.mark_as_written();
- break;
-
- case Packet_descriptor::WRITE_TIMESTAMP: {
- Locked_ptr node { open_node.node() };
- if (!node.valid())
- break;
-
- if (_writeable == Session_writeable::WRITEABLE)
- packet.with_timestamp([&] (File_system::Timestamp const time) {
- node->update_modification_time(time);
- succeeded = true;
- });
- break;
- }
-
- case Packet_descriptor::CONTENT_CHANGED:
- Genode::error("CONTENT_CHANGED packets from clients have no effect");
- return;
-
- case Packet_descriptor::READ_READY:
- /* not supported */
- succeeded = true;
- break;
-
- case Packet_descriptor::SYNC: {
- Locked_ptr node { open_node.node() };
- if (!node.valid())
- break;
- node->notify_listeners();
- open_node.unmark_as_written();
- succeeded = true;
- break;
- }
- }
-
- packet.length(res_length);
- packet.succeeded(succeeded);
- tx_sink()->acknowledge_packet(packet);
- }
-
- void _process_packet()
- {
- Packet_descriptor packet = tx_sink()->get_packet();
-
- /* assume failure by default */
- packet.succeeded(false);
-
- auto process_packet_fn = [&] (Open_node &open_node) {
- _process_packet_op(packet, open_node);
- };
-
- try {
- _open_node_registry.apply(packet.handle(), process_packet_fn);
- } catch (Id_space::Unknown_id const &) {
- Genode::error("Invalid_handle");
- tx_sink()->acknowledge_packet(packet);
- } catch (Genode::Packet_descriptor::Invalid_packet) {
- Genode::error("dropping invalid File_system packet");
- }
- }
-
- void _process_packets()
- {
- 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 (most start with '/')
- */
- static void _assert_valid_path(char const *path)
- {
- if (!path || path[0] != '/') {
- Genode::warning("malformed path '", Genode::Cstring(path), "'");
- throw Lookup_failed();
- }
- }
-
- public:
-
- /**
- * Constructor
- */
- Session_component(size_t tx_buf_size, Genode::Entrypoint &ep,
- Genode::Ram_allocator &ram, Genode::Region_map &rm,
- Genode::Allocator &alloc,
- Directory &root, Session_writeable writeable)
- :
- Session_rpc_object(ram.alloc(tx_buf_size), rm, ep.rpc_ep()),
- _ep(ep),
- _ram(ram),
- _alloc(alloc),
- _root(root),
- _writeable(writeable),
- _process_packet_handler(_ep, *this, &Session_component::_process_packets)
- {
- /*
- * Register '_process_packets' method as signal handler for
- * packet-avail and ready-to-ack signals.
- */
- _tx.sigh_packet_avail(_process_packet_handler);
- _tx.sigh_ready_to_ack(_process_packet_handler);
- }
-
- /**
- * Destructor
- */
- ~Session_component()
- {
- while (_open_node_registry.apply_any([&] (Open_node &node) {
- destroy(_alloc, &node); })) { }
-
- Dataspace_capability ds = tx_sink()->dataspace();
- _ram.free(static_cap_cast(ds));
- }
-
-
- /***************************
- ** File_system interface **
- ***************************/
-
- File_handle file(Dir_handle dir_handle, Name const &name,
- Mode mode, bool create) override
- {
- if (!valid_name(name.string()))
- throw Invalid_name();
-
- auto file_fn = [&] (Open_node &open_node) {
-
- Locked_ptr dir { open_node.node() };
-
- if (!dir.valid())
- throw Unavailable();
-
- if (_writeable == Session_writeable::READ_ONLY)
- if (mode != STAT_ONLY && mode != READ_ONLY)
- throw Permission_denied();
-
- if (create) {
-
- if (_writeable == Session_writeable::READ_ONLY)
- throw Permission_denied();
-
- if (dir->has_sub_node_unsynchronized(name.string()))
- throw Node_already_exists();
-
- try {
- File * const file = new (_alloc)
- File(_alloc, name.string());
-
- dir->adopt_unsynchronized(file);
- }
- catch (Allocator::Out_of_memory) { throw No_space(); }
- }
-
- File *file = dir->lookup_file(name.string());
-
- Open_node *open_file =
- new (_alloc) Open_node(file->weak_ptr(), _open_node_registry);
-
- return open_file->id();
- };
-
- try {
- return File_handle {
- _open_node_registry.apply(dir_handle, file_fn).value
- };
- } catch (Id_space::Unknown_id const &) {
- throw Invalid_handle();
- }
- }
-
- Symlink_handle symlink(Dir_handle dir_handle, Name const &name, bool create) override
- {
- if (!valid_name(name.string()))
- throw Invalid_name();
-
- auto symlink_fn = [&] (Open_node &open_node) {
-
- Locked_ptr dir { open_node.node() };
-
- if (!dir.valid())
- throw Unavailable();
-
- if (create) {
-
- if (_writeable == Session_writeable::READ_ONLY)
- throw Permission_denied();
-
- if (dir->has_sub_node_unsynchronized(name.string()))
- throw Node_already_exists();
-
- try {
- Symlink * const symlink = new (_alloc)
- Symlink(name.string());
-
- dir->adopt_unsynchronized(symlink);
- }
- catch (Allocator::Out_of_memory) { throw No_space(); }
- }
-
- Symlink *symlink = dir->lookup_symlink(name.string());
-
- Open_node *open_symlink =
- new (_alloc) Open_node(symlink->weak_ptr(), _open_node_registry);
-
- return open_symlink->id();
- };
-
- try {
- return Symlink_handle {
- _open_node_registry.apply(dir_handle, symlink_fn).value
- };
- } catch (Id_space::Unknown_id const &) {
- throw Invalid_handle();
- }
- }
-
- Dir_handle dir(Path const &path, bool create) override
- {
- char const *path_str = path.string();
-
- _assert_valid_path(path_str);
-
- /* skip leading '/' */
- path_str++;
-
- if (create) {
-
- if (_writeable == Session_writeable::READ_ONLY)
- throw Permission_denied();
-
- if (!path.valid_string())
- throw Name_too_long();
-
- Directory *parent = _root.lookup_parent(path_str);
-
- char const *name = basename(path_str);
-
- if (parent->has_sub_node_unsynchronized(name))
- throw Node_already_exists();
-
- try {
- parent->adopt_unsynchronized(new (_alloc) Directory(name));
- } catch (Allocator::Out_of_memory) {
- throw No_space();
- }
- }
-
- Directory *dir = _root.lookup_dir(path_str);
-
- Open_node *open_dir =
- new (_alloc) Open_node(dir->weak_ptr(), _open_node_registry);
-
- return Dir_handle { open_dir->id().value };
- }
-
- Node_handle node(Path const &path) override
- {
- _assert_valid_path(path.string());
-
- Node *node = _root.lookup(path.string() + 1);
-
- Open_node *open_node =
- new (_alloc) Open_node(node->weak_ptr(), _open_node_registry);
-
- return open_node->id();
- }
-
- Watch_handle watch(Path const &path) override
- {
- _assert_valid_path(path.string());
-
- Node *node = _root.lookup(path.string() + 1);
-
- Open_node *watcher = new (_alloc)
- Open_node(node->weak_ptr(), _open_node_registry);
-
- /*
- * like other open nodes, just the only
- * kind registered for notifications
- */
- watcher->register_notify(*tx_sink());
-
- return Watch_handle { watcher->id().value };
- }
-
- void close(Node_handle handle) override
- {
- auto close_fn = [&] (Open_node &open_node) {
- destroy(_alloc, &open_node);
- };
-
- try {
- _open_node_registry.apply(handle, close_fn);
- } catch (Id_space::Unknown_id const &) {
- throw Invalid_handle();
- }
- }
-
- Status status(Node_handle node_handle) override
- {
- auto status_fn = [&] (Open_node &open_node) {
- Locked_ptr node { open_node.node() };
- if (!node.valid())
- throw Unavailable();
- return node->status(_writeable);
- };
-
- try {
- return _open_node_registry.apply(node_handle, status_fn);
- } catch (Id_space::Unknown_id const &) {
- throw Invalid_handle();
- }
- }
-
- void control(Node_handle, Control) override { }
-
- void unlink(Dir_handle dir_handle, Name const &name) override
- {
- if (!valid_name(name.string()))
- throw Invalid_name();
-
- if (_writeable == Session_writeable::READ_ONLY)
- throw Permission_denied();
-
- auto unlink_fn = [&] (Open_node &open_node) {
-
- Locked_ptr dir { open_node.node() };
-
- if (!dir.valid())
- throw Unavailable();
-
- Node *node = dir->lookup(name.string());
-
- dir->discard(node);
-
- destroy(_alloc, node);
- };
-
- try {
- _open_node_registry.apply(dir_handle, unlink_fn);
- } catch (Id_space::Unknown_id const &) {
- throw Invalid_handle();
- }
- }
-
- void truncate(File_handle file_handle, file_size_t size) override
- {
- if (_writeable == Session_writeable::READ_ONLY)
- throw Permission_denied();
-
- auto truncate_fn = [&] (Open_node &open_node) {
- Locked_ptr node { open_node.node() };
- if (!node.valid())
- throw Unavailable();
- node->truncate(size);
- open_node.mark_as_written();
- };
-
- try {
- _open_node_registry.apply(file_handle, truncate_fn);
- } catch (Id_space::Unknown_id const &) {
- throw Invalid_handle();
- }
- }
-
- void move(Dir_handle from_dir_handle, Name const &from_name,
- Dir_handle to_dir_handle, Name const &to_name) override
- {
- if (_writeable == Session_writeable::READ_ONLY)
- throw Permission_denied();
-
- if (!valid_name(from_name.string()))
- throw Lookup_failed();
-
- if (!valid_name(to_name.string()))
- throw Invalid_name();
-
- auto move_fn = [&] (Open_node &open_from_dir_node) {
-
- auto inner_move_fn = [&] (Open_node &open_to_dir_node) {
-
- Locked_ptr from_dir { open_from_dir_node.node() };
-
- if (!from_dir.valid())
- throw Unavailable();
-
- Node *node = from_dir->lookup(from_name.string());
- node->name(to_name.string());
-
- if (!(open_to_dir_node.node() == open_from_dir_node.node())) {
-
- Locked_ptr to_dir { open_to_dir_node.node() };
-
- if (!to_dir.valid())
- throw Unavailable();
-
- from_dir->discard(node);
- to_dir->adopt_unsynchronized(node);
-
- node->mark_as_updated();
- node->notify_listeners();
- }
- };
-
- try {
- _open_node_registry.apply(to_dir_handle, inner_move_fn);
- } catch (Id_space::Unknown_id const &) {
- throw Invalid_handle();
- }
- };
-
- try {
- _open_node_registry.apply(from_dir_handle, move_fn);
- } catch (Id_space::Unknown_id const &) {
- throw Invalid_handle();
- }
- }
-};
-
-
-class Ram_fs::Root : public Root_component
-{
- private:
-
- Genode::Entrypoint &_ep;
- Genode::Allocator &_alloc;
- Genode::Ram_allocator &_ram;
- Genode::Region_map &_rm;
- Genode::Xml_node const _config;
- Directory &_root_dir;
-
- protected:
-
- Session_component *_create_session(const char *args) override
- {
- /*
- * Determine client-specific policy defined implicitly by
- * the client's label.
- */
-
- Genode::Path session_root;
-
- Directory *session_root_dir = nullptr;
- bool writeable = false;
-
- Session_label const label = label_from_args(args);
- try {
- Session_policy policy(label, _config);
-
- /*
- * Determine directory that is used as root directory of
- * the session. Clients without a specified root are denied.
- */
- if (!policy.has_attribute("root")) {
- Genode::error("missing \"root\" attribute in policy definition");
- throw Service_denied();
- }
-
- typedef String Root;
- Root const root = policy.attribute_value("root", Root());
- session_root.import(root.string(), "/");
-
- /*
- * Determine if the session is writeable.
- * Policy overrides client argument, both default to false.
- */
- if (policy.attribute_value("writeable", false))
- writeable = Arg_string::find_arg(args, "writeable").bool_value(false);
-
- } catch (Session_policy::No_policy_defined) {
- Genode::error("invalid session request, no matching policy");
- throw Service_denied();
- }
-
- /* apply client's root offset */
- {
- char tmp[MAX_PATH_LEN] { };
- Arg_string::find_arg(args, "root").string(tmp, sizeof(tmp), "/");
- if (Genode::strcmp("/", tmp, sizeof(tmp))) {
- session_root.append("/");
- session_root.append(tmp);
- }
- }
- session_root.remove_trailing('/');
- if (session_root == "/") {
- session_root_dir = &_root_dir;
- } else {
- try {
- /*
- * The root path is specified with a leading path
- * delimiter. For performing the lookup, we skip the first
- * character.
- */
- session_root_dir = _root_dir.lookup_dir(
- session_root.base() + 1);
- }
- catch (Lookup_failed) { throw Service_denied(); }
- }
-
- size_t ram_quota =
- Arg_string::find_arg(args, "ram_quota" ).aligned_size();
- size_t tx_buf_size =
- Arg_string::find_arg(args, "tx_buf_size").aligned_size();
-
- if (!tx_buf_size) {
- Genode::error(label, " requested a session with a zero length transmission buffer");
- throw Service_denied();
- }
-
- /*
- * 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) {
- Genode::error("insufficient 'ram_quota', got ", ram_quota, ", "
- "need ", session_size);
- throw Insufficient_ram_quota();
- }
- return new (md_alloc())
- Session_component(tx_buf_size, _ep, _ram, _rm, _alloc,
- *session_root_dir,
- writeable ? Session_writeable::WRITEABLE
- : Session_writeable::READ_ONLY);
- }
-
- public:
-
- /**
- * Constructor
- *
- * \param ep entrypoint
- * \param md_alloc meta-data allocator
- * \param alloc general-purpose allocator
- * \param root_dir root-directory handle (anchor for fs)
- */
- Root(Genode::Entrypoint &ep, Genode::Ram_allocator &ram,
- Genode::Region_map &rm, Genode::Xml_node config,
- Allocator &md_alloc, Allocator &alloc, Directory &root_dir)
- :
- Root_component(&ep.rpc_ep(), &md_alloc),
- _ep(ep), _alloc(alloc), _ram(ram), _rm(rm), _config(config),
- _root_dir(root_dir)
- { }
-};
-
-
-static void preload_content(Genode::Env &env,
- Genode::Allocator &alloc,
- Genode::Xml_node node,
- Ram_fs::Directory &dir)
-{
- using namespace File_system;
-
- for (unsigned i = 0; i < node.num_sub_nodes(); i++) {
- Xml_node sub_node = node.sub_node(i);
-
- /*
- * Lookup name attribtue, let 'Nonexistent_attribute' exception fall
- * through because this configuration error is considered fatal.
- */
- typedef String Name;
- Name const name = sub_node.attribute_value("name", Name());
-
- /*
- * Create directory
- */
- if (sub_node.has_type("dir")) {
-
- Ram_fs::Directory *sub_dir = new (&alloc) Ram_fs::Directory(name.string());
-
- /* traverse into the new directory */
- preload_content(env, alloc, sub_node, *sub_dir);
-
- dir.adopt_unsynchronized(sub_dir);
- }
-
- /*
- * Create file from ROM module
- */
- if (sub_node.has_type("rom")) {
-
- /* read "as" attribute, use "name" as default */
- Name const as = sub_node.attribute_value("as", name);
-
- /* read file content from ROM module */
- try {
- Attached_rom_dataspace rom(env, name.string());
-
- Ram_fs::File &file = *new (&alloc) Ram_fs::File(alloc, as.string());
- file.write(rom.local_addr(), rom.size(), 0);
- dir.adopt_unsynchronized(&file);
- }
- catch (Rom_connection::Rom_connection_failed) {
- Genode::warning("failed to open ROM module \"", name, "\""); }
- catch (Region_map::Region_conflict) {
- Genode::warning("Could not locally attach ROM module \"", name, "\""); }
- }
-
- /*
- * Create file from inline data provided as content of the XML node
- */
- if (sub_node.has_type("inline")) {
-
- Ram_fs::File &file = *new (&alloc) Ram_fs::File(alloc, name.string());
-
- sub_node.with_raw_content([&] (char const *start, size_t length) {
- file.write(start, length, 0); });
-
- dir.adopt_unsynchronized(&file);
- }
- }
-}
-
-
-struct Ram_fs::Main
-{
- Genode::Env &_env;
-
- Directory _root_dir { "" };
-
- Genode::Attached_rom_dataspace _config { _env, "config" };
-
- /*
- * Initialize root interface
- */
- Genode::Sliced_heap _sliced_heap { _env.ram(), _env.rm() };
-
- Genode::Heap _heap { _env.ram(), _env.rm() };
-
- Root _fs_root { _env.ep(), _env.ram(), _env.rm(), _config.xml(),
- _sliced_heap, _heap, _root_dir };
-
- Main(Genode::Env &env) : _env(env)
- {
- /* preload RAM file system with content as declared in the config */
- try {
- preload_content(_env, _heap, _config.xml().sub_node("content"), _root_dir); }
- catch (Xml_node::Nonexistent_sub_node) { }
-
- _env.parent().announce(_env.ep().manage(_fs_root));
- }
-};
-
-
-void Component::construct(Genode::Env &env) { static Ram_fs::Main inst(env); }
diff --git a/repos/os/src/server/ram_fs/node.h b/repos/os/src/server/ram_fs/node.h
deleted file mode 100644
index d044a6a72..000000000
--- a/repos/os/src/server/ram_fs/node.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * \brief File-system node
- * \author Norman Feske
- * \date 2012-04-11
- */
-
-/*
- * Copyright (C) 2012-2017 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.
- */
-
-#ifndef _INCLUDE__RAM_FS__NODE_H_
-#define _INCLUDE__RAM_FS__NODE_H_
-
-/* Genode includes */
-#include
-#include
-#include
-
-namespace Ram_fs {
- using namespace Genode;
- using File_system::seek_off_t;
- using File_system::Status;
- using File_system::Timestamp;
- class Node;
- class File;
- class Symlink;
-
- enum class Session_writeable { READ_ONLY, WRITEABLE };
-}
-
-
-class Ram_fs::Node : public File_system::Node_base,
- private Weak_object,
- private List::Element
-{
- public:
-
- typedef char Name[128];
-
- using List::Element::next;
- using Weak_object::weak_ptr;
-
- private:
-
- friend class List;
- friend class Locked_ptr;
-
- int _ref_count;
- Name _name;
- unsigned long const _inode;
- Timestamp _modification_time { };
-
- /**
- * Generate unique inode number
- */
- static unsigned long _unique_inode()
- {
- static unsigned long inode_count;
- return ++inode_count;
- }
-
- public:
-
- Node()
- : _ref_count(0), _inode(_unique_inode())
- {
- _name[0] = 0;
- _modification_time.value = File_system::Timestamp::INVALID;
- }
-
- virtual ~Node() { lock_for_destruction(); }
-
- unsigned long inode() const { return _inode; }
- char const *name() const { return _name; }
-
- /**
- * Assign name
- */
- void name(char const *name) { strncpy(_name, name, sizeof(_name)); }
-
- void update_modification_time(Timestamp const time)
- {
- _modification_time = time;
- }
-
- Timestamp modification_time() const { return _modification_time; }
-
- /*
- * 'Session_writeable' is supplied to the 'read' method to reflect the
- * writeability in directory entries read from 'Directory' nodes.
- */
- virtual size_t read(char *dst, size_t len, seek_off_t, Session_writeable) = 0;
- virtual size_t write(char const *src, size_t len, seek_off_t) = 0;
-
- virtual Status status(Session_writeable) = 0;
-
-
- /* File functionality */
-
- virtual void truncate(File_system::file_size_t)
- {
- Genode::error(__PRETTY_FUNCTION__, " called on a non-file node");
- }
-
-
- /* Directory functionality */
-
- virtual bool has_sub_node_unsynchronized(char const *) const
- {
- Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node");
- return false;
- }
-
- virtual void adopt_unsynchronized(Node *)
- {
- Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node");
- }
-
- virtual File *lookup_file(char const *)
- {
- Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node");
- return nullptr;
- }
-
- virtual Symlink *lookup_symlink(char const *)
- {
- Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node");
- return nullptr;
- }
-
- virtual Node *lookup(char const *, bool = false)
- {
- Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node");
- return nullptr;
- }
-
- virtual void discard(Node *)
- {
- Genode::error(__PRETTY_FUNCTION__, " called on a non-directory node");
- }
-
-
-};
-
-#endif /* _INCLUDE__RAM_FS__NODE_H_ */
diff --git a/repos/os/src/server/ram_fs/symlink.h b/repos/os/src/server/ram_fs/symlink.h
deleted file mode 100644
index 099afe7d1..000000000
--- a/repos/os/src/server/ram_fs/symlink.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * \brief Symlink file-system node
- * \author Norman Feske
- * \date 2012-04-11
- */
-
-/*
- * Copyright (C) 2012-2017 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.
- */
-
-#ifndef _INCLUDE__RAM_FS__SYMLINK_H_
-#define _INCLUDE__RAM_FS__SYMLINK_H_
-
-/* local includes */
-#include "node.h"
-
-namespace Ram_fs { class Symlink; }
-
-
-class Ram_fs::Symlink : public Node
-{
- private:
-
- char _link_to[File_system::MAX_PATH_LEN];
- size_t _len;
-
- public:
-
- Symlink(char const *name): _len(0) { Node::name(name); }
-
- size_t read(char *dst, size_t len, seek_off_t seek_offset, Session_writeable) override
- {
- size_t count = min(len, _len-seek_offset);
- Genode::memcpy(dst, _link_to+seek_offset, count);
- return count;
- }
-
- size_t write(char const *src, size_t len, seek_off_t seek_offset) override
- {
- size_t const consumed_len = len;
-
- /* Ideal symlink operations are atomic. */
- if (seek_offset) return 0;
-
- for (size_t i = 0; i < len; ++i) {
- if (src[i] == '\0') {
- len = i;
- break;
- }
- }
-
- /*
- * if the target is too long return a
- * short result to indicate the error
- */
- if (len > sizeof(_link_to))
- return len >> 1;
-
- Genode::memcpy(_link_to, src, len);
- _len = len;
-
- return consumed_len;
- }
-
- Status status(Session_writeable writeable) override
- {
- return {
- .size = _len,
- .type = File_system::Node_type::SYMLINK,
- .rwx = { .readable = true,
- .writeable = (writeable == Session_writeable::WRITEABLE),
- .executable = true },
- .inode = inode(),
- .modification_time = modification_time()
- };
- }
-};
-
-#endif /* _INCLUDE__RAM_FS__SYMLINK_H_ */
diff --git a/repos/os/src/server/ram_fs/target.mk b/repos/os/src/server/ram_fs/target.mk
deleted file mode 100644
index 5023a7f3d..000000000
--- a/repos/os/src/server/ram_fs/target.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-TARGET = ram_fs
-SRC_CC = main.cc
-LIBS = base
-INC_DIR += $(PRG_DIR)