diff --git a/repos/libports/include/libc-plugin/vfs.h b/repos/libports/include/libc-plugin/vfs.h deleted file mode 100644 index e6ebd600a7..0000000000 --- a/repos/libports/include/libc-plugin/vfs.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * \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/lib/mk/libc.mk b/repos/libports/lib/mk/libc.mk index e6fcd6f7c2..0d5b8aa90c 100644 --- a/repos/libports/lib/mk/libc.mk +++ b/repos/libports/lib/mk/libc.mk @@ -4,7 +4,7 @@ LIBS = libc-string libc-locale libc-stdlib libc-stdio libc-gen libc-gdtoa \ libc-inet libc-stdtime libc-regex libc-compat libc-setjmp -LIBS += base config +LIBS += base config vfs # # Back end diff --git a/repos/libports/src/lib/libc/vfs_plugin.cc b/repos/libports/src/lib/libc/vfs_plugin.cc index 468aaf4ce2..eeabcd3114 100644 --- a/repos/libports/src/lib/libc/vfs_plugin.cc +++ b/repos/libports/src/lib/libc/vfs_plugin.cc @@ -17,18 +17,6 @@ #include #include -/* supported builtin file systems */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - /* libc includes */ #include #include @@ -46,7 +34,6 @@ /* libc plugin interface */ #include #include -#include /* libc-internal includes */ #include @@ -87,119 +74,6 @@ static void vfs_stat_to_libc_stat_struct(Vfs::Directory_service::Stat const &src } -class Libc_file_system_factory : public Vfs::File_system_factory -{ - private: - - struct Entry_base : Libc::File_system_factory, - Genode::List::Element - { - Entry_base(char const *name) : File_system_factory(name) { } - }; - - template - struct Builtin_entry : Entry_base - { - Builtin_entry() : Entry_base(FILE_SYSTEM::name()) { } - - Vfs::File_system *create(Genode::Xml_node node) override - { - return new (Genode::env()->heap()) FILE_SYSTEM(node); - } - }; - - 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 - void _add_builtin_fs() - { - _list.insert(new (Genode::env()->heap()) Builtin_entry()); - } - - Vfs::File_system *_try_create(Genode::Xml_node node) - { - for (Entry_base *e = _list.first(); e; e = e->next()) - if (e->matches(node)) - return e->create(node); - - 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 - { - /* try if type is handled by the currently registered fs types */ - 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; - } - - Libc_file_system_factory() - { - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - } -}; - - namespace Libc { Genode::Xml_node config() __attribute__((weak)); @@ -283,8 +157,6 @@ class Libc::Vfs_plugin : public Libc::Plugin { private: - Libc_file_system_factory _fs_factory; - Vfs::Dir_file_system _root_dir; Genode::Xml_node _vfs_config() @@ -327,7 +199,7 @@ class Libc::Vfs_plugin : public Libc::Plugin /** * Constructor */ - Vfs_plugin() : _root_dir(_vfs_config(), _fs_factory) + Vfs_plugin() : _root_dir(_vfs_config(), Vfs::global_file_system_factory()) { chdir(initial_cwd()); diff --git a/repos/libports/src/lib/vfs/jitterentropy/vfs.cc b/repos/libports/src/lib/vfs/jitterentropy/vfs.cc index 456009e2f5..31a9cd7357 100644 --- a/repos/libports/src/lib/vfs/jitterentropy/vfs.cc +++ b/repos/libports/src/lib/vfs/jitterentropy/vfs.cc @@ -12,24 +12,22 @@ */ /* Genode includes */ -#include +#include /* local includes */ #include -struct Jitterentropy_factory : Libc::File_system_factory +struct Jitterentropy_factory : Vfs::File_system_factory { - Jitterentropy_factory() : File_system_factory("jitterentropy") { } - - Vfs::File_system *create(Genode::Xml_node node) + Vfs::File_system *create(Genode::Xml_node node) override { return new (Genode::env()->heap()) Jitterentropy_file_system(node); } }; -extern "C" Libc::File_system_factory *Libc_file_system_factory(void) +extern "C" Vfs::File_system_factory *vfs_file_system_factory(void) { static Jitterentropy_factory factory; return &factory; diff --git a/repos/os/include/vfs/file_system_factory.h b/repos/os/include/vfs/file_system_factory.h index 798af93189..60fa640ac5 100644 --- a/repos/os/include/vfs/file_system_factory.h +++ b/repos/os/include/vfs/file_system_factory.h @@ -16,7 +16,16 @@ #include -namespace Vfs { class File_system_factory; } +namespace Vfs { + + struct File_system_factory; + struct Global_file_system_factory; + + /** + * Return singleton instance of a file-system factory + */ + Global_file_system_factory &global_file_system_factory(); +} struct Vfs::File_system_factory @@ -24,4 +33,17 @@ struct Vfs::File_system_factory virtual File_system *create(Xml_node node) = 0; }; + +struct Vfs::Global_file_system_factory : File_system_factory +{ + /** + * Register an additional factory for new file-system type + * + * \name name of file-system type + * \factory factory to create instances of this file-system type + */ + virtual void extend(char const *name, File_system_factory &factory) = 0; +}; + + #endif /* _INCLUDE__VFS__FILE_SYSTEM_FACTORY_H_ */ diff --git a/repos/os/lib/mk/vfs.mk b/repos/os/lib/mk/vfs.mk new file mode 100644 index 0000000000..204aa12100 --- /dev/null +++ b/repos/os/lib/mk/vfs.mk @@ -0,0 +1,3 @@ +SRC_CC += file_system_factory.cc + +vpath %.cc $(REP_DIR)/src/lib/vfs diff --git a/repos/os/src/lib/vfs/file_system_factory.cc b/repos/os/src/lib/vfs/file_system_factory.cc new file mode 100644 index 0000000000..23cf19e3d7 --- /dev/null +++ b/repos/os/src/lib/vfs/file_system_factory.cc @@ -0,0 +1,213 @@ +/* + * \brief File-system factory implementation + * \author Norman Feske + * \date 2014-04-09 + */ + +/* + * 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. + */ + +/* Genode includes */ +#include +#include + +/* supported builtin file systems */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class Default_file_system_factory : public Vfs::Global_file_system_factory +{ + private: + + typedef Genode::String<128> Fs_type_name; + typedef Genode::String<128> Node_name; + typedef Genode::String<128> Library_name; + + struct Entry_base : Vfs::File_system_factory, + Genode::List::Element + { + Fs_type_name name; + + Entry_base(Fs_type_name const &name) : name(name) { } + + bool matches(Genode::Xml_node node) const { + return node.has_type(name.string()); } + }; + + + template + struct Builtin_entry : Entry_base + { + Builtin_entry() : Entry_base(FILE_SYSTEM::name()) { } + + Vfs::File_system *create(Genode::Xml_node node) override + { + return new (Genode::env()->heap()) FILE_SYSTEM(node); + } + }; + + struct External_entry : Entry_base + { + File_system_factory &_fs_factory; + + External_entry(Fs_type_name const &name, + Vfs::File_system_factory &fs_factory) + : + Entry_base(name), _fs_factory(fs_factory) { } + + Vfs::File_system *create(Genode::Xml_node node) override { + return _fs_factory.create(node); } + }; + + Genode::List _list; + + template + void _add_builtin_fs() + { + _list.insert(new (Genode::env()->heap()) Builtin_entry()); + } + + Vfs::File_system *_try_create(Genode::Xml_node node) + { + for (Entry_base *e = _list.first(); e; e = e->next()) + if (e->matches(node)) + return e->create(node); + + return 0; + } + + /** + * Return name of factory provided by the shared library + */ + static char const *_factory_symbol() + { + return "vfs_file_system_factory"; + } + + /** + * Return name of VFS node + */ + Node_name _node_name(Genode::Xml_node node) + { + char node_name [Node_name::capacity()]; + node.type_name(node_name, sizeof(node_name)); + return Node_name(node_name); + } + + /** + * Return matching library name for a given vfs node name + */ + Library_name _library_name(Node_name const &node_name) + { + char lib_name [Library_name::capacity()]; + Genode::snprintf(lib_name, sizeof(lib_name), "vfs_%s.lib.so", + node_name.string()); + + return Library_name(lib_name); + } + + class Factory_not_available { }; + + /** + * \throw Factory_not_available + */ + Vfs::File_system_factory &_load_factory(Library_name const &lib_name) + { + Genode::Shared_object *shared_object = nullptr; + + try { + shared_object = new (Genode::env()->heap()) + Genode::Shared_object(lib_name.string()); + + typedef Vfs::File_system_factory *(*Query_fn)(); + + Query_fn query_fn = shared_object->lookup(_factory_symbol()); + + return *query_fn(); + + } catch (Genode::Shared_object::Invalid_file) { + PWRN("could not open '%s'", lib_name.string()); + throw Factory_not_available(); + + } catch (Genode::Shared_object::Invalid_symbol) { + PWRN("could not find symbol '%s' in '%s'", + _factory_symbol(), lib_name.string()); + + Genode::destroy(Genode::env()->heap(), shared_object); + throw Factory_not_available(); + } + } + + bool _probe_external_factory(Genode::Xml_node node) + { + Library_name const lib_name = _library_name(_node_name(node)); + + try { + _list.insert(new (Genode::env()->heap()) + External_entry(_node_name(node).string(), _load_factory(lib_name))); + return true; + + } catch (Factory_not_available) { return false; } + } + + public: + + Vfs::File_system *create(Genode::Xml_node node) override + { + /* try if type is handled by the currently registered fs types */ + if (Vfs::File_system *fs = _try_create(node)) + return fs; + + /* probe for file system implementation available as shared lib */ + if (_probe_external_factory(node)) { + /* try again with the new file system type loaded */ + if (Vfs::File_system *fs = _try_create(node)) + return fs; + } + + return 0; + } + + void extend(char const *name, File_system_factory &factory) override + { + _list.insert(new (Genode::env()->heap()) + External_entry(name, factory)); + } + + Default_file_system_factory() + { + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + } +}; + + +namespace Vfs { + + Global_file_system_factory &global_file_system_factory() + { + static Default_file_system_factory inst; + return inst; + } +} diff --git a/repos/ports/src/noux/main.cc b/repos/ports/src/noux/main.cc index a3ca6760c6..ac085f8295 100644 --- a/repos/ports/src/noux/main.cc +++ b/repos/ports/src/noux/main.cc @@ -1031,56 +1031,13 @@ void *operator new (Genode::size_t size) { return Genode::env()->heap()->alloc(size); } - -class File_system_factory : public Vfs::File_system_factory +template +struct File_system_factory : Vfs::File_system_factory { - public: - - struct Entry_base : 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); - } - }; - - template - struct Entry : Entry_base - { - Entry(char const *name) : Entry_base(name) { } - - Vfs::File_system *create(Genode::Xml_node node) override - { - return new FILE_SYSTEM(node); - } - }; - - private: - - Genode::List _list; - - public: - - template - void add_fs_type() - { - _list.insert(new Entry(FS::name())); - } - - Vfs::File_system *create(Genode::Xml_node node) override - { - for (Entry_base *e = _list.first(); e; e = e->next()) - if (e->matches(node)) - return e->create(node); - - return 0; - } + Vfs::File_system *create(Genode::Xml_node node) + { + return new FILE_SYSTEM(node); + } }; @@ -1108,18 +1065,14 @@ int main(int argc, char **argv) verbose = config()->xml_node().attribute("verbose").has_value("yes"); } catch (Xml_node::Nonexistent_attribute) { } - /* register file systems */ - static File_system_factory fs_factory; - fs_factory.add_fs_type(); - fs_factory.add_fs_type(); - fs_factory.add_fs_type(); - fs_factory.add_fs_type(); - fs_factory.add_fs_type(); - fs_factory.add_fs_type(); - fs_factory.add_fs_type(); - fs_factory.add_fs_type(); - fs_factory.add_fs_type(); - fs_factory.add_fs_type(); + /* register additional file systems to the VFS */ + Vfs::Global_file_system_factory &fs_factory = Vfs::global_file_system_factory(); + + File_system_factory stdio_file_system_factory; + File_system_factory random_file_system_factory; + + fs_factory.extend("stdio", stdio_file_system_factory); + fs_factory.extend("random", random_file_system_factory); /* initialize virtual file system */ static Vfs::Dir_file_system diff --git a/repos/ports/src/noux/minimal/target.mk b/repos/ports/src/noux/minimal/target.mk index c358824726..1ee56ce883 100644 --- a/repos/ports/src/noux/minimal/target.mk +++ b/repos/ports/src/noux/minimal/target.mk @@ -1,5 +1,5 @@ TARGET = noux -LIBS = base alarm config +LIBS = alarm config vfs ld SRC_CC = main.cc dummy_net.cc INC_DIR += $(PRG_DIR) INC_DIR += $(PRG_DIR)/../ diff --git a/repos/ports/src/noux/net/target.mk b/repos/ports/src/noux/net/target.mk index 5038942df8..c303fa08c4 100644 --- a/repos/ports/src/noux/net/target.mk +++ b/repos/ports/src/noux/net/target.mk @@ -1,5 +1,5 @@ TARGET = noux_net -LIBS += alarm libc libc_lwip_nic_dhcp config +LIBS += alarm libc libc_lwip_nic_dhcp config vfs SRC_CC = main.cc net.cc