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)