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:

! [...]
! <config>
!   <libc>
!     <vfs>
!       <dir name="dev"> <jitterentropy name="random"/> </dir>
!     </vfs>
!   </libc>
! </config>
! [...]

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.
This commit is contained in:
Josef Söntgen 2014-08-19 17:21:10 +02:00 committed by Norman Feske
parent c745aa4454
commit 2bf67136c6
2 changed files with 91 additions and 16 deletions

View File

@ -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 <vfs/file_system.h>
#include <util/xml_node.h>
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_ */

View File

@ -41,10 +41,12 @@
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/disk.h>
#include <dlfcn.h>
/* libc plugin interface */
#include <libc-plugin/plugin.h>
#include <libc-plugin/fd_alloc.h>
#include <libc-plugin/vfs.h>
/* libc-internal includes */
#include <libc_mem_alloc.h>
@ -89,18 +91,10 @@ class Libc_file_system_factory : public Vfs::File_system_factory
{
private:
struct Entry_base : Genode::List<Entry_base>::Element
struct Entry_base : Libc::File_system_factory,
Genode::List<Entry_base>::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 <typename FILE_SYSTEM>
@ -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<Entry_base> _list;
template <typename FILE_SYSTEM>
@ -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;
}