mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-03 04:26:45 +00:00
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:
parent
f957fcdd98
commit
82e6d7cf52
@ -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
|
||||||
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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 ®istry)
|
Rpc_entrypoint &ep,
|
||||||
: _ep(ep), _forked(forked), _cpu(label.string()), _registry(registry)
|
Child_policy::Name const &label,
|
||||||
{ _ep.manage(this); }
|
bool forked,
|
||||||
|
Dataspace_registry ®istry)
|
||||||
|
:
|
||||||
|
_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_ */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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_ */
|
|
@ -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_ */
|
||||||
|
@ -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_ */
|
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
|
||||||
|
@ -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_ */
|
||||||
|
@ -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 ®istry)
|
Dataspace_registry ®istry)
|
||||||
:
|
:
|
||||||
_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
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_ */
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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_ */
|
||||||
|
@ -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();
|
||||||
|
@ -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_ */
|
||||||
|
@ -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 ®istry)
|
Ram_session_component(Ram_session &ram, Allocator &alloc,
|
||||||
: _ep(ep), _used_quota(0), _registry(registry) { _ep.manage(this); }
|
Rpc_entrypoint &ep, Dataspace_registry ®istry)
|
||||||
|
:
|
||||||
|
_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_ */
|
||||||
|
@ -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_ */
|
|
@ -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_ */
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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()
|
||||||
|
@ -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_ */
|
||||||
|
@ -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_ */
|
|
798
repos/ports/src/noux/syscall.cc
Normal file
798
repos/ports/src/noux/syscall.cc
Normal 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(¬ifiers[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(¬ifiers[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;
|
||||||
|
}
|
@ -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_ */
|
|
@ -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_ */
|
||||||
|
102
repos/ports/src/noux/timeout_scheduler.h
Normal file
102
repos/ports/src/noux/timeout_scheduler.h
Normal 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_ */
|
@ -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_ */
|
||||||
|
48
repos/ports/src/noux/verbose.h
Normal file
48
repos/ports/src/noux/verbose.h
Normal 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_ */
|
@ -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_ */
|
||||||
|
@ -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_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user