From 2bf67136c6eeb60433442a9ddb93a548292f8a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Tue, 19 Aug 2014 17:21:10 +0200 Subject: [PATCH] libc: add support for external vfs file systems These file systems are provided on-demand by loading a shared library when the fstab node is traversed. By convention this library is named after the file system it provides. For example a file system that provides a 'random' file system node is called 'vfs_random.lib.so'. It is still possible to give the the node another name in the vfs. The following code snippts illustrates this matter: ! [...] ! ! ! ! ! ! ! ! [...] Here the jitterentropy file system, implemented in 'vfs_jitterentropy.lib.so' provides a file system node named 'random' in the 'dev' directory. When traversing the vfs section the libc will try to load 'vfs_jitterentropy.lib.so' but programs may access the file system only via '/dev/random'. Fixes #1240. --- repos/libports/include/libc-plugin/vfs.h | 39 +++++++++++++ repos/libports/src/lib/libc/vfs_plugin.cc | 68 +++++++++++++++++------ 2 files changed, 91 insertions(+), 16 deletions(-) create mode 100644 repos/libports/include/libc-plugin/vfs.h diff --git a/repos/libports/include/libc-plugin/vfs.h b/repos/libports/include/libc-plugin/vfs.h new file mode 100644 index 000000000..e6ebd600a --- /dev/null +++ b/repos/libports/include/libc-plugin/vfs.h @@ -0,0 +1,39 @@ +/* + * \brief vfs plugin interface + * \author Josef Soentgen + * \date 2014-08-19 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _LIBC_PLUGIN__VFS_H_ +#define _LIBC_PLUGIN__VFS_H_ + +/* Genode includes */ +#include +#include + +namespace Libc { + struct File_system_factory; + + typedef Libc::File_system_factory*(*File_system_factory_func)(void); +} + +struct Libc::File_system_factory +{ + char const * const name; + + File_system_factory(char const *name) : name(name) { } + + virtual Vfs::File_system *create(Genode::Xml_node node) = 0; + + virtual bool matches(Genode::Xml_node node) const { + return node.has_type(name); } +}; + +#endif /* _LIBC_PLUGIN__VFS_H_ */ diff --git a/repos/libports/src/lib/libc/vfs_plugin.cc b/repos/libports/src/lib/libc/vfs_plugin.cc index acb628b32..d8e029295 100644 --- a/repos/libports/src/lib/libc/vfs_plugin.cc +++ b/repos/libports/src/lib/libc/vfs_plugin.cc @@ -41,10 +41,12 @@ #include #include #include +#include /* libc plugin interface */ #include #include +#include /* libc-internal includes */ #include @@ -89,18 +91,10 @@ class Libc_file_system_factory : public Vfs::File_system_factory { private: - struct Entry_base : Genode::List::Element + struct Entry_base : Libc::File_system_factory, + Genode::List::Element { - char const * const name; - - Entry_base(char const *name) : name(name) { } - - virtual Vfs::File_system *create(Genode::Xml_node node) = 0; - - bool matches(Genode::Xml_node node) const - { - return node.has_type(name); - } + Entry_base(char const *name) : File_system_factory(name) { } }; template @@ -114,6 +108,20 @@ class Libc_file_system_factory : public Vfs::File_system_factory } }; + struct External_entry : Entry_base + { + Libc::File_system_factory &_fs; + + External_entry(char const *name, Libc::File_system_factory_func func) + : Entry_base(name), _fs(*func()) { } + + Vfs::File_system *create(Genode::Xml_node node) override { + return _fs.create(node); } + + bool matches(Genode::Xml_node node) const override { + return node.has_type(_fs.name); } + }; + Genode::List _list; template @@ -131,6 +139,33 @@ class Libc_file_system_factory : public Vfs::File_system_factory return 0; } + bool _probe_lib(Genode::Xml_node node) + { + enum { MAX_LIB_NAME = 64, MAX_NAME = 32 }; + char lib_name[MAX_LIB_NAME]; + char name[MAX_NAME]; + + node.type_name(name, sizeof(name)); + Genode::snprintf(lib_name, sizeof(lib_name), "vfs_%s.lib.so", name); + + void *lib = dlopen(lib_name, RTLD_LAZY); + if (!lib) { + PWRN("could not open '%s'", lib_name); + return false; + } + + Libc::File_system_factory_func func = (Libc::File_system_factory_func) + dlsym(lib, "Libc_file_system_factory"); + if (!func) { + PWRN("could not find symbol 'Libc_file_system_factory' in '%s'", lib_name); + dlclose(lib); + return false; + } + + _list.insert(new (Genode::env()->heap()) External_entry(name, func)); + return true; + } + public: Vfs::File_system *create(Genode::Xml_node node) override @@ -139,11 +174,12 @@ class Libc_file_system_factory : public Vfs::File_system_factory if (Vfs::File_system *fs = _try_create(node)) return fs; - /* XXX probe for file system implementation available as shared lib */ - - /* try again with the new file system type loaded */ - if (Vfs::File_system *fs = _try_create(node)) - return fs; + /* probe for file system implementation available as shared lib */ + if (_probe_lib(node)) { + /* try again with the new file system type loaded */ + if (Vfs::File_system *fs = _try_create(node)) + return fs; + } return 0; }