noux: API transition

This patch removes the dependency of the deprecated Genode API,
fixes the coding style, and removes the "random" file system
(superseded by the VFS plugin mechanism).

Ref #1987
This commit is contained in:
Norman Feske 2017-01-06 12:12:39 +01:00
parent f957fcdd98
commit 82e6d7cf52
40 changed files with 4666 additions and 5174 deletions

View File

@ -30,11 +30,13 @@
namespace Noux { namespace Noux {
using namespace Genode; using namespace Genode;
struct Sysio;
}
struct Sysio
{ struct Noux::Sysio
{
/* signal numbers must match with libc signal numbers */ /* signal numbers must match with libc signal numbers */
enum Signal { enum Signal {
SIG_INT = 2, SIG_INT = 2,
@ -503,7 +505,6 @@ namespace Noux {
SYSIO_DECL(getdtablesize, { }, { int n; }); SYSIO_DECL(getdtablesize, { }, { int n; });
}; };
};
}; };
#undef SYSIO_DECL #undef SYSIO_DECL

View File

@ -15,14 +15,18 @@
#define _NOUX__ARGS_H_ #define _NOUX__ARGS_H_
/* Genode includes */ /* Genode includes */
#include <os/attached_ram_dataspace.h> #include <base/attached_ram_dataspace.h>
#include <util/string.h> #include <util/string.h>
#include <base/log.h> #include <base/log.h>
namespace Noux { namespace Noux {
class Args;
class Args_dataspace;
}
class Args
{ class Noux::Args
{
protected: protected:
char * const _buf; char * const _buf;
@ -92,15 +96,15 @@ namespace Noux {
i += strlen(&_buf[i]) + 1, j++) i += strlen(&_buf[i]) + 1, j++)
log("arg(", j, "): \"", Cstring(&_buf[i]), "\""); log("arg(", j, "): \"", Cstring(&_buf[i]), "\"");
} }
}; };
class Args_dataspace : private Attached_ram_dataspace, public Args
{
public:
Args_dataspace(size_t size, Args const &from = Args()) struct Noux::Args_dataspace : private Attached_ram_dataspace, Args
{
Args_dataspace(Ram_session &ram, Region_map &rm,
size_t size, Args const &from = Args())
: :
Attached_ram_dataspace(env()->ram_session(), size), Attached_ram_dataspace(ram, rm, size),
Args(local_addr<char>(), size) Args(local_addr<char>(), size)
{ {
if (from.len() > size - 2) if (from.len() > size - 2)
@ -110,7 +114,6 @@ namespace Noux {
} }
using Attached_ram_dataspace::cap; using Attached_ram_dataspace::cap;
}; };
}
#endif /* _NOUX__ARGS_H_ */ #endif /* _NOUX__ARGS_H_ */

View File

@ -15,16 +15,12 @@
#define _NOUX__CHILD_H_ #define _NOUX__CHILD_H_
/* Genode includes */ /* Genode includes */
#include <base/signal.h> #include <base/attached_ram_dataspace.h>
#include <base/semaphore.h> #include <base/attached_rom_dataspace.h>
#include <cap_session/cap_session.h> #include <vfs/dir_file_system.h>
#include <pd_session/connection.h>
#include <os/attached_ram_dataspace.h>
#include <os/attached_rom_dataspace.h>
/* Noux includes */ /* Noux includes */
#include <file_descriptor_registry.h> #include <file_descriptor_registry.h>
#include <vfs/dir_file_system.h>
#include <noux_session/capability.h> #include <noux_session/capability.h>
#include <args.h> #include <args.h>
#include <environment.h> #include <environment.h>
@ -34,19 +30,44 @@
#include <child_policy.h> #include <child_policy.h>
#include <io_receptor_registry.h> #include <io_receptor_registry.h>
#include <destruct_queue.h> #include <destruct_queue.h>
#include <destruct_dispatcher.h>
#include <interrupt_handler.h> #include <interrupt_handler.h>
#include <kill_broadcaster.h> #include <kill_broadcaster.h>
#include <parent_execve.h> #include <parent_execve.h>
#include <local_rom_service.h> #include <local_rom_service.h>
#include <verbose.h>
#include <user_info.h>
#include <timeout_scheduler.h>
namespace Noux { namespace Noux {
class Pid_allocator;
/** /**
* Return singleton instance of Io_receptor_registry
*/
Io_receptor_registry *io_receptor_registry();
/*
* Return lock for protecting the signal queue
*/
Genode::Lock &signal_lock();
class Child_config;
class Child;
/**
* Return true is child is the init process
*/
bool init_process(Child *child);
void init_process_exited(int);
}
/**
* Allocator for process IDs * Allocator for process IDs
*/ */
class Pid_allocator class Noux::Pid_allocator
{ {
private: private:
Lock _lock; Lock _lock;
@ -61,96 +82,65 @@ namespace Noux {
Lock::Guard guard(_lock); Lock::Guard guard(_lock);
return _num_pids++; return _num_pids++;
} }
}; };
/**
* Return singleton instance of PID allocator
*/
Pid_allocator *pid_allocator();
/** struct Noux::Child_config : Attached_ram_dataspace
* Return singleton instance of timeout scheduler {
*/
class Timeout_scheduler;
Timeout_scheduler *timeout_scheduler();
/**
* Return singleton instance of user information
*/
class User_info;
User_info *user_info();
/**
* Return singleton instance of Io_receptor_registry
*/
Io_receptor_registry *io_receptor_registry();
/*
* Return lock for protecting the signal queue
*/
Genode::Lock &signal_lock();
class Child;
/**
* Return true is child is the init process
*/
bool init_process(Child *child);
void init_process_exited(int);
struct Child_config : Attached_ram_dataspace
{
enum { CONFIG_DS_SIZE = 4096 }; enum { CONFIG_DS_SIZE = 4096 };
Child_config(Genode::Ram_session &ram) Child_config(Ram_session &ram, Region_map &local_rm, Verbose const &verbose)
: Attached_ram_dataspace(&ram, CONFIG_DS_SIZE) :
Attached_ram_dataspace(ram, local_rm, CONFIG_DS_SIZE)
{ {
Genode::strncpy(local_addr<char>(), Xml_generator xml(local_addr<char>(), CONFIG_DS_SIZE, "config", [&] ()
"<config/>", {
CONFIG_DS_SIZE); if (verbose.ld())
xml.attribute("ld_verbose", "yes");
try { });
Attached_rom_dataspace noux_config("config");
if (noux_config.xml().attribute_value("ld_verbose", false))
Genode::strncpy(local_addr<char>(),
"<config ld_verbose=\"yes\"/>",
CONFIG_DS_SIZE);
} catch (Genode::Rom_connection::Rom_connection_failed) { }
} }
}; };
class Child : public Rpc_object<Session>,
class Noux::Child : public Rpc_object<Session>,
public File_descriptor_registry, public File_descriptor_registry,
public Family_member, public Family_member,
public Destruct_queue::Element<Child>, public Destruct_queue::Element<Child>,
public Interrupt_handler public Interrupt_handler
{ {
private: private:
Child_policy::Name const _name; Child_policy::Name const _name;
Verbose const &_verbose;
User_info const &_user_info;
Parent_exit *_parent_exit; Parent_exit *_parent_exit;
Kill_broadcaster &_kill_broadcaster; Kill_broadcaster &_kill_broadcaster;
Timeout_scheduler &_timeout_scheduler;
Parent_execve &_parent_execve; Parent_execve &_parent_execve;
Pid_allocator &_pid_allocator;
Signal_receiver &_sig_rec; Env &_env;
Vfs::Dir_file_system &_root_dir; Vfs::Dir_file_system &_root_dir;
Destruct_queue &_destruct_queue; Destruct_queue &_destruct_queue;
Destruct_dispatcher _destruct_dispatcher { _destruct_queue, this };
Signal_context_capability _destruct_context_cap =
_sig_rec.manage(&_destruct_dispatcher);
Pd_session &_env_pd_session; /* used for creating 'Rpc_entrypoint' */ void _handle_destruct() { _destruct_queue.insert(this); }
Signal_handler<Child> _destruct_handler {
_env.ep(), *this, &Child::_handle_destruct };
Allocator &_heap;
/** /**
* Entrypoint used to serve the RPC interfaces of the * Entrypoint used to serve the RPC interfaces of the
* locally-provided services * locally-provided services
*/ */
enum { STACK_SIZE = 8*1024*sizeof(long) }; enum { STACK_SIZE = 8*1024*sizeof(long) };
Rpc_entrypoint _ep { &_env_pd_session, STACK_SIZE, "noux_process", false }; Rpc_entrypoint _ep { &_env.pd(), STACK_SIZE, "noux_process", false };
Ram_session &_ref_ram; Ram_session &_ref_ram;
Ram_session_capability const _ref_ram_cap; Ram_session_capability const _ref_ram_cap;
@ -158,13 +148,13 @@ namespace Noux {
/** /**
* Registry of dataspaces owned by the Noux process * Registry of dataspaces owned by the Noux process
*/ */
Dataspace_registry _ds_registry; Dataspace_registry _ds_registry { _heap };
/** /**
* Locally-provided PD service * Locally-provided PD service
*/ */
typedef Local_service<Pd_session_component> Pd_service; typedef Local_service<Pd_session_component> Pd_service;
Pd_session_component _pd { _ep, _name, _ds_registry }; Pd_session_component _pd { _heap, _env, _ep, _name, _ds_registry };
Pd_service::Single_session_factory _pd_factory { _pd }; Pd_service::Single_session_factory _pd_factory { _pd };
Pd_service _pd_service { _pd_factory }; Pd_service _pd_service { _pd_factory };
@ -172,7 +162,7 @@ namespace Noux {
* Locally-provided RAM service * Locally-provided RAM service
*/ */
typedef Local_service<Ram_session_component> Ram_service; typedef Local_service<Ram_session_component> Ram_service;
Ram_session_component _ram { _ep, _ds_registry }; Ram_session_component _ram { _ref_ram, _heap, _ep, _ds_registry };
Ram_service::Single_session_factory _ram_factory { _ram }; Ram_service::Single_session_factory _ram_factory { _ram };
Ram_service _ram_service { _ram_factory }; Ram_service _ram_service { _ram_factory };
@ -180,7 +170,7 @@ namespace Noux {
* Locally-provided CPU service * Locally-provided CPU service
*/ */
typedef Local_service<Cpu_session_component> Cpu_service; typedef Local_service<Cpu_session_component> Cpu_service;
Cpu_session_component _cpu { _ep, _name, false, _ds_registry }; Cpu_session_component _cpu { _env, _ep, _name, false, _ds_registry };
Cpu_service::Single_session_factory _cpu_factory { _cpu }; Cpu_service::Single_session_factory _cpu_factory { _cpu };
Cpu_service _cpu_service { _cpu_factory }; Cpu_service _cpu_service { _cpu_factory };
@ -197,7 +187,7 @@ namespace Noux {
/* /*
* Locally-provided ROM service * Locally-provided ROM service
*/ */
Local_rom_factory _rom_factory { _ep, _root_dir, _ds_registry }; Local_rom_factory _rom_factory { _heap, _env, _ep, _root_dir, _ds_registry };
Local_rom_service _rom_service { _rom_factory }; Local_rom_service _rom_service { _rom_factory };
/** /**
@ -208,17 +198,17 @@ namespace Noux {
/** /**
* Environment variables * Environment variables
*/ */
Environment _env; Environment _sysio_env;
/* /*
* Child configuration * Child configuration
*/ */
Child_config _config { *env()->ram_session() }; Child_config _config { _ref_ram, _env.rm(), _verbose };
enum { PAGE_SIZE = 4096, PAGE_MASK = ~(PAGE_SIZE - 1) }; enum { PAGE_SIZE = 4096, PAGE_MASK = ~(PAGE_SIZE - 1) };
enum { SYSIO_DS_SIZE = PAGE_MASK & (sizeof(Sysio) + PAGE_SIZE - 1) }; enum { SYSIO_DS_SIZE = PAGE_MASK & (sizeof(Sysio) + PAGE_SIZE - 1) };
Attached_ram_dataspace _sysio_ds { env()->ram_session(), SYSIO_DS_SIZE }; Attached_ram_dataspace _sysio_ds { _ref_ram, _env.rm(), SYSIO_DS_SIZE };
Sysio &_sysio = *_sysio_ds.local_addr<Sysio>(); Sysio &_sysio = *_sysio_ds.local_addr<Sysio>();
typedef Ring_buffer<enum Sysio::Signal, Sysio::SIGNAL_QUEUE_SIZE> typedef Ring_buffer<enum Sysio::Signal, Sysio::SIGNAL_QUEUE_SIZE>
@ -229,7 +219,7 @@ namespace Noux {
Static_dataspace_info _sysio_ds_info; Static_dataspace_info _sysio_ds_info;
Static_dataspace_info _args_ds_info; Static_dataspace_info _args_ds_info;
Static_dataspace_info _env_ds_info; Static_dataspace_info _sysio_env_ds_info;
Static_dataspace_info _config_ds_info; Static_dataspace_info _config_ds_info;
Child_policy _child_policy; Child_policy _child_policy;
@ -299,10 +289,8 @@ namespace Noux {
*/ */
bool _syscall_net(Syscall sc); bool _syscall_net(Syscall sc);
void _destruct() { void _destruct()
{
_sig_rec.dissolve(&_destruct_dispatcher);
_ep.dissolve(this); _ep.dissolve(this);
if (init_process(this)) if (init_process(this))
@ -330,53 +318,58 @@ namespace Noux {
* the parent * the parent
*/ */
Child(Child_policy::Name const &name, Child(Child_policy::Name const &name,
Verbose const &verbose,
User_info const &user_info,
Parent_exit *parent_exit, Parent_exit *parent_exit,
Kill_broadcaster &kill_broadcaster, Kill_broadcaster &kill_broadcaster,
Timeout_scheduler &timeout_scheduler,
Parent_execve &parent_execve, Parent_execve &parent_execve,
Pid_allocator &pid_allocator,
int pid, int pid,
Signal_receiver &sig_rec, Env &env,
Vfs::Dir_file_system &root_dir, Vfs::Dir_file_system &root_dir,
Args const &args, Args const &args,
Sysio::Env const &env, Sysio::Env const &sysio_env,
Pd_session &env_pd_session, Allocator &heap,
Ram_session &ref_ram, Ram_session &ref_ram,
Ram_session_capability ref_ram_cap, Ram_session_capability ref_ram_cap,
Parent_services &parent_services, Parent_services &parent_services,
Rpc_entrypoint &resources_ep,
bool forked, bool forked,
Allocator &destruct_alloc, Destruct_queue &destruct_queue)
Destruct_queue &destruct_queue,
bool verbose)
: :
Family_member(pid), Family_member(pid),
Destruct_queue::Element<Child>(&destruct_alloc), Destruct_queue::Element<Child>(heap),
_name(name), _name(name),
_verbose(verbose),
_user_info(user_info),
_parent_exit(parent_exit), _parent_exit(parent_exit),
_kill_broadcaster(kill_broadcaster), _kill_broadcaster(kill_broadcaster),
_timeout_scheduler(timeout_scheduler),
_parent_execve(parent_execve), _parent_execve(parent_execve),
_sig_rec(sig_rec), _pid_allocator(pid_allocator),
_env(env),
_root_dir(root_dir), _root_dir(root_dir),
_destruct_queue(destruct_queue), _destruct_queue(destruct_queue),
_env_pd_session(env_pd_session), _heap(heap),
_ref_ram(ref_ram), _ref_ram_cap(ref_ram_cap), _ref_ram(ref_ram), _ref_ram_cap(ref_ram_cap),
_args(ARGS_DS_SIZE, args), _args(ref_ram, _env.rm(), ARGS_DS_SIZE, args),
_env(env), _sysio_env(_ref_ram, _env.rm(), sysio_env),
_parent_services(parent_services), _parent_services(parent_services),
_sysio_ds_info(_ds_registry, _sysio_ds.cap()), _sysio_ds_info(_ds_registry, _sysio_ds.cap()),
_args_ds_info(_ds_registry, _args.cap()), _args_ds_info(_ds_registry, _args.cap()),
_env_ds_info(_ds_registry, _env.cap()), _sysio_env_ds_info(_ds_registry, _sysio_env.cap()),
_config_ds_info(_ds_registry, _config.cap()), _config_ds_info(_ds_registry, _config.cap()),
_child_policy(name, _child_policy(name,
forked ? Rom_session_component::forked_magic_binary_name() forked ? Rom_session_component::forked_magic_binary_name()
: name, : name,
_args.cap(), _env.cap(), _config.cap(), _args.cap(), _sysio_env.cap(), _config.cap(),
_ep, _pd_service, _ram_service, _cpu_service, _ep, _pd_service, _ram_service, _cpu_service,
_noux_service, _rom_service, _parent_services, _noux_service, _rom_service, _parent_services,
*this, parent_exit, *this, _destruct_context_cap, *this, parent_exit, *this, _destruct_handler,
ref_ram, ref_ram_cap, verbose), ref_ram, ref_ram_cap, _verbose.enabled()),
_child(*Genode::env()->rm_session(), _ep, _child_policy) _child(_env.rm(), _ep, _child_policy)
{ {
if (verbose) if (_verbose.enabled())
_args.dump(); _args.dump();
if (!_child.main_thread_cap().valid()) { if (!_child.main_thread_cap().valid()) {
@ -394,7 +387,7 @@ namespace Noux {
/* poke parent_cap_addr into child's address space */ /* poke parent_cap_addr into child's address space */
Capability<Parent>::Raw const raw = _child.parent_cap().raw(); Capability<Parent>::Raw const raw = _child.parent_cap().raw();
_pd.poke(parent_cap_addr, &raw, sizeof(raw)); _pd.poke(_env.rm(), parent_cap_addr, (char *)&raw, sizeof(raw));
/* start execution of new main thread at supplied trampoline */ /* start execution of new main thread at supplied trampoline */
_cpu.start_main_thread(ip, sp); _cpu.start_main_thread(ip, sp);
@ -408,7 +401,7 @@ namespace Noux {
/* trigger exit of main event loop */ /* trigger exit of main event loop */
init_process_exited(_child_policy.exit_value()); init_process_exited(_child_policy.exit_value());
} else { } else {
Signal_transmitter(_destruct_context_cap).submit(); Signal_transmitter(_destruct_handler).submit();
} }
} }
@ -471,7 +464,7 @@ namespace Noux {
/* Register the interrupt handler only once per IO channel */ /* Register the interrupt handler only once per IO channel */
if (_is_the_only_fd_for_io_channel(fd, io_channel)) { if (_is_the_only_fd_for_io_channel(fd, io_channel)) {
Io_channel_listener *l = new (env()->heap()) Io_channel_listener(this); Io_channel_listener *l = new (_heap) Io_channel_listener(this);
io_channel->register_interrupt_handler(l); io_channel->register_interrupt_handler(l);
} }
@ -489,7 +482,7 @@ namespace Noux {
if (_is_the_only_fd_for_io_channel(fd, io_channel)) { if (_is_the_only_fd_for_io_channel(fd, io_channel)) {
Io_channel_listener *l = io_channel->lookup_io_channel_listener(this); Io_channel_listener *l = io_channel->lookup_io_channel_listener(this);
io_channel->unregister_interrupt_handler(l); io_channel->unregister_interrupt_handler(l);
Genode::destroy(env()->heap(), l); Genode::destroy(_heap, l);
} }
File_descriptor_registry::remove_io_channel(fd); File_descriptor_registry::remove_io_channel(fd);
@ -521,28 +514,28 @@ namespace Noux {
Family_member *do_execve(const char *filename, Family_member *do_execve(const char *filename,
Args const &args, Args const &args,
Sysio::Env const &env, Sysio::Env const &env) override
bool verbose)
{ {
Lock::Guard signal_lock_guard(signal_lock()); Lock::Guard signal_lock_guard(signal_lock());
Child *child = new Child(filename, Child *child = new (_heap) Child(filename,
_verbose,
_user_info,
_parent_exit, _parent_exit,
_kill_broadcaster, _kill_broadcaster,
_timeout_scheduler,
_parent_execve, _parent_execve,
_pid_allocator,
pid(), pid(),
_sig_rec, _env,
_root_dir, _root_dir,
args, args,
env, env,
_env_pd_session, _heap,
_ref_ram, _ref_ram_cap, _ref_ram, _ref_ram_cap,
_parent_services, _parent_services,
_ep,
false, false,
*Genode::env()->heap(), _destruct_queue);
_destruct_queue,
verbose);
_assign_io_channels_to(child); _assign_io_channels_to(child);
@ -562,7 +555,7 @@ namespace Noux {
flush(); flush();
/* signal main thread to remove ourself */ /* signal main thread to remove ourself */
Genode::Signal_transmitter(_destruct_context_cap).submit(); Signal_transmitter(_destruct_handler).submit();
/* start executing the new process */ /* start executing the new process */
child->start(); child->start();
@ -580,8 +573,6 @@ namespace Noux {
{ {
submit_signal(Sysio::SIG_INT); submit_signal(Sysio::SIG_INT);
} }
};
}; };
#endif /* _NOUX__CHILD_H_ */ #endif /* _NOUX__CHILD_H_ */

View File

@ -23,16 +23,18 @@
#include <range_checked_index.h> #include <range_checked_index.h>
namespace Noux { namespace Noux {
template <size_t> class Child_env;
using namespace Genode; using namespace Genode;
}
/**
/**
* \param ARGS_SIZE size of the argument buffer given * \param ARGS_SIZE size of the argument buffer given
* to the constructor * to the constructor
*/ */
template <size_t ARGS_SIZE> template <Noux::size_t ARGS_SIZE>
class Child_env class Noux::Child_env
{ {
private: private:
enum { MAX_LEN_INTERPRETER_LINE = 128 }; enum { MAX_LEN_INTERPRETER_LINE = 128 };
@ -49,7 +51,8 @@ namespace Noux {
/** /**
* Handle the case that the given binary needs an interpreter * Handle the case that the given binary needs an interpreter
*/ */
void _process_binary_name_and_args(const char *binary_name, void _process_binary_name_and_args(Region_map &local_rm,
const char *binary_name,
Dataspace_capability binary_ds, Dataspace_capability binary_ds,
const char *args) const char *args)
{ {
@ -63,7 +66,7 @@ namespace Noux {
const char *binary_addr = 0; const char *binary_addr = 0;
if (interpretable) if (interpretable)
try { try {
binary_addr = Genode::env()->rm_session()->attach(binary_ds); binary_addr = local_rm.attach(binary_ds);
} catch(...) { } catch(...) {
PWRN("could not attach dataspace"); PWRN("could not attach dataspace");
interpretable = false; interpretable = false;
@ -74,7 +77,7 @@ namespace Noux {
interpretable = false; interpretable = false;
if (!interpretable) { if (!interpretable) {
Genode::env()->rm_session()->detach(binary_addr); local_rm.detach(binary_addr);
_binary_name = binary_name; _binary_name = binary_name;
Genode::memcpy(_args, args, ARGS_SIZE); Genode::memcpy(_args, args, ARGS_SIZE);
return; return;
@ -139,16 +142,16 @@ namespace Noux {
Genode::memcpy(&_args[args_buf_cursor], Genode::memcpy(&_args[args_buf_cursor],
args, ARGS_SIZE); args, ARGS_SIZE);
Genode::env()->rm_session()->detach(binary_addr); local_rm.detach(binary_addr);
} }
public: public:
Child_env(const char *binary_name, Dataspace_capability binary_ds, Child_env(Region_map &local_rm, const char *binary_name,
const char *args, Sysio::Env env) Dataspace_capability binary_ds, const char *args, Sysio::Env env)
{ {
_process_env(env); _process_env(env);
_process_binary_name_and_args(binary_name, binary_ds, args); _process_binary_name_and_args(local_rm, binary_name, binary_ds, args);
} }
char const *binary_name() const { return _binary_name; } char const *binary_name() const { return _binary_name; }
@ -156,7 +159,6 @@ namespace Noux {
Args args() { return Args(_args, sizeof(_args)); } Args args() { return Args(_args, sizeof(_args)); }
Sysio::Env const &env() const { return _env; } Sysio::Env const &env() const { return _env; }
}; };
}
#endif /* _NOUX__CHILD_ENV_H_ */ #endif /* _NOUX__CHILD_ENV_H_ */

View File

@ -33,8 +33,12 @@ namespace Noux {
typedef Local_service<Cpu_session_component> Cpu_service; typedef Local_service<Cpu_session_component> Cpu_service;
typedef Local_service<Rpc_object<Session> > Noux_service; typedef Local_service<Rpc_object<Session> > Noux_service;
class Child_policy : public Genode::Child_policy class Child_policy;
{ }
class Noux::Child_policy : public Genode::Child_policy
{
private: private:
Name const _name; Name const _name;
@ -187,7 +191,6 @@ namespace Noux {
{ {
return &static_cast<Pd_session_component &>(pd).address_space_region_map(); return &static_cast<Pd_session_component &>(pd).address_space_region_map();
} }
}; };
}
#endif /* _NOUX__CHILD_POLICY_H_ */ #endif /* _NOUX__CHILD_POLICY_H_ */

View File

@ -34,11 +34,13 @@
#include <pd_session_component.h> #include <pd_session_component.h>
namespace Noux { namespace Noux {
class Cpu_session_component;
using namespace Genode; using namespace Genode;
}
class Cpu_session_component : public Rpc_object<Cpu_session>
{ class Noux::Cpu_session_component : public Rpc_object<Cpu_session>
{
private: private:
Rpc_entrypoint &_ep; Rpc_entrypoint &_ep;
@ -51,6 +53,8 @@ namespace Noux {
Dataspace_capability _trace_control; Dataspace_capability _trace_control;
Dataspace_registry &_registry; Dataspace_registry &_registry;
Constructible<Static_dataspace_info> _ds_info;
public: public:
/** /**
@ -64,10 +68,16 @@ namespace Noux {
* The 'forked' parameter controls the policy applied to the * The 'forked' parameter controls the policy applied to the
* startup of the main thread. * startup of the main thread.
*/ */
Cpu_session_component(Rpc_entrypoint &ep, Child_policy::Name const &label, Cpu_session_component(Env &env,
bool forked, Dataspace_registry &registry) Rpc_entrypoint &ep,
: _ep(ep), _forked(forked), _cpu(label.string()), _registry(registry) Child_policy::Name const &label,
{ _ep.manage(this); } bool forked,
Dataspace_registry &registry)
:
_ep(ep), _forked(forked), _cpu(env, label.string()), _registry(registry)
{
_ep.manage(this);
}
~Cpu_session_component() ~Cpu_session_component()
{ {
@ -75,11 +85,6 @@ namespace Noux {
if (!_trace_control.valid()) if (!_trace_control.valid())
return; return;
auto lambda = [&] (Static_dataspace_info *rdi) { return rdi; };
Static_dataspace_info *ds_info = _registry.apply(_trace_control, lambda);
if (ds_info)
destroy(env()->heap(), ds_info);
} }
/** /**
@ -148,8 +153,7 @@ namespace Noux {
{ {
if (!_trace_control.valid()) { if (!_trace_control.valid()) {
_trace_control = _cpu.trace_control(); _trace_control = _cpu.trace_control();
new (env()->heap()) Static_dataspace_info(_registry, _ds_info.construct(_registry, _trace_control);
_trace_control);
} }
return _trace_control; return _trace_control;
} }
@ -164,7 +168,6 @@ namespace Noux {
Capability<Native_cpu> native_cpu() override { Capability<Native_cpu> native_cpu() override {
return _cpu.native_cpu(); } return _cpu.native_cpu(); }
}; };
}
#endif /* _NOUX__CPU_SESSION_COMPONENT_H_ */ #endif /* _NOUX__CPU_SESSION_COMPONENT_H_ */

View File

@ -19,19 +19,24 @@
#include <dataspace/client.h> #include <dataspace/client.h>
namespace Noux { namespace Noux {
class Dataspace_user;
class Dataspace_registry;
class Dataspace_info; class Dataspace_info;
class Dataspace_registry;
struct Static_dataspace_info;
using namespace Genode;
}
struct Dataspace_user : List<Dataspace_user>::Element struct Noux::Dataspace_user : List<Dataspace_user>::Element
{ {
virtual void dissolve(Dataspace_info &ds) = 0; virtual void dissolve(Dataspace_info &ds) = 0;
}; };
class Dataspace_info : public Object_pool<Dataspace_info>::Entry class Noux::Dataspace_info : public Object_pool<Dataspace_info>::Entry
{ {
private: private:
size_t _size; size_t _size;
@ -84,6 +89,11 @@ namespace Noux {
/** /**
* Create shadow copy of dataspace * Create shadow copy of dataspace
* *
* \param ram backing store used for copied dataspaces
* \param local_rm region map used for temporarily attaching
* dataspaces to the local address space
* \param alloc allocator used for creatng new 'Dataspace_info'
* objects
* \param ds_registry registry for keeping track of * \param ds_registry registry for keeping track of
* the new dataspace * the new dataspace
* \param ep entrypoint used to serve the RPC * \param ep entrypoint used to serve the RPC
@ -93,17 +103,23 @@ namespace Noux {
* \return capability for the new dataspace * \return capability for the new dataspace
*/ */
virtual Dataspace_capability fork(Ram_session &ram, virtual Dataspace_capability fork(Ram_session &ram,
Region_map &local_rm,
Allocator &alloc,
Dataspace_registry &ds_registry, Dataspace_registry &ds_registry,
Rpc_entrypoint &ep) = 0; Rpc_entrypoint &ep) = 0;
/** /**
* Write raw byte sequence into dataspace * Write raw byte sequence into dataspace
* *
* \param local_rm region map used for temporarily attaching
* the targeted dataspace to the local address
* space
* \param dst_offset destination offset within dataspace * \param dst_offset destination offset within dataspace
* \param src data source buffer * \param src data source buffer
* \param len length of source buffer in bytes * \param len length of source buffer in bytes
*/ */
virtual void poke(addr_t dst_offset, void const *src, size_t len) = 0; virtual void poke(Region_map &local_rm, addr_t dst_offset,
char const *src, size_t len) = 0;
/** /**
* Return leaf region map that covers a given address * Return leaf region map that covers a given address
@ -115,13 +131,19 @@ namespace Noux {
/* by default a dataspace is no sub region map, so return invalid */ /* by default a dataspace is no sub region map, so return invalid */
return Capability<Region_map>(); return Capability<Region_map>();
} }
}; };
class Dataspace_registry : public Object_pool<Dataspace_info> class Noux::Dataspace_registry : public Object_pool<Dataspace_info>
{ {
private:
Allocator &_alloc;
public: public:
Dataspace_registry(Allocator &alloc) : _alloc(alloc) { }
~Dataspace_registry() ~Dataspace_registry()
{ {
/* /*
@ -132,14 +154,13 @@ namespace Noux {
* created via 'Rm_dataspace_info::fork', are not handled by * created via 'Rm_dataspace_info::fork', are not handled by
* those destructors. So we have to clean them up here. * those destructors. So we have to clean them up here.
*/ */
remove_all([&] (Dataspace_info *info) { remove_all([&] (Dataspace_info *info) { destroy(_alloc, info); });
destroy(env()->heap(), info); });
} }
}; };
struct Static_dataspace_info : Dataspace_info struct Noux::Static_dataspace_info : Dataspace_info
{ {
Dataspace_registry &_ds_registry; Dataspace_registry &_ds_registry;
Static_dataspace_info(Dataspace_registry &ds_registry, Static_dataspace_info(Dataspace_registry &ds_registry,
@ -152,6 +173,7 @@ namespace Noux {
~Static_dataspace_info() ~Static_dataspace_info()
{ {
auto lambda = [this] (Static_dataspace_info *info) { auto lambda = [this] (Static_dataspace_info *info) {
if (!info) { if (!info) {
error("lookup of binary ds info failed"); error("lookup of binary ds info failed");
return; return;
@ -165,17 +187,18 @@ namespace Noux {
} }
Dataspace_capability fork(Ram_session &, Dataspace_capability fork(Ram_session &,
Region_map &,
Allocator &,
Dataspace_registry &, Dataspace_registry &,
Rpc_entrypoint &) Rpc_entrypoint &) override
{ {
return ds_cap(); return ds_cap();
} }
void poke(addr_t dst_offset, void const *src, size_t len) void poke(Region_map &, addr_t, char const *, size_t) override
{ {
error("attempt to poke onto a static dataspace"); error("attempt to poke onto a static dataspace");
} }
}; };
}
#endif /* _NOUX__DATASPACE_REGISTRY_H_ */ #endif /* _NOUX__DATASPACE_REGISTRY_H_ */

View File

@ -1,48 +0,0 @@
/*
* \brief Signal_dispatcher which adds a destruct queue element into a
* destruct queue
* \author Christian Prochaska
* \date 2013-01-03
*/
/*
* Copyright (C) 2013-2013 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 _NOUX__DESTRUCT_DISPATCHER_H_
#define _NOUX__DESTRUCT_DISPATCHER_H_
/* Genode includes */
#include <base/signal.h>
/* Noux includes */
#include <destruct_queue.h>
namespace Noux {
using namespace Genode;
class Destruct_dispatcher : public Signal_dispatcher_base
{
private:
Destruct_queue &_destruct_queue;
Destruct_queue::Element_base *_element;
public:
Destruct_dispatcher(Destruct_queue &destruct_queue,
Destruct_queue::Element_base *element)
: _destruct_queue(destruct_queue), _element(element) { }
void dispatch(unsigned)
{
_destruct_queue.insert(_element);
}
};
}
#endif /* _NOUX__DESTRUCT_DISPATCHER_H_ */

View File

@ -18,10 +18,11 @@
#include <base/allocator.h> #include <base/allocator.h>
#include <util/list.h> #include <util/list.h>
namespace Noux { namespace Noux { class Destruct_queue; }
class Destruct_queue
{ class Noux::Destruct_queue
{
public: public:
struct Element_base : Genode::List<Element_base>::Element struct Element_base : Genode::List<Element_base>::Element
@ -44,7 +45,7 @@ namespace Noux {
{ {
private: private:
Genode::Allocator *_alloc; Genode::Allocator &_alloc;
public: public:
@ -54,7 +55,7 @@ namespace Noux {
* \param alloc the allocator which was used to allocate * \param alloc the allocator which was used to allocate
* the element * the element
*/ */
Element(Genode::Allocator *alloc) : _alloc(alloc) { } Element(Genode::Allocator &alloc) : _alloc(alloc) { }
virtual ~Element() { }; virtual ~Element() { };
@ -68,13 +69,18 @@ namespace Noux {
Genode::List<Element_base> _destruct_list; Genode::List<Element_base> _destruct_list;
Genode::Lock _destruct_list_lock; Genode::Lock _destruct_list_lock;
Signal_context_capability _sigh;
public: public:
Destruct_queue(Signal_context_capability sigh) : _sigh(sigh) { }
void insert(Element_base *element) void insert(Element_base *element)
{ {
Genode::Lock::Guard guard(_destruct_list_lock); Genode::Lock::Guard guard(_destruct_list_lock);
_destruct_list.insert(element); _destruct_list.insert(element);
Signal_transmitter(_sigh).submit();
} }
void flush() void flush()
@ -87,8 +93,6 @@ namespace Noux {
element->destroy(); element->destroy();
} }
} }
}; };
}
#endif /* _NOUX__DESTRUCT_QUEUE_H_ */ #endif /* _NOUX__DESTRUCT_QUEUE_H_ */

View File

@ -1,28 +0,0 @@
/*
* \brief Dummy input I/O channel to be used for non-interactive init
* \author Norman Feske
* \date 2011-02-17
*/
/*
* Copyright (C) 2011-2013 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 _NOUX__DUMMY_INPUT_IO_CHANNEL_H_
#define _NOUX__DUMMY_INPUT_IO_CHANNEL_H_
/* Noux includes */
#include <io_channel.h>
namespace Noux {
class Sysio;
struct Dummy_input_io_channel : public Io_channel
{ };
}
#endif /* _NOUX__DUMMY_INPUT_IO_CHANNEL_H_ */

View File

@ -11,18 +11,24 @@
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
#ifndef _NOUX__ENVIRONMENT_H_
#define _NOUX__ENVIRONMENT_H_
/* Genode includes */ /* Genode includes */
#include <util/string.h> #include <util/string.h>
#include <os/attached_ram_dataspace.h> #include <base/attached_ram_dataspace.h>
#include <base/printf.h>
/* Noux includes */ /* Noux includes */
#include <path.h> #include <path.h>
namespace Noux { namespace Noux {
class Environment;
using namespace Genode;
}
class Environment : private Attached_ram_dataspace
{ class Noux::Environment : private Attached_ram_dataspace
{
private: private:
Sysio::Env *_env; Sysio::Env *_env;
@ -30,10 +36,13 @@ namespace Noux {
public: public:
/** /**
* Constructor
*
* \param env comma-separated list of environment variables * \param env comma-separated list of environment variables
*/ */
Environment(Sysio::Env const &env) : Environment(Ram_session &ram, Region_map &local_rm, Sysio::Env const &env)
Attached_ram_dataspace(Genode::env()->ram_session(), sizeof(Sysio::Env)), :
Attached_ram_dataspace(ram, local_rm, sizeof(Sysio::Env)),
_env(local_addr<Sysio::Env>()) _env(local_addr<Sysio::Env>())
{ {
memcpy(_env, env, sizeof(Sysio::Env)); memcpy(_env, env, sizeof(Sysio::Env));
@ -45,5 +54,6 @@ namespace Noux {
* Return list of environment variables as zero-separated list * Return list of environment variables as zero-separated list
*/ */
Sysio::Env const &env() { return *_env; } Sysio::Env const &env() { return *_env; }
}; };
}
#endif /* _NOUX__ENVIRONMENT_H_ */

View File

@ -22,12 +22,13 @@
#include <parent_exit.h> #include <parent_exit.h>
#include <parent_execve.h> #include <parent_execve.h>
namespace Noux { namespace Noux { class Family_member; }
class Family_member : public List<Family_member>::Element,
class Noux::Family_member : public List<Family_member>::Element,
public Parent_exit, public Parent_exit,
public Parent_execve public Parent_execve
{ {
private: private:
int const _pid; int const _pid;
@ -114,21 +115,18 @@ namespace Noux {
/* Called by the parent from 'execve_child()' */ /* Called by the parent from 'execve_child()' */
virtual Family_member *do_execve(const char *filename, virtual Family_member *do_execve(const char *filename,
Args const &args, Args const &args,
Sysio::Env const &env, Sysio::Env const &env) = 0;
bool verbose) = 0;
/* Called by the child on the parent (via Parent_execve) */ /* Called by the child on the parent (via Parent_execve) */
void execve_child(Family_member &child, void execve_child(Family_member &child,
const char *filename, const char *filename,
Args const &args, Args const &args,
Sysio::Env const &env, Sysio::Env const &env)
bool verbose)
{ {
Lock::Guard guard(_lock); Lock::Guard guard(_lock);
Family_member *new_child = child.do_execve(filename, Family_member *new_child = child.do_execve(filename,
args, args,
env, env);
verbose);
_list.insert(new_child); _list.insert(new_child);
_list.remove(&child); _list.remove(&child);
} }
@ -174,7 +172,6 @@ namespace Noux {
/* either a child exited or a signal occurred */ /* either a child exited or a signal occurred */
return poll4(); return poll4();
} }
}; };
}
#endif /* _NOUX__FAMILY_MEMBER_H_ */ #endif /* _NOUX__FAMILY_MEMBER_H_ */

View File

@ -17,10 +17,11 @@
/* Noux includes */ /* Noux includes */
#include <io_channel.h> #include <io_channel.h>
namespace Noux { namespace Noux { class File_descriptor_registry; }
class File_descriptor_registry
{ class Noux::File_descriptor_registry
{
public: public:
enum { MAX_FILE_DESCRIPTORS = 64 }; enum { MAX_FILE_DESCRIPTORS = 64 };
@ -115,7 +116,6 @@ namespace Noux {
for (unsigned i = 0; i < MAX_FILE_DESCRIPTORS; i++) for (unsigned i = 0; i < MAX_FILE_DESCRIPTORS; i++)
_reset_fd(i); _reset_fd(i);
} }
}; };
}
#endif /* _NOUX__FILE_DESCRIPTOR_REGISTRY_H_ */ #endif /* _NOUX__FILE_DESCRIPTOR_REGISTRY_H_ */

View File

@ -28,30 +28,33 @@
#include <io_channel_listener.h> #include <io_channel_listener.h>
namespace Noux { namespace Noux {
class Terminal_io_channel;
extern Genode::Lock &signal_lock(); extern Genode::Lock &signal_lock();
/** class Io_channel_backend;
class Io_channel;
class Terminal_io_channel;
}
/**
* Input/output channel backend that is used for calling * Input/output channel backend that is used for calling
* different methos which does not belong to the original * different methods, which does not belong to the original
* interface, e.g. network methods. * interface, e.g. network methods.
*/ */
class Io_channel_backend struct Noux::Io_channel_backend
{ {
public:
virtual ~Io_channel_backend() { } virtual ~Io_channel_backend() { }
virtual int type() const { return -1; } virtual int type() const { return -1; }
}; };
/**
/**
* Input/output channel interface * Input/output channel interface
*/ */
class Io_channel : public Reference_counter class Noux::Io_channel : public Reference_counter
{ {
private: private:
/** /**
@ -71,16 +74,16 @@ namespace Noux {
virtual ~Io_channel() { } virtual ~Io_channel() { }
virtual Io_channel_backend* backend() { return 0; } virtual Io_channel_backend *backend() { return nullptr; }
virtual bool write(Sysio *sysio, size_t &offset) { return false; } virtual bool write(Sysio &sysio, size_t &offset) { return false; }
virtual bool read(Sysio *sysio) { return false; } virtual bool read(Sysio &sysio) { return false; }
virtual bool fstat(Sysio *sysio) { return false; } virtual bool fstat(Sysio &sysio) { return false; }
virtual bool ftruncate(Sysio *sysio) { return false; } virtual bool ftruncate(Sysio &sysio) { return false; }
virtual bool fcntl(Sysio *sysio) { return false; } virtual bool fcntl(Sysio &sysio) { return false; }
virtual bool dirent(Sysio *sysio) { return false; } virtual bool dirent(Sysio &sysio) { return false; }
virtual bool ioctl(Sysio *sysio) { return false; } virtual bool ioctl(Sysio &sysio) { return false; }
virtual bool lseek(Sysio *sysio) { return false; } virtual bool lseek(Sysio &sysio) { return false; }
/** /**
* Return true if an unblocking condition of the channel is satisfied * Return true if an unblocking condition of the channel is satisfied
@ -195,7 +198,6 @@ namespace Noux {
* and is only implemented by Vfs_io_channel. * and is only implemented by Vfs_io_channel.
*/ */
virtual bool path(char *path, size_t len) { return false; } virtual bool path(char *path, size_t len) { return false; }
}; };
}
#endif /* _NOUX__IO_CHANNEL_H_ */ #endif /* _NOUX__IO_CHANNEL_H_ */

View File

@ -20,9 +20,7 @@
/* Noux includes */ /* Noux includes */
#include <interrupt_handler.h> #include <interrupt_handler.h>
namespace Noux { namespace Noux { typedef List_element<Interrupt_handler> Io_channel_listener; }
typedef List_element<Interrupt_handler> Io_channel_listener;
}
#endif /* _NOUX__IO_CHANNEL_LISTENER__H_ */ #endif /* _NOUX__IO_CHANNEL_LISTENER__H_ */

View File

@ -20,29 +20,31 @@
namespace Noux { namespace Noux {
struct Io_receptor;
struct Io_receptor_registry;
}
struct Io_receptor : List<Io_receptor>::Element
{ struct Noux::Io_receptor : List<Io_receptor>::Element
{
private: private:
Lock *_lock; Lock *_lock;
public: public:
Io_receptor(Lock *lock) Io_receptor(Lock *lock) : _lock(lock) { }
:
_lock(lock)
{ }
void check_and_wakeup() void check_and_wakeup()
{ {
if (_lock) if (_lock)
_lock->unlock(); _lock->unlock();
} }
}; };
class Io_receptor_registry
{ class Noux::Io_receptor_registry
{
private: private:
List<Io_receptor> _receptors; List<Io_receptor> _receptors;
@ -74,9 +76,6 @@ namespace Noux {
} }
Io_receptor *first() { return _receptors.first(); } Io_receptor *first() { return _receptors.first(); }
};
};
}
#endif /* _NOUX__IO_RECEPTOR_REGISTRY_H_ */ #endif /* _NOUX__IO_RECEPTOR_REGISTRY_H_ */

View File

@ -36,16 +36,19 @@ class Noux::Local_rom_factory : public Local_rom_service::Factory
{ {
private: private:
Allocator &_alloc;
Env &_env;
Rpc_entrypoint &_ep; Rpc_entrypoint &_ep;
Vfs::Dir_file_system &_root_dir; Vfs::Dir_file_system &_root_dir;
Dataspace_registry &_registry; Dataspace_registry &_registry;
public: public:
Local_rom_factory(Rpc_entrypoint &ep, Vfs::Dir_file_system &root_dir, Local_rom_factory(Allocator &alloc, Env &env, Rpc_entrypoint &ep,
Vfs::Dir_file_system &root_dir,
Dataspace_registry &registry) Dataspace_registry &registry)
: :
_ep(ep), _root_dir(root_dir), _registry(registry) _alloc(alloc), _env(env), _ep(ep), _root_dir(root_dir), _registry(registry)
{ } { }
Rom_session_component &create(Args const &args, Affinity) override Rom_session_component &create(Args const &args, Affinity) override
@ -54,8 +57,8 @@ class Noux::Local_rom_factory : public Local_rom_service::Factory
Rom_session_component::Name const rom_name = Rom_session_component::Name const rom_name =
label_from_args(args.string()).last_element(); label_from_args(args.string()).last_element();
return *new (env()->heap()) return *new (_alloc)
Rom_session_component(_ep, _root_dir, _registry, rom_name); Rom_session_component(_alloc, _env, _ep, _root_dir, _registry, rom_name);
} }
catch (Rom_connection::Rom_connection_failed) { throw Denied(); } catch (Rom_connection::Rom_connection_failed) { throw Denied(); }
} }
@ -64,7 +67,7 @@ class Noux::Local_rom_factory : public Local_rom_service::Factory
void destroy(Rom_session_component &session) override void destroy(Rom_session_component &session) override
{ {
Genode::destroy(env()->heap(), &session); Genode::destroy(_alloc, &session);
} }
}; };

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,9 @@
TARGET = noux TARGET = noux
LIBS = alarm vfs LIBS = alarm vfs
SRC_CC = main.cc dummy_net.cc SRC_CC = main.cc syscall.cc dummy_net.cc
INC_DIR += $(PRG_DIR) INC_DIR += $(PRG_DIR)
INC_DIR += $(PRG_DIR)/../ INC_DIR += $(PRG_DIR)/../
vpath main.cc $(PRG_DIR)/.. vpath main.cc $(PRG_DIR)/..
vpath syscall.cc $(PRG_DIR)/..
vpath dummy_net.cc $(PRG_DIR) vpath dummy_net.cc $(PRG_DIR)

View File

@ -72,6 +72,7 @@ void init_network()
libc_select_notify = select_notify; libc_select_notify = select_notify;
} }
/********************************* /*********************************
** Noux net syscall dispatcher ** ** Noux net syscall dispatcher **
*********************************/ *********************************/
@ -117,16 +118,16 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
break; break;
case SYSCALL_SOCKET: case SYSCALL_SOCKET:
{ {
Socket_io_channel *socket_io_channel = new Socket_io_channel(); Socket_io_channel *socket_io_channel = new (_heap) Socket_io_channel();
GET_SOCKET_IO_CHANNEL_BACKEND(socket_io_channel->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(socket_io_channel->backend(), backend);
if (!backend->socket(&_sysio)) { if (!backend->socket(_sysio)) {
delete socket_io_channel; delete socket_io_channel;
return false; return false;
} }
Shared_pointer<Io_channel> io_channel(socket_io_channel, Genode::env()->heap()); Shared_pointer<Io_channel> io_channel(socket_io_channel, _heap);
_sysio.socket_out.fd = add_io_channel(io_channel); _sysio.socket_out.fd = add_io_channel(io_channel);
@ -138,7 +139,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return backend->getsockopt(&_sysio); return backend->getsockopt(_sysio);
} }
case SYSCALL_SETSOCKOPT: case SYSCALL_SETSOCKOPT:
{ {
@ -146,7 +147,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return backend->setsockopt(&_sysio); return backend->setsockopt(_sysio);
} }
case SYSCALL_ACCEPT: case SYSCALL_ACCEPT:
{ {
@ -154,12 +155,12 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
int socket = backend->accept(&_sysio); int socket = backend->accept(_sysio);
if (socket == -1) if (socket == -1)
return false; return false;
Socket_io_channel *socket_io_channel = new Socket_io_channel(socket); Socket_io_channel *socket_io_channel = new (_heap) Socket_io_channel(socket);
Shared_pointer<Io_channel> io_channel(socket_io_channel, Genode::env()->heap()); Shared_pointer<Io_channel> io_channel(socket_io_channel, _heap);
_sysio.accept_out.fd = add_io_channel(io_channel); _sysio.accept_out.fd = add_io_channel(io_channel);
@ -171,7 +172,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return (backend->bind(&_sysio) == -1) ? false : true; return (backend->bind(_sysio) == -1) ? false : true;
} }
case SYSCALL_LISTEN: case SYSCALL_LISTEN:
{ {
@ -179,7 +180,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return (backend->listen(&_sysio) == -1) ? false : true; return (backend->listen(_sysio) == -1) ? false : true;
} }
case SYSCALL_SEND: case SYSCALL_SEND:
{ {
@ -187,7 +188,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return (backend->send(&_sysio) == -1) ? false : true; return (backend->send(_sysio) == -1) ? false : true;
} }
case SYSCALL_SENDTO: case SYSCALL_SENDTO:
{ {
@ -195,7 +196,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return (backend->sendto(&_sysio) == -1) ? false : true; return (backend->sendto(_sysio) == -1) ? false : true;
} }
case SYSCALL_RECV: case SYSCALL_RECV:
{ {
@ -203,7 +204,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return (backend->recv(&_sysio) == -1) ? false : true; return (backend->recv(_sysio) == -1) ? false : true;
} }
case SYSCALL_RECVFROM: case SYSCALL_RECVFROM:
{ {
@ -211,7 +212,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return (backend->recvfrom(&_sysio) == -1) ? false : true; return (backend->recvfrom(_sysio) == -1) ? false : true;
} }
case SYSCALL_GETPEERNAME: case SYSCALL_GETPEERNAME:
{ {
@ -219,7 +220,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return (backend->getpeername(&_sysio) == -1) ? false : true; return (backend->getpeername(_sysio) == -1) ? false : true;
} }
case SYSCALL_SHUTDOWN: case SYSCALL_SHUTDOWN:
{ {
@ -227,7 +228,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return (backend->shutdown(&_sysio) == -1) ? false : true; return (backend->shutdown(_sysio) == -1) ? false : true;
} }
case SYSCALL_CONNECT: case SYSCALL_CONNECT:
{ {
@ -235,7 +236,7 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend); GET_SOCKET_IO_CHANNEL_BACKEND(io->backend(), backend);
return (backend->connect(&_sysio) == -1) ? false : true; return (backend->connect(_sysio) == -1) ? false : true;
} }
} }

View File

@ -32,11 +32,14 @@
#include <fcntl.h> #include <fcntl.h>
#include <errno.h> #include <errno.h>
namespace Noux { namespace Noux {
class Socket_io_channel_backend;
class Socket_io_channel;
}
class Socket_io_channel_backend : public Io_channel_backend
{ class Noux::Socket_io_channel_backend : public Io_channel_backend
{
private: private:
int _socket; int _socket;
@ -69,23 +72,23 @@ namespace Noux {
* Io_channel interface implementation (only needed methods) * Io_channel interface implementation (only needed methods)
*/ */
bool write(Sysio *sysio, ::size_t &count) bool write(Sysio &sysio, ::size_t &count)
{ {
ssize_t result = ::write(_socket, sysio->write_in.chunk, ssize_t result = ::write(_socket, sysio.write_in.chunk,
sysio->write_in.count); sysio.write_in.count);
if (result > -1) { if (result > -1) {
sysio->write_out.count = result; sysio.write_out.count = result;
count = result; count = result;
return true; return true;
} }
switch (errno) { switch (errno) {
/* case EAGAIN: sysio->error.read = Sysio::READ_ERR_AGAIN; break; */ /* case EAGAIN: sysio.error.read = Sysio::READ_ERR_AGAIN; break; */
case EWOULDBLOCK: sysio->error.read = Vfs::File_io_service::READ_ERR_WOULD_BLOCK; break; case EWOULDBLOCK: sysio.error.read = Vfs::File_io_service::READ_ERR_WOULD_BLOCK; break;
case EINVAL: sysio->error.read = Vfs::File_io_service::READ_ERR_INVALID; break; case EINVAL: sysio.error.read = Vfs::File_io_service::READ_ERR_INVALID; break;
case EIO: sysio->error.read = Vfs::File_io_service::READ_ERR_IO; break; case EIO: sysio.error.read = Vfs::File_io_service::READ_ERR_IO; break;
default: default:
log(__func__, ": unhandled errno: ", (int)errno); log(__func__, ": unhandled errno: ", (int)errno);
break; break;
@ -94,22 +97,22 @@ namespace Noux {
return false; return false;
} }
bool read(Sysio *sysio) bool read(Sysio &sysio)
{ {
::size_t const max_count = Genode::min(sysio->read_in.count, sizeof(sysio->read_out.chunk)); ::size_t const max_count = Genode::min(sysio.read_in.count, sizeof(sysio.read_out.chunk));
ssize_t result = ::read(_socket, sysio->read_out.chunk, max_count); ssize_t result = ::read(_socket, sysio.read_out.chunk, max_count);
if (result > -1) { if (result > -1) {
sysio->read_out.count = result; sysio.read_out.count = result;
return true; return true;
} }
switch (errno) { switch (errno) {
/* case EAGAIN: sysio->error.read = Sysio::READ_ERR_AGAIN; break; */ /* case EAGAIN: sysio.error.read = Sysio::READ_ERR_AGAIN; break; */
case EWOULDBLOCK: sysio->error.read = Vfs::File_io_service::READ_ERR_WOULD_BLOCK; break; case EWOULDBLOCK: sysio.error.read = Vfs::File_io_service::READ_ERR_WOULD_BLOCK; break;
case EINVAL: sysio->error.read = Vfs::File_io_service::READ_ERR_INVALID; break; case EINVAL: sysio.error.read = Vfs::File_io_service::READ_ERR_INVALID; break;
case EIO: sysio->error.read = Vfs::File_io_service::READ_ERR_IO; break; case EIO: sysio.error.read = Vfs::File_io_service::READ_ERR_IO; break;
default: default:
log(__func__, ": unhandled errno: ", (int)errno); log(__func__, ": unhandled errno: ", (int)errno);
break; break;
@ -118,36 +121,36 @@ namespace Noux {
return false; return false;
} }
bool fcntl(Sysio *sysio) bool fcntl(Sysio &sysio)
{ {
int cmd = -1; int cmd = -1;
switch (sysio->fcntl_in.cmd) { switch (sysio.fcntl_in.cmd) {
case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: cmd = F_GETFL; break; case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: cmd = F_GETFL; break;
case Sysio::FCNTL_CMD_SET_FILE_STATUS_FLAGS: cmd = F_SETFL; break; case Sysio::FCNTL_CMD_SET_FILE_STATUS_FLAGS: cmd = F_SETFL; break;
default: default:
log("invalid fcntl command: ", (int)sysio->fcntl_in.cmd); log("invalid fcntl command: ", (int)sysio.fcntl_in.cmd);
sysio->error.fcntl = Sysio::FCNTL_ERR_CMD_INVALID; sysio.error.fcntl = Sysio::FCNTL_ERR_CMD_INVALID;
return false; return false;
} }
int result = ::fcntl(_socket, cmd, sysio->fcntl_in.long_arg); int result = ::fcntl(_socket, cmd, sysio.fcntl_in.long_arg);
sysio->fcntl_out.result = result; sysio.fcntl_out.result = result;
return true; return true;
} }
bool dirent(Sysio *sysio) { return false; } bool dirent(Sysio &sysio) { return false; }
bool ioctl(Sysio *sysio) bool ioctl(Sysio &sysio)
{ {
int request; int request;
switch (sysio->ioctl_in.request) { switch (sysio.ioctl_in.request) {
case Vfs::File_io_service::IOCTL_OP_FIONBIO: request = FIONBIO; break; case Vfs::File_io_service::IOCTL_OP_FIONBIO: request = FIONBIO; break;
default: default:
log(__func__, ": invalid ioctl request: ", (int)sysio->ioctl_in.request); log(__func__, ": invalid ioctl request: ", (int)sysio.ioctl_in.request);
return false; return false;
} }
int result = ::ioctl(_socket, request, NULL); int result = ::ioctl(_socket, request, NULL);
@ -211,25 +214,25 @@ namespace Noux {
* Socket methods * Socket methods
*/ */
int accept(Sysio *sysio) int accept(Sysio &sysio)
{ {
int result; int result;
if (sysio->accept_in.addrlen == 0) { if (sysio.accept_in.addrlen == 0) {
result = ::accept(_socket, NULL, NULL); result = ::accept(_socket, NULL, NULL);
} }
else { else {
result = ::accept(_socket, (sockaddr *)&sysio->accept_in.addr, result = ::accept(_socket, (sockaddr *)&sysio.accept_in.addr,
&sysio->accept_in.addrlen); &sysio.accept_in.addrlen);
} }
if (result == -1) { if (result == -1) {
switch (errno) { switch (errno) {
/* case EAGAIN: sysio->error.accept = Sysio::ACCEPT_ERR_AGAIN; break; */ /* case EAGAIN: sysio.error.accept = Sysio::ACCEPT_ERR_AGAIN; break; */
case ENOMEM: sysio->error.accept = Sysio::ACCEPT_ERR_NO_MEMORY; break; case ENOMEM: sysio.error.accept = Sysio::ACCEPT_ERR_NO_MEMORY; break;
case EINVAL: sysio->error.accept = Sysio::ACCEPT_ERR_INVALID; break; case EINVAL: sysio.error.accept = Sysio::ACCEPT_ERR_INVALID; break;
case EOPNOTSUPP: sysio->error.accept = Sysio::ACCEPT_ERR_NOT_SUPPORTED; break; case EOPNOTSUPP: sysio.error.accept = Sysio::ACCEPT_ERR_NOT_SUPPORTED; break;
case EWOULDBLOCK: sysio->error.accept = Sysio::ACCEPT_ERR_WOULD_BLOCK; break; case EWOULDBLOCK: sysio.error.accept = Sysio::ACCEPT_ERR_WOULD_BLOCK; break;
default: default:
log(__func__, ": unhandled errno: ", (int)errno); log(__func__, ": unhandled errno: ", (int)errno);
break; break;
@ -239,17 +242,17 @@ namespace Noux {
return result; return result;
} }
int bind(Sysio *sysio) int bind(Sysio &sysio)
{ {
int result = ::bind(_socket, (const struct sockaddr *)&sysio->bind_in.addr, int result = ::bind(_socket, (const struct sockaddr *)&sysio.bind_in.addr,
sysio->bind_in.addrlen); sysio.bind_in.addrlen);
if (result == -1) { if (result == -1) {
switch (errno) { switch (errno) {
case EACCES: sysio->error.bind = Sysio::BIND_ERR_ACCESS; break; case EACCES: sysio.error.bind = Sysio::BIND_ERR_ACCESS; break;
case EADDRINUSE: sysio->error.bind = Sysio::BIND_ERR_ADDR_IN_USE; break; case EADDRINUSE: sysio.error.bind = Sysio::BIND_ERR_ADDR_IN_USE; break;
case EINVAL: sysio->error.bind = Sysio::BIND_ERR_INVALID; break; case EINVAL: sysio.error.bind = Sysio::BIND_ERR_INVALID; break;
case ENOMEM: sysio->error.bind = Sysio::BIND_ERR_NO_MEMORY; break; case ENOMEM: sysio.error.bind = Sysio::BIND_ERR_NO_MEMORY; break;
default: default:
log(__func__, ": unhandled errno: ", (int)errno); log(__func__, ": unhandled errno: ", (int)errno);
break; break;
@ -259,21 +262,21 @@ namespace Noux {
return result; return result;
} }
int connect(Sysio *sysio) int connect(Sysio &sysio)
{ {
int result = ::connect(_socket, (struct sockaddr *)&sysio->connect_in.addr, int result = ::connect(_socket, (struct sockaddr *)&sysio.connect_in.addr,
sysio->connect_in.addrlen); sysio.connect_in.addrlen);
if (result == -1) { if (result == -1) {
switch (errno) { switch (errno) {
case EAGAIN: sysio->error.connect = Sysio::CONNECT_ERR_AGAIN; break; case EAGAIN: sysio.error.connect = Sysio::CONNECT_ERR_AGAIN; break;
case EALREADY: sysio->error.connect = Sysio::CONNECT_ERR_ALREADY; break; case EALREADY: sysio.error.connect = Sysio::CONNECT_ERR_ALREADY; break;
case EADDRINUSE: sysio->error.connect = Sysio::CONNECT_ERR_ADDR_IN_USE; break; case EADDRINUSE: sysio.error.connect = Sysio::CONNECT_ERR_ADDR_IN_USE; break;
case EINPROGRESS: sysio->error.connect = Sysio::CONNECT_ERR_IN_PROGRESS; break; case EINPROGRESS: sysio.error.connect = Sysio::CONNECT_ERR_IN_PROGRESS; break;
case EISCONN: sysio->error.connect = Sysio::CONNECT_ERR_IS_CONNECTED; break; case EISCONN: sysio.error.connect = Sysio::CONNECT_ERR_IS_CONNECTED; break;
case ECONNRESET: sysio->error.connect = Sysio::CONNECT_ERR_RESET; break; case ECONNRESET: sysio.error.connect = Sysio::CONNECT_ERR_RESET; break;
case ECONNABORTED: sysio->error.connect = Sysio::CONNECT_ERR_ABORTED; break; case ECONNABORTED: sysio.error.connect = Sysio::CONNECT_ERR_ABORTED; break;
case EHOSTUNREACH: sysio->error.connect = Sysio::CONNECT_ERR_NO_ROUTE; break; case EHOSTUNREACH: sysio.error.connect = Sysio::CONNECT_ERR_NO_ROUTE; break;
default: default:
log(__func__, ": unhandled errno: ", (int)errno); log(__func__, ": unhandled errno: ", (int)errno);
@ -284,30 +287,30 @@ namespace Noux {
return result; return result;
} }
int getpeername(Sysio *sysio) int getpeername(Sysio &sysio)
{ {
return ::getpeername(_socket, (struct sockaddr *)&sysio->getpeername_in.addr, return ::getpeername(_socket, (struct sockaddr *)&sysio.getpeername_in.addr,
(socklen_t *)&sysio->getpeername_in.addrlen); (socklen_t *)&sysio.getpeername_in.addrlen);
} }
bool getsockopt(Sysio *sysio) bool getsockopt(Sysio &sysio)
{ {
int result = ::getsockopt(_socket, sysio->getsockopt_in.level, int result = ::getsockopt(_socket, sysio.getsockopt_in.level,
sysio->getsockopt_in.optname, sysio.getsockopt_in.optname,
sysio->getsockopt_in.optval, sysio.getsockopt_in.optval,
&sysio->getsockopt_in.optlen); &sysio.getsockopt_in.optlen);
return (result == -1) ? false : true; return (result == -1) ? false : true;
} }
int listen(Sysio *sysio) int listen(Sysio &sysio)
{ {
int result = ::listen(_socket, sysio->listen_in.backlog); int result = ::listen(_socket, sysio.listen_in.backlog);
if (result == -1) { if (result == -1) {
switch (errno) { switch (errno) {
case EADDRINUSE: sysio->error.listen = Sysio::LISTEN_ERR_ADDR_IN_USE; break; case EADDRINUSE: sysio.error.listen = Sysio::LISTEN_ERR_ADDR_IN_USE; break;
case EOPNOTSUPP: sysio->error.listen = Sysio::LISTEN_ERR_NOT_SUPPORTED; break; case EOPNOTSUPP: sysio.error.listen = Sysio::LISTEN_ERR_NOT_SUPPORTED; break;
default: default:
log(__func__, ": unhandled errno: ", (int)errno); log(__func__, ": unhandled errno: ", (int)errno);
break; break;
@ -317,130 +320,130 @@ namespace Noux {
return result; return result;
} }
ssize_t recv(Sysio *sysio) ssize_t recv(Sysio &sysio)
{ {
ssize_t result = ::recv(_socket, sysio->recv_in.buf, sysio->recv_in.len, sysio->recv_in.flags); ssize_t result = ::recv(_socket, sysio.recv_in.buf, sysio.recv_in.len, sysio.recv_in.flags);
if (result == -1) { if (result == -1) {
switch (errno) { switch (errno) {
/*case EAGAIN: sysio->error.recv = Sysio::RECV_ERR_AGAIN; break; */ /*case EAGAIN: sysio.error.recv = Sysio::RECV_ERR_AGAIN; break; */
case EWOULDBLOCK: sysio->error.recv = Sysio::RECV_ERR_WOULD_BLOCK; break; case EWOULDBLOCK: sysio.error.recv = Sysio::RECV_ERR_WOULD_BLOCK; break;
case EINVAL: sysio->error.recv = Sysio::RECV_ERR_INVALID; break; case EINVAL: sysio.error.recv = Sysio::RECV_ERR_INVALID; break;
case ENOTCONN: sysio->error.recv = Sysio::RECV_ERR_NOT_CONNECTED; break; case ENOTCONN: sysio.error.recv = Sysio::RECV_ERR_NOT_CONNECTED; break;
default: default:
log(__func__, ": unhandled errno: ", (int)errno); log(__func__, ": unhandled errno: ", (int)errno);
break; break;
} }
} }
sysio->recv_out.len = result; sysio.recv_out.len = result;
return result; return result;
} }
ssize_t recvfrom(Sysio *sysio) ssize_t recvfrom(Sysio &sysio)
{ {
ssize_t result = ::recvfrom(_socket, sysio->recv_in.buf, sysio->recv_in.len, ssize_t result = ::recvfrom(_socket, sysio.recv_in.buf, sysio.recv_in.len,
sysio->recv_in.flags, (struct sockaddr *)&sysio->recvfrom_in.src_addr, sysio.recv_in.flags, (struct sockaddr *)&sysio.recvfrom_in.src_addr,
&sysio->recvfrom_in.addrlen); &sysio.recvfrom_in.addrlen);
if (result == -1) { if (result == -1) {
switch (errno) { switch (errno) {
/*case EAGAIN: sysio->error.recv = Sysio::RECV_ERR_AGAIN; break; */ /*case EAGAIN: sysio.error.recv = Sysio::RECV_ERR_AGAIN; break; */
case EWOULDBLOCK: sysio->error.recv = Sysio::RECV_ERR_WOULD_BLOCK; break; case EWOULDBLOCK: sysio.error.recv = Sysio::RECV_ERR_WOULD_BLOCK; break;
case EINVAL: sysio->error.recv = Sysio::RECV_ERR_INVALID; break; case EINVAL: sysio.error.recv = Sysio::RECV_ERR_INVALID; break;
case ENOTCONN: sysio->error.recv = Sysio::RECV_ERR_NOT_CONNECTED; break; case ENOTCONN: sysio.error.recv = Sysio::RECV_ERR_NOT_CONNECTED; break;
default: default:
log(__func__, " unhandled errno: ", (int)errno); log(__func__, " unhandled errno: ", (int)errno);
break; break;
} }
} }
sysio->recvfrom_out.len = result; sysio.recvfrom_out.len = result;
return result; return result;
} }
bool setsockopt(Sysio *sysio) bool setsockopt(Sysio &sysio)
{ {
/* /*
* Filter options out because lwip only supports several socket * Filter options out because lwip only supports several socket
* options. Therefore for now we silently return 0 and notify * options. Therefore for now we silently return 0 and notify
* the user via debug message. * the user via debug message.
*/ */
switch (sysio->setsockopt_in.optname) { switch (sysio.setsockopt_in.optname) {
case SO_DEBUG: case SO_DEBUG:
case SO_LINGER: case SO_LINGER:
warning("SOL_SOCKET option '", sysio->setsockopt_in.optname, "' " warning("SOL_SOCKET option '", sysio.setsockopt_in.optname, "' "
"is currently not supported, however we report success"); "is currently not supported, however we report success");
return true; return true;
} }
int result = ::setsockopt(_socket, sysio->setsockopt_in.level, int result = ::setsockopt(_socket, sysio.setsockopt_in.level,
sysio->setsockopt_in.optname, sysio.setsockopt_in.optname,
sysio->setsockopt_in.optval, sysio.setsockopt_in.optval,
sysio->setsockopt_in.optlen); sysio.setsockopt_in.optlen);
return (result == -1) ? false : true; return (result == -1) ? false : true;
} }
ssize_t send(Sysio *sysio) ssize_t send(Sysio &sysio)
{ {
ssize_t result = ::send(_socket, sysio->send_in.buf, sysio->send_in.len, ssize_t result = ::send(_socket, sysio.send_in.buf, sysio.send_in.len,
sysio->send_in.flags); sysio.send_in.flags);
if (result == -1) { if (result == -1) {
switch (errno) { switch (errno) {
/*case EAGAIN: sysio->error.send = Sysio::SEND_ERR_AGAIN; break; */ /*case EAGAIN: sysio.error.send = Sysio::SEND_ERR_AGAIN; break; */
case EWOULDBLOCK: sysio->error.send = Sysio::SEND_ERR_WOULD_BLOCK; break; case EWOULDBLOCK: sysio.error.send = Sysio::SEND_ERR_WOULD_BLOCK; break;
case ECONNRESET: sysio->error.send = Sysio::SEND_ERR_CONNECTION_RESET; break; case ECONNRESET: sysio.error.send = Sysio::SEND_ERR_CONNECTION_RESET; break;
case EINVAL: sysio->error.send = Sysio::SEND_ERR_INVALID; break; case EINVAL: sysio.error.send = Sysio::SEND_ERR_INVALID; break;
case EISCONN: sysio->error.send = Sysio::SEND_ERR_IS_CONNECTED; break; case EISCONN: sysio.error.send = Sysio::SEND_ERR_IS_CONNECTED; break;
case ENOMEM: sysio->error.send = Sysio::SEND_ERR_NO_MEMORY; break; case ENOMEM: sysio.error.send = Sysio::SEND_ERR_NO_MEMORY; break;
default: default:
log(__func__, ": unhandled errno: ", (int)errno); log(__func__, ": unhandled errno: ", (int)errno);
break; break;
} }
} }
sysio->send_out.len = result; sysio.send_out.len = result;
return result; return result;
} }
ssize_t sendto(Sysio *sysio) ssize_t sendto(Sysio &sysio)
{ {
ssize_t result = ::sendto(_socket, sysio->sendto_in.buf, sysio->sendto_in.len, ssize_t result = ::sendto(_socket, sysio.sendto_in.buf, sysio.sendto_in.len,
sysio->sendto_in.flags, sysio.sendto_in.flags,
(const struct sockaddr *) &sysio->sendto_in.dest_addr, (const struct sockaddr *) &sysio.sendto_in.dest_addr,
sysio->sendto_in.addrlen); sysio.sendto_in.addrlen);
if (result == -1) { if (result == -1) {
switch (errno) { switch (errno) {
/*case EAGAIN: sysio->error.send = Sysio::SEND_ERR_AGAIN; break; */ /*case EAGAIN: sysio.error.send = Sysio::SEND_ERR_AGAIN; break; */
case EWOULDBLOCK: sysio->error.send = Sysio::SEND_ERR_WOULD_BLOCK; break; case EWOULDBLOCK: sysio.error.send = Sysio::SEND_ERR_WOULD_BLOCK; break;
case ECONNRESET: sysio->error.send = Sysio::SEND_ERR_CONNECTION_RESET; break; case ECONNRESET: sysio.error.send = Sysio::SEND_ERR_CONNECTION_RESET; break;
case EINVAL: sysio->error.send = Sysio::SEND_ERR_INVALID; break; case EINVAL: sysio.error.send = Sysio::SEND_ERR_INVALID; break;
case EISCONN: sysio->error.send = Sysio::SEND_ERR_IS_CONNECTED; break; case EISCONN: sysio.error.send = Sysio::SEND_ERR_IS_CONNECTED; break;
case ENOMEM: sysio->error.send = Sysio::SEND_ERR_NO_MEMORY; break; case ENOMEM: sysio.error.send = Sysio::SEND_ERR_NO_MEMORY; break;
default: default:
log(__func__, ": unhandled errno: ", (int)errno); log(__func__, ": unhandled errno: ", (int)errno);
break; break;
} }
} }
sysio->sendto_out.len = result; sysio.sendto_out.len = result;
return result; return result;
} }
int shutdown(Sysio *sysio) int shutdown(Sysio &sysio)
{ {
int result = ::shutdown(_socket, sysio->shutdown_in.how); int result = ::shutdown(_socket, sysio.shutdown_in.how);
if (result == -1) { if (result == -1) {
switch (errno) { switch (errno) {
case ENOTCONN: sysio->error.shutdown = Sysio::SHUTDOWN_ERR_NOT_CONNECTED; break; case ENOTCONN: sysio.error.shutdown = Sysio::SHUTDOWN_ERR_NOT_CONNECTED; break;
default: default:
log(__func__, ": unhandled errno: ", (int)errno); log(__func__, ": unhandled errno: ", (int)errno);
break; break;
@ -450,74 +453,49 @@ namespace Noux {
return result; return result;
} }
bool socket(Sysio *sysio) bool socket(Sysio &sysio)
{ {
_socket = ::socket(sysio->socket_in.domain, _socket = ::socket(sysio.socket_in.domain,
sysio->socket_in.type, sysio.socket_in.type,
sysio->socket_in.protocol); sysio.socket_in.protocol);
return (_socket == -1) ? false : true; return (_socket == -1) ? false : true;
} }
}; };
class Socket_io_channel : public Io_channel
{ class Noux::Socket_io_channel : public Io_channel
{
private: private:
Socket_io_channel_backend _backend;
Socket_io_channel_backend *_backend;
public: public:
Socket_io_channel() Socket_io_channel() { }
: Socket_io_channel(int s) : _backend(s) { }
_backend(new (env()->heap()) Socket_io_channel_backend()) ~Socket_io_channel() { }
{ }
Socket_io_channel(int s) /*
:
_backend(new (env()->heap()) Socket_io_channel_backend(s))
{ }
~Socket_io_channel()
{
destroy(env()->heap(), _backend);
}
/**
* Io_channel interface (only needed methods) * Io_channel interface (only needed methods)
*/ */
Io_channel_backend *backend() { return _backend; } Io_channel_backend *backend() { return &_backend; }
bool write(Sysio *sysio, ::size_t &count) bool write(Sysio &sysio, ::size_t &count)
{ {
return _backend->write(sysio, count); return _backend.write(sysio, count);
} }
bool read(Sysio *sysio) bool read(Sysio &sysio) { return _backend.read(sysio); }
{ bool fcntl(Sysio &sysio) { return _backend.fcntl(sysio); }
return _backend->read(sysio); bool ioctl(Sysio &sysio) { return _backend.ioctl(sysio); }
}
bool fcntl(Sysio* sysio)
{
return _backend->fcntl(sysio);
}
bool ioctl(Sysio *sysio)
{
return _backend->ioctl(sysio);
}
bool check_unblock(bool rd, bool wr, bool ex) const bool check_unblock(bool rd, bool wr, bool ex) const
{ {
return _backend->check_unblock(rd, wr, ex); return _backend.check_unblock(rd, wr, ex);
} }
};
};
}
#endif /* _NOUX__SOCKET_IO_CHANNEL_H_ */ #endif /* _NOUX__SOCKET_IO_CHANNEL_H_ */

View File

@ -1,10 +1,10 @@
TARGET = noux_net TARGET = noux_net
LIBS += alarm libc libc_lwip_nic_dhcp vfs LIBS += alarm libc libc_lwip_nic_dhcp vfs
SRC_CC = main.cc syscall.cc net.cc
SRC_CC = main.cc net.cc
INC_DIR += $(PRG_DIR) INC_DIR += $(PRG_DIR)
INC_DIR += $(PRG_DIR)/../ INC_DIR += $(PRG_DIR)/../
vpath main.cc $(PRG_DIR)/.. vpath main.cc $(PRG_DIR)/..
vpath syscall.cc $(PRG_DIR)/..
vpath net.cc $(PRG_DIR) vpath net.cc $(PRG_DIR)

View File

@ -18,18 +18,17 @@
#include <noux_session/sysio.h> #include <noux_session/sysio.h>
namespace Noux { namespace Noux {
struct Family_member; struct Family_member;
struct Parent_execve;
}
struct Parent_execve
{ struct Noux::Parent_execve
{
virtual void execve_child(Family_member &child, virtual void execve_child(Family_member &child,
const char *filename, const char *filename,
Args const &args, Args const &args,
Sysio::Env const &env, Sysio::Env const &env) = 0;
bool verbose) = 0;
};
}; };
#endif /* _NOUX__PARENT_EXECVE__H_ */ #endif /* _NOUX__PARENT_EXECVE__H_ */

View File

@ -42,13 +42,14 @@ class Noux::Pd_session_component : public Rpc_object<Pd_session>
/** /**
* Constructor * Constructor
*/ */
Pd_session_component(Rpc_entrypoint &ep, Child_policy::Name const &name, Pd_session_component(Allocator &alloc, Env &env, Rpc_entrypoint &ep,
Child_policy::Name const &name,
Dataspace_registry &ds_registry) Dataspace_registry &ds_registry)
: :
_ep(ep), _pd(name.string()), _ep(ep), _pd(env, name.string()),
_address_space(_ep, ds_registry, _pd, _pd.address_space()), _address_space(alloc, _ep, ds_registry, _pd, _pd.address_space()),
_stack_area (_ep, ds_registry, _pd, _pd.stack_area()), _stack_area (alloc, _ep, ds_registry, _pd, _pd.stack_area()),
_linker_area (_ep, ds_registry, _pd, _pd.linker_area()) _linker_area (alloc, _ep, ds_registry, _pd, _pd.linker_area())
{ {
_ep.manage(this); _ep.manage(this);
} }
@ -60,9 +61,9 @@ class Noux::Pd_session_component : public Rpc_object<Pd_session>
Pd_session_capability core_pd_cap() { return _pd.cap(); } Pd_session_capability core_pd_cap() { return _pd.cap(); }
void poke(addr_t dst_addr, void const *src, size_t len) void poke(Region_map &rm, addr_t dst_addr, char const *src, size_t len)
{ {
_address_space.poke(dst_addr, src, len); _address_space.poke(rm, dst_addr, src, len);
} }
Capability<Region_map> lookup_region_map(addr_t const addr) Capability<Region_map> lookup_region_map(addr_t const addr)
@ -76,13 +77,15 @@ class Noux::Pd_session_component : public Rpc_object<Pd_session>
void replay(Ram_session &dst_ram, void replay(Ram_session &dst_ram,
Pd_session_component &dst_pd, Pd_session_component &dst_pd,
Region_map &local_rm,
Allocator &alloc,
Dataspace_registry &ds_registry, Dataspace_registry &ds_registry,
Rpc_entrypoint &ep) Rpc_entrypoint &ep)
{ {
/* replay region map into new protection domain */ /* replay region map into new protection domain */
_stack_area .replay(dst_ram, dst_pd.stack_area_region_map(), ds_registry, ep); _stack_area .replay(dst_ram, dst_pd.stack_area_region_map(), local_rm, alloc, ds_registry, ep);
_linker_area .replay(dst_ram, dst_pd.linker_area_region_map(), ds_registry, ep); _linker_area .replay(dst_ram, dst_pd.linker_area_region_map(), local_rm, alloc, ds_registry, ep);
_address_space.replay(dst_ram, dst_pd.address_space_region_map(), ds_registry, ep); _address_space.replay(dst_ram, dst_pd.address_space_region_map(), local_rm, alloc, ds_registry, ep);
Region_map &dst_address_space = dst_pd.address_space_region_map(); Region_map &dst_address_space = dst_pd.address_space_region_map();
Region_map &dst_stack_area = dst_pd.stack_area_region_map(); Region_map &dst_stack_area = dst_pd.stack_area_region_map();

View File

@ -18,9 +18,14 @@
#include <io_channel.h> #include <io_channel.h>
namespace Noux { namespace Noux {
class Pipe;
class Pipe_sink_io_channel;
class Pipe_source_io_channel;
}
class Pipe : public Reference_counter
{ class Noux::Pipe : public Reference_counter
{
private: private:
Lock mutable _lock; Lock mutable _lock;
@ -207,37 +212,37 @@ namespace Noux {
Lock::Guard guard(_lock); Lock::Guard guard(_lock);
_read_ready_sigh = sigh; _read_ready_sigh = sigh;
} }
}; };
class Pipe_sink_io_channel : public Io_channel, public Signal_dispatcher_base class Noux::Pipe_sink_io_channel : public Io_channel
{ {
private: private:
Signal_handler<Pipe_sink_io_channel> _write_ready_handler;
void _handle_write_ready() { Io_channel::invoke_all_notifiers(); }
Shared_pointer<Pipe> _pipe; Shared_pointer<Pipe> _pipe;
Signal_receiver &_sig_rec;
public: public:
Pipe_sink_io_channel(Shared_pointer<Pipe> pipe, Pipe_sink_io_channel(Shared_pointer<Pipe> pipe, Entrypoint &ep)
Signal_receiver &sig_rec) :
: _pipe(pipe), _sig_rec(sig_rec) _write_ready_handler(ep, *this, &Pipe_sink_io_channel::_handle_write_ready),
_pipe(pipe)
{ {
pipe->register_write_ready_sigh(_sig_rec.manage(this)); pipe->register_write_ready_sigh(_write_ready_handler);
} }
~Pipe_sink_io_channel() ~Pipe_sink_io_channel() { _pipe->writer_close(); }
{
_sig_rec.dissolve(this);
_pipe->writer_close();
}
bool check_unblock(bool rd, bool wr, bool ex) const override bool check_unblock(bool rd, bool wr, bool ex) const override
{ {
return wr && _pipe->any_space_avail_for_writing(); return wr && _pipe->any_space_avail_for_writing();
} }
bool write(Sysio *sysio, size_t &offset) override bool write(Sysio &sysio, size_t &offset) override
{ {
/* /*
* If the write operation is larger than the space available in * If the write operation is larger than the space available in
@ -249,18 +254,18 @@ namespace Noux {
*/ */
/* dimension the pipe write operation to the not yet written data */ /* dimension the pipe write operation to the not yet written data */
size_t curr_count = _pipe->write(sysio->write_in.chunk + offset, size_t curr_count = _pipe->write(sysio.write_in.chunk + offset,
sysio->write_in.count - offset); sysio.write_in.count - offset);
offset += curr_count; offset += curr_count;
return true; return true;
} }
bool fcntl(Sysio *sysio) override bool fcntl(Sysio &sysio) override
{ {
switch (sysio->fcntl_in.cmd) { switch (sysio.fcntl_in.cmd) {
case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS:
sysio->fcntl_out.result = Sysio::OPEN_MODE_WRONLY; sysio.fcntl_out.result = Sysio::OPEN_MODE_WRONLY;
return true; return true;
default: default:
@ -268,47 +273,35 @@ namespace Noux {
} }
} }
bool fstat(Sysio *sysio) override bool fstat(Sysio &sysio) override
{ {
sysio->fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV; sysio.fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV;
return true; return true;
} }
};
/************************************** class Noux::Pipe_source_io_channel : public Io_channel
** Signal_dispatcher_base interface ** {
**************************************/
/**
* Called by Noux main loop on the occurrence of new STDIN input
*/
void dispatch(unsigned) override
{
Io_channel::invoke_all_notifiers();
}
};
class Pipe_source_io_channel : public Io_channel, public Signal_dispatcher_base
{
private: private:
Signal_handler<Pipe_source_io_channel> _read_avail_handler;
void _handle_read_avail() { Io_channel::invoke_all_notifiers(); }
Shared_pointer<Pipe> _pipe; Shared_pointer<Pipe> _pipe;
Signal_receiver &_sig_rec;
public: public:
Pipe_source_io_channel(Shared_pointer<Pipe> pipe, Signal_receiver &sig_rec) Pipe_source_io_channel(Shared_pointer<Pipe> pipe, Entrypoint &ep)
: _pipe(pipe), _sig_rec(sig_rec) :
_read_avail_handler(ep, *this, &Pipe_source_io_channel::_handle_read_avail),
_pipe(pipe)
{ {
_pipe->register_read_ready_sigh(sig_rec.manage(this)); _pipe->register_read_ready_sigh(_read_avail_handler);
} }
~Pipe_source_io_channel() ~Pipe_source_io_channel() { _pipe->reader_close(); }
{
_sig_rec.dissolve(this);
_pipe->reader_close();
}
bool check_unblock(bool rd, bool wr, bool ex) const override bool check_unblock(bool rd, bool wr, bool ex) const override
{ {
@ -319,24 +312,24 @@ namespace Noux {
return (rd && _pipe->data_avail_for_reading()); return (rd && _pipe->data_avail_for_reading());
} }
bool read(Sysio *sysio) override bool read(Sysio &sysio) override
{ {
size_t const max_count = size_t const max_count =
min(sysio->read_in.count, min(sysio.read_in.count,
sizeof(sysio->read_out.chunk)); sizeof(sysio.read_out.chunk));
sysio->read_out.count = sysio.read_out.count =
_pipe->read(sysio->read_out.chunk, max_count); _pipe->read(sysio.read_out.chunk, max_count);
return true; return true;
} }
bool fcntl(Sysio *sysio) override bool fcntl(Sysio &sysio) override
{ {
switch (sysio->fcntl_in.cmd) { switch (sysio.fcntl_in.cmd) {
case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS:
sysio->fcntl_out.result = Sysio::OPEN_MODE_RDONLY; sysio.fcntl_out.result = Sysio::OPEN_MODE_RDONLY;
return true; return true;
default: default:
@ -344,24 +337,11 @@ namespace Noux {
} }
} }
bool fstat(Sysio *sysio) override bool fstat(Sysio &sysio) override
{ {
sysio->fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV; sysio.fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV;
return true; return true;
} }
};
/**************************************
** Signal_dispatcher_base interface **
**************************************/
/**
* Called by Noux main loop on the occurrence of new STDIN input
*/
void dispatch(unsigned) override
{
Io_channel::invoke_all_notifiers();
}
};
}
#endif /* _NOUX__PIPE_IO_CHANNEL_H_ */ #endif /* _NOUX__PIPE_IO_CHANNEL_H_ */

View File

@ -26,80 +26,77 @@
/* Genode includes */ /* Genode includes */
#include <ram_session/client.h> #include <ram_session/client.h>
#include <base/rpc_server.h> #include <base/rpc_server.h>
#include <base/env.h>
/* Noux includes */ /* Noux includes */
#include <dataspace_registry.h> #include <dataspace_registry.h>
namespace Noux { namespace Noux {
struct Ram_dataspace_info;
struct Ram_session_component;
using namespace Genode;
}
struct Ram_dataspace_info : Dataspace_info,
struct Noux::Ram_dataspace_info : Dataspace_info,
List<Ram_dataspace_info>::Element List<Ram_dataspace_info>::Element
{ {
Ram_dataspace_info(Ram_dataspace_capability ds_cap) Ram_dataspace_info(Ram_dataspace_capability ds_cap)
: Dataspace_info(ds_cap) { } : Dataspace_info(ds_cap) { }
Dataspace_capability fork(Ram_session &ram, Dataspace_capability fork(Ram_session &ram,
Region_map &local_rm,
Allocator &alloc,
Dataspace_registry &ds_registry, Dataspace_registry &ds_registry,
Rpc_entrypoint &) override Rpc_entrypoint &) override
{ {
size_t const size = Dataspace_client(ds_cap()).size(); size_t const size = Dataspace_client(ds_cap()).size();
Ram_dataspace_capability dst_ds_cap;
Ram_dataspace_capability dst_ds;
try { dst_ds = ram.alloc(size); }
catch (...) { return Dataspace_capability(); }
void *src = 0;
try { try {
src = env()->rm_session()->attach(ds_cap()); dst_ds_cap = ram.alloc(size);
} catch (...) { }
void *dst = 0; Attached_dataspace src_ds(local_rm, ds_cap());
try { Attached_dataspace dst_ds(local_rm, dst_ds_cap);
dst = env()->rm_session()->attach(dst_ds); memcpy(dst_ds.local_addr<char>(), src_ds.local_addr<char>(), size);
} catch (...) { }
if (src && dst) ds_registry.insert(new (alloc) Ram_dataspace_info(dst_ds_cap));
memcpy(dst, src, size); return dst_ds_cap;
if (src) env()->rm_session()->detach(src); } catch (...) {
if (dst) env()->rm_session()->detach(dst); error("fork of RAM dataspace failed");
if (dst_ds_cap.valid())
ram.free(dst_ds_cap);
if (!src || !dst) {
ram.free(dst_ds);
return Dataspace_capability(); return Dataspace_capability();
} }
ds_registry.insert(new (env()->heap()) Ram_dataspace_info(dst_ds));
return dst_ds;
} }
void poke(addr_t dst_offset, void const *src, size_t len) void poke(Region_map &rm, addr_t dst_offset, char const *src, size_t len) override
{ {
if (!src) return;
if ((dst_offset >= size()) || (dst_offset + len > size())) { if ((dst_offset >= size()) || (dst_offset + len > size())) {
error("illegal attemt to write beyond dataspace boundary"); error("illegal attemt to write beyond dataspace boundary");
return; return;
} }
char *dst = 0;
try { try {
dst = env()->rm_session()->attach(ds_cap()); Attached_dataspace ds(rm, ds_cap());
} catch (...) { } memcpy(ds.local_addr<char>() + dst_offset, src, len);
} catch (...) { warning("poke: failed to attach RAM dataspace"); }
if (src && dst)
memcpy(dst + dst_offset, src, len);
if (dst) env()->rm_session()->detach(dst);
} }
}; };
class Ram_session_component : public Rpc_object<Ram_session> class Noux::Ram_session_component : public Rpc_object<Ram_session>
{ {
private: private:
Ram_session &_ram;
Allocator &_alloc;
Rpc_entrypoint &_ep; Rpc_entrypoint &_ep;
List<Ram_dataspace_info> _list; List<Ram_dataspace_info> _list;
@ -118,8 +115,14 @@ namespace Noux {
/** /**
* Constructor * Constructor
*/ */
Ram_session_component(Rpc_entrypoint &ep, Dataspace_registry &registry) Ram_session_component(Ram_session &ram, Allocator &alloc,
: _ep(ep), _used_quota(0), _registry(registry) { _ep.manage(this); } Rpc_entrypoint &ep, Dataspace_registry &registry)
:
_ram(ram), _alloc(alloc), _ep(ep), _used_quota(0),
_registry(registry)
{
_ep.manage(this);
}
/** /**
* Destructor * Destructor
@ -140,10 +143,9 @@ namespace Noux {
Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) Ram_dataspace_capability alloc(size_t size, Cache_attribute cached)
{ {
Ram_dataspace_capability ds_cap = Ram_dataspace_capability ds_cap =
env()->ram_session()->alloc(size, cached); _ram.alloc(size, cached);
Ram_dataspace_info *ds_info = new (env()->heap()) Ram_dataspace_info *ds_info = new (_alloc) Ram_dataspace_info(ds_cap);
Ram_dataspace_info(ds_cap);
_used_quota += ds_info->size(); _used_quota += ds_info->size();
@ -172,17 +174,16 @@ namespace Noux {
_list.remove(ds_info); _list.remove(ds_info);
_used_quota -= ds_info->size(); _used_quota -= ds_info->size();
env()->ram_session()->free(ds_cap); _ram.free(ds_cap);
}; };
_registry.apply(ds_cap, lambda); _registry.apply(ds_cap, lambda);
destroy(env()->heap(), ds_info); destroy(_alloc, ds_info);
} }
int ref_account(Ram_session_capability) { return 0; } int ref_account(Ram_session_capability) { return 0; }
int transfer_quota(Ram_session_capability, size_t) { return 0; } int transfer_quota(Ram_session_capability, size_t) { return 0; }
size_t quota() { return env()->ram_session()->quota(); } size_t quota() { return _ram.quota(); }
size_t used() { return _used_quota; } size_t used() { return _used_quota; }
}; };
}
#endif /* _NOUX__RAM_SESSION_COMPONENT_H_ */ #endif /* _NOUX__RAM_SESSION_COMPONENT_H_ */

View File

@ -1,281 +0,0 @@
/*
* \brief Device Random filesystem
* \author Josef Soentgen
* \date 2012-07-31
*/
/*
* Copyright (C) 2012-2013 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 _NOUX__RANDOM_FILE_SYSTEM_H_
#define _NOUX__RANDOM_FILE_SYSTEM_H_
/* Genode includes */
#include <base/printf.h>
#include <base/stdint.h>
#include <util/string.h>
/* Noux includes */
#include <noux_session/sysio.h>
#include <vfs/single_file_system.h>
/*-
* Copyright (c) 2010, 2012
* Thorsten Glaser <tg@mirbsd.org>
* Copyright (c) 2012
* Josef Soentgen <cnuke@mirbsd.org>
*
* Provided that these terms and disclaimer and all copyright notices
* are retained or reproduced in an accompanying document, permission
* is granted to deal in this work without restriction, including un-
* limited rights to use, publicly perform, distribute, sell, modify,
* merge, give away, or sublicence.
*
* This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
* the utmost extent permitted by applicable law, neither express nor
* implied; without malicious intent or gross negligence. In no event
* may a licensor, author or contributor be held liable for indirect,
* direct, other damage, loss, or other issues arising in any way out
* of dealing in the work, even if advised of the possibility of such
* damage or existence of a defect, except proven that it results out
* of said person's immediate fault when using the work as intended.
*-
* arc4random for use as NOUX random device.
*
* From:
* MirOS: src/kern/c/arcfour_base.c,v 1.1 2010/09/12 17:10:49 tg Exp
* MirOS: src/kern/c/arcfour_ksa.c,v 1.1 2010/09/12 17:10:50 tg Exp
* MirOS: src/lib/libc/crypt/arc4random_base.c,v 1.4 2011/07/06 22:22:09 tg Exp
* MirOS: src/lib/libc/crypt/arc4random_buf.c,v 1.1 2010/09/12 17:10:53 tg Exp
*/
namespace Noux {
using namespace Genode;
/**
* Arcfour cipher re-implementation from (alledged) spec description.
*/
class Arc4random
{
private:
uint8_t S[256];
uint8_t i;
uint8_t j;
uint16_t num;
uint8_t initialised;
/*
* Base cipher operation: initialise state
*/
void init(void)
{
register uint8_t n = 0;
do {
S[n] = n;
} while (++n);
i = j = 0;
}
/*
* Base cipher operation: get byte of keystream.
*/
uint8_t byte(void)
{
register uint8_t si, sj;
si = S[++i];
j += si;
sj = S[j];
S[i] = sj;
S[j] = si;
return (S[(uint8_t)(si + sj)]);
}
/*
* Normal key scheduling algorithm.
*/
void ksa(const uint8_t *key, size_t keylen)
{
register uint8_t si, n = 0;
--i;
do {
++i;
si = S[i];
j = (uint8_t)(j + si + key[n++ % keylen]);
S[i] = S[j];
S[j] = si;
} while (n);
j = ++i;
}
/*
* arc4random implementation
*/
void stir_unlocked(void)
{
register unsigned int m;
uint8_t n;
struct {
// struct timeval tv;
// pid_t mypid;
uint32_t mypid;
const void *stkptr, *bssptr, *txtptr;
uint16_t num;
uint8_t initialised;
// FIXME sizeof (sb) should be as close to 256 as possible
} sb;
/* save some state; while not a secret, helps through variety */
//sb.mypid = getpid();
sb.mypid = 42;
sb.stkptr = &sb;
sb.bssptr = &i;
//sb.txtptr = &byte;
sb.txtptr = (const void *)0xDEADBEEF;;
sb.num = num;
sb.initialised = initialised;
/* initialise i, j and the S-box if not done yet */
if (!initialised) {
init();
initialised = 1;
}
// FIXME initialize more sb member
/* dance around by some bytes for added protection */
n = byte();
/* and carry some over to below */
m = byte();
while (n--)
(void)byte();
m += byte();
/* while time is not a secret, it helps through variety */
//gettimeofday(&sb.tv, NULL);
/* actually add the hopefully random-containing seed */
ksa((const uint8_t *)&sb, sizeof(sb));
/* throw away the first part of the arcfour keystream */
/* with some bytes varied for added protection */
m += 256 * 4 + (byte() & 0x1F);
while (m--)
(void)byte();
/* state is now good for so many bytes: (not so much in NOUX) */
num = 2000;
}
void buf(void *buf_, unsigned long long len)
{
size_t chunk;
uint8_t *buf = (uint8_t *)buf_;
uint8_t m, n;
/* operate in chunks of at most 256 bytes */
while ((chunk = len > 256 ? 256 : len) > 0) {
/* adjust len */
len -= chunk;
/* is the state good for this? (or even initialised, yet?) */
if (num < chunk)
stir_unlocked();
/* dance around a few bytes for added protection */
m = byte() & 3;
/* and carry some down below */
n = byte() & 3;
while (m--)
(void)byte();
/* actually read out the keystream into buf */
while (chunk--) {
*buf++ = byte();
}
/* dance around the bytes read from above, for protection */
while (n--)
(void)byte();
}
}
public:
Arc4random(void* bytes, size_t nbytes)
:
i(0),
j(0),
num(0),
initialised(0)
{
memset(S, 0, 256);
}
void get(void *_buf, unsigned long long len)
{
buf(_buf, len);
}
};
class Random_file_system : public Vfs::Single_file_system
{
private:
Arc4random _arc4random;
public:
Random_file_system(Genode::Env&, Genode::Allocator&,
Genode::Xml_node config)
:
Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config),
_arc4random(0, 0)
{ }
static char const *name() { return "random"; }
/********************************
** File I/O service interface **
********************************/
Write_result write(Vfs::Vfs_handle *, char const *,
Vfs::file_size buf_size,
Vfs::file_size &out_count) override
{
out_count = buf_size;
return WRITE_OK;
}
Read_result read(Vfs::Vfs_handle *vfs_handle, char *dst,
Vfs::file_size count,
Vfs::file_size &out_count) override
{
_arc4random.get(dst, count);
out_count = count;
return READ_OK;
}
Ftruncate_result ftruncate(Vfs::Vfs_handle *,
Vfs::file_size) override
{
return FTRUNCATE_OK;
}
};
}
#endif /* _NOUX__RANDOM_H_ */

View File

@ -17,15 +17,17 @@
namespace Noux { namespace Noux {
class Index_out_of_range { }; class Index_out_of_range { };
template <typename> struct Range_checked_index;
}
template <typename T>
struct Range_checked_index template <typename T>
{ struct Noux::Range_checked_index
{
T value; T value;
T const max; T const max;
Range_checked_index(T value, T max) Range_checked_index(T value, T max) : value(value), max(max) { }
: value(value), max(max) { }
T operator++ (int) T operator++ (int)
{ {
@ -38,7 +40,6 @@ namespace Noux {
} }
operator T () { return value; } operator T () { return value; }
}; };
}
#endif /* _NOUX__RANGE_CHECKED_INDEX_H_ */ #endif /* _NOUX__RANGE_CHECKED_INDEX_H_ */

View File

@ -36,6 +36,8 @@ class Noux::Region_map_component : public Rpc_object<Region_map>,
static constexpr bool verbose_attach = false; static constexpr bool verbose_attach = false;
static constexpr bool verbose_replay = false; static constexpr bool verbose_replay = false;
Allocator &_alloc;
Rpc_entrypoint &_ep; Rpc_entrypoint &_ep;
/** /**
@ -104,13 +106,13 @@ class Noux::Region_map_component : public Rpc_object<Region_map>,
* quota upgrades * quota upgrades
* \param rm region map at core * \param rm region map at core
*/ */
Region_map_component(Rpc_entrypoint &ep, Region_map_component(Allocator &alloc, Rpc_entrypoint &ep,
Dataspace_registry &ds_registry, Dataspace_registry &ds_registry,
Pd_connection &pd, Pd_connection &pd,
Capability<Region_map> rm) Capability<Region_map> rm)
: :
Dataspace_info(Region_map_client(rm).dataspace()), Dataspace_info(Region_map_client(rm).dataspace()),
_ep(ep), _rm(rm), _pd(pd), _ds_registry(ds_registry) _alloc(alloc), _ep(ep), _rm(rm), _pd(pd), _ds_registry(ds_registry)
{ {
_ep.manage(this); _ep.manage(this);
_ds_registry.insert(this); _ds_registry.insert(this);
@ -159,6 +161,8 @@ class Noux::Region_map_component : public Rpc_object<Region_map>,
*/ */
void replay(Ram_session &dst_ram, void replay(Ram_session &dst_ram,
Region_map &dst_rm, Region_map &dst_rm,
Region_map &local_rm,
Allocator &alloc,
Dataspace_registry &ds_registry, Dataspace_registry &ds_registry,
Rpc_entrypoint &ep) Rpc_entrypoint &ep)
{ {
@ -170,7 +174,7 @@ class Noux::Region_map_component : public Rpc_object<Region_map>,
Dataspace_capability ds; Dataspace_capability ds;
if (info) { if (info) {
ds = info->fork(dst_ram, ds_registry, ep); ds = info->fork(dst_ram, local_rm, alloc, ds_registry, ep);
/* /*
* XXX We could detect dataspaces that are attached * XXX We could detect dataspaces that are attached
@ -242,7 +246,7 @@ class Noux::Region_map_component : public Rpc_object<Region_map>,
} }
} }
Region * region = new (env()->heap()) Region * region = new (_alloc)
Region(*this, ds, size, offset, local_addr); Region(*this, ds, size, offset, local_addr);
/* register region as user of RAM dataspaces */ /* register region as user of RAM dataspaces */
@ -289,10 +293,9 @@ class Noux::Region_map_component : public Rpc_object<Region_map>,
_ds_registry.apply(region->ds, [&] (Dataspace_info *info) { _ds_registry.apply(region->ds, [&] (Dataspace_info *info) {
if (info) info->unregister_user(*region); }); if (info) info->unregister_user(*region); });
destroy(env()->heap(), region); destroy(_alloc, region);
_rm.detach(local_addr); _rm.detach(local_addr);
} }
void fault_handler(Signal_context_capability handler) override void fault_handler(Signal_context_capability handler) override
@ -323,6 +326,8 @@ class Noux::Region_map_component : public Rpc_object<Region_map>,
******************************/ ******************************/
Dataspace_capability fork(Ram_session &, Dataspace_capability fork(Ram_session &,
Region_map &,
Allocator &,
Dataspace_registry &, Dataspace_registry &,
Rpc_entrypoint &) override Rpc_entrypoint &) override
{ {
@ -358,7 +363,7 @@ class Noux::Region_map_component : public Rpc_object<Region_map>,
return _ds_registry.apply(region->ds, lambda); return _ds_registry.apply(region->ds, lambda);
} }
void poke(addr_t dst_addr, void const *src, size_t len) override void poke(Region_map &rm, addr_t dst_addr, char const *src, size_t len) override
{ {
Dataspace_capability ds_cap; Dataspace_capability ds_cap;
addr_t local_addr; addr_t local_addr;
@ -395,7 +400,7 @@ class Noux::Region_map_component : public Rpc_object<Region_map>,
error("attempt to write to unknown dataspace type"); error("attempt to write to unknown dataspace type");
for (;;); for (;;);
} }
info->poke(dst_addr - local_addr, src, len); info->poke(rm, dst_addr - local_addr, src, len);
}); });
} }
}; };

View File

@ -32,14 +32,16 @@ struct Noux::Rom_dataspace_info : Dataspace_info
~Rom_dataspace_info() { } ~Rom_dataspace_info() { }
Dataspace_capability fork(Ram_session &, Dataspace_capability fork(Ram_session &,
Region_map &,
Allocator &alloc,
Dataspace_registry &ds_registry, Dataspace_registry &ds_registry,
Rpc_entrypoint &) override Rpc_entrypoint &) override
{ {
ds_registry.insert(new (env()->heap()) Rom_dataspace_info(ds_cap())); ds_registry.insert(new (alloc) Rom_dataspace_info(ds_cap()));
return ds_cap(); return ds_cap();
} }
void poke(addr_t dst_offset, void const *src, size_t len) void poke(Region_map &, addr_t dst_offset, char const *src, size_t len)
{ {
error("attempt to poke onto a ROM dataspace"); error("attempt to poke onto a ROM dataspace");
} }
@ -101,7 +103,7 @@ class Noux::Rom_session_component : public Rpc_object<Rom_session>
*/ */
Constructible<Rom_connection> _rom_from_parent; Constructible<Rom_connection> _rom_from_parent;
Dataspace_capability _init_ds_cap(Name const &name) Dataspace_capability _init_ds_cap(Env &env, Name const &name)
{ {
if (name.string()[0] == '/') { if (name.string()[0] == '/') {
_rom_from_vfs.construct(_root_dir, name); _rom_from_vfs.construct(_root_dir, name);
@ -111,7 +113,7 @@ class Noux::Rom_session_component : public Rpc_object<Rom_session>
if (name == forked_magic_binary_name()) if (name == forked_magic_binary_name())
return Dataspace_capability(); return Dataspace_capability();
_rom_from_parent.construct(name.string()); _rom_from_parent.construct(env, name.string());
Dataspace_capability ds = _rom_from_parent->dataspace(); Dataspace_capability ds = _rom_from_parent->dataspace();
return ds; return ds;
} }
@ -120,14 +122,15 @@ class Noux::Rom_session_component : public Rpc_object<Rom_session>
public: public:
Rom_session_component(Rpc_entrypoint &ep, Vfs::Dir_file_system &root_dir, Rom_session_component(Allocator &alloc, Env &env, Rpc_entrypoint &ep,
Vfs::Dir_file_system &root_dir,
Dataspace_registry &ds_registry, Name const &name) Dataspace_registry &ds_registry, Name const &name)
: :
_ep(ep), _root_dir(root_dir), _ds_registry(ds_registry), _ep(ep), _root_dir(root_dir), _ds_registry(ds_registry),
_ds_cap(_init_ds_cap(name)) _ds_cap(_init_ds_cap(env, name))
{ {
_ep.manage(this); _ep.manage(this);
_ds_registry.insert(new (env()->heap()) Rom_dataspace_info(_ds_cap)); _ds_registry.insert(new (alloc) Rom_dataspace_info(_ds_cap));
} }
~Rom_session_component() ~Rom_session_component()

View File

@ -23,11 +23,14 @@
#include <noux_session/sysio.h> #include <noux_session/sysio.h>
namespace Noux { namespace Noux {
class Reference_counter;
class Shared_pointer_base; class Shared_pointer_base;
template <typename T> class Shared_pointer;
}
class Reference_counter
{ class Noux::Reference_counter
{
private: private:
Lock _lock; Lock _lock;
@ -53,11 +56,11 @@ namespace Noux {
public: public:
Reference_counter() : _value(0) { } Reference_counter() : _value(0) { }
}; };
class Shared_pointer_base class Noux::Shared_pointer_base
{ {
protected: protected:
Reference_counter *_ref_counter; Reference_counter *_ref_counter;
@ -72,12 +75,12 @@ namespace Noux {
return _ref_counter && (_ref_counter->_dec_ref_count() == 0); } return _ref_counter && (_ref_counter->_dec_ref_count() == 0); }
long count() const { return _ref_counter ? _ref_counter->_value : -99; } long count() const { return _ref_counter ? _ref_counter->_value : -99; }
}; };
template <typename T> template <typename T>
class Shared_pointer : public Shared_pointer_base class Noux::Shared_pointer : public Shared_pointer_base
{ {
private: private:
T *_ptr; T *_ptr;
@ -98,8 +101,8 @@ namespace Noux {
Shared_pointer() : Shared_pointer_base(0), _ptr(0), _alloc(0) { } Shared_pointer() : Shared_pointer_base(0), _ptr(0), _alloc(0) { }
Shared_pointer(T *ptr, Allocator *alloc) Shared_pointer(T *ptr, Allocator &alloc)
: Shared_pointer_base(ptr), _ptr(ptr), _alloc(alloc) : Shared_pointer_base(ptr), _ptr(ptr), _alloc(&alloc)
{ {
_inc_ref_count(); _inc_ref_count();
} }
@ -151,7 +154,6 @@ namespace Noux {
{ {
return Shared_pointer<To>(dynamic_cast<To *>(_ptr), _alloc); return Shared_pointer<To>(dynamic_cast<To *>(_ptr), _alloc);
} }
}; };
}
#endif /* _NOUX__SHARED_POINTER_H_ */ #endif /* _NOUX__SHARED_POINTER_H_ */

View File

@ -1,111 +0,0 @@
/*
* \brief Stdio filesystem
* \author Josef Soentgen
* \date 2012-08-02
*/
/*
* Copyright (C) 2012-2013 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 _NOUX__STDIO_FILE_SYSTEM_H_
#define _NOUX__STDIO_FILE_SYSTEM_H_
/* Genode includes */
#include <base/log.h>
#include <util/string.h>
#include <vfs/single_file_system.h>
/* Noux includes */
#include <noux_session/sysio.h>
#include "terminal_connection.h"
namespace Noux {
class Stdio_file_system : public Vfs::Single_file_system
{
private:
Terminal::Session_client *_terminal;
bool _echo;
public:
Stdio_file_system(Genode::Env&, Genode::Allocator&,
Genode::Xml_node config)
:
Single_file_system(NODE_TYPE_CHAR_DEVICE, name(), config),
_terminal(terminal()),
_echo(true)
{ }
static char const *name() { return "stdio"; }
/********************************
** File I/O service interface **
********************************/
Write_result write(Vfs::Vfs_handle *, char const *buf,
Vfs::file_size buf_size,
Vfs::file_size &out_count) override
{
buf_size = buf_size > 0xFFFFFFFFULL ? ~0UL : buf_size;
out_count = _terminal->write(buf, buf_size);
return WRITE_OK;
}
Read_result read(Vfs::Vfs_handle *, char *dst,
Vfs::file_size count,
Vfs::file_size &out_count) override
{
count = count > 0xFFFFFFFFULL ? ~0UL : count;
out_count = _terminal->read(dst, count);
if (_echo)
_terminal->write(dst, count);
return READ_OK;
}
Ftruncate_result ftruncate(Vfs::Vfs_handle *,
Vfs::file_size) override
{
return FTRUNCATE_OK;
}
Ioctl_result ioctl(Vfs::Vfs_handle *vfs_handle, Ioctl_opcode opcode,
Ioctl_arg arg, Ioctl_out &out) override
{
switch (opcode) {
case Vfs::File_io_service::IOCTL_OP_TIOCSETAF:
{
_echo = (arg & (Vfs::File_io_service::IOCTL_VAL_ECHO));
return IOCTL_OK;
}
case Vfs::File_io_service::IOCTL_OP_TIOCSETAW:
{
warning(__func__, ": OP_TIOCSETAW not implemented");
return IOCTL_ERR_INVALID;
}
default:
warning(__func__, ": invalid ioctl(request=", Hex(opcode), ")");
break;
}
return IOCTL_ERR_INVALID;
}
};
}
#endif /* _NOUX__STDIO_FILE_SYSTEM_H_ */

View File

@ -0,0 +1,798 @@
/*
* \brief Noux syscall dispatcher
* \author Norman Feske
* \date 2011-02-14
*/
/*
* Copyright (C) 2011-2013 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.
*/
/* Noux includes */
#include <child.h>
#include <child_env.h>
#include <vfs_io_channel.h>
#include <pipe_io_channel.h>
namespace Noux {
/**
* This function is used to generate inode values from the given
* path using the FNV-1a algorithm.
*/
inline uint32_t hash_path(const char *path, size_t len)
{
const unsigned char * p = reinterpret_cast<const unsigned char*>(path);
uint32_t hash = 2166136261U;
for (size_t i = 0; i < len; i++) {
hash ^= p[i];
hash *= 16777619;
}
return hash;
}
};
bool Noux::Child::syscall(Noux::Session::Syscall sc)
{
if (_verbose.syscalls())
log("PID ", pid(), " -> SYSCALL ", Noux::Session::syscall_name(sc));
bool result = false;
try {
switch (sc) {
case SYSCALL_WRITE:
{
size_t const count_in = _sysio.write_in.count;
for (size_t offset = 0; offset != count_in; ) {
Shared_pointer<Io_channel> io = _lookup_channel(_sysio.write_in.fd);
if (!io->nonblocking())
_block_for_io_channel(io, false, true, false);
if (io->check_unblock(false, true, false)) {
/*
* 'io->write' is expected to update
* '_sysio.write_out.count' and 'offset'
*/
result = io->write(_sysio, offset);
if (result == false)
break;
} else {
if (result == false) {
/* nothing was written yet */
_sysio.error.write = Vfs::File_io_service::WRITE_ERR_INTERRUPT;
}
break;
}
}
break;
}
case SYSCALL_READ:
{
Shared_pointer<Io_channel> io = _lookup_channel(_sysio.read_in.fd);
if (!io->nonblocking())
_block_for_io_channel(io, true, false, false);
if (io->check_unblock(true, false, false))
result = io->read(_sysio);
else
_sysio.error.read = Vfs::File_io_service::READ_ERR_INTERRUPT;
break;
}
case SYSCALL_FTRUNCATE:
{
Shared_pointer<Io_channel> io = _lookup_channel(_sysio.ftruncate_in.fd);
_block_for_io_channel(io, false, true, false);
if (io->check_unblock(false, true, false))
result = io->ftruncate(_sysio);
else
_sysio.error.ftruncate = Vfs::File_io_service::FTRUNCATE_ERR_INTERRUPT;
break;
}
case SYSCALL_STAT:
case SYSCALL_LSTAT: /* XXX implement difference between 'lstat' and 'stat' */
{
/**
* We calculate the inode by hashing the path because there is
* no inode registry in noux.
*/
size_t path_len = strlen(_sysio.stat_in.path);
uint32_t path_hash = hash_path(_sysio.stat_in.path, path_len);
Vfs::Directory_service::Stat stat_out;
_sysio.error.stat = _root_dir.stat(_sysio.stat_in.path, stat_out);
result = (_sysio.error.stat == Vfs::Directory_service::STAT_OK);
/*
* Instead of using the uid/gid given by the actual file system
* we use the ones specificed in the config.
*/
if (result) {
stat_out.uid = _user_info.uid();
stat_out.gid = _user_info.gid();
stat_out.inode = path_hash;
}
_sysio.stat_out.st = stat_out;
break;
}
case SYSCALL_FSTAT:
{
Shared_pointer<Io_channel> io = _lookup_channel(_sysio.fstat_in.fd);
result = io->fstat(_sysio);
if (result) {
Sysio::Path path;
/**
* Only actual fd's are valid fstat targets.
*/
if (io->path(path, sizeof (path))) {
size_t path_len = strlen(path);
uint32_t path_hash = hash_path(path, path_len);
_sysio.stat_out.st.inode = path_hash;
}
}
break;
}
case SYSCALL_FCNTL:
if (_sysio.fcntl_in.cmd == Sysio::FCNTL_CMD_SET_FD_FLAGS) {
/* we assume that there is only the close-on-execve flag */
_lookup_channel(_sysio.fcntl_in.fd)->close_on_execve =
!!_sysio.fcntl_in.long_arg;
result = true;
break;
}
result = _lookup_channel(_sysio.fcntl_in.fd)->fcntl(_sysio);
break;
case SYSCALL_OPEN:
{
Vfs::Vfs_handle *vfs_handle = 0;
_sysio.error.open = _root_dir.open(_sysio.open_in.path,
_sysio.open_in.mode,
&vfs_handle, _heap);
if (!vfs_handle)
break;
char const *leaf_path = _root_dir.leaf_path(_sysio.open_in.path);
/*
* File descriptors of opened directories are handled by
* '_root_dir'. In this case, we use the absolute path as leaf
* path because path operations always refer to the global
* root.
*/
if (&vfs_handle->ds() == &_root_dir)
leaf_path = _sysio.open_in.path;
Shared_pointer<Io_channel>
channel(new (_heap) Vfs_io_channel(_sysio.open_in.path,
leaf_path, &_root_dir,
vfs_handle, _env.ep()),
_heap);
_sysio.open_out.fd = add_io_channel(channel);
result = true;
break;
}
case SYSCALL_CLOSE:
{
remove_io_channel(_sysio.close_in.fd);
result = true;
break;
}
case SYSCALL_IOCTL:
result = _lookup_channel(_sysio.ioctl_in.fd)->ioctl(_sysio);
break;
case SYSCALL_LSEEK:
result = _lookup_channel(_sysio.lseek_in.fd)->lseek(_sysio);
break;
case SYSCALL_DIRENT:
result = _lookup_channel(_sysio.dirent_in.fd)->dirent(_sysio);
break;
case SYSCALL_EXECVE:
{
/*
* We have to check the dataspace twice because the binary
* could be a script that uses an interpreter which maybe
* does not exist.
*/
Dataspace_capability binary_ds =
_root_dir.dataspace(_sysio.execve_in.filename);
if (!binary_ds.valid()) {
_sysio.error.execve = Sysio::EXECVE_NONEXISTENT;
break;
}
Child_env<sizeof(_sysio.execve_in.args)>
child_env(_env.rm(),
_sysio.execve_in.filename, binary_ds,
_sysio.execve_in.args, _sysio.execve_in.env);
_root_dir.release(_sysio.execve_in.filename, binary_ds);
binary_ds = _root_dir.dataspace(child_env.binary_name());
if (!binary_ds.valid()) {
_sysio.error.execve = Sysio::EXECVE_NONEXISTENT;
break;
}
_root_dir.release(child_env.binary_name(), binary_ds);
try {
_parent_execve.execve_child(*this,
child_env.binary_name(),
child_env.args(),
child_env.env());
/*
* 'return' instead of 'break' to skip possible signal delivery,
* which might cause the old child process to exit itself
*/
return true;
}
catch (Child::Binary_does_not_exist) {
_sysio.error.execve = Sysio::EXECVE_NONEXISTENT; }
catch (Child::Insufficient_memory) {
_sysio.error.execve = Sysio::EXECVE_NOMEM; }
break;
}
case SYSCALL_SELECT:
{
size_t in_fds_total = _sysio.select_in.fds.total_fds();
Sysio::Select_fds in_fds;
for (Genode::size_t i = 0; i < in_fds_total; i++)
in_fds.array[i] = _sysio.select_in.fds.array[i];
in_fds.num_rd = _sysio.select_in.fds.num_rd;
in_fds.num_wr = _sysio.select_in.fds.num_wr;
in_fds.num_ex = _sysio.select_in.fds.num_ex;
int _rd_array[in_fds_total];
int _wr_array[in_fds_total];
long timeout_sec = _sysio.select_in.timeout.sec;
long timeout_usec = _sysio.select_in.timeout.usec;
bool timeout_reached = false;
/* reset the blocker lock to the 'locked' state */
_blocker.unlock();
_blocker.lock();
/*
* Register ourself at all watched I/O channels
*
* We instantiate as many notifiers as we have file
* descriptors to observe. Each notifier is associated
* with the child's blocking semaphore. When any of the
* notifiers get woken up, the semaphore gets unblocked.
*
* XXX However, the blocker may get unblocked for other
* conditions such as the destruction of the child.
* ...to be done.
*/
Wake_up_notifier notifiers[in_fds_total];
for (Genode::size_t i = 0; i < in_fds_total; i++) {
int fd = in_fds.array[i];
if (!fd_in_use(fd)) continue;
Shared_pointer<Io_channel> io = io_channel_by_fd(fd);
notifiers[i].lock = &_blocker;
io->register_wake_up_notifier(&notifiers[i]);
}
/**
* Register ourself at the Io_receptor_registry
*
* Each entry in the registry will be unblocked if an external
* event has happend, e.g. network I/O.
*/
Io_receptor receptor(&_blocker);
io_receptor_registry()->register_receptor(&receptor);
/*
* Block for one action of the watched file descriptors
*/
for (;;) {
/*
* Check I/O channels of specified file descriptors for
* unblock condition. Return if one I/O channel satisfies
* the condition.
*/
size_t unblock_rd = 0;
size_t unblock_wr = 0;
size_t unblock_ex = 0;
/* process read fds */
for (Genode::size_t i = 0; i < in_fds_total; i++) {
int fd = in_fds.array[i];
if (!fd_in_use(fd)) continue;
Shared_pointer<Io_channel> io = io_channel_by_fd(fd);
if (in_fds.watch_for_rd(i))
if (io->check_unblock(true, false, false)) {
_rd_array[unblock_rd++] = fd;
}
if (in_fds.watch_for_wr(i))
if (io->check_unblock(false, true, false)) {
_wr_array[unblock_wr++] = fd;
}
if (in_fds.watch_for_ex(i))
if (io->check_unblock(false, false, true)) {
unblock_ex++;
}
}
if (unblock_rd || unblock_wr || unblock_ex) {
/**
* Merge the fd arrays in one output array
*/
for (size_t i = 0; i < unblock_rd; i++) {
_sysio.select_out.fds.array[i] = _rd_array[i];
}
_sysio.select_out.fds.num_rd = unblock_rd;
/* XXX could use a pointer to select_out.fds.array instead */
for (size_t j = unblock_rd, i = 0; i < unblock_wr; i++, j++) {
_sysio.select_out.fds.array[j] = _wr_array[i];
}
_sysio.select_out.fds.num_wr = unblock_wr;
/* exception fds are currently not considered */
_sysio.select_out.fds.num_ex = unblock_ex;
result = true;
break;
}
/*
* Return if timeout is zero or timeout exceeded
*/
if (_sysio.select_in.timeout.zero() || timeout_reached) {
/*
if (timeout_reached) log("timeout_reached");
else log("timeout.zero()");
*/
_sysio.select_out.fds.num_rd = 0;
_sysio.select_out.fds.num_wr = 0;
_sysio.select_out.fds.num_ex = 0;
result = true;
break;
}
/*
* Return if signals are pending
*/
if (!_pending_signals.empty()) {
_sysio.error.select = Sysio::SELECT_ERR_INTERRUPT;
break;
}
/*
* Block at barrier except when reaching the timeout
*/
if (!_sysio.select_in.timeout.infinite()) {
unsigned long to_msec = (timeout_sec * 1000) + (timeout_usec / 1000);
Timeout_state ts;
Timeout_alarm ta(ts, _blocker, _timeout_scheduler, to_msec);
/* block until timeout is reached or we were unblocked */
_blocker.lock();
if (ts.timed_out) {
timeout_reached = 1;
}
else {
/*
* We woke up before reaching the timeout,
* so we discard the alarm
*/
ta.discard();
}
}
else {
/* let's block infinitely */
_blocker.lock();
}
}
/*
* Unregister barrier at watched I/O channels
*/
for (Genode::size_t i = 0; i < in_fds_total; i++) {
int fd = in_fds.array[i];
if (!fd_in_use(fd)) continue;
Shared_pointer<Io_channel> io = io_channel_by_fd(fd);
io->unregister_wake_up_notifier(&notifiers[i]);
}
/*
* Unregister receptor
*/
io_receptor_registry()->unregister_receptor(&receptor);
break;
}
case SYSCALL_FORK:
{
Genode::addr_t ip = _sysio.fork_in.ip;
Genode::addr_t sp = _sysio.fork_in.sp;
Genode::addr_t parent_cap_addr = _sysio.fork_in.parent_cap_addr;
int const new_pid = _pid_allocator.alloc();
Child * child = nullptr;
try {
/*
* XXX To ease debugging, it would be useful to generate a
* unique name that includes the PID instead of just
* reusing the name of the parent.
*/
child = new (_heap) Child(_child_policy.name(),
_verbose,
_user_info,
this,
_kill_broadcaster,
_timeout_scheduler,
*this,
_pid_allocator,
new_pid,
_env,
_root_dir,
_args,
_sysio_env.env(),
_heap,
_ref_ram, _ref_ram_cap,
_parent_services,
true,
_destruct_queue);
} catch (Child::Insufficient_memory) {
_sysio.error.fork = Sysio::FORK_NOMEM;
break;
}
Family_member::insert(child);
_assign_io_channels_to(child);
/* copy our address space into the new child */
try {
_pd.replay(child->ram(), child->pd(), _env.rm(), _heap,
child->ds_registry(), _ep);
/* start executing the main thread of the new process */
child->start_forked_main_thread(ip, sp, parent_cap_addr);
/* activate child entrypoint, thereby starting the new process */
child->start();
_sysio.fork_out.pid = new_pid;
result = true;
}
catch (Region_map::Region_conflict) {
error("region conflict while replaying the address space"); }
break;
}
case SYSCALL_GETPID:
{
_sysio.getpid_out.pid = pid();
return true;
}
case SYSCALL_WAIT4:
{
Family_member *exited = _sysio.wait4_in.nohang ? poll4() : wait4();
if (exited) {
_sysio.wait4_out.pid = exited->pid();
_sysio.wait4_out.status = exited->exit_status();
Family_member::remove(exited);
static_cast<Child *>(exited)->submit_exit_signal();
} else {
if (_sysio.wait4_in.nohang) {
_sysio.wait4_out.pid = 0;
_sysio.wait4_out.status = 0;
} else {
_sysio.error.wait4 = Sysio::WAIT4_ERR_INTERRUPT;
break;
}
}
result = true;
break;
}
case SYSCALL_PIPE:
{
Shared_pointer<Pipe> pipe (new (_heap) Pipe, _heap);
Shared_pointer<Io_channel> pipe_sink (new (_heap) Pipe_sink_io_channel (pipe, _env.ep()), _heap);
Shared_pointer<Io_channel> pipe_source(new (_heap) Pipe_source_io_channel(pipe, _env.ep()), _heap);
_sysio.pipe_out.fd[0] = add_io_channel(pipe_source);
_sysio.pipe_out.fd[1] = add_io_channel(pipe_sink);
result = true;
break;
}
case SYSCALL_DUP2:
{
int fd = add_io_channel(io_channel_by_fd(_sysio.dup2_in.fd),
_sysio.dup2_in.to_fd);
_sysio.dup2_out.fd = fd;
result = true;
break;
}
case SYSCALL_UNLINK:
_sysio.error.unlink = _root_dir.unlink(_sysio.unlink_in.path);
result = (_sysio.error.unlink == Vfs::Directory_service::UNLINK_OK);
break;
case SYSCALL_READLINK:
{
Vfs::file_size out_count = 0;
_sysio.error.readlink =
_root_dir.readlink(_sysio.readlink_in.path,
_sysio.readlink_out.chunk,
min(_sysio.readlink_in.bufsiz,
sizeof(_sysio.readlink_out.chunk)),
out_count);
_sysio.readlink_out.count = out_count;
result = (_sysio.error.readlink == Vfs::Directory_service::READLINK_OK);
break;
}
case SYSCALL_RENAME:
_sysio.error.rename = _root_dir.rename(_sysio.rename_in.from_path,
_sysio.rename_in.to_path);
result = (_sysio.error.rename == Vfs::Directory_service::RENAME_OK);
break;
case SYSCALL_MKDIR:
_sysio.error.mkdir = _root_dir.mkdir(_sysio.mkdir_in.path, 0);
result = (_sysio.error.mkdir == Vfs::Directory_service::MKDIR_OK);
break;
case SYSCALL_SYMLINK:
_sysio.error.symlink = _root_dir.symlink(_sysio.symlink_in.oldpath,
_sysio.symlink_in.newpath);
result = (_sysio.error.symlink == Vfs::Directory_service::SYMLINK_OK);
break;
case SYSCALL_USERINFO:
{
if (_sysio.userinfo_in.request == Sysio::USERINFO_GET_UID
|| _sysio.userinfo_in.request == Sysio::USERINFO_GET_GID) {
_sysio.userinfo_out.uid = _user_info.uid();
_sysio.userinfo_out.gid = _user_info.gid();
result = true;
break;
}
/*
* Since NOUX supports exactly one user, return false if we
* got a unknown uid.
*/
if (_sysio.userinfo_in.uid != _user_info.uid())
break;
Genode::memcpy(_sysio.userinfo_out.name,
_user_info.name().string(),
sizeof(User_info::Name));
Genode::memcpy(_sysio.userinfo_out.shell,
_user_info.shell().string(),
sizeof(User_info::Shell));
Genode::memcpy(_sysio.userinfo_out.home,
_user_info.home().string(),
sizeof(User_info::Home));
_sysio.userinfo_out.uid = _user_info.uid();
_sysio.userinfo_out.gid = _user_info.gid();
result = true;
break;
}
case SYSCALL_GETTIMEOFDAY:
{
/**
* Since the timeout_scheduler thread is started after noux it
* basicly returns the eleapsed time since noux was started. We
* abuse this timer to provide a more useful implemenation of
* gettimeofday() to make certain programs (e.g. ping(1)) happy.
* Note: this is just a short-term solution because Genode currently
* lacks a proper time interface (there is a RTC driver however, but
* there is no interface for it).
*/
unsigned long time = _timeout_scheduler.curr_time();
_sysio.gettimeofday_out.sec = (time / 1000);
_sysio.gettimeofday_out.usec = (time % 1000) * 1000;
result = true;
break;
}
case SYSCALL_CLOCK_GETTIME:
{
/**
* It's the same procedure as in SYSCALL_GETTIMEOFDAY.
*/
unsigned long time = _timeout_scheduler.curr_time();
switch (_sysio.clock_gettime_in.clock_id) {
/* CLOCK_SECOND is used by time(3) in the libc. */
case Sysio::CLOCK_ID_SECOND:
{
_sysio.clock_gettime_out.sec = (time / 1000);
_sysio.clock_gettime_out.nsec = 0;
result = true;
break;
}
default:
{
_sysio.clock_gettime_out.sec = 0;
_sysio.clock_gettime_out.nsec = 0;
_sysio.error.clock = Sysio::CLOCK_ERR_INVALID;
break;
}
}
break;
}
case SYSCALL_UTIMES:
{
/**
* This systemcall is currently not implemented because we lack
* the needed mechanisms in most file-systems.
*
* But we return true anyway to keep certain programs, e.g. make
* happy.
*/
result = true;
break;
}
case SYSCALL_SYNC:
{
_root_dir.sync("/");
result = true;
break;
}
case SYSCALL_KILL:
{
if (_kill_broadcaster.kill(_sysio.kill_in.pid,
_sysio.kill_in.sig))
result = true;
else
_sysio.error.kill = Sysio::KILL_ERR_SRCH;
break;
}
case SYSCALL_GETDTABLESIZE:
{
_sysio.getdtablesize_out.n =
Noux::File_descriptor_registry::MAX_FILE_DESCRIPTORS;
result = true;
break;
}
case SYSCALL_SOCKET:
case SYSCALL_GETSOCKOPT:
case SYSCALL_SETSOCKOPT:
case SYSCALL_ACCEPT:
case SYSCALL_BIND:
case SYSCALL_LISTEN:
case SYSCALL_SEND:
case SYSCALL_SENDTO:
case SYSCALL_RECV:
case SYSCALL_RECVFROM:
case SYSCALL_GETPEERNAME:
case SYSCALL_SHUTDOWN:
case SYSCALL_CONNECT:
result = _syscall_net(sc);
break;
case SYSCALL_INVALID: break;
}
}
catch (Invalid_fd) {
_sysio.error.general = Vfs::Directory_service::ERR_FD_INVALID;
error("invalid file descriptor"); }
catch (...) { error("unexpected exception"); }
/* handle signals which might have occured */
while (!_pending_signals.empty() &&
(_sysio.pending_signals.avail_capacity() > 0)) {
_sysio.pending_signals.add(_pending_signals.get());
}
return result;
}

View File

@ -1,30 +0,0 @@
/*
* \brief Terminal connection
* \author Josef Soentgen
* \date 2012-08-02
*/
/*
* Copyright (C) 2012-2013 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 _NOUX__TERMINAL_CONNECTION_H_
#define _NOUX__TERMINAL_CONNECTION_H_
/* Genode includes */
#include <base/printf.h>
#include <base/lock.h>
#include <terminal_session/connection.h>
#include <util/string.h>
/* Noux includes */
#include <noux_session/sysio.h>
#include <vfs/file_system.h>
namespace Noux { Terminal::Connection *terminal(); }
#endif /* _NOUX__TERMINAL_CONNECTION_H_ */

View File

@ -24,21 +24,27 @@
#include <io_channel.h> #include <io_channel.h>
#include <noux_session/sysio.h> #include <noux_session/sysio.h>
namespace Noux { namespace Noux { struct Terminal_io_channel; }
struct Terminal_io_channel : Io_channel, Signal_dispatcher_base
{ struct Noux::Terminal_io_channel : Io_channel
Terminal::Session &terminal; {
Signal_receiver &sig_rec; Terminal::Session &_terminal;
bool eof;
Signal_handler<Terminal_io_channel> _read_avail_handler;
bool eof = false;
enum Type { STDIN, STDOUT, STDERR } type; enum Type { STDIN, STDOUT, STDERR } type;
Ring_buffer<char, Sysio::CHUNK_SIZE + 1> read_buffer; Ring_buffer<char, Sysio::CHUNK_SIZE + 1> read_buffer;
Terminal_io_channel(Terminal::Session &terminal, Type type, Terminal_io_channel(Terminal::Session &terminal, Type type,
Signal_receiver &sig_rec) Entrypoint &ep)
: terminal(terminal), sig_rec(sig_rec), eof(false), type(type) :
_terminal(terminal),
_read_avail_handler(ep, *this, &Terminal_io_channel::_handle_read_avail),
type(type)
{ {
/* /*
* Enable wake up STDIN channel on the presence of new input * Enable wake up STDIN channel on the presence of new input
@ -52,30 +58,24 @@ namespace Noux {
* blocking system calls such as 'select'. * blocking system calls such as 'select'.
*/ */
if (type == STDIN) { if (type == STDIN) {
terminal.read_avail_sigh(sig_rec.manage(this)); terminal.read_avail_sigh(_read_avail_handler);
} }
} }
~Terminal_io_channel() bool write(Sysio &sysio, size_t &offset) override
{ {
try { sig_rec.dissolve(this); } size_t const count = min(sysio.write_in.count,
catch (Genode::Signal_receiver::Context_not_associated) { } sizeof(sysio.write_in.chunk));
}
bool write(Sysio *sysio, size_t &offset) override _terminal.write(sysio.write_in.chunk, count);
{
size_t const count = min(sysio->write_in.count,
sizeof(sysio->write_in.chunk));
terminal.write(sysio->write_in.chunk, count); sysio.write_out.count = count;
sysio->write_out.count = count;
offset = count; offset = count;
return true; return true;
} }
bool read(Sysio *sysio) override bool read(Sysio &sysio) override
{ {
if (type != STDIN) { if (type != STDIN) {
error("attempt to read from terminal output channel"); error("attempt to read from terminal output channel");
@ -84,18 +84,18 @@ namespace Noux {
/* deliver EOF observed by the previous 'read' call */ /* deliver EOF observed by the previous 'read' call */
if (eof) { if (eof) {
sysio->read_out.count = 0; sysio.read_out.count = 0;
eof = false; eof = false;
return true; return true;
} }
size_t const max_count = size_t const max_count =
min(sysio->read_in.count, min(sysio.read_in.count,
sizeof(sysio->read_out.chunk)); sizeof(sysio.read_out.chunk));
for (sysio->read_out.count = 0; for (sysio.read_out.count = 0;
(sysio->read_out.count < max_count) && !read_buffer.empty(); (sysio.read_out.count < max_count) && !read_buffer.empty();
sysio->read_out.count++) { sysio.read_out.count++) {
char c = read_buffer.get(); char c = read_buffer.get();
@ -112,19 +112,19 @@ namespace Noux {
* 'read' call. This condition is tracked by the 'eof' * 'read' call. This condition is tracked by the 'eof'
* variable. * variable.
*/ */
if (sysio->read_out.count > 0) if (sysio.read_out.count > 0)
eof = true; eof = true;
return true; return true;
} }
sysio->read_out.chunk[sysio->read_out.count] = c; sysio.read_out.chunk[sysio.read_out.count] = c;
} }
return true; return true;
} }
bool fcntl(Sysio *sysio) override bool fcntl(Sysio &sysio) override
{ {
/** /**
* Actually it is "inappropiate" to use fcntl() directly on terminals * Actually it is "inappropiate" to use fcntl() directly on terminals
@ -133,10 +133,10 @@ namespace Noux {
* *
* Some GNU programms check if stdout is open by calling fcntl(stdout, F_GETFL, ...). * Some GNU programms check if stdout is open by calling fcntl(stdout, F_GETFL, ...).
*/ */
switch (sysio->fcntl_in.cmd) { switch (sysio.fcntl_in.cmd) {
case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS:
sysio->fcntl_out.result = 0; sysio.fcntl_out.result = 0;
return true; return true;
default: default:
@ -146,14 +146,14 @@ namespace Noux {
return false; return false;
} }
bool fstat(Sysio *sysio) override bool fstat(Sysio &sysio) override
{ {
/* /*
* Supply stat values such that libc is happy. I.e., the libc * Supply stat values such that libc is happy. I.e., the libc
* is checking for the file descriptor 1 being a character * is checking for the file descriptor 1 being a character
* device. * device.
*/ */
sysio->fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV; sysio.fstat_out.st.mode = Sysio::STAT_MODE_CHARDEV;
return true; return true;
} }
@ -169,15 +169,15 @@ namespace Noux {
return (rd && (type == STDIN) && !read_buffer.empty()); return (rd && (type == STDIN) && !read_buffer.empty());
} }
bool ioctl(Sysio *sysio) override bool ioctl(Sysio &sysio) override
{ {
switch (sysio->ioctl_in.request) { switch (sysio.ioctl_in.request) {
case Vfs::File_io_service::IOCTL_OP_TIOCGWINSZ: case Vfs::File_io_service::IOCTL_OP_TIOCGWINSZ:
{ {
Terminal::Session::Size size = terminal.size(); Terminal::Session::Size size = _terminal.size();
sysio->ioctl_out.tiocgwinsz.rows = size.lines(); sysio.ioctl_out.tiocgwinsz.rows = size.lines();
sysio->ioctl_out.tiocgwinsz.columns = size.columns(); sysio.ioctl_out.tiocgwinsz.columns = size.columns();
return true; return true;
} }
@ -195,26 +195,18 @@ namespace Noux {
default: default:
warning("invalid ioctl request ", (int)sysio->ioctl_in.request); warning("invalid ioctl request ", (int)sysio.ioctl_in.request);
return false; return false;
}; };
} }
void _handle_read_avail()
/**************************************
** Signal_dispatcher_base interface **
**************************************/
/**
* Called by Noux main loop on the occurrence of new STDIN input
*/
void dispatch(unsigned) override
{ {
while ((read_buffer.avail_capacity() > 0) && while ((read_buffer.avail_capacity() > 0) &&
terminal.avail()) { _terminal.avail()) {
char c; char c;
terminal.read(&c, 1); _terminal.read(&c, 1);
enum { INTERRUPT = 3 }; enum { INTERRUPT = 3 };
@ -227,7 +219,6 @@ namespace Noux {
Io_channel::invoke_all_notifiers(); Io_channel::invoke_all_notifiers();
} }
}; };
}
#endif /* _NOUX__TERMINAL_IO_CHANNEL_H_ */ #endif /* _NOUX__TERMINAL_IO_CHANNEL_H_ */

View File

@ -0,0 +1,102 @@
/*
* \brief Timeout mechanism for 'select'
* \author Norman Feske
* \date 2011-02-14
*/
/*
* Copyright (C) 2011-2013 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 _NOUX__TIMEOUT_SCHEDULER_H_
#define _NOUX__TIMEOUT_SCHEDULER_H_
#include <timer_session/connection.h>
#include <os/alarm.h>
namespace Noux {
class Timeout_scheduler;
class Timeout_state;
class Timeout_alarm;
using namespace Genode;
}
class Noux::Timeout_scheduler : public Alarm_scheduler
{
private:
Timer::Connection _timer;
Alarm::Time _curr_time { 0 };
enum { TIMER_GRANULARITY_MSEC = 10 };
Signal_handler<Timeout_scheduler> _timer_handler;
void _handle_timer()
{
_curr_time = _timer.elapsed_ms();
Alarm_scheduler::handle(_curr_time);
}
public:
Timeout_scheduler(Env &env)
:
_timer(env),
_timer_handler(env.ep(), *this, &Timeout_scheduler::_handle_timer)
{
_timer.sigh(_timer_handler);
_timer.trigger_periodic(TIMER_GRANULARITY_MSEC*1000);
}
Alarm::Time curr_time() const { return _curr_time; }
};
struct Noux::Timeout_state
{
bool timed_out;
Timeout_state() : timed_out(false) { }
};
class Noux::Timeout_alarm : public Alarm
{
private:
Timeout_state &_state;
Lock &_blocker;
Timeout_scheduler &_scheduler;
public:
Timeout_alarm(Timeout_state &st, Lock &blocker,
Timeout_scheduler &scheduler, Time timeout)
:
_state(st),
_blocker(blocker),
_scheduler(scheduler)
{
_scheduler.schedule_absolute(this, _scheduler.curr_time() + timeout);
_state.timed_out = false;
}
void discard() { _scheduler.discard(this); }
protected:
bool on_alarm(unsigned) override
{
_state.timed_out = true;
_blocker.unlock();
return false;
}
};
#endif /* _NOUX__TIMEOUT_SCHEDULER_H_ */

View File

@ -1,6 +1,7 @@
/* /*
* \brief User information * \brief User information
* \author Josef Soentgen * \author Josef Soentgen
* \author Norman Feske
* \date 2012-07-23 * \date 2012-07-23
*/ */
@ -22,49 +23,54 @@
#include <noux_session/sysio.h> #include <noux_session/sysio.h>
namespace Noux { namespace Noux {
class User_info;
using namespace Genode; using namespace Genode;
}
struct User_info {
class Noux::User_info : Noncopyable
{
public:
typedef String<Sysio::MAX_USERNAME_LEN> Name;
typedef String<Sysio::MAX_SHELL_LEN> Shell;
typedef String<Sysio::MAX_HOME_LEN> Home;
private:
unsigned const _uid;
unsigned const _gid;
Name const _name;
Shell const _shell;
Home const _home;
template <typename S>
S _sub_node_name(Xml_node node, char const *sub_node, S const &default_name)
{
if (!node.has_sub_node(sub_node))
return default_name;
return node.sub_node(sub_node).attribute_value("name", default_name);
}
public: public:
char name[Sysio::MAX_USERNAME_LEN]; User_info(Xml_node node)
char shell[Sysio::MAX_SHELL_LEN]; :
char home[Sysio::MAX_HOME_LEN]; _uid (node.attribute_value("uid", 0UL)),
_gid (node.attribute_value("gid", 0UL)),
_name(node.attribute_value("name", Name("root"))),
_shell(_sub_node_name(node, "shell", Shell("/bin/bash"))),
_home (_sub_node_name(node, "home", Home("name")))
{ }
unsigned int uid; unsigned uid() const { return _uid; }
unsigned int gid; unsigned gid() const { return _gid; }
User_info() : uid(0), gid(0) Name name() const { return _name; }
{ Shell shell() const { return _shell; }
strncpy(name, "root", sizeof(name)); Home home() const { return _home; }
strncpy(home, "/", sizeof(home)); };
strncpy(shell, "/bin/bash", sizeof(shell));
}
void set_info(Genode::Xml_node user_info_node)
{
try {
user_info_node.attribute("name").value(name, sizeof(name));
user_info_node.attribute("uid").value(&uid);
user_info_node.attribute("gid").value(&gid);
for (unsigned i = 0; i < user_info_node.num_sub_nodes(); i++) {
Xml_node sub_node = user_info_node.sub_node(i);
if (sub_node.has_type("shell")) {
sub_node.attribute("name").value(shell, sizeof(shell));
}
if (sub_node.has_type("home")) {
sub_node.attribute("name").value(home, sizeof(home));
}
}
}
catch (...) { }
}
};
}
#endif /* _NOUX__USER_INFO_H_ */ #endif /* _NOUX__USER_INFO_H_ */

View File

@ -0,0 +1,48 @@
/*
* \brief Noux verbosity
* \author Norman Feske
* \date 2017-01-17
*/
/*
* Copyright (C) 2017 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 _NOUX__VERBOSE_H_
#define _NOUX__VERBOSE_H_
#include <util/noncopyable.h>
#include <util/xml_node.h>
namespace Noux { struct Verbose; }
class Noux::Verbose : Genode::Noncopyable
{
private:
bool const _enabled;
bool const _ld;
bool const _syscalls;
bool const _quota;
public:
Verbose(Genode::Xml_node config)
:
_enabled (config.attribute_value("verbose", false)),
_ld (config.attribute_value("ld_verbose", false)),
_syscalls(config.attribute_value("verbose_syscalls", false)),
_quota (config.attribute_value("verbose_quota", false))
{ }
bool enabled() const { return _enabled; }
bool ld() const { return _ld; }
bool syscalls() const { return _syscalls; }
bool quota() const { return _quota; }
};
#endif /* _NOUX__VERBOSE_H_ */

View File

@ -18,106 +18,112 @@
#include <io_channel.h> #include <io_channel.h>
#include <vfs/dir_file_system.h> #include <vfs/dir_file_system.h>
namespace Noux { namespace Noux { struct Vfs_io_channel; }
struct Vfs_io_channel : Io_channel, Signal_dispatcher_base
struct Noux::Vfs_io_channel : Io_channel
{
Signal_handler<Vfs_io_channel> _read_avail_handler;
void _handle_read_avail()
{ {
Io_channel::invoke_all_notifiers();
}
Vfs::Vfs_handle *_fh; Vfs::Vfs_handle *_fh;
Absolute_path _path; Absolute_path _path;
Absolute_path _leaf_path; Absolute_path _leaf_path;
Signal_receiver &_sig_rec;
Vfs_io_channel(char const *path, char const *leaf_path, Vfs_io_channel(char const *path, char const *leaf_path,
Vfs::Dir_file_system *root_dir, Vfs::Vfs_handle *vfs_handle, Vfs::Dir_file_system *root_dir, Vfs::Vfs_handle *vfs_handle,
Signal_receiver &sig_rec) Entrypoint &ep)
: _fh(vfs_handle), _path(path), _leaf_path(leaf_path), :
_sig_rec(sig_rec) _read_avail_handler(ep, *this, &Vfs_io_channel::_handle_read_avail),
_fh(vfs_handle), _path(path), _leaf_path(leaf_path)
{ {
_fh->fs().register_read_ready_sigh(_fh, _sig_rec.manage(this)); _fh->fs().register_read_ready_sigh(_fh, _read_avail_handler);
} }
~Vfs_io_channel() ~Vfs_io_channel()
{ {
_sig_rec.dissolve(this);
_fh->ds().close(_fh); _fh->ds().close(_fh);
} }
bool write(Sysio *sysio, size_t &offset) override bool write(Sysio &sysio, size_t &offset) override
{ {
Vfs::file_size out_count = 0; Vfs::file_size out_count = 0;
sysio->error.write = _fh->fs().write(_fh, sysio->write_in.chunk, sysio.error.write = _fh->fs().write(_fh, sysio.write_in.chunk,
sysio->write_in.count, out_count); sysio.write_in.count, out_count);
if (sysio->error.write != Vfs::File_io_service::WRITE_OK) if (sysio.error.write != Vfs::File_io_service::WRITE_OK)
return false; return false;
_fh->advance_seek(out_count); _fh->advance_seek(out_count);
sysio->write_out.count = out_count; sysio.write_out.count = out_count;
offset = out_count; offset = out_count;
return true; return true;
} }
bool read(Sysio *sysio) override bool read(Sysio &sysio) override
{ {
size_t count = min(sysio->read_in.count, sizeof(sysio->read_out.chunk)); size_t count = min(sysio.read_in.count, sizeof(sysio.read_out.chunk));
Vfs::file_size out_count = 0; Vfs::file_size out_count = 0;
sysio->error.read = _fh->fs().read(_fh, sysio->read_out.chunk, count, out_count); sysio.error.read = _fh->fs().read(_fh, sysio.read_out.chunk, count, out_count);
if (sysio->error.read != Vfs::File_io_service::READ_OK) if (sysio.error.read != Vfs::File_io_service::READ_OK)
return false; return false;
sysio->read_out.count = out_count; sysio.read_out.count = out_count;
_fh->advance_seek(out_count); _fh->advance_seek(out_count);
return true; return true;
} }
bool fstat(Sysio *sysio) override bool fstat(Sysio &sysio) override
{ {
/* /*
* 'sysio.stat_in' is not used in '_fh->ds().stat()', * 'sysio.stat_in' is not used in '_fh->ds().stat()',
* so no 'sysio' member translation is needed here * so no 'sysio' member translation is needed here
*/ */
Vfs::Directory_service::Stat stat; Vfs::Directory_service::Stat stat;
sysio->error.stat = _fh->ds().stat(_leaf_path.base(), stat); sysio.error.stat = _fh->ds().stat(_leaf_path.base(), stat);
sysio->fstat_out.st = stat; sysio.fstat_out.st = stat;
return (sysio->error.stat == Vfs::Directory_service::STAT_OK); return (sysio.error.stat == Vfs::Directory_service::STAT_OK);
} }
bool ftruncate(Sysio *sysio) override bool ftruncate(Sysio &sysio) override
{ {
sysio->error.ftruncate = _fh->fs().ftruncate(_fh, sysio->ftruncate_in.length); sysio.error.ftruncate = _fh->fs().ftruncate(_fh, sysio.ftruncate_in.length);
return (sysio->error.ftruncate == Vfs::File_io_service::FTRUNCATE_OK); return (sysio.error.ftruncate == Vfs::File_io_service::FTRUNCATE_OK);
} }
bool fcntl(Sysio *sysio) override bool fcntl(Sysio &sysio) override
{ {
switch (sysio->fcntl_in.cmd) { switch (sysio.fcntl_in.cmd) {
case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS:
sysio->fcntl_out.result = _fh->status_flags(); sysio.fcntl_out.result = _fh->status_flags();
return true; return true;
case Sysio::FCNTL_CMD_SET_FILE_STATUS_FLAGS: case Sysio::FCNTL_CMD_SET_FILE_STATUS_FLAGS:
_fh->status_flags(sysio->fcntl_in.long_arg); _fh->status_flags(sysio.fcntl_in.long_arg);
return true; return true;
default: default:
PWRN("invalid fcntl command %d", sysio->fcntl_in.cmd); PWRN("invalid fcntl command %d", sysio.fcntl_in.cmd);
sysio->error.fcntl = Sysio::FCNTL_ERR_CMD_INVALID; sysio.error.fcntl = Sysio::FCNTL_ERR_CMD_INVALID;
return false; return false;
}; };
} }
@ -128,19 +134,19 @@ namespace Noux {
* to directories). Hence, '_path' is the absolute path of the * to directories). Hence, '_path' is the absolute path of the
* directory to inspect. * directory to inspect.
*/ */
bool dirent(Sysio *sysio) override bool dirent(Sysio &sysio) override
{ {
/* /*
* Return artificial dir entries for "." and ".." * Return artificial dir entries for "." and ".."
*/ */
unsigned const index = _fh->seek() / sizeof(Sysio::Dirent); unsigned const index = _fh->seek() / sizeof(Sysio::Dirent);
if (index < 2) { if (index < 2) {
sysio->dirent_out.entry.type = Vfs::Directory_service::DIRENT_TYPE_DIRECTORY; sysio.dirent_out.entry.type = Vfs::Directory_service::DIRENT_TYPE_DIRECTORY;
strncpy(sysio->dirent_out.entry.name, strncpy(sysio.dirent_out.entry.name,
index ? ".." : ".", index ? ".." : ".",
sizeof(sysio->dirent_out.entry.name)); sizeof(sysio.dirent_out.entry.name));
sysio->dirent_out.entry.fileno = 1; sysio.dirent_out.entry.fileno = 1;
_fh->advance_seek(sizeof(Sysio::Dirent)); _fh->advance_seek(sizeof(Sysio::Dirent));
return true; return true;
} }
@ -153,7 +159,7 @@ namespace Noux {
Vfs::Directory_service::Dirent dirent; Vfs::Directory_service::Dirent dirent;
if (!_fh->ds().dirent(_path.base(), index - 2, dirent)) if (!_fh->ds().dirent(_path.base(), index - 2, dirent))
return false; return false;
sysio->dirent_out.entry = dirent; sysio.dirent_out.entry = dirent;
_fh->advance_seek(sizeof(Sysio::Dirent)); _fh->advance_seek(sizeof(Sysio::Dirent));
return true; return true;
@ -166,35 +172,35 @@ namespace Noux {
* call it prior saving all input arguments from the original sysio * call it prior saving all input arguments from the original sysio
* structure. * structure.
*/ */
size_t size(Sysio *sysio) size_t size(Sysio &sysio)
{ {
if (fstat(sysio)) if (fstat(sysio))
return sysio->fstat_out.st.size; return sysio.fstat_out.st.size;
return 0; return 0;
} }
bool ioctl(Sysio *sysio) override bool ioctl(Sysio &sysio) override
{ {
Vfs::File_system::Ioctl_arg arg = (Vfs::File_system::Ioctl_arg)sysio->ioctl_in.argp; Vfs::File_system::Ioctl_arg arg = (Vfs::File_system::Ioctl_arg)sysio.ioctl_in.argp;
sysio->error.ioctl = _fh->fs().ioctl(_fh, sysio->ioctl_in.request, arg, sysio->ioctl_out); sysio.error.ioctl = _fh->fs().ioctl(_fh, sysio.ioctl_in.request, arg, sysio.ioctl_out);
return (sysio->error.ioctl == Vfs::File_io_service::IOCTL_OK); return (sysio.error.ioctl == Vfs::File_io_service::IOCTL_OK);
} }
bool lseek(Sysio *sysio) override bool lseek(Sysio &sysio) override
{ {
switch (sysio->lseek_in.whence) { switch (sysio.lseek_in.whence) {
case Sysio::LSEEK_SET: _fh->seek(sysio->lseek_in.offset); break; case Sysio::LSEEK_SET: _fh->seek(sysio.lseek_in.offset); break;
case Sysio::LSEEK_CUR: _fh->advance_seek(sysio->lseek_in.offset); break; case Sysio::LSEEK_CUR: _fh->advance_seek(sysio.lseek_in.offset); break;
case Sysio::LSEEK_END: case Sysio::LSEEK_END:
off_t offset = sysio->lseek_in.offset; off_t offset = sysio.lseek_in.offset;
sysio->fstat_in.fd = sysio->lseek_in.fd; sysio.fstat_in.fd = sysio.lseek_in.fd;
_fh->seek(size(sysio) + offset); _fh->seek(size(sysio) + offset);
break; break;
} }
sysio->lseek_out.offset = _fh->seek(); sysio.lseek_out.offset = _fh->seek();
return true; return true;
} }
@ -210,20 +216,6 @@ namespace Noux {
return true; return true;
} }
};
/**************************************
** Signal_dispatcher_base interface **
**************************************/
/**
* Called by Noux main loop on the occurrence of new input
*/
void dispatch(unsigned) override
{
Io_channel::invoke_all_notifiers();
}
};
}
#endif /* _NOUX__VFS_IO_CHANNEL_H_ */ #endif /* _NOUX__VFS_IO_CHANNEL_H_ */

View File

@ -18,21 +18,16 @@
#include <util/list.h> #include <util/list.h>
#include <base/lock.h> #include <base/lock.h>
namespace Noux { namespace Noux { struct Wake_up_notifier; }
struct Wake_up_notifier : List<Wake_up_notifier>::Element
{ struct Noux::Wake_up_notifier : List<Wake_up_notifier>::Element
{
Lock *lock; Lock *lock;
Wake_up_notifier(Lock *lock = 0) Wake_up_notifier(Lock *lock = nullptr) : lock(lock) { }
: lock(lock) { }
void wake_up() void wake_up() { if (lock) lock->unlock(); }
{
if (lock)
lock->unlock();
}
};
}; };
#endif /* _NOUX__WAKE_UP_NOTIFIER__H_ */ #endif /* _NOUX__WAKE_UP_NOTIFIER__H_ */