mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-19 08:36:49 +00:00
libc: don't copy Xml_node
This patch reworks the libc's internal config handling by replacing scattered Xml_node accesses by the new 'Config' type that is parsed at once. The config ROM has been moved from 'Env_implementation' to the libc kernel. Issue #5411
This commit is contained in:
parent
636eb7b53f
commit
368509ff9b
@ -33,7 +33,7 @@ static void populate_args_and_env(Libc::Env &env, int &argc, char **&argv, char
|
||||
attr.with_raw_value(fn); });
|
||||
};
|
||||
|
||||
env.config([&] (Xml_node const &node) {
|
||||
env.with_config([&] (Xml_node const &node) {
|
||||
|
||||
int envc = 0;
|
||||
|
||||
@ -84,7 +84,7 @@ static void populate_args_and_env(Libc::Env &env, int &argc, char **&argv, char
|
||||
/* insert an environment variable */
|
||||
if (node.has_type("env")) try {
|
||||
|
||||
auto check_attr = [] (Xml_node node, auto key) {
|
||||
auto check_attr = [] (Xml_node const &node, auto key) {
|
||||
if (!node.has_attribute(key))
|
||||
Genode::warning("<env> node lacks '", key, "' attribute"); };
|
||||
|
||||
|
@ -22,41 +22,43 @@
|
||||
#define _INCLUDE__LIBC__COMPONENT_H_
|
||||
|
||||
#include <util/meta.h>
|
||||
#include <util/callable.h>
|
||||
#include <base/env.h>
|
||||
#include <base/stdint.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
namespace Libc { class Config_accessor; }
|
||||
|
||||
struct Libc::Config_accessor : Genode::Interface, Genode::Noncopyable
|
||||
{
|
||||
using With_config = Genode::Callable<void, Genode::Xml_node const &>;
|
||||
|
||||
virtual void _with_config(With_config::Ft const &) const = 0;
|
||||
|
||||
/**
|
||||
* Call 'fn' with the 'Xml_node const &' of the component configuration
|
||||
*/
|
||||
void with_config(auto const &fn) const
|
||||
{
|
||||
_with_config( With_config::Fn { fn } );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace Libc { class Env; }
|
||||
|
||||
namespace Vfs { struct Env; }
|
||||
|
||||
|
||||
/**
|
||||
* Interface to be provided by the component implementation
|
||||
*/
|
||||
class Libc::Env : public Genode::Env
|
||||
struct Libc::Env : Genode::Env, Config_accessor
|
||||
{
|
||||
private:
|
||||
|
||||
virtual Genode::Xml_node _config_xml() const = 0;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Component configuration
|
||||
*/
|
||||
template <typename FUNC>
|
||||
void config(FUNC const &func) const {
|
||||
func(_config_xml()); }
|
||||
|
||||
/**
|
||||
* Virtual file system configured for this component
|
||||
*/
|
||||
virtual Vfs::Env &vfs_env() = 0;
|
||||
|
||||
/**
|
||||
* Libc configuration for this component
|
||||
*/
|
||||
virtual Genode::Xml_node libc_config() = 0;
|
||||
/**
|
||||
* Virtual file system configured for this component
|
||||
*/
|
||||
virtual Vfs::Env &vfs_env() = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -45,8 +45,6 @@ void Component::construct(Genode::Env &env)
|
||||
static long _kernel_obj[(sizeof(Libc::Kernel) + sizeof(long))/sizeof(long)];
|
||||
Libc::Kernel &kernel = *new (_kernel_obj) Libc::Kernel(env, heap);
|
||||
|
||||
Libc::libc_config_init(kernel.libc_env().libc_config());
|
||||
|
||||
/*
|
||||
* XXX The following two steps leave us with the dilemma that we don't know
|
||||
* which linked library may depend on the successfull initialization of a
|
||||
|
@ -314,7 +314,7 @@ static Libc::Binary_name *_binary_name_ptr;
|
||||
static Libc::File_descriptor_allocator *_fd_alloc_ptr;
|
||||
|
||||
|
||||
void Libc::init_execve(Env &env, Genode::Allocator &alloc, void *user_stack_ptr,
|
||||
void Libc::init_execve(Genode::Env &env, Genode::Allocator &alloc, void *user_stack_ptr,
|
||||
Reset_malloc_heap &reset_malloc_heap, Binary_name &binary_name,
|
||||
File_descriptor_allocator &fd_alloc)
|
||||
{
|
||||
|
@ -74,10 +74,12 @@ void Libc::init_file_operations(Cwd &cwd, File_descriptor_allocator &fd_alloc,
|
||||
_fd_alloc_ptr = &fd_alloc;
|
||||
_cwd_ptr = &cwd;
|
||||
|
||||
config_accessor.config().with_optional_sub_node("libc", [&] (Xml_node libc) {
|
||||
libc.with_optional_sub_node("mmap", [&] (Xml_node mmap) {
|
||||
_mmap_align_log2 = mmap.attribute_value("align_log2",
|
||||
(unsigned int)PAGE_SHIFT);
|
||||
config_accessor.with_config([&] (Xml_node const &config) {
|
||||
config.with_optional_sub_node("libc", [&] (Xml_node libc) {
|
||||
libc.with_optional_sub_node("mmap", [&] (Xml_node mmap) {
|
||||
_mmap_align_log2 = mmap.attribute_value("align_log2",
|
||||
(unsigned int)PAGE_SHIFT);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ namespace { using Fn = Monitor::Function_result; }
|
||||
|
||||
static pid_t fork_result;
|
||||
|
||||
static Env *_env_ptr;
|
||||
static Genode::Env *_env_ptr;
|
||||
static File_descriptor_allocator *_fd_alloc_ptr;
|
||||
static Allocator *_alloc_ptr;
|
||||
static Monitor *_monitor_ptr;
|
||||
@ -88,34 +88,35 @@ struct Libc::Child_config
|
||||
{
|
||||
Constructible<Attached_ram_dataspace> _ds { };
|
||||
|
||||
Env &_env;
|
||||
Genode::Env &_env;
|
||||
|
||||
pid_t const _pid;
|
||||
|
||||
void _generate(Xml_generator &xml, Xml_node const &config,
|
||||
File_descriptor_allocator &);
|
||||
|
||||
Child_config(Env &env, Config_accessor const &config_accessor,
|
||||
Child_config(Genode::Env &env, Config_accessor const &config_accessor,
|
||||
File_descriptor_allocator &fd_alloc, pid_t pid)
|
||||
:
|
||||
_env(env), _pid(pid)
|
||||
{
|
||||
Xml_node const config = config_accessor.config();
|
||||
config_accessor.with_config([&] (Xml_node const &config) {
|
||||
|
||||
size_t buffer_size = 4096;
|
||||
size_t buffer_size = 4096;
|
||||
|
||||
retry<Xml_generator::Buffer_exceeded>(
|
||||
retry<Xml_generator::Buffer_exceeded>(
|
||||
|
||||
[&] () {
|
||||
_ds.construct(env.ram(), env.rm(), buffer_size);
|
||||
[&] {
|
||||
_ds.construct(env.ram(), env.rm(), buffer_size);
|
||||
|
||||
Xml_generator
|
||||
xml(_ds->local_addr<char>(), buffer_size, "config", [&] () {
|
||||
_generate(xml, config, fd_alloc); });
|
||||
},
|
||||
Xml_generator
|
||||
xml(_ds->local_addr<char>(), buffer_size, "config", [&] {
|
||||
_generate(xml, config, fd_alloc); });
|
||||
},
|
||||
|
||||
[&] () { buffer_size += 4096; }
|
||||
);
|
||||
[&] { buffer_size += 4096; }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Rom_dataspace_capability ds_cap() const
|
||||
@ -201,8 +202,8 @@ class Libc::Parent_services : Noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
Env &_env;
|
||||
Allocator &_alloc;
|
||||
Genode::Env &_env;
|
||||
Allocator &_alloc;
|
||||
|
||||
using Registered_service = Registered<Parent_service>;
|
||||
|
||||
@ -210,7 +211,8 @@ class Libc::Parent_services : Noncopyable
|
||||
|
||||
public:
|
||||
|
||||
Parent_services(Env &env, Allocator &alloc) : _env(env), _alloc(alloc) { }
|
||||
Parent_services(Genode::Env &env, Allocator &alloc)
|
||||
: _env(env), _alloc(alloc) { }
|
||||
|
||||
~Parent_services()
|
||||
{
|
||||
@ -290,7 +292,7 @@ struct Libc::Local_rom_services : Noncopyable
|
||||
|
||||
Registry<Registered_service> _services { };
|
||||
|
||||
Local_rom_services(Env &env, Entrypoint &fork_ep, Allocator &alloc)
|
||||
Local_rom_services(Genode::Env &env, Entrypoint &fork_ep, Allocator &alloc)
|
||||
:
|
||||
_alloc(alloc)
|
||||
{
|
||||
@ -340,7 +342,7 @@ struct Libc::Local_clone_service : Noncopyable
|
||||
.cap_quota = { Clone_session::CAP_QUOTA } };
|
||||
}
|
||||
|
||||
Session(Env &env, Entrypoint &ep)
|
||||
Session(Genode::Env &env, Entrypoint &ep)
|
||||
:
|
||||
Session_object<Clone_session, Session>(ep.rpc_ep(), _resources(),
|
||||
"cloned", Session::Diag()),
|
||||
@ -387,7 +389,7 @@ struct Libc::Local_clone_service : Noncopyable
|
||||
|
||||
Service service { _factory };
|
||||
|
||||
Local_clone_service(Env &env, Entrypoint &ep, Child_ready &child_ready)
|
||||
Local_clone_service(Genode::Env &env, Entrypoint &ep, Child_ready &child_ready)
|
||||
:
|
||||
_session(env, ep), _child_ready(child_ready),
|
||||
_child_ready_handler(env.ep(), *this, &Local_clone_service::_handle_child_ready),
|
||||
@ -398,7 +400,7 @@ struct Libc::Local_clone_service : Noncopyable
|
||||
|
||||
struct Libc::Forked_child : Child_policy, Child_ready
|
||||
{
|
||||
Env &_env;
|
||||
Genode::Env &_env;
|
||||
|
||||
Binary_name const _binary_name;
|
||||
|
||||
@ -551,7 +553,7 @@ struct Libc::Forked_child : Child_policy, Child_ready
|
||||
|
||||
Child _child;
|
||||
|
||||
Forked_child(Env &env,
|
||||
Forked_child(Genode::Env &env,
|
||||
File_descriptor_allocator &fd_alloc,
|
||||
Entrypoint &fork_ep,
|
||||
Allocator &alloc,
|
||||
@ -585,7 +587,7 @@ static Forked_child * fork_kernel_routine()
|
||||
abort();
|
||||
}
|
||||
|
||||
Env &env = *_env_ptr;
|
||||
Genode::Env &env = *_env_ptr;
|
||||
Allocator &alloc = *_alloc_ptr;
|
||||
Libc::Signal &signal = *_signal_ptr;
|
||||
|
||||
@ -752,7 +754,7 @@ extern "C" pid_t __sys_wait4(pid_t pid, int *status, int options, rusage *rusage
|
||||
extern "C" pid_t wait4(pid_t, int *, int, rusage *) __attribute__((weak, alias("__sys_wait4")));
|
||||
|
||||
|
||||
void Libc::init_fork(Env &env, File_descriptor_allocator &fd_alloc,
|
||||
void Libc::init_fork(Genode::Env &env, File_descriptor_allocator &fd_alloc,
|
||||
Config_accessor const &config_accessor,
|
||||
Allocator &alloc, Heap &malloc_heap, pid_t pid,
|
||||
Monitor &monitor, Signal &signal,
|
||||
|
@ -86,7 +86,7 @@ static passwd passwd_from_fields(Passwd_fields &fields)
|
||||
}
|
||||
|
||||
|
||||
void Libc::init_passwd(Xml_node config)
|
||||
void Libc::init_passwd(Xml_node const &config)
|
||||
{
|
||||
static Passwd_fields fields {
|
||||
.name = config.attribute_value("name", Passwd_string("root")),
|
||||
|
@ -23,18 +23,30 @@ extern "C" {
|
||||
/* libc-internal includes */
|
||||
#include <internal/errno.h>
|
||||
#include <internal/types.h>
|
||||
#include <internal/init.h>
|
||||
|
||||
/* Genode includes */
|
||||
#include <trace/timestamp.h>
|
||||
#include <base/log.h>
|
||||
#include <util/string.h>
|
||||
|
||||
namespace Libc { extern char const *config_rng(); }
|
||||
|
||||
using namespace Libc;
|
||||
|
||||
static Config const *_config_ptr;
|
||||
|
||||
void Libc::init_random(Config const &config)
|
||||
{
|
||||
_config_ptr = &config;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t read_rng(char *buf, size_t buflen)
|
||||
{
|
||||
struct Missing_call_of_init_random : Genode::Exception { };
|
||||
if (!_config_ptr)
|
||||
throw Missing_call_of_init_random();
|
||||
|
||||
static int rng_fd { -1 };
|
||||
static bool fallback { false };
|
||||
|
||||
@ -51,7 +63,7 @@ static ssize_t read_rng(char *buf, size_t buflen)
|
||||
}
|
||||
|
||||
if (rng_fd == -1) {
|
||||
if (!::strcmp(config_rng(), "")) {
|
||||
if (_config_ptr->rng.length() <= 1) {
|
||||
warning("Libc RNG not configured");
|
||||
|
||||
/* initialize the FreeBSD random facility */
|
||||
@ -61,9 +73,9 @@ static ssize_t read_rng(char *buf, size_t buflen)
|
||||
return read_rng(buf, buflen);
|
||||
}
|
||||
|
||||
rng_fd = open(config_rng(), O_RDONLY);
|
||||
rng_fd = open(_config_ptr->rng.string(), O_RDONLY);
|
||||
if (rng_fd == -1) {
|
||||
error("RNG device ", Cstring(config_rng()), " not readable!");
|
||||
error("RNG device ", _config_ptr->rng.string(), " not readable!");
|
||||
exit(~0);
|
||||
}
|
||||
}
|
||||
|
94
repos/libports/src/lib/libc/internal/config.h
Normal file
94
repos/libports/src/lib/libc/internal/config.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* \brief Libc config
|
||||
* \author Norman Feske
|
||||
* \date 2025-03-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2025 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _LIBC__INTERNAL__CONFIG_H_
|
||||
#define _LIBC__INTERNAL__CONFIG_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/xml_node.h>
|
||||
#include <base/component.h>
|
||||
|
||||
/* libc includes */
|
||||
#include <unistd.h>
|
||||
#include <internal/types.h>
|
||||
|
||||
namespace Libc { class Config; }
|
||||
|
||||
|
||||
struct Libc::Config
|
||||
{
|
||||
using Path = String<Vfs::MAX_PATH_LEN>;
|
||||
|
||||
bool update_mtime, cloned;
|
||||
pid_t pid;
|
||||
Path rtc, rng, pipe, socket, nameserver;
|
||||
size_t stack_size;
|
||||
|
||||
static Config _from_libc_xml(Xml_node const &libc)
|
||||
{
|
||||
Path const socket = libc.attribute_value("socket", Path());
|
||||
Path const default_nameserver { socket, "/nameserver" };
|
||||
|
||||
size_t stack_size = Component::stack_size();
|
||||
libc.with_optional_sub_node("stack", [&] (Xml_node stack) {
|
||||
stack_size = stack.attribute_value("size", Number_of_bytes(0)); });
|
||||
|
||||
return {
|
||||
.update_mtime = libc.attribute_value("update_mtime", true),
|
||||
.cloned = libc.attribute_value("cloned", false),
|
||||
.pid = libc.attribute_value("pid", pid_t(0)),
|
||||
.rtc = libc.attribute_value("rtc", Path()),
|
||||
.rng = libc.attribute_value("rng", Path()),
|
||||
.pipe = libc.attribute_value("pipe", Path()),
|
||||
.socket = socket,
|
||||
.nameserver = libc.attribute_value("nameserver_file",
|
||||
default_nameserver),
|
||||
.stack_size = stack_size,
|
||||
};
|
||||
}
|
||||
|
||||
static Config from_xml(Xml_node const &config)
|
||||
{
|
||||
Config result { };
|
||||
config.with_optional_sub_node("libc", [&] (Xml_node const &libc) {
|
||||
result = _from_libc_xml(libc); });
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace Libc {
|
||||
|
||||
static inline void with_vfs_config(Xml_node const &config, auto const &fn)
|
||||
{
|
||||
static Xml_node const empty_vfs { "<vfs/>" };
|
||||
|
||||
config.with_sub_node("vfs",
|
||||
[&] (Xml_node const &vfs_config) { fn(vfs_config); },
|
||||
[&] {
|
||||
config.with_sub_node("libc",
|
||||
[&] (Xml_node const &libc) {
|
||||
libc.with_sub_node("vfs",
|
||||
[&] (Xml_node const &vfs_config) {
|
||||
warning("'<config> <libc> <vfs/>' is deprecated, "
|
||||
"please move to '<config> <vfs/>'");
|
||||
fn(vfs_config);
|
||||
},
|
||||
[&] { fn(empty_vfs); });
|
||||
},
|
||||
[&] { fn(empty_vfs); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _LIBC__INTERNAL__CONFIG_H_ */
|
@ -26,48 +26,22 @@
|
||||
namespace Libc { class Env_implementation; }
|
||||
|
||||
|
||||
class Libc::Env_implementation : public Libc::Env, public Config_accessor
|
||||
class Libc::Env_implementation : public Libc::Env
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
|
||||
Attached_rom_dataspace _config { _env, "config" };
|
||||
Vfs::Env &_vfs_env;
|
||||
|
||||
Xml_node _vfs_config()
|
||||
{
|
||||
try { return _config.xml().sub_node("vfs"); }
|
||||
catch (Xml_node::Nonexistent_sub_node) { }
|
||||
try {
|
||||
Xml_node node = _config.xml().sub_node("libc").sub_node("vfs");
|
||||
warning("'<config> <libc> <vfs/>' is deprecated, "
|
||||
"please move to '<config> <vfs/>'");
|
||||
return node;
|
||||
}
|
||||
catch (Xml_node::Nonexistent_sub_node) { }
|
||||
|
||||
return Xml_node("<vfs/>");
|
||||
}
|
||||
|
||||
Xml_node _libc_config()
|
||||
{
|
||||
try { return _config.xml().sub_node("libc"); }
|
||||
catch (Xml_node::Nonexistent_sub_node) { }
|
||||
|
||||
return Xml_node("<libc/>");
|
||||
}
|
||||
|
||||
Vfs::Simple_env _vfs_env;
|
||||
|
||||
Xml_node _config_xml() const override {
|
||||
return _config.xml(); };
|
||||
Attached_rom_dataspace const &_config_rom;
|
||||
|
||||
public:
|
||||
|
||||
Env_implementation(Genode::Env &env, Genode::Allocator &alloc,
|
||||
Vfs::Env::User &vfs_user)
|
||||
Env_implementation(Genode::Env &env, Vfs::Env &vfs_env,
|
||||
Attached_rom_dataspace const &config_rom)
|
||||
:
|
||||
_env(env), _vfs_env(_env, alloc, _vfs_config(), vfs_user)
|
||||
_env(env), _vfs_env(vfs_env), _config_rom(config_rom)
|
||||
{ }
|
||||
|
||||
Vfs::File_system &vfs() { return _vfs_env.root_dir(); }
|
||||
@ -77,18 +51,12 @@ class Libc::Env_implementation : public Libc::Env, public Config_accessor
|
||||
** Libc::Env interface **
|
||||
*************************/
|
||||
|
||||
Vfs::Env &vfs_env() override {
|
||||
return _vfs_env; }
|
||||
void _with_config(With_config::Ft const &fn) const override
|
||||
{
|
||||
fn(_config_rom.xml());
|
||||
}
|
||||
|
||||
Xml_node libc_config() override {
|
||||
return _libc_config(); }
|
||||
|
||||
|
||||
/*************************************
|
||||
** Libc::Config_accessor interface **
|
||||
*************************************/
|
||||
|
||||
Xml_node config() const override { return _config.xml(); }
|
||||
Vfs::Env &vfs_env() override { return _vfs_env; }
|
||||
|
||||
|
||||
/***************************
|
||||
|
@ -18,13 +18,16 @@
|
||||
#include <base/env.h>
|
||||
#include <base/heap.h>
|
||||
#include <util/xml_node.h>
|
||||
#include <util/callable.h>
|
||||
#include <vfs/types.h> /* for 'MAX_PATH_LEN' */
|
||||
|
||||
/* libc includes */
|
||||
#include <setjmp.h> /* for 'jmp_buf' type */
|
||||
#include <libc/component.h>
|
||||
|
||||
/* libc-internal includes */
|
||||
#include <internal/types.h>
|
||||
#include <internal/config.h>
|
||||
|
||||
namespace Libc {
|
||||
|
||||
@ -41,7 +44,6 @@ namespace Libc {
|
||||
struct Timer_accessor;
|
||||
struct Cwd;
|
||||
struct Atexit;
|
||||
struct Config_accessor;
|
||||
|
||||
/**
|
||||
* Support for shared libraries
|
||||
@ -88,12 +90,7 @@ namespace Libc {
|
||||
/**
|
||||
* Support for getpwent
|
||||
*/
|
||||
void init_passwd(Xml_node);
|
||||
|
||||
/**
|
||||
* Set libc config node
|
||||
*/
|
||||
void libc_config_init(Xml_node node);
|
||||
void init_passwd(Xml_node const &);
|
||||
|
||||
/**
|
||||
* Malloc allocator
|
||||
@ -114,8 +111,8 @@ namespace Libc {
|
||||
/**
|
||||
* Socket fs
|
||||
*/
|
||||
void init_socket_fs(Monitor &, File_descriptor_allocator &);
|
||||
void init_socket_operations(File_descriptor_allocator &);
|
||||
void init_socket_fs(Monitor &, File_descriptor_allocator &, Config const &);
|
||||
void init_socket_operations(File_descriptor_allocator &, Config const &);
|
||||
|
||||
/**
|
||||
* Pthread/semaphore support
|
||||
@ -125,11 +122,6 @@ namespace Libc {
|
||||
Genode::Allocator &);
|
||||
void init_semaphore_support(Timer_accessor &);
|
||||
|
||||
struct Config_accessor : Interface
|
||||
{
|
||||
virtual Xml_node config() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fork mechanism
|
||||
*/
|
||||
@ -164,6 +156,11 @@ namespace Libc {
|
||||
* Kqueue support
|
||||
*/
|
||||
void init_kqueue(Genode::Allocator &, Monitor &, File_descriptor_allocator &);
|
||||
|
||||
/**
|
||||
* Random-number support
|
||||
*/
|
||||
void init_random(Config const &);
|
||||
}
|
||||
|
||||
#endif /* _LIBC__INTERNAL__INIT_H_ */
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <libc/select.h>
|
||||
|
||||
/* libc-internal includes */
|
||||
#include <internal/types.h>
|
||||
#include <internal/malloc_ram_allocator.h>
|
||||
#include <internal/cloned_malloc_heap_range.h>
|
||||
#include <internal/timer.h>
|
||||
@ -44,6 +43,7 @@
|
||||
#include <internal/cwd.h>
|
||||
#include <internal/atexit.h>
|
||||
#include <internal/rtc.h>
|
||||
#include <internal/config.h>
|
||||
|
||||
namespace Libc {
|
||||
class Kernel;
|
||||
@ -169,38 +169,36 @@ struct Libc::Kernel final : Vfs::Read_ready_response_handler,
|
||||
}
|
||||
};
|
||||
|
||||
Attached_rom_dataspace _config_rom { _env, "config" };
|
||||
|
||||
Config const _config = Config::from_xml(_config_rom.xml());
|
||||
|
||||
void _with_libc_config(auto const &fn) const
|
||||
{
|
||||
_config_rom.xml().with_sub_node("libc",
|
||||
[&] (Xml_node const &libc) { fn(libc); },
|
||||
[&] { fn( Xml_node { "<libc/>" } ); });
|
||||
}
|
||||
|
||||
void _with_libc_sub_config(char const *tag, auto const &fn) const
|
||||
{
|
||||
_with_libc_config([&] (Xml_node const &libc) {
|
||||
libc.with_sub_node(tag,
|
||||
[&] (Xml_node const pthread) { fn(pthread); },
|
||||
[&] { fn(Xml_node(String<64>("<", tag, "/>").string())); }); });
|
||||
};
|
||||
|
||||
Vfs_user _vfs_user { _io_progressed };
|
||||
|
||||
Env_implementation _libc_env { _env, _heap, _vfs_user };
|
||||
Constructible<Vfs::Simple_env> _vfs_env { };
|
||||
|
||||
bool const _update_mtime = _libc_env.libc_config().attribute_value("update_mtime", true);
|
||||
bool const _vfs_env_initialized = (
|
||||
with_vfs_config(_config_rom.xml(), [&] (Xml_node const &vfs_config) {
|
||||
_vfs_env.construct(_env, _heap, vfs_config, _vfs_user); }), true );
|
||||
|
||||
Vfs_plugin _vfs { _libc_env, _fd_alloc, _libc_env.vfs_env(), _heap, *this,
|
||||
_update_mtime ? Vfs_plugin::Update_mtime::YES
|
||||
: Vfs_plugin::Update_mtime::NO,
|
||||
*this /* current_real_time */,
|
||||
_libc_env.config() };
|
||||
Env_implementation _libc_env { _env, *_vfs_env, _config_rom };
|
||||
|
||||
bool const _cloned = _libc_env.libc_config().attribute_value("cloned", false);
|
||||
pid_t const _pid = _libc_env.libc_config().attribute_value("pid", 0U);
|
||||
|
||||
Xml_node _passwd_config()
|
||||
{
|
||||
return _libc_env.libc_config().has_sub_node("passwd")
|
||||
? _libc_env.libc_config().sub_node("passwd")
|
||||
: Xml_node("<empty/>");
|
||||
}
|
||||
|
||||
Xml_node _pthread_config()
|
||||
{
|
||||
return _libc_env.libc_config().has_sub_node("pthread")
|
||||
? _libc_env.libc_config().sub_node("pthread")
|
||||
: Xml_node("<pthread/>");
|
||||
}
|
||||
|
||||
using Config_attr = String<Vfs::MAX_PATH_LEN>;
|
||||
|
||||
Config_attr const _rtc_path = _libc_env.libc_config().attribute_value("rtc", Config_attr());
|
||||
Vfs_plugin _vfs { _fd_alloc, _heap, _config, *_vfs_env, *this, *this };
|
||||
|
||||
Constructible<Rtc> _rtc { };
|
||||
|
||||
@ -214,7 +212,7 @@ struct Libc::Kernel final : Vfs::Read_ready_response_handler,
|
||||
|
||||
void _handle_user_interrupt();
|
||||
|
||||
Signal _signal { _pid };
|
||||
Signal _signal { _config.pid };
|
||||
|
||||
Atexit _atexit { _heap };
|
||||
|
||||
@ -229,11 +227,8 @@ struct Libc::Kernel final : Vfs::Read_ready_response_handler,
|
||||
|
||||
addr_t _kernel_stack = Thread::mystack().top;
|
||||
|
||||
size_t _user_stack_size();
|
||||
|
||||
void *_user_stack = {
|
||||
_myself.alloc_secondary_stack(_myself.name().string(),
|
||||
_user_stack_size()) };
|
||||
void *_user_stack = _myself.alloc_secondary_stack(_myself.name().string(),
|
||||
_config.stack_size);
|
||||
|
||||
enum State { KERNEL, USER };
|
||||
|
||||
@ -437,7 +432,7 @@ struct Libc::Kernel final : Vfs::Read_ready_response_handler,
|
||||
if (!_setjmp(_kernel_context)) {
|
||||
/* _setjmp() returned directly -> switch to user stack and call application code */
|
||||
|
||||
if (_cloned) {
|
||||
if (_config.cloned) {
|
||||
_main_monitor_job->complete();
|
||||
_switch_to_user();
|
||||
} else {
|
||||
@ -683,13 +678,13 @@ struct Libc::Kernel final : Vfs::Read_ready_response_handler,
|
||||
|
||||
bool has_real_time() const override
|
||||
{
|
||||
return (_rtc_path != "");
|
||||
return (_config.rtc.length() > 1);
|
||||
}
|
||||
|
||||
timespec current_real_time() override
|
||||
{
|
||||
if (!_rtc.constructed())
|
||||
_rtc.construct(_vfs, _heap, _rtc_path, *this);
|
||||
_rtc.construct(_vfs, _heap, _config.rtc, *this);
|
||||
|
||||
return _rtc->read(current_time());
|
||||
}
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include <base/allocator.h>
|
||||
#include <base/ram_allocator.h>
|
||||
|
||||
/* libc-internal includes */
|
||||
#include <internal/types.h>
|
||||
|
||||
namespace Libc { struct Malloc_ram_allocator; }
|
||||
|
||||
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include <internal/plugin.h>
|
||||
#include <internal/fd_alloc.h>
|
||||
#include <internal/errno.h>
|
||||
#include <internal/config.h>
|
||||
#include <internal/current_time.h>
|
||||
|
||||
namespace Libc { class Vfs_plugin; }
|
||||
|
||||
@ -84,11 +86,10 @@ class Libc::Vfs_plugin final : public Plugin
|
||||
File_descriptor_allocator &_fd_alloc;
|
||||
Genode::Allocator &_alloc;
|
||||
Vfs::File_system &_root_fs;
|
||||
Constructible<Genode::Directory> _root_dir { };
|
||||
Genode::Directory _root_dir;
|
||||
Vfs::Read_ready_response_handler &_response_handler;
|
||||
Update_mtime const _update_mtime;
|
||||
Config const &_config;
|
||||
Current_real_time &_current_real_time;
|
||||
bool const _pipe_configured;
|
||||
Registry<Mmap_entry> _mmap_registry;
|
||||
|
||||
/*
|
||||
@ -104,12 +105,7 @@ class Libc::Vfs_plugin final : public Plugin
|
||||
template <typename FN>
|
||||
void with_file(Absolute_path const &path, FN const &fn)
|
||||
{
|
||||
if (!_vfs_plugin._root_dir.constructed()) {
|
||||
warning("Vfs_plugin::_root_dir unexpectedly not constructed");
|
||||
return;
|
||||
}
|
||||
|
||||
Directory &root_dir = *_vfs_plugin._root_dir;
|
||||
Directory &root_dir = _vfs_plugin._root_dir;
|
||||
|
||||
if (path != _path && root_dir.file_exists(path.string())) {
|
||||
_file.construct(root_dir, path);
|
||||
@ -171,52 +167,32 @@ class Libc::Vfs_plugin final : public Plugin
|
||||
template <typename FN>
|
||||
void _with_info(File_descriptor &fd, FN const &fn);
|
||||
|
||||
static bool _init_pipe_configured(Xml_node config)
|
||||
{
|
||||
bool result = false;
|
||||
config.with_optional_sub_node("libc", [&] (Xml_node libc_node) {
|
||||
result = libc_node.has_attribute("pipe"); });
|
||||
return result;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Vfs_plugin(Libc::Env &env,
|
||||
Libc::File_descriptor_allocator &fd_alloc,
|
||||
Vfs::Env &vfs_env,
|
||||
Vfs_plugin(File_descriptor_allocator &fd_alloc,
|
||||
Genode::Allocator &alloc,
|
||||
Config const &config,
|
||||
Vfs::Env &vfs_env,
|
||||
Vfs::Read_ready_response_handler &handler,
|
||||
Update_mtime update_mtime,
|
||||
Current_real_time ¤t_real_time,
|
||||
Xml_node config)
|
||||
Current_real_time ¤t_real_time)
|
||||
:
|
||||
_fd_alloc(fd_alloc),
|
||||
_alloc(alloc),
|
||||
_root_fs(env.vfs_env().root_dir()),
|
||||
_root_fs(vfs_env.root_dir()),
|
||||
_root_dir(vfs_env),
|
||||
_response_handler(handler),
|
||||
_update_mtime(update_mtime),
|
||||
_current_real_time(current_real_time),
|
||||
_pipe_configured(_init_pipe_configured(config))
|
||||
{
|
||||
if (config.has_sub_node("libc"))
|
||||
_root_dir.construct(vfs_env);
|
||||
}
|
||||
_config(config),
|
||||
_current_real_time(current_real_time)
|
||||
{ }
|
||||
|
||||
~Vfs_plugin() final { }
|
||||
|
||||
template <typename FN>
|
||||
void with_root_dir(FN const &fn)
|
||||
{
|
||||
if (_root_dir.constructed())
|
||||
fn(*_root_dir);
|
||||
}
|
||||
void with_root_dir(auto const &fn) { fn(_root_dir); }
|
||||
|
||||
bool root_dir_has_dirents() const { return _root_fs.num_dirent("/") > 0; }
|
||||
|
||||
bool supports_access(const char *, int) override { return true; }
|
||||
bool supports_mkdir(const char *, mode_t) override { return true; }
|
||||
bool supports_open(const char *, int) override { return true; }
|
||||
bool supports_pipe() override { return _pipe_configured; }
|
||||
bool supports_pipe() override { return _config.pipe.length() > 1; }
|
||||
bool supports_poll() override { return true; }
|
||||
bool supports_readlink(const char *, char *, ::size_t) override { return true; }
|
||||
bool supports_rename(const char *, const char *) override { return true; }
|
||||
|
@ -22,6 +22,7 @@ Libc::Kernel * Libc::Kernel::_kernel_ptr;
|
||||
|
||||
extern char **environ;
|
||||
|
||||
char const *libc_resolv_path; /* expected by res_init.c */
|
||||
|
||||
/**
|
||||
* Blockade for main context
|
||||
@ -44,17 +45,6 @@ inline void Libc::Main_blockade::wakeup()
|
||||
}
|
||||
|
||||
|
||||
size_t Libc::Kernel::_user_stack_size()
|
||||
{
|
||||
size_t size = Component::stack_size();
|
||||
|
||||
_libc_env.libc_config().with_optional_sub_node("stack", [&] (Xml_node stack) {
|
||||
size = stack.attribute_value("size", Number_of_bytes(0)); });
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
void Libc::Kernel::reset_malloc_heap()
|
||||
{
|
||||
_malloc_ram.construct(_heap, _env.ram());
|
||||
@ -81,7 +71,7 @@ void Libc::Kernel::_init_file_descriptors()
|
||||
|
||||
Diag_guard(Kernel &kernel) : kernel(kernel) { }
|
||||
|
||||
~Diag_guard() { if (show) log(kernel._libc_env.libc_config()); }
|
||||
~Diag_guard() { if (show) log(kernel._config_rom.xml()); }
|
||||
|
||||
} diag_guard { *this };
|
||||
|
||||
@ -251,33 +241,34 @@ void Libc::Kernel::_init_file_descriptors()
|
||||
|
||||
if (_vfs.root_dir_has_dirents()) {
|
||||
|
||||
Xml_node const node = _libc_env.libc_config();
|
||||
_config_rom.xml().with_optional_sub_node("libc", [&] (Xml_node const &node) {
|
||||
|
||||
using Path = String<Vfs::MAX_PATH_LEN>;
|
||||
using Path = String<Vfs::MAX_PATH_LEN>;
|
||||
|
||||
if (node.has_attribute("cwd"))
|
||||
_cwd.import(node.attribute_value("cwd", Path()).string(), _cwd.base());
|
||||
if (node.has_attribute("cwd"))
|
||||
_cwd.import(node.attribute_value("cwd", Path()).string(), _cwd.base());
|
||||
|
||||
init_fd(node, "stdin", 0, O_RDONLY);
|
||||
init_fd(node, "stdout", 1, O_WRONLY);
|
||||
init_fd(node, "stderr", 2, O_WRONLY);
|
||||
init_fd(node, "stdin", 0, O_RDONLY);
|
||||
init_fd(node, "stdout", 1, O_WRONLY);
|
||||
init_fd(node, "stderr", 2, O_WRONLY);
|
||||
|
||||
node.for_each_sub_node("fd", [&] (Xml_node fd) {
|
||||
node.for_each_sub_node("fd", [&] (Xml_node fd) {
|
||||
|
||||
unsigned const id = fd.attribute_value("id", 0U);
|
||||
unsigned const id = fd.attribute_value("id", 0U);
|
||||
|
||||
bool const rd = fd.attribute_value("readable", false);
|
||||
bool const wr = fd.attribute_value("writeable", false);
|
||||
bool const rd = fd.attribute_value("readable", false);
|
||||
bool const wr = fd.attribute_value("writeable", false);
|
||||
|
||||
unsigned const flags = rd ? (wr ? O_RDWR : O_RDONLY)
|
||||
: (wr ? O_WRONLY : 0);
|
||||
unsigned const flags = rd ? (wr ? O_RDWR : O_RDONLY)
|
||||
: (wr ? O_WRONLY : 0);
|
||||
|
||||
if (!fd.has_attribute("path")) {
|
||||
warning("unknown path for file descriptor ", id);
|
||||
diag_guard.show = true;
|
||||
}
|
||||
if (!fd.has_attribute("path")) {
|
||||
warning("unknown path for file descriptor ", id);
|
||||
diag_guard.show = true;
|
||||
}
|
||||
|
||||
init_fd(fd, "path", id, flags);
|
||||
init_fd(fd, "path", id, flags);
|
||||
});
|
||||
});
|
||||
|
||||
/* prevent use of IDs of stdin, stdout, and stderr for other files */
|
||||
@ -360,12 +351,14 @@ void Libc::Kernel::_clone_state_from_parent()
|
||||
* the shared-memory buffer of the clone session may otherwise potentially
|
||||
* interfere with such a heap region.
|
||||
*/
|
||||
_libc_env.libc_config().for_each_sub_node("heap", [&] (Xml_node node) {
|
||||
Range const range = range_attr(node);
|
||||
new (_heap)
|
||||
Registered<Cloned_malloc_heap_range>(_cloned_heap_ranges,
|
||||
_env.ram(), _env.rm(),
|
||||
range); });
|
||||
_with_libc_config([&] (Xml_node const &libc) {
|
||||
libc.for_each_sub_node("heap", [&] (Xml_node const &node) {
|
||||
Range const range = range_attr(node);
|
||||
new (_heap)
|
||||
Registered<Cloned_malloc_heap_range>(_cloned_heap_ranges,
|
||||
_env.ram(), _env.rm(),
|
||||
range); });
|
||||
});
|
||||
|
||||
_clone_connection.construct(_env);
|
||||
|
||||
@ -381,34 +374,36 @@ void Libc::Kernel::_clone_state_from_parent()
|
||||
_clone_connection->memory_content(&_main_monitor_job, sizeof(_main_monitor_job));
|
||||
_valid_user_context = true;
|
||||
|
||||
_libc_env.libc_config().for_each_sub_node([&] (Xml_node node) {
|
||||
auto copy_from_parent = [&] (Range range)
|
||||
{
|
||||
_clone_connection->memory_content((void *)range.start, range.num_bytes);
|
||||
};
|
||||
|
||||
auto copy_from_parent = [&] (Range range)
|
||||
{
|
||||
_clone_connection->memory_content((void *)range.start, range.num_bytes);
|
||||
};
|
||||
_with_libc_config([&] (Xml_node const &libc) {
|
||||
libc.for_each_sub_node([&] (Xml_node const &node) {
|
||||
|
||||
/* clone application stack */
|
||||
if (node.type() == "stack")
|
||||
copy_from_parent(range_attr(node));
|
||||
|
||||
/* clone RW segment of a shared library or the binary */
|
||||
if (node.type() == "rw") {
|
||||
using Name = String<64>;
|
||||
Name const name = node.attribute_value("name", Name());
|
||||
|
||||
/*
|
||||
* The blacklisted segments are initialized via the
|
||||
* regular startup of the child.
|
||||
*/
|
||||
bool const blacklisted = (name == "ld.lib.so")
|
||||
|| (name == "libc.lib.so")
|
||||
|| (name == "libm.lib.so")
|
||||
|| (name == "posix.lib.so")
|
||||
|| (strcmp(name.string(), "vfs", 3) == 0);
|
||||
if (!blacklisted)
|
||||
/* clone application stack */
|
||||
if (node.type() == "stack")
|
||||
copy_from_parent(range_attr(node));
|
||||
}
|
||||
|
||||
/* clone RW segment of a shared library or the binary */
|
||||
if (node.type() == "rw") {
|
||||
using Name = String<64>;
|
||||
Name const name = node.attribute_value("name", Name());
|
||||
|
||||
/*
|
||||
* The blacklisted segments are initialized via the
|
||||
* regular startup of the child.
|
||||
*/
|
||||
bool const blacklisted = (name == "ld.lib.so")
|
||||
|| (name == "libc.lib.so")
|
||||
|| (name == "libm.lib.so")
|
||||
|| (name == "posix.lib.so")
|
||||
|| (strcmp(name.string(), "vfs", 3) == 0);
|
||||
if (!blacklisted)
|
||||
copy_from_parent(range_attr(node));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/* import application-heap state from parent */
|
||||
@ -484,6 +479,8 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap)
|
||||
:
|
||||
_env(env), _heap(heap)
|
||||
{
|
||||
libc_resolv_path = _config.nameserver.string();
|
||||
|
||||
init_atexit(_atexit);
|
||||
|
||||
_atexit_fd_alloc_ptr = &_fd_alloc;
|
||||
@ -491,11 +488,13 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap)
|
||||
|
||||
init_semaphore_support(_timer_accessor);
|
||||
init_pthread_support(*this, _timer_accessor);
|
||||
init_pthread_support(env.cpu(), _pthread_config(), _heap);
|
||||
|
||||
_with_libc_sub_config("pthread", [&] (Xml_node const &pthread_config) {
|
||||
init_pthread_support(env.cpu(), pthread_config, _heap); });
|
||||
|
||||
_env.ep().register_io_progress_handler(*this);
|
||||
|
||||
if (_cloned) {
|
||||
if (_config.cloned) {
|
||||
_clone_state_from_parent();
|
||||
|
||||
} else {
|
||||
@ -503,7 +502,7 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap)
|
||||
init_malloc(*_malloc_heap);
|
||||
}
|
||||
|
||||
init_fork(_env, _fd_alloc, _libc_env, _heap, *_malloc_heap, _pid, *this,
|
||||
init_fork(_env, _fd_alloc, _libc_env, _heap, *_malloc_heap, _config.pid, *this,
|
||||
_signal, _binary_name);
|
||||
init_execve(_env, _heap, _user_stack, *this, _binary_name, _fd_alloc);
|
||||
init_plugin(*this);
|
||||
@ -515,11 +514,15 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap)
|
||||
init_alarm(_timer_accessor, _signal);
|
||||
init_poll(_signal, *this, _fd_alloc);
|
||||
init_select(*this);
|
||||
init_socket_fs(*this, _fd_alloc);
|
||||
init_socket_operations(_fd_alloc);
|
||||
init_passwd(_passwd_config());
|
||||
init_socket_fs(*this, _fd_alloc, _config);
|
||||
init_socket_operations(_fd_alloc, _config);
|
||||
|
||||
_with_libc_sub_config("passwd", [&] (Xml_node const &passwd_config) {
|
||||
init_passwd(passwd_config); });
|
||||
|
||||
init_signal(_signal);
|
||||
init_kqueue(_heap, *this, _fd_alloc);
|
||||
init_random(_config);
|
||||
|
||||
_init_file_descriptors();
|
||||
|
||||
@ -535,6 +538,6 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap)
|
||||
* pipe reference counter may reach an intermediate value of zero,
|
||||
* triggering the destruction of the pipe.
|
||||
*/
|
||||
if (_cloned)
|
||||
if (_config.cloned)
|
||||
_clone_connection.destruct();
|
||||
}
|
||||
|
@ -45,7 +45,6 @@
|
||||
|
||||
|
||||
namespace Libc {
|
||||
extern char const *config_socket();
|
||||
bool read_ready_from_kernel(File_descriptor *);
|
||||
bool write_ready_from_kernel(File_descriptor *);
|
||||
}
|
||||
@ -53,11 +52,15 @@ namespace Libc {
|
||||
|
||||
static Libc::Monitor *_monitor_ptr;
|
||||
|
||||
static Libc::Config const *_config_ptr;
|
||||
|
||||
void Libc::init_socket_fs(Monitor &monitor, File_descriptor_allocator &fd_alloc)
|
||||
|
||||
void Libc::init_socket_fs(Monitor &monitor, File_descriptor_allocator &fd_alloc,
|
||||
Config const &config)
|
||||
{
|
||||
_monitor_ptr = &monitor;
|
||||
_fd_alloc_ptr = &fd_alloc;
|
||||
_config_ptr = &config;
|
||||
}
|
||||
|
||||
|
||||
@ -148,7 +151,7 @@ struct Libc::Socket_fs::Context : Plugin_context
|
||||
}
|
||||
|
||||
Absolute_path const _path {
|
||||
_read_socket_path().base(), config_socket() };
|
||||
_read_socket_path().base(), _config_ptr->socket.string() };
|
||||
|
||||
enum Fd { DATA, PEEK, CONNECT, BIND, LISTEN, ACCEPT, LOCAL, REMOTE, MAX };
|
||||
|
||||
@ -1163,7 +1166,7 @@ extern "C" int socket_fs_shutdown(int libc_fd, int how)
|
||||
|
||||
extern "C" int socket_fs_socket(int domain, int type, int protocol)
|
||||
{
|
||||
Socket_fs::Absolute_path path(config_socket());
|
||||
Socket_fs::Absolute_path path(_config_ptr->socket.string());
|
||||
|
||||
if (path == "") {
|
||||
error(__func__, ": socket fs not mounted");
|
||||
@ -1266,7 +1269,7 @@ extern "C" int getifaddrs(struct ifaddrs **ifap)
|
||||
|
||||
using Socket_fs::Absolute_path;
|
||||
|
||||
Absolute_path const root(config_socket());
|
||||
Absolute_path const root(_config_ptr->socket.string());
|
||||
|
||||
if (read_ifaddr_file(address, Absolute_path("address", root.base())))
|
||||
return -1;
|
||||
|
@ -31,15 +31,18 @@ extern "C" {
|
||||
#include <internal/init.h>
|
||||
|
||||
|
||||
void Libc::init_socket_operations(Libc::File_descriptor_allocator &fd_alloc)
|
||||
using namespace Libc;
|
||||
|
||||
static Config const *_config_ptr;
|
||||
|
||||
void Libc::init_socket_operations(Libc::File_descriptor_allocator &fd_alloc,
|
||||
Config const &config)
|
||||
{
|
||||
_fd_alloc_ptr = &fd_alloc;
|
||||
_config_ptr = &config;
|
||||
}
|
||||
|
||||
|
||||
using namespace Libc;
|
||||
|
||||
|
||||
#define __SYS_(ret_type, name, args, body) \
|
||||
extern "C" {\
|
||||
ret_type __sys_##name args body \
|
||||
@ -47,8 +50,6 @@ using namespace Libc;
|
||||
ret_type name args __attribute__((alias("__sys_" #name))); \
|
||||
} \
|
||||
|
||||
namespace Libc { extern char const *config_socket(); }
|
||||
|
||||
|
||||
/***********************
|
||||
** Address functions **
|
||||
@ -56,7 +57,7 @@ namespace Libc { extern char const *config_socket(); }
|
||||
|
||||
extern "C" int getpeername(int libc_fd, sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_getpeername(libc_fd, addr, addrlen);
|
||||
|
||||
return Libc::Errno(ENOTSOCK);
|
||||
@ -69,7 +70,7 @@ int _getpeername(int libc_fd, sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
extern "C" int getsockname(int libc_fd, sockaddr *addr, socklen_t *addrlen)
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_getsockname(libc_fd, addr, addrlen);
|
||||
|
||||
FD_FUNC_WRAPPER(getsockname, libc_fd, addr, addrlen);
|
||||
@ -86,7 +87,7 @@ int _getsockname(int libc_fd, sockaddr *addr, socklen_t *addrlen);
|
||||
|
||||
__SYS_(int, accept, (int libc_fd, sockaddr *addr, socklen_t *addrlen),
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_accept(libc_fd, addr, addrlen);
|
||||
|
||||
File_descriptor *ret_fd;
|
||||
@ -103,7 +104,7 @@ __SYS_(int, accept4, (int libc_fd, struct sockaddr *addr, socklen_t *addrlen, in
|
||||
|
||||
extern "C" int bind(int libc_fd, sockaddr const *addr, socklen_t addrlen)
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_bind(libc_fd, addr, addrlen);
|
||||
|
||||
FD_FUNC_WRAPPER(bind, libc_fd, addr, addrlen);
|
||||
@ -116,7 +117,7 @@ int _bind(int libc_fd, sockaddr const *addr, socklen_t addrlen);
|
||||
|
||||
__SYS_(int, connect, (int libc_fd, sockaddr const *addr, socklen_t addrlen),
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_connect(libc_fd, addr, addrlen);
|
||||
|
||||
FD_FUNC_WRAPPER(connect, libc_fd, addr, addrlen);
|
||||
@ -125,7 +126,7 @@ __SYS_(int, connect, (int libc_fd, sockaddr const *addr, socklen_t addrlen),
|
||||
|
||||
extern "C" int listen(int libc_fd, int backlog)
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_listen(libc_fd, backlog);
|
||||
|
||||
FD_FUNC_WRAPPER(listen, libc_fd, backlog);
|
||||
@ -135,7 +136,7 @@ extern "C" int listen(int libc_fd, int backlog)
|
||||
__SYS_(ssize_t, recvfrom, (int libc_fd, void *buf, ::size_t len, int flags,
|
||||
sockaddr *src_addr, socklen_t *src_addrlen),
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_recvfrom(libc_fd, buf, len, flags, src_addr, src_addrlen);
|
||||
|
||||
FD_FUNC_WRAPPER(recvfrom, libc_fd, buf, len, flags, src_addr, src_addrlen);
|
||||
@ -144,7 +145,7 @@ __SYS_(ssize_t, recvfrom, (int libc_fd, void *buf, ::size_t len, int flags,
|
||||
|
||||
__SYS_(ssize_t, recv, (int libc_fd, void *buf, ::size_t len, int flags),
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_recv(libc_fd, buf, len, flags);
|
||||
|
||||
FD_FUNC_WRAPPER(recv, libc_fd, buf, len, flags);
|
||||
@ -153,7 +154,7 @@ __SYS_(ssize_t, recv, (int libc_fd, void *buf, ::size_t len, int flags),
|
||||
|
||||
__SYS_(ssize_t, recvmsg, (int libc_fd, msghdr *msg, int flags),
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_recvmsg(libc_fd, msg, flags);
|
||||
|
||||
FD_FUNC_WRAPPER(recvmsg, libc_fd, msg, flags);
|
||||
@ -163,7 +164,7 @@ __SYS_(ssize_t, recvmsg, (int libc_fd, msghdr *msg, int flags),
|
||||
__SYS_(ssize_t, sendto, (int libc_fd, void const *buf, ::size_t len, int flags,
|
||||
sockaddr const *dest_addr, socklen_t dest_addrlen),
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_sendto(libc_fd, buf, len, flags, dest_addr, dest_addrlen);
|
||||
|
||||
FD_FUNC_WRAPPER(sendto, libc_fd, buf, len, flags, dest_addr, dest_addrlen);
|
||||
@ -172,7 +173,7 @@ __SYS_(ssize_t, sendto, (int libc_fd, void const *buf, ::size_t len, int flags,
|
||||
|
||||
extern "C" ssize_t send(int libc_fd, void const *buf, ::size_t len, int flags)
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_send(libc_fd, buf, len, flags);
|
||||
|
||||
FD_FUNC_WRAPPER(send, libc_fd, buf, len, flags);
|
||||
@ -182,7 +183,7 @@ extern "C" ssize_t send(int libc_fd, void const *buf, ::size_t len, int flags)
|
||||
extern "C" int getsockopt(int libc_fd, int level, int optname,
|
||||
void *optval, socklen_t *optlen)
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_getsockopt(libc_fd, level, optname, optval, optlen);
|
||||
|
||||
FD_FUNC_WRAPPER(getsockopt, libc_fd, level, optname, optval, optlen);
|
||||
@ -197,7 +198,7 @@ int _getsockopt(int libc_fd, int level, int optname,
|
||||
extern "C" int setsockopt(int libc_fd, int level, int optname,
|
||||
void const *optval, socklen_t optlen)
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_setsockopt(libc_fd, level, optname, optval, optlen);
|
||||
|
||||
FD_FUNC_WRAPPER(setsockopt, libc_fd, level, optname, optval, optlen);
|
||||
@ -211,7 +212,7 @@ int _setsockopt(int libc_fd, int level, int optname,
|
||||
|
||||
extern "C" int shutdown(int libc_fd, int how)
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_shutdown(libc_fd, how);
|
||||
|
||||
FD_FUNC_WRAPPER(shutdown, libc_fd, how);
|
||||
@ -219,7 +220,7 @@ extern "C" int shutdown(int libc_fd, int how)
|
||||
|
||||
__SYS_(int, socket, (int domain, int type, int protocol),
|
||||
{
|
||||
if (*config_socket())
|
||||
if (_config_ptr->socket.length() > 1)
|
||||
return socket_fs_socket(domain, type, protocol);
|
||||
|
||||
Plugin *plugin;
|
||||
|
@ -138,81 +138,8 @@ static void vfs_stat_to_libc_stat_struct(Vfs::Directory_service::Stat const &src
|
||||
}
|
||||
|
||||
|
||||
static Genode::Xml_node *_config_node;
|
||||
|
||||
char const *libc_resolv_path;
|
||||
|
||||
|
||||
namespace Libc {
|
||||
|
||||
Xml_node config() __attribute__((weak));
|
||||
Xml_node config()
|
||||
{
|
||||
if (!_config_node) {
|
||||
error("libc config not initialized - aborting");
|
||||
exit(1);
|
||||
}
|
||||
return *_config_node;
|
||||
}
|
||||
|
||||
class Config_attr
|
||||
{
|
||||
private:
|
||||
|
||||
using Value = String<Vfs::MAX_PATH_LEN>;
|
||||
Value const _value;
|
||||
|
||||
public:
|
||||
|
||||
Config_attr(char const *attr_name, char const *default_value)
|
||||
:
|
||||
_value(config().attribute_value(attr_name,
|
||||
Value(default_value)))
|
||||
{ }
|
||||
|
||||
char const *string() const { return _value.string(); }
|
||||
};
|
||||
|
||||
char const *config_pipe() __attribute__((weak));
|
||||
char const *config_pipe()
|
||||
{
|
||||
static Config_attr attr("pipe", "");
|
||||
return attr.string();
|
||||
}
|
||||
|
||||
char const *config_rng() __attribute__((weak));
|
||||
char const *config_rng()
|
||||
{
|
||||
static Config_attr rng("rng", "");
|
||||
return rng.string();
|
||||
}
|
||||
|
||||
char const *config_socket() __attribute__((weak));
|
||||
char const *config_socket()
|
||||
{
|
||||
static Config_attr socket("socket", "");
|
||||
return socket.string();
|
||||
}
|
||||
|
||||
char const *config_nameserver_file() __attribute__((weak));
|
||||
char const *config_nameserver_file()
|
||||
{
|
||||
static Genode::String<Vfs::MAX_PATH_LEN> default_value {
|
||||
config_socket(), "/nameserver" };
|
||||
|
||||
static Config_attr ns_file("nameserver_file",
|
||||
default_value.string());
|
||||
return ns_file.string();
|
||||
}
|
||||
|
||||
void libc_config_init(Xml_node node)
|
||||
{
|
||||
static Xml_node config = node;
|
||||
_config_node = &config;
|
||||
|
||||
libc_resolv_path = config_nameserver_file();
|
||||
}
|
||||
|
||||
bool read_ready_from_kernel(File_descriptor *fd)
|
||||
{
|
||||
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
||||
@ -255,10 +182,10 @@ void Libc::Vfs_plugin::_with_info(File_descriptor &fd, FN const &fn)
|
||||
char buffer[4096] { };
|
||||
|
||||
Byte_range_ptr range(buffer,
|
||||
min((size_t)(_root_dir->file_size(path.string())),
|
||||
min((size_t)(_root_dir.file_size(path.string())),
|
||||
sizeof(buffer)));
|
||||
|
||||
with_xml_file_content(file, range, [&] (Xml_node node) { fn(node); });
|
||||
with_xml_file_content(file, range, [&] (Xml_node const &node) { fn(node); });
|
||||
});
|
||||
}
|
||||
|
||||
@ -551,13 +478,14 @@ struct Sync
|
||||
Vfs::Vfs_handle &vfs_handle;
|
||||
Vfs::Timestamp mtime { };
|
||||
|
||||
Sync(Vfs::Vfs_handle &vfs_handle, Libc::Vfs_plugin::Update_mtime update_mtime,
|
||||
struct Attr { bool update_mtime; };
|
||||
|
||||
Sync(Vfs::Vfs_handle &vfs_handle, Attr const attr,
|
||||
Libc::Current_real_time ¤t_real_time)
|
||||
:
|
||||
vfs_handle(vfs_handle)
|
||||
{
|
||||
if (update_mtime == Libc::Vfs_plugin::Update_mtime::NO
|
||||
|| !current_real_time.has_real_time()) {
|
||||
if (!attr.update_mtime || !current_real_time.has_real_time()) {
|
||||
|
||||
state = TIMESTAMP_UPDATED;
|
||||
|
||||
@ -599,7 +527,7 @@ int Libc::Vfs_plugin::close_from_kernel(File_descriptor *fd)
|
||||
|
||||
if ((fd->modified) || (fd->flags & O_CREAT)) {
|
||||
/* XXX mtime not updated here */
|
||||
Sync sync { *handle, Update_mtime::NO, _current_real_time };
|
||||
Sync sync { *handle, { .update_mtime = false }, _current_real_time };
|
||||
|
||||
while (!sync.complete()) {
|
||||
Libc::Kernel::kernel().wakeup_remote_peers();
|
||||
@ -618,7 +546,7 @@ int Libc::Vfs_plugin::close(File_descriptor *fd)
|
||||
{
|
||||
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
||||
|
||||
Sync sync { *handle , _update_mtime, _current_real_time };
|
||||
Sync sync { *handle, { .update_mtime = _config.update_mtime }, _current_real_time };
|
||||
|
||||
monitor().monitor([&] {
|
||||
if ((fd->modified) || (fd->flags & O_CREAT))
|
||||
@ -711,7 +639,7 @@ int Libc::Vfs_plugin::fstat(File_descriptor *fd, struct stat *buf)
|
||||
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
||||
|
||||
if (fd->modified) {
|
||||
Sync sync { *handle , _update_mtime, _current_real_time };
|
||||
Sync sync { *handle , { .update_mtime = _config.update_mtime }, _current_real_time };
|
||||
|
||||
monitor().monitor([&] {
|
||||
if (!sync.complete()) {
|
||||
@ -1108,7 +1036,7 @@ Libc::Vfs_plugin::_ioctl_tio(File_descriptor *fd, unsigned long request, char *a
|
||||
if (request == TIOCGWINSZ) {
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() == "terminal") {
|
||||
::winsize *winsize = (::winsize *)argp;
|
||||
winsize->ws_row = info.attribute_value("rows", 25U);
|
||||
@ -1169,7 +1097,7 @@ Libc::Vfs_plugin::_ioctl_dio(File_descriptor *fd, unsigned long request, char *a
|
||||
if (request == DIOCGMEDIASIZE) {
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() == "block") {
|
||||
|
||||
size_t const size =
|
||||
@ -1232,7 +1160,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() != "oss") {
|
||||
return;
|
||||
}
|
||||
@ -1268,7 +1196,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
|
||||
if (info.type() != "oss") {
|
||||
return;
|
||||
@ -1300,7 +1228,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
int play_underruns = 0;
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() != "oss") {
|
||||
return;
|
||||
}
|
||||
@ -1347,7 +1275,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() != "oss") {
|
||||
return;
|
||||
}
|
||||
@ -1372,7 +1300,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() != "oss") {
|
||||
return;
|
||||
}
|
||||
@ -1434,7 +1362,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() != "oss") {
|
||||
return;
|
||||
}
|
||||
@ -1547,7 +1475,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
if (!argp) return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() != "oss") {
|
||||
return;
|
||||
}
|
||||
@ -1610,7 +1538,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
monitor().monitor([&] {
|
||||
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() != "oss") {
|
||||
return;
|
||||
}
|
||||
@ -1663,7 +1591,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
monitor().monitor([&] {
|
||||
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() != "oss") {
|
||||
return;
|
||||
}
|
||||
@ -1753,7 +1681,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
bool legacy_oss = false;
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() != "oss") return;
|
||||
|
||||
/* assume legacy if version is not set, current is 2 */
|
||||
@ -1779,7 +1707,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
}
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() != "oss") {
|
||||
return;
|
||||
}
|
||||
@ -1818,7 +1746,7 @@ Libc::Vfs_plugin::_ioctl_sndctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
auto result = Fn::INCOMPLETE;
|
||||
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
|
||||
if (info.type() != "oss") return;
|
||||
|
||||
@ -1868,7 +1796,7 @@ Libc::Vfs_plugin::_ioctl_tapctl(File_descriptor *fd, unsigned long request, char
|
||||
ifreq *ifr = reinterpret_cast<ifreq*>(argp);
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() == "tap") {
|
||||
String<IFNAMSIZ> name = info.attribute_value("name", String<IFNAMSIZ> { });
|
||||
copy_cstring(ifr->ifr_name, name.string(), IFNAMSIZ);
|
||||
@ -1884,7 +1812,7 @@ Libc::Vfs_plugin::_ioctl_tapctl(File_descriptor *fd, unsigned long request, char
|
||||
return { true, EINVAL };
|
||||
|
||||
monitor().monitor([&] {
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() == "tap") {
|
||||
Net::Mac_address mac = info.attribute_value("mac_addr", Net::Mac_address { });
|
||||
mac.copy(argp);
|
||||
@ -1913,7 +1841,7 @@ Libc::Vfs_plugin::_ioctl_tapctl(File_descriptor *fd, unsigned long request, char
|
||||
|
||||
monitor().monitor([&] {
|
||||
/* check whether mac address changed, return ENOTSUP if not */
|
||||
_with_info(*fd, [&] (Xml_node info) {
|
||||
_with_info(*fd, [&] (Xml_node const &info) {
|
||||
if (info.type() == "tap") {
|
||||
if (!info.has_attribute("mac_addr"))
|
||||
result = ENOTSUP;
|
||||
@ -2026,7 +1954,7 @@ int Libc::Vfs_plugin::ioctl(File_descriptor *fd, unsigned long request, char *ar
|
||||
int Libc::Vfs_plugin::ftruncate(File_descriptor *fd, ::off_t length)
|
||||
{
|
||||
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
||||
Sync sync { *handle, _update_mtime, _current_real_time };
|
||||
Sync sync { *handle, { .update_mtime = _config.update_mtime }, _current_real_time };
|
||||
|
||||
bool succeeded = false;
|
||||
int result_errno = 0;
|
||||
@ -2106,7 +2034,7 @@ int Libc::Vfs_plugin::fsync(File_descriptor *fd)
|
||||
if (!fd->modified)
|
||||
return 0;
|
||||
|
||||
Sync sync { *handle, _update_mtime, _current_real_time };
|
||||
Sync sync { *handle, { .update_mtime = _config.update_mtime }, _current_real_time };
|
||||
|
||||
monitor().monitor([&] {
|
||||
if (!sync.complete()) {
|
||||
@ -2167,8 +2095,8 @@ int Libc::Vfs_plugin::symlink(const char *target_path, const char *link_path)
|
||||
}
|
||||
|
||||
/* must be done outside the monitor because constructor needs libc I/O */
|
||||
sync.construct(*handle, _update_mtime, _current_real_time);
|
||||
|
||||
sync.construct(*handle, Sync::Attr { .update_mtime = _config.update_mtime },
|
||||
_current_real_time);
|
||||
{
|
||||
bool succeeded { false };
|
||||
int result_errno { 0 };
|
||||
@ -2520,7 +2448,7 @@ int Libc::Vfs_plugin::munmap(void *addr, ::size_t)
|
||||
|
||||
int Libc::Vfs_plugin::pipe(Libc::File_descriptor *pipefdo[2])
|
||||
{
|
||||
Absolute_path base_path(Libc::config_pipe());
|
||||
Absolute_path base_path(_config.pipe);
|
||||
if (base_path == "") {
|
||||
error(__func__, ": pipe fs not mounted");
|
||||
return Errno(EACCES);
|
||||
|
@ -32,6 +32,7 @@ $(MIRROR_FROM_PORT_DIR):
|
||||
|
||||
MIRROR_FROM_LIBPORTS := lib/mk/libc-mem.mk \
|
||||
lib/mk/libc-common.inc \
|
||||
src/lib/libc/internal/config.h \
|
||||
src/lib/libc/internal/init.h \
|
||||
src/lib/libc/internal/mem_alloc.h \
|
||||
src/lib/libc/internal/monitor.h \
|
||||
|
@ -38,6 +38,7 @@ MIRROR_FROM_LIBPORTS := \
|
||||
lib/mk/qemu-usb-webcam.inc \
|
||||
lib/mk/spec/x86_32/qemu-usb.mk \
|
||||
lib/mk/spec/x86_64/qemu-usb.mk \
|
||||
src/lib/libc/internal/config.h \
|
||||
src/lib/libc/internal/init.h \
|
||||
src/lib/libc/internal/mem_alloc.h \
|
||||
src/lib/libc/internal/monitor.h \
|
||||
|
Loading…
x
Reference in New Issue
Block a user