b4ebefd616
This patch changes the way how CLI monitor obtains its subsystem configurations. Originally, this information was provided via the Genode::config mechanism. But for managing complex scenarios, the config node becomes very complex. Hence, it is preferrable to have a distinct file for each subsystem configuration. The CLI monitor scans the directory '/subsystems' for files ending with ".subsystem". Each file has the same syntax as the formerly used subsystem nodes.
162 lines
3.9 KiB
C++
162 lines
3.9 KiB
C++
/*
|
|
* \brief Registry of subsystem configuration
|
|
* \author Norman Feske
|
|
* \date 2015-01-27
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2015 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 _SUBSYSTEM_CONFIG_REGISTRY_H_
|
|
#define _SUBSYSTEM_CONFIG_REGISTRY_H_
|
|
|
|
/* Genode includes */
|
|
#include <vfs/file_system.h>
|
|
#include <vfs/vfs_handle.h>
|
|
|
|
class Subsystem_config_registry
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Exception type
|
|
*/
|
|
class Nonexistent_subsystem_config { };
|
|
|
|
private:
|
|
|
|
Vfs::File_system &_fs;
|
|
|
|
enum { CONFIG_BUF_SIZE = 32*1024 };
|
|
char _config_buf[CONFIG_BUF_SIZE];
|
|
|
|
char const *_subsystems_path() { return "/subsystems"; }
|
|
char const *_subsystem_suffix() { return ".subsystem"; }
|
|
|
|
/**
|
|
* Return index of ".subsystem" suffix in dirent name
|
|
*
|
|
* \return index, or 0 if no matching suffix could be found
|
|
*/
|
|
unsigned _subsystem_suffix(Vfs::Directory_service::Dirent const &dirent)
|
|
{
|
|
unsigned found = 0;
|
|
for (unsigned i = 0; i < sizeof(dirent.name) && dirent.name[i]; i++)
|
|
if (Genode::strcmp(_subsystem_suffix(), &dirent.name[i]) == 0)
|
|
found = i;
|
|
|
|
return found;
|
|
}
|
|
|
|
|
|
public:
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
Subsystem_config_registry(Vfs::File_system &fs)
|
|
:
|
|
_fs(fs)
|
|
{ }
|
|
|
|
/**
|
|
* Execute functor 'fn' for specified subsystem name
|
|
*
|
|
* The functor is called with the subsystem XML node as argument
|
|
*
|
|
* \throw Nonexistent_subsystem_config
|
|
*/
|
|
template <typename FN>
|
|
void for_config(char const *name, FN const &fn)
|
|
{
|
|
/*
|
|
* Load subsystem configuration
|
|
*/
|
|
|
|
Genode::Path<256> path(_subsystems_path());
|
|
path.append("/");
|
|
path.append(name);
|
|
path.append(_subsystem_suffix());
|
|
|
|
Vfs::Vfs_handle *handle = nullptr;
|
|
|
|
Vfs::Directory_service::Open_result const open_result =
|
|
_fs.open(path.base(),
|
|
Vfs::Directory_service::OPEN_MODE_RDONLY,
|
|
&handle);
|
|
|
|
Vfs::Vfs_handle::Guard handle_guard(handle);
|
|
|
|
if (open_result != Vfs::Directory_service::OPEN_OK) {
|
|
PERR("could not open '%s', err=%d", path.base(), open_result);
|
|
throw Nonexistent_subsystem_config();
|
|
}
|
|
|
|
Vfs::file_size out_count = 0;
|
|
Vfs::File_io_service::Read_result read_result =
|
|
handle->fs().read(handle, _config_buf, sizeof(_config_buf), out_count);
|
|
|
|
if (read_result != Vfs::File_io_service::READ_OK) {
|
|
PERR("could not read '%s', err=%d", path.base(), read_result);
|
|
throw Nonexistent_subsystem_config();
|
|
}
|
|
|
|
try {
|
|
Genode::Xml_node subsystem_node(_config_buf, out_count);
|
|
fn(subsystem_node);
|
|
|
|
} catch (Genode::Xml_node::Invalid_syntax) {
|
|
PERR("subsystem configuration has invalid syntax");
|
|
throw Nonexistent_subsystem_config();
|
|
|
|
} catch (Genode::Xml_node::Nonexistent_sub_node) {
|
|
PERR("invalid subsystem configuration");
|
|
throw Nonexistent_subsystem_config();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Call specified functor for each subsystem config
|
|
*/
|
|
template <typename FN>
|
|
void for_each_config(FN const &fn)
|
|
{
|
|
/* iterate over the directory entries */
|
|
for (unsigned i = 0;; i++) {
|
|
|
|
Vfs::Directory_service::Dirent dirent;
|
|
|
|
Vfs::Directory_service::Dirent_result dirent_result =
|
|
_fs.dirent(_subsystems_path(), i, dirent);
|
|
|
|
if (dirent_result != Vfs::Directory_service::DIRENT_OK) {
|
|
PERR("could not access directory '%s'", _subsystems_path());
|
|
return;
|
|
}
|
|
|
|
if (dirent.type == Vfs::Directory_service::DIRENT_TYPE_END)
|
|
return;
|
|
|
|
unsigned const subsystem_suffix = _subsystem_suffix(dirent);
|
|
|
|
/* if file has a matching suffix, apply 'fn' */
|
|
if (subsystem_suffix) {
|
|
|
|
/* subsystem name is file name without the suffix */
|
|
char name[sizeof(dirent.name)];
|
|
Genode::strncpy(name, dirent.name, subsystem_suffix + 1);
|
|
|
|
try {
|
|
for_config(name, fn);
|
|
} catch (Nonexistent_subsystem_config) { }
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
#endif /* _PROCESS_ARG_REGISTRY_H_ */
|