mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 06:57:51 +00:00
vfs: decouple file-system factory from libc
This patch moves the VFS file-system factory to a separate vfs library that is independent from libc. This enables libc-less Genode programs to easily use the VFS infrastructure. Fixes #1561
This commit is contained in:
parent
435721ea19
commit
e3be65833f
@ -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 <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_ */
|
@ -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
|
||||
|
@ -17,18 +17,6 @@
|
||||
#include <vfs/dir_file_system.h>
|
||||
#include <os/config.h>
|
||||
|
||||
/* supported builtin file systems */
|
||||
#include <vfs/tar_file_system.h>
|
||||
#include <vfs/fs_file_system.h>
|
||||
#include <vfs/terminal_file_system.h>
|
||||
#include <vfs/null_file_system.h>
|
||||
#include <vfs/zero_file_system.h>
|
||||
#include <vfs/block_file_system.h>
|
||||
#include <vfs/log_file_system.h>
|
||||
#include <vfs/rom_file_system.h>
|
||||
#include <vfs/inline_file_system.h>
|
||||
#include <vfs/rtc_file_system.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
@ -46,7 +34,6 @@
|
||||
/* 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>
|
||||
@ -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<Entry_base>::Element
|
||||
{
|
||||
Entry_base(char const *name) : File_system_factory(name) { }
|
||||
};
|
||||
|
||||
template <typename FILE_SYSTEM>
|
||||
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<Entry_base> _list;
|
||||
|
||||
template <typename FILE_SYSTEM>
|
||||
void _add_builtin_fs()
|
||||
{
|
||||
_list.insert(new (Genode::env()->heap()) Builtin_entry<FILE_SYSTEM>());
|
||||
}
|
||||
|
||||
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<Vfs::Tar_file_system>();
|
||||
_add_builtin_fs<Vfs::Fs_file_system>();
|
||||
_add_builtin_fs<Vfs::Terminal_file_system>();
|
||||
_add_builtin_fs<Vfs::Null_file_system>();
|
||||
_add_builtin_fs<Vfs::Zero_file_system>();
|
||||
_add_builtin_fs<Vfs::Block_file_system>();
|
||||
_add_builtin_fs<Vfs::Log_file_system>();
|
||||
_add_builtin_fs<Vfs::Rom_file_system>();
|
||||
_add_builtin_fs<Vfs::Inline_file_system>();
|
||||
_add_builtin_fs<Vfs::Rtc_file_system>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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());
|
||||
|
||||
|
@ -12,24 +12,22 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <libc-plugin/vfs.h>
|
||||
#include <vfs/file_system_factory.h>
|
||||
|
||||
/* local includes */
|
||||
#include <vfs_jitterentropy.h>
|
||||
|
||||
|
||||
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;
|
||||
|
@ -16,7 +16,16 @@
|
||||
|
||||
#include <vfs/file_system.h>
|
||||
|
||||
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_ */
|
||||
|
3
repos/os/lib/mk/vfs.mk
Normal file
3
repos/os/lib/mk/vfs.mk
Normal file
@ -0,0 +1,3 @@
|
||||
SRC_CC += file_system_factory.cc
|
||||
|
||||
vpath %.cc $(REP_DIR)/src/lib/vfs
|
213
repos/os/src/lib/vfs/file_system_factory.cc
Normal file
213
repos/os/src/lib/vfs/file_system_factory.cc
Normal file
@ -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 <vfs/file_system_factory.h>
|
||||
#include <base/shared_object.h>
|
||||
|
||||
/* supported builtin file systems */
|
||||
#include <vfs/tar_file_system.h>
|
||||
#include <vfs/fs_file_system.h>
|
||||
#include <vfs/terminal_file_system.h>
|
||||
#include <vfs/null_file_system.h>
|
||||
#include <vfs/zero_file_system.h>
|
||||
#include <vfs/block_file_system.h>
|
||||
#include <vfs/log_file_system.h>
|
||||
#include <vfs/rom_file_system.h>
|
||||
#include <vfs/inline_file_system.h>
|
||||
#include <vfs/rtc_file_system.h>
|
||||
|
||||
|
||||
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<Entry_base>::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 <typename FILE_SYSTEM>
|
||||
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<Entry_base> _list;
|
||||
|
||||
template <typename FILE_SYSTEM>
|
||||
void _add_builtin_fs()
|
||||
{
|
||||
_list.insert(new (Genode::env()->heap()) Builtin_entry<FILE_SYSTEM>());
|
||||
}
|
||||
|
||||
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<Query_fn>(_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<Vfs::Tar_file_system>();
|
||||
_add_builtin_fs<Vfs::Fs_file_system>();
|
||||
_add_builtin_fs<Vfs::Terminal_file_system>();
|
||||
_add_builtin_fs<Vfs::Null_file_system>();
|
||||
_add_builtin_fs<Vfs::Zero_file_system>();
|
||||
_add_builtin_fs<Vfs::Block_file_system>();
|
||||
_add_builtin_fs<Vfs::Log_file_system>();
|
||||
_add_builtin_fs<Vfs::Rom_file_system>();
|
||||
_add_builtin_fs<Vfs::Inline_file_system>();
|
||||
_add_builtin_fs<Vfs::Rtc_file_system>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace Vfs {
|
||||
|
||||
Global_file_system_factory &global_file_system_factory()
|
||||
{
|
||||
static Default_file_system_factory inst;
|
||||
return inst;
|
||||
}
|
||||
}
|
@ -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 <typename FILE_SYSTEM>
|
||||
struct File_system_factory : Vfs::File_system_factory
|
||||
{
|
||||
public:
|
||||
|
||||
struct Entry_base : 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);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FILE_SYSTEM>
|
||||
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<Entry_base> _list;
|
||||
|
||||
public:
|
||||
|
||||
template <typename FS>
|
||||
void add_fs_type()
|
||||
{
|
||||
_list.insert(new Entry<FS>(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<Vfs::Tar_file_system>();
|
||||
fs_factory.add_fs_type<Vfs::Fs_file_system>();
|
||||
fs_factory.add_fs_type<Vfs::Terminal_file_system>();
|
||||
fs_factory.add_fs_type<Vfs::Null_file_system>();
|
||||
fs_factory.add_fs_type<Vfs::Zero_file_system>();
|
||||
fs_factory.add_fs_type<Vfs::Block_file_system>();
|
||||
fs_factory.add_fs_type<Vfs::Block_file_system>();
|
||||
fs_factory.add_fs_type<Vfs::Rtc_file_system>();
|
||||
fs_factory.add_fs_type<Stdio_file_system>();
|
||||
fs_factory.add_fs_type<Random_file_system>();
|
||||
/* 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> stdio_file_system_factory;
|
||||
File_system_factory<Random_file_system> 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
|
||||
|
@ -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)/../
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user