From a34fb617a76fcf00ce06c253c48cbd10482cbf7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= <jws@sysret.de>
Date: Tue, 7 Mar 2017 15:16:15 +0100
Subject: [PATCH] ffat: remove deprecated env usage

Issue #2310.
---
 repos/libports/include/ffat/block.h         |  26 ++++
 repos/libports/run/libc_ffat_fs.run         |  28 +++--
 repos/libports/run/libc_filesystem_test.inc |  33 +++--
 repos/libports/src/lib/ffat/diskio_block.cc |  23 +++-
 repos/libports/src/lib/libc_ffat/plugin.cc  |  34 +++--
 repos/libports/src/server/ffat_fs/main.cc   | 133 ++++++++++----------
 repos/libports/src/server/ffat_fs/target.mk |   2 +-
 repos/libports/src/test/libc_ffat/main.cc   |  85 ++++++++-----
 repos/libports/src/test/libc_ffat/target.mk |   2 +-
 repos/libports/src/test/libc_vfs/target.mk  |   2 +-
 repos/ports/src/test/libc_noux/target.mk    |   2 +-
 11 files changed, 233 insertions(+), 137 deletions(-)
 create mode 100644 repos/libports/include/ffat/block.h

diff --git a/repos/libports/include/ffat/block.h b/repos/libports/include/ffat/block.h
new file mode 100644
index 0000000000..6d6a2e82aa
--- /dev/null
+++ b/repos/libports/include/ffat/block.h
@@ -0,0 +1,26 @@
+/*
+ * \brief  Block session initialize function
+ * \author Josef Soentgen
+ * \date   2017-03-07
+ */
+
+/*
+ * Copyright (C) 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__FFAT__BLOCK_H_
+#define _INCLUDE__FFAT__BLOCK_H_
+
+namespace Genode {
+	struct Env;
+	struct Allocator;
+}
+
+namespace Ffat {
+	void block_init(Genode::Env &, Genode::Allocator &heap);
+}
+
+#endif /* _INCLUDE__FFAT__BLOCK_H_ */
diff --git a/repos/libports/run/libc_ffat_fs.run b/repos/libports/run/libc_ffat_fs.run
index 868fc8e2a6..2136a7d122 100644
--- a/repos/libports/run/libc_ffat_fs.run
+++ b/repos/libports/run/libc_ffat_fs.run
@@ -5,10 +5,11 @@
 #
 
 set use_sd_card_drv [expr [have_spec omap4] || [have_spec arndale] || [have_spec pl180]]
-set use_ahci_drv   [have_spec x86]
+set use_ahci_drv   [expr [have_spec x86] && ![have_spec linux]]
+set use_ram_blk    [have_spec linux]
 set mkfs [check_installed mkfs.vfat]
 
-if {[expr [have_spec linux] || [have_spec odroid_xu]]} {
+if {[have_spec odroid_xu]} {
         puts "Run script does not support this platform"; exit }
 
 #
@@ -24,6 +25,7 @@ set build_components {
 
 lappend_if $use_ahci_drv    build_components drivers/ahci
 lappend_if $use_sd_card_drv build_components drivers/sd_card
+lappend_if $use_ram_blk     build_components server/ram_blk
 
 source ${genode_dir}/repos/base/run/platform_drv.inc
 append_platform_drv_build_components
@@ -63,12 +65,11 @@ set config {
 	<start name="test-libc_vfs">
 		<resource name="RAM" quantum="2M"/>
 		<config>
-			<libc stdout="/dev/log">
-				<vfs>
-					<dir name="dev"> <log/> </dir>
-					<fs/>
-				</vfs>
-			</libc>
+			<libc stdout="/dev/log"/>
+			<vfs>
+				<dir name="dev"> <log/> </dir>
+				<fs/>
+			</vfs>
 		</config>
 	</start>}
 
@@ -76,7 +77,7 @@ append_platform_drv_config
 
 append_if $use_ahci_drv config {
 	<start name="ahci_drv">
-		<resource name="RAM" quantum="1M"/>
+		<resource name="RAM" quantum="2M"/>
 		<provides> <service name="Block"/> </provides>
 		<config>
 			<policy label_prefix="ffat_fs" device="0" />
@@ -91,6 +92,13 @@ append_if $use_sd_card_drv config {
 	</start>
 }
 
+append_if $use_ram_blk config {
+	<start name="ram_blk">
+		<resource name="RAM" quantum="128M" />
+		<provides><service name="Block"/></provides>
+		<config file="test.hda" block_size="512"/>
+	</start>}
+
 append config {
 </config>
 }
@@ -110,6 +118,8 @@ set boot_modules {
 
 lappend_if $use_ahci_drv     boot_modules ahci_drv
 lappend_if $use_sd_card_drv  boot_modules sd_card_drv
+lappend_if $use_ram_blk      boot_modules ram_blk
+lappend_if $use_ram_blk      boot_modules test.hda
 
 append_platform_drv_boot_modules
 
diff --git a/repos/libports/run/libc_filesystem_test.inc b/repos/libports/run/libc_filesystem_test.inc
index c99d706e49..efd610188b 100644
--- a/repos/libports/run/libc_filesystem_test.inc
+++ b/repos/libports/run/libc_filesystem_test.inc
@@ -13,15 +13,15 @@ if {[have_spec odroid_xu] || [have_spec zynq]} {
 set use_sd_card_drv [expr [have_spec omap4] || [have_spec arndale] || [have_spec pl180]]
 
 # use AHCI on x86
-set use_ahci        [have_spec x86]
+set use_ahci        [expr [have_spec x86] && ![have_spec linux]]
+
+# use ram_blk on Linux
+set use_ram_blk     [have_spec linux]
 
 if {[catch { exec which $mkfs_cmd } ]} {
 	puts stderr "Error: $mkfs_cmd not installed, aborting test"; exit }
 
-if {[have_spec linux]} {
-	puts "Run script does not support this platform"; exit }
-
-if {![have_include "power_on/qemu"]} {
+if {[expr ![have_include "power_on/qemu"] && !$use_ram_blk]} {
 	puts "\nPlease setup your native sd or hard drive. Remove this fail stop";
 	puts "check when you have prepared your native environment.\n";
 	exit 0
@@ -41,6 +41,7 @@ lappend build_components test/libc_$filesystem
 
 lappend_if $use_ahci        build_components drivers/ahci
 lappend_if $use_sd_card_drv build_components drivers/sd_card
+lappend_if $use_ram_blk     build_components server/ram_blk
 
 source ${genode_dir}/repos/base/run/platform_drv.inc
 append_platform_drv_build_components
@@ -82,15 +83,14 @@ append config {
 append_if [have_include "power_on/qemu"] config {
 			<write-read size="1M" buffer_size="8K"/>}
 append config {
-			<libc stdout="/dev/log" stderr="/dev/log">
-				<vfs>
-					<dir name="dev">}
+			<libc stdout="/dev/log" stderr="/dev/log"/>
+			<vfs>
+				<dir name="dev">}
 append config $libc_dev_blkdev
 append config {
-						<log/>
-					</dir>
-				</vfs>
-			</libc>
+					<log/>
+				</dir>
+			</vfs>
 		</config>
 	</start>}
 
@@ -117,6 +117,13 @@ append_if $use_sd_card_drv config {
 	</start>
 }
 
+append_if $use_ram_blk config {
+	<start name="ram_blk">
+		<resource name="RAM" quantum="128M" />
+		<provides><service name="Block"/></provides>
+		<config file="test.hda" block_size="512"/>
+	</start>}
+
 append config {
 </config>
 }
@@ -139,6 +146,8 @@ append boot_modules libc_$filesystem.lib.so
 
 lappend_if $use_ahci         boot_modules ahci_drv
 lappend_if $use_sd_card_drv  boot_modules sd_card_drv
+lappend_if $use_ram_blk      boot_modules ram_blk
+lappend_if $use_ram_blk      boot_modules test.hda
 
 append_platform_drv_boot_modules
 
diff --git a/repos/libports/src/lib/ffat/diskio_block.cc b/repos/libports/src/lib/ffat/diskio_block.cc
index f960015351..bd543ae121 100644
--- a/repos/libports/src/lib/ffat/diskio_block.cc
+++ b/repos/libports/src/lib/ffat/diskio_block.cc
@@ -16,20 +16,35 @@
 #include <base/log.h>
 #include <block_session/connection.h>
 
+/* Genode block backend */
+#include <ffat/block.h>
+
 /* Ffat includes */
 extern "C" {
 #include <ffat/diskio.h>
 }
 
+namespace Ffat {
+	void block_init(Genode::Env &, Genode::Allocator &alloc);
+}
+
 using namespace Genode;
 
 static bool const verbose = false;
 
-static Genode::Allocator_avl _block_alloc(Genode::env()->heap());
-static Block::Connection *_block_connection;
+static Constructible<Genode::Allocator_avl> _block_alloc;
+static Constructible<Block::Connection>     _block_connection;
 static size_t _blk_size = 0;
 static Block::sector_t _blk_cnt  = 0;
 static Block::Session::Tx::Source *_source;
+static Genode::Env *_global_env;
+
+
+void Ffat::block_init(Genode::Env &env, Genode::Allocator &alloc)
+{
+	_global_env = &env;
+	_block_alloc.construct(&alloc);
+}
 
 
 extern "C" DSTATUS disk_initialize (BYTE drv)
@@ -50,7 +65,7 @@ extern "C" DSTATUS disk_initialize (BYTE drv)
 	}
 
 	try {
-		_block_connection = new (Genode::env()->heap()) Block::Connection(&_block_alloc);
+		_block_connection.construct(*_global_env, &*_block_alloc);
 	} catch(...) {
 		Genode::error("could not open block connection");
 		return STA_NOINIT;
@@ -64,7 +79,7 @@ extern "C" DSTATUS disk_initialize (BYTE drv)
 	/* check for read- and write-capability */
 	if (!ops.supported(Block::Packet_descriptor::READ)) {
 		Genode::error("block device not readable!");
-		destroy(env()->heap(), _block_connection);
+		_block_connection.destruct();
 		return STA_NOINIT;
 	}
 	if (!ops.supported(Block::Packet_descriptor::WRITE)) {
diff --git a/repos/libports/src/lib/libc_ffat/plugin.cc b/repos/libports/src/lib/libc_ffat/plugin.cc
index 385592cfbd..9ddec49983 100644
--- a/repos/libports/src/lib/libc_ffat/plugin.cc
+++ b/repos/libports/src/lib/libc_ffat/plugin.cc
@@ -13,6 +13,7 @@
 
 /* Genode includes */
 #include <base/env.h>
+#include <base/heap.h>
 #include <base/log.h>
 #include <os/path.h>
 
@@ -28,6 +29,9 @@
 #include <libc-plugin/plugin.h>
 #include <libc-plugin/fd_alloc.h>
 
+/* Genode block backend */
+#include <ffat/block.h>
+
 /* ffat includes */
 namespace Ffat { extern "C" {
 #include <ffat/ff.h>
@@ -138,6 +142,8 @@ class Plugin : public Libc::Plugin
 {
 	private:
 
+		Genode::Constructible<Genode::Heap> _heap;
+
 		Ffat::FATFS _fatfs;
 
 		Ffat::FIL *_get_ffat_file(Libc::File_descriptor *fd)
@@ -170,8 +176,20 @@ class Plugin : public Libc::Plugin
 		/**
 		 * Constructor
 		 */
-		Plugin() : Libc::Plugin(PLUGIN_PRIORITY)
+		Plugin() : Libc::Plugin(PLUGIN_PRIORITY) { }
+
+		~Plugin()
 		{
+			/* unmount the file system */
+			Ffat::f_mount(0, NULL);
+		}
+
+		void init(Genode::Env &env) override
+		{
+			_heap.construct(env.ram(), env.rm());
+
+			Ffat::block_init(env, *_heap);
+
 			/* mount the file system */
 			if (verbose)
 				Genode::log(__func__, ": mounting device ...");
@@ -181,12 +199,6 @@ class Plugin : public Libc::Plugin
 			}
 		}
 
-		~Plugin()
-		{
-			/* unmount the file system */
-			Ffat::f_mount(0, NULL);
-		}
-
 		/*
 		 * TODO: decide if the file named <path> shall be handled by this plugin
 		 */
@@ -251,14 +263,14 @@ class Plugin : public Libc::Plugin
 
 			if (!ffat_file){
 				/* directory */
-				Genode::destroy(Genode::env()->heap(), context(fd));
+				Genode::destroy(&*_heap, context(fd));
 				Libc::file_descriptor_allocator()->free(fd);
 				return 0;
 			}
 
 			FRESULT res = f_close(ffat_file);
 
-			Genode::destroy(Genode::env()->heap(), context(fd));
+			Genode::destroy(&*_heap, context(fd));
 			Libc::file_descriptor_allocator()->free(fd);
 
 			switch(res) {
@@ -513,7 +525,7 @@ class Plugin : public Libc::Plugin
 
 			switch(res) {
 				case FR_OK: {
-					Plugin_context *context = new (Genode::env()->heap())
+					Plugin_context *context = new (&*_heap)
 						File_plugin_context(pathname, ffat_file);
 					context->status_flags(flags);
 					Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->alloc(this, context);
@@ -533,7 +545,7 @@ class Plugin : public Libc::Plugin
 						Genode::log(__func__, ": opendir res=", (int)f_opendir_res);
 					switch(f_opendir_res) {
 						case FR_OK: {
-							Plugin_context *context = new (Genode::env()->heap())
+							Plugin_context *context = new (&*_heap)
 								Directory_plugin_context(pathname, ffat_dir);
 							context->status_flags(flags);
 							Libc::File_descriptor *f =
diff --git a/repos/libports/src/server/ffat_fs/main.cc b/repos/libports/src/server/ffat_fs/main.cc
index 7731ddab72..1dbc9fe756 100644
--- a/repos/libports/src/server/ffat_fs/main.cc
+++ b/repos/libports/src/server/ffat_fs/main.cc
@@ -12,12 +12,11 @@
  */
 
 /* Genode includes */
+#include <base/component.h>
 #include <file_system/node_handle_registry.h>
 #include <file_system_session/rpc_object.h>
 #include <root/component.h>
-#include <cap_session/connection.h>
 #include <base/attached_rom_dataspace.h>
-#include <os/config.h>
 #include <os/session_policy.h>
 #include <util/xml_node.h>
 #include <base/heap.h>
@@ -28,6 +27,9 @@
 #include <file.h>
 #include <util.h>
 
+/* Genode block backend */
+#include <ffat/block.h>
+
 /* ffat includes */
 namespace Ffat { extern "C" {
 #include <ffat/ff.h>
@@ -57,12 +59,14 @@ namespace File_system {
 	{
 		private:
 
+			Genode::Env          &_env;
+			Genode::Allocator    &_heap;
+
 			Directory            &_root;
 			Node_handle_registry  _handle_registry;
 			bool                  _writable;
 
-			Signal_dispatcher<Session_component> _process_packet_dispatcher;
-
+			Signal_handler<Session_component> _process_packet_dispatcher;
 
 			/******************************
 			 ** Packet-stream processing **
@@ -132,7 +136,7 @@ namespace File_system {
 			 * Called by signal dispatcher, executed in the context of the main
 			 * thread (not serialized with the RPC functions)
 			 */
-			void _process_packets(unsigned)
+			void _process_packets()
 			{
 				while (tx_sink()->packet_avail()) {
 
@@ -171,15 +175,16 @@ namespace File_system {
 			/**
 			 * Constructor
 			 */
-			Session_component(size_t tx_buf_size, Rpc_entrypoint &ep,
-			                  Region_map &rm,
-			                  Signal_receiver &sig_rec,
-			                  Directory &root, bool writable)
+			Session_component(Genode::Env       &env,
+			                  Genode::Allocator &heap,
+			                  size_t             tx_buf_size,
+			                  Directory         &root,
+			                  bool               writable)
 			:
-				Session_rpc_object(env()->ram_session()->alloc(tx_buf_size), rm, ep),
-				_root(root),
-				_writable(writable),
-				_process_packet_dispatcher(sig_rec, *this,
+				Session_rpc_object(env.ram().alloc(tx_buf_size),
+				                   env.rm(), env.ep().rpc_ep()),
+				_env(env), _heap(heap), _root(root), _writable(writable),
+				_process_packet_dispatcher(env.ep(), *this,
 				                           &Session_component::_process_packets)
 			{
 				/*
@@ -196,10 +201,9 @@ namespace File_system {
 			~Session_component()
 			{
 				Dataspace_capability ds = tx_sink()->dataspace();
-				env()->ram_session()->free(static_cap_cast<Ram_dataspace>(ds));
+				_env.ram().free(static_cap_cast<Ram_dataspace>(ds));
 			}
 
-
 			/***************************
 			 ** File_system interface **
 			 ***************************/
@@ -244,7 +248,7 @@ namespace File_system {
 
 				switch(res) {
 					case FR_OK: {
-						File *file_node = new (env()->heap()) File(absolute_path.base());
+						File *file_node = new (&_heap) File(absolute_path.base());
 						file_node->ffat_fil(ffat_fil);
 						return _handle_registry.alloc(file_node);
 					}
@@ -300,7 +304,7 @@ namespace File_system {
 				 *  The 'Directory' constructor removes trailing slashes,
 				 *  except for "/"
 				 */
-				Directory *dir_node = new (env()->heap()) Directory(path.string());
+				Directory *dir_node = new (&_heap) Directory(path.string());
 
 				using namespace Ffat;
 
@@ -356,7 +360,7 @@ namespace File_system {
 								throw Lookup_failed();
 						}
 					} catch (Exception e) {
-						destroy(env()->heap(), dir_node);
+						destroy(&_heap, dir_node);
 						throw e;
 					}
 				}
@@ -396,7 +400,7 @@ namespace File_system {
 							throw Lookup_failed();
 					}
 				} catch (Exception e) {
-					destroy(env()->heap(), dir_node);
+					destroy(&_heap, dir_node);
 					throw e;
 				}
 			}
@@ -417,7 +421,7 @@ namespace File_system {
 					throw Lookup_failed();
 				}
 
-				Node *node = new (env()->heap()) Node(absolute_path.base());
+				Node *node = new (&_heap) Node(absolute_path.base());
 
 				/* f_stat() does not work for "/" */
 				if (!is_root(node->name())) {
@@ -462,7 +466,7 @@ namespace File_system {
 								throw Lookup_failed();
 						}
 					} catch (Exception e) {
-						destroy(env()->heap(), node);
+						destroy(&_heap, node);
 						throw e;
 					}
 				}
@@ -493,7 +497,7 @@ namespace File_system {
 					FRESULT res = f_close(file->ffat_fil());
 
 					/* free the node */
-					destroy(env()->heap(), file);
+					destroy(&_heap, file);
 
 					switch(res) {
 						case FR_OK:
@@ -825,10 +829,11 @@ namespace File_system {
 	{
 		private:
 
-			Rpc_entrypoint  &_channel_ep;
-			Region_map      &_rm;
-			Signal_receiver &_sig_rec;
-			Directory       &_root_dir;
+			Genode::Env       &_env;
+			Genode::Allocator &_md_alloc;
+			Genode::Allocator &_heap;
+
+			Directory         &_root_dir;
 
 		protected:
 
@@ -901,7 +906,7 @@ namespace File_system {
 									throw Root::Unavailable();
 							}
 
-							session_root_dir = new (env()->heap()) Directory(root);
+							session_root_dir = new (&_md_alloc) Directory(root);
 						}
 					} catch (Xml_node::Nonexistent_attribute) {
 						error("missing \"root\" attribute in policy definition");
@@ -942,7 +947,7 @@ namespace File_system {
 					throw Root::Quota_exceeded();
 				}
 				return new (md_alloc())
-					Session_component(tx_buf_size, _channel_ep, _rm, _sig_rec,
+					Session_component(_env, _heap, tx_buf_size,
 					                  *session_root_dir, writeable);
 			}
 
@@ -951,52 +956,52 @@ namespace File_system {
 			/**
 			 * Constructor
 			 *
-			 * \param session_ep  session entrypoint
-			 * \param sig_rec     signal receiver used for handling the
-			 *                    data-flow signals of packet streams
-			 * \param md_alloc    meta-data allocator
+			 * \param env   reference to Genode environment
+			 * \param heap  meta-data allocator
+			 * \param root  normal root directory if root in policy starts
+			 *              at root
 			 */
-			Root(Rpc_entrypoint &session_ep, Allocator &md_alloc,
-			     Region_map &rm,
-			     Signal_receiver &sig_rec, Directory &root_dir)
+			Root(Genode::Env &env, Allocator &md_alloc, Genode::Allocator &heap,
+			     Directory &root)
 			:
-				Root_component<Session_component>(&session_ep, &md_alloc),
-				_channel_ep(session_ep), _rm(rm), _sig_rec(sig_rec),
-				_root_dir(root_dir)
+				Root_component<Session_component>(&env.ep().rpc_ep(), &md_alloc),
+				_env(env), _md_alloc(md_alloc), _heap(heap), _root_dir(root)
 			{ }
 	};
 };
 
 
-int main(int, char **)
+struct Main
 {
-	using namespace File_system;
-	using namespace Ffat;
+	Genode::Env         &_env;
+	Genode::Heap         _heap        { _env.ram(), _env.rm() };
+	Genode::Sliced_heap  _sliced_heap { _env.ram(), _env.rm() };
 
-	static Ffat::FATFS _fatfs;
+	File_system::Directory _root_dir { "/" };
+	File_system::Root      _root { _env, _sliced_heap, _heap, _root_dir };
 
-	/* mount the file system */
-	if (f_mount(0, &_fatfs) != Ffat::FR_OK) {
-		error("mount failed");
-		return -1;
+	Ffat::FATFS _fatfs;
+
+	Main(Genode::Env &env) : _env(env)
+	{
+		Ffat::block_init(_env, _heap);
+
+		using namespace File_system;
+		using namespace Ffat;
+
+		/* mount the file system */
+		if (f_mount(0, &_fatfs) != Ffat::FR_OK) {
+			error("mount failed");
+
+			struct Mount_failed : Genode::Exception { };
+			throw Mount_failed();
+		}
+
+		Genode::log("--- Starting Ffat_fs ---");
+
+		_env.parent().announce(_env.ep().manage(_root));
 	}
+};
 
-	enum { STACK_SIZE = 3*sizeof(addr_t)*1024 };
-	static Cap_connection cap;
-	static Rpc_entrypoint ep(&cap, STACK_SIZE, "ffat_fs_ep");
-	static Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
-	static Signal_receiver sig_rec;
 
-	static Directory root_dir("/");
-
-	static File_system::Root root(ep, sliced_heap, *env()->rm_session(), sig_rec, root_dir);
-
-	env()->parent()->announce(ep.manage(&root));
-
-	for (;;) {
-		Signal s = sig_rec.wait_for_signal();
-		static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
-	}
-
-	return 0;
-}
+void Component::construct(Genode::Env &env) { static Main main(env); }
diff --git a/repos/libports/src/server/ffat_fs/target.mk b/repos/libports/src/server/ffat_fs/target.mk
index 0ec6a59b92..bea2bf85b2 100644
--- a/repos/libports/src/server/ffat_fs/target.mk
+++ b/repos/libports/src/server/ffat_fs/target.mk
@@ -1,4 +1,4 @@
 TARGET   = ffat_fs
 SRC_CC   = main.cc
-LIBS     = base ffat_block config
+LIBS     = base ffat_block
 INC_DIR += $(PRG_DIR)
diff --git a/repos/libports/src/test/libc_ffat/main.cc b/repos/libports/src/test/libc_ffat/main.cc
index 744f4eb273..1fc88fda13 100644
--- a/repos/libports/src/test/libc_ffat/main.cc
+++ b/repos/libports/src/test/libc_ffat/main.cc
@@ -13,7 +13,8 @@
  */
 
 /* Genode includes */
-#include <os/config.h>
+#include <base/attached_rom_dataspace.h>
+#include <libc/component.h>
 
 /* libc includes */
 #include <dirent.h>
@@ -27,14 +28,27 @@
 #include <errno.h>
 
 
-static void test_write_read()
+struct Test_failed : Genode::Exception { };
+
+#define CALL_AND_CHECK(ret, operation, condition, info_string, ...) \
+	printf("calling " #operation " " info_string "\n", ##__VA_ARGS__); \
+	ret = operation; \
+	if (condition) { \
+		printf(#operation " succeeded\n"); \
+	} else { \
+		printf(#operation " failed, " #ret "=%ld, errno=%d\n", (long)ret, errno); \
+		throw Test_failed(); \
+	}
+
+
+static void test_write_read(Genode::Xml_node node)
 {
 	size_t rounds      = 4;
 	size_t size        = 4*1024*1024;
 	size_t buffer_size = 32*1024;
 
 	try {
-		Genode::Xml_node config = Genode::config()->xml_node().sub_node("write-read");
+		Genode::Xml_node config = node.sub_node("write-read");
 
 		try { config.attribute("rounds").value(&rounds); } catch (...) { }
 
@@ -78,18 +92,7 @@ static void test_write_read()
 }
 
 
-#define CALL_AND_CHECK(ret, operation, condition, info_string, ...) \
-	printf("calling " #operation " " info_string "\n", ##__VA_ARGS__); \
-	ret = operation; \
-	if (condition) { \
-		printf(#operation " succeeded\n"); \
-	} else { \
-		printf(#operation " failed, " #ret "=%ld, errno=%d\n", (long)ret, errno); \
-		return -1; \
-	}
-
-
-int main(int argc, char *argv[])
+static void test(Genode::Xml_node node)
 {
 	int ret, fd;
 	ssize_t count;
@@ -108,7 +111,7 @@ int main(int argc, char *argv[])
 	unsigned int iterations = 1;
 
 	try {
-		Genode::config()->xml_node().sub_node("iterations").attribute("value").value(&iterations);
+		node.sub_node("iterations").attribute("value").value(&iterations);
 	} catch(...) { }
 
 	for (unsigned int i = 0; i < iterations; i++) {
@@ -148,7 +151,7 @@ int main(int argc, char *argv[])
 		printf("content of file: \"%s\"\n", buf);
 		if (strcmp(buf, pattern) != 0) {
 			printf("unexpected content of file\n");
-			return -1;
+			throw Test_failed();
 		} else {
 			printf("file content is correct\n");
 		}
@@ -176,7 +179,7 @@ int main(int argc, char *argv[])
 		printf("content of file: \"%s\"\n", buf);
 		if (strcmp(buf, &pattern[2]) != 0) {
 			printf("unexpected content of file\n");
-			return -1;
+			throw Test_failed();
 		} else {
 			printf("file content is correct\n");
 		}
@@ -205,7 +208,7 @@ int main(int argc, char *argv[])
 		printf("content of buffer: \"%s\"\n", buf);
 		if (strcmp(buf, pattern) != 0) {
 			printf("unexpected content of file\n");
-			return -1;
+			throw Test_failed();
 		} else {
 			printf("file content is correct\n");
 		}
@@ -234,21 +237,21 @@ int main(int argc, char *argv[])
 		CALL_AND_CHECK(ret, ftruncate(fd, 100), ret == 0, ""); /* increase size */
 		CALL_AND_CHECK(ret, close(fd), ret == 0, "");
 		CALL_AND_CHECK(ret, stat(file_name4, &stat_buf),
-		               (ret == 0) && (stat_buf.st_size == 100),
-		               "file_name=%s", file_name4);
+					   (ret == 0) && (stat_buf.st_size == 100),
+					   "file_name=%s", file_name4);
 		CALL_AND_CHECK(fd, open(file_name4, O_WRONLY), fd >= 0, "file_name=%s", file_name4);
 		CALL_AND_CHECK(ret, ftruncate(fd, 10), ret == 0, ""); /* decrease size */
 		CALL_AND_CHECK(ret, close(fd), ret == 0, "");
 		CALL_AND_CHECK(ret, stat(file_name4, &stat_buf),
-		               (ret == 0) && (stat_buf.st_size == 10),
-		               "file_name=%s", file_name4);
+					   (ret == 0) && (stat_buf.st_size == 10),
+					   "file_name=%s", file_name4);
 
 		/* test 'O_TRUNC' flag */
 		CALL_AND_CHECK(fd, open(file_name4, O_WRONLY | O_TRUNC), fd >= 0, "file_name=%s", file_name4);
 		CALL_AND_CHECK(ret, close(fd), ret == 0, "");
 		CALL_AND_CHECK(ret, stat(file_name4, &stat_buf),
-		               (ret == 0) && (stat_buf.st_size == 0),
-		               "file_name=%s", file_name4);
+					   (ret == 0) && (stat_buf.st_size == 0),
+					   "file_name=%s", file_name4);
 
 		/* test 'fchdir()' */
 		CALL_AND_CHECK(fd, open(dir_name, O_RDONLY), fd >= 0, "dir_name=%s", dir_name);
@@ -268,7 +271,7 @@ int main(int argc, char *argv[])
 			CALL_AND_CHECK(ret, mkdir("a", 0777), ((ret == 0) || (errno == EEXIST)), "dir_name=%s", "a");
 			CALL_AND_CHECK(ret, mkdir("c", 0777), ((ret == 0) || (errno == EEXIST)), "dir_name=%s", "c");
 			CALL_AND_CHECK(ret, symlink("../a", "c/d"),
-			               ((ret == 0) || (errno == EEXIST)), "dir_name=%s", "/c/d");
+						   ((ret == 0) || (errno == EEXIST)), "dir_name=%s", "/c/d");
 			CALL_AND_CHECK(ret, symlink("c", "e"), ((ret == 0) || (errno == EEXIST)), "dir_name=%s", "e");
 
 			CALL_AND_CHECK(fd, open("a/b", O_CREAT | O_WRONLY), fd >= 0, "file_name=%s", "a/b");
@@ -281,7 +284,7 @@ int main(int argc, char *argv[])
 			printf("content of file: \"%s\"\n", buf);
 			if (strcmp(buf, pattern) != 0) {
 				printf("unexpected content of file\n");
-				return -1;
+				throw Test_failed();
 			} else {
 				printf("file content is correct\n");
 			}
@@ -294,10 +297,26 @@ int main(int argc, char *argv[])
 		if (i < (iterations - 1))
 			sleep(2);
 	}
-
-	test_write_read();
-
-	printf("test finished\n");
-
-	return 0;
 }
+
+
+struct Main
+{
+	Main(Genode::Env &env)
+	{
+		Genode::Attached_rom_dataspace config_rom { env, "config" };
+
+		Libc::with_libc([&] () {
+
+			test(config_rom.xml());
+			test_write_read(config_rom.xml());
+
+			printf("test finished\n");
+		});
+
+		env.parent().exit(0);
+	}
+};
+
+
+void Libc::Component::construct(Libc::Env &env) { static Main main(env); }
diff --git a/repos/libports/src/test/libc_ffat/target.mk b/repos/libports/src/test/libc_ffat/target.mk
index 1e58fbbc59..3b2a9e960b 100644
--- a/repos/libports/src/test/libc_ffat/target.mk
+++ b/repos/libports/src/test/libc_ffat/target.mk
@@ -1,3 +1,3 @@
 TARGET = test-libc_ffat
-LIBS   = posix libc_ffat
+LIBS   = libc libc_ffat
 SRC_CC = main.cc
diff --git a/repos/libports/src/test/libc_vfs/target.mk b/repos/libports/src/test/libc_vfs/target.mk
index 93caeecc0a..c49e6ca3c5 100644
--- a/repos/libports/src/test/libc_vfs/target.mk
+++ b/repos/libports/src/test/libc_vfs/target.mk
@@ -1,5 +1,5 @@
 TARGET = test-libc_vfs
-LIBS   = posix
+LIBS   = libc
 SRC_CC = main.cc
 
 # we re-use the libc_ffat test
diff --git a/repos/ports/src/test/libc_noux/target.mk b/repos/ports/src/test/libc_noux/target.mk
index 09ef4ee2e4..a707af66d7 100644
--- a/repos/ports/src/test/libc_noux/target.mk
+++ b/repos/ports/src/test/libc_noux/target.mk
@@ -1,5 +1,5 @@
 TARGET = test-libc_noux
-LIBS   = posix libc_noux
+LIBS   = libc libc_noux
 SRC_CC = main.cc
 
 # we re-use the libc_ffat test