diff --git a/repos/ports/include/noux_session/capability.h b/repos/ports/include/noux_session/capability.h deleted file mode 100644 index 37afc81e7..000000000 --- a/repos/ports/include/noux_session/capability.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief Noux-session capability type - * \author Norman Feske - * \date 2011-02-15 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__NOUX_SESSION__CAPABILITY_H_ -#define _INCLUDE__NOUX_SESSION__CAPABILITY_H_ - -#include -#include - -namespace Noux { typedef Capability Session_capability; } - -#endif /* _INCLUDE__NOUX_SESSION__CAPABILITY_H_ */ diff --git a/repos/ports/include/noux_session/client.h b/repos/ports/include/noux_session/client.h deleted file mode 100644 index 5eb40faeb..000000000 --- a/repos/ports/include/noux_session/client.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * \brief Noux-session client interface - * \author Norman Feske - * \date 2011-02-15 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__NOUX_SESSION__CLIENT_H_ -#define _INCLUDE__NOUX_SESSION__CLIENT_H_ - -#include -#include -#include -#include - -namespace Noux { - - struct Session_client : Rpc_client - { - explicit Session_client(Session_capability session) - : Rpc_client(session) { } - - - Dataspace_capability sysio_dataspace() - { - return call(); - } - - bool syscall(Syscall sc) - { - static bool verbose = false; - - bool result = call(sc); - - if ((result == false) && verbose) - error("syscall ", syscall_name(sc), " failed"); - - return result; - } - - int next_open_fd(int start_fd) - { - return call(start_fd); - } - - Capability lookup_region_map(addr_t const addr) - { - return call(addr); - } - }; -} - -#endif /* _INCLUDE__NOUX_SESSION__CLIENT_H_ */ diff --git a/repos/ports/include/noux_session/connection.h b/repos/ports/include/noux_session/connection.h deleted file mode 100644 index d8b73a031..000000000 --- a/repos/ports/include/noux_session/connection.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * \brief Noux connection - * \author Norman Feske - * \date 2011-02-15 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__NOUX_SESSION__CONNECTION_H_ -#define _INCLUDE__NOUX_SESSION__CONNECTION_H_ - -#include -#include - -namespace Noux { struct Connection; } - - -struct Noux::Connection : Genode::Connection, Session_client -{ - /** - * Constructor - */ - Connection(Genode::Env &env) - : - Genode::Connection(env, session(env.parent(), "")), - Session_client(cap()) - { } - - /** - * Remove session ID of the noux session from the ID space. - * - * This must by done before reinitializing the noux connection in a - * freshly forked process. Otherwise, an overwritten 'Noux::Connection' - * object would still be referenced by the AVL tree of the the ID space. - */ - void discard_session_id() - { - _id_space_element.~Element(); - } -}; - -#endif /* _INCLUDE__NOUX_SESSION__CONNECTION_H_ */ diff --git a/repos/ports/include/noux_session/noux_session.h b/repos/ports/include/noux_session/noux_session.h deleted file mode 100644 index 2911333de..000000000 --- a/repos/ports/include/noux_session/noux_session.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * \brief Noux session interface - * \author Norman Feske - * \date 2011-02-15 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__NOUX_SESSION__NOUX_SESSION_H_ -#define _INCLUDE__NOUX_SESSION__NOUX_SESSION_H_ - -#include -#include -#include -#include - -#define NOUX_DECL_SYSCALL_NAME(name) \ - case SYSCALL_##name: return #name; - -namespace Noux { - - using namespace Genode; - - struct Session : Genode::Session - { - static const char *service_name() { return "Noux"; } - - enum { CAP_QUOTA = 3 }; - - virtual ~Session() { } - - virtual Dataspace_capability sysio_dataspace() = 0; - - /** - * Return leaf region map that covers a given address - * - * \param addr address that is covered by the requested region map - */ - virtual Capability lookup_region_map(addr_t const addr) = 0; - - enum Syscall { - SYSCALL_WRITE, - SYSCALL_READ, - SYSCALL_STAT, - SYSCALL_LSTAT, - SYSCALL_FSTAT, - SYSCALL_FTRUNCATE, - SYSCALL_FCNTL, - SYSCALL_OPEN, - SYSCALL_CLOSE, - SYSCALL_IOCTL, - SYSCALL_LSEEK, - SYSCALL_DIRENT, - SYSCALL_EXECVE, - SYSCALL_SELECT, - SYSCALL_FORK, - SYSCALL_GETPID, - SYSCALL_WAIT4, - SYSCALL_PIPE, - SYSCALL_DUP2, - SYSCALL_UNLINK, - SYSCALL_READLINK, - SYSCALL_RENAME, - SYSCALL_MKDIR, - SYSCALL_SYMLINK, - SYSCALL_SOCKET, - SYSCALL_GETSOCKOPT, - SYSCALL_SETSOCKOPT, - SYSCALL_ACCEPT, - SYSCALL_BIND, - SYSCALL_LISTEN, - SYSCALL_SEND, - SYSCALL_SENDTO, - SYSCALL_RECV, - SYSCALL_RECVFROM, - SYSCALL_GETPEERNAME, - SYSCALL_SHUTDOWN, - SYSCALL_CONNECT, - SYSCALL_USERINFO, - SYSCALL_GETTIMEOFDAY, - SYSCALL_CLOCK_GETTIME, - SYSCALL_UTIMES, - SYSCALL_SYNC, - SYSCALL_KILL, - SYSCALL_GETDTABLESIZE, - SYSCALL_INVALID = -1 - }; - - static char const *syscall_name(Syscall sc) - { - switch (sc) { - NOUX_DECL_SYSCALL_NAME(WRITE) - NOUX_DECL_SYSCALL_NAME(READ) - NOUX_DECL_SYSCALL_NAME(STAT) - NOUX_DECL_SYSCALL_NAME(LSTAT) - NOUX_DECL_SYSCALL_NAME(FSTAT) - NOUX_DECL_SYSCALL_NAME(FTRUNCATE) - NOUX_DECL_SYSCALL_NAME(FCNTL) - NOUX_DECL_SYSCALL_NAME(OPEN) - NOUX_DECL_SYSCALL_NAME(CLOSE) - NOUX_DECL_SYSCALL_NAME(IOCTL) - NOUX_DECL_SYSCALL_NAME(LSEEK) - NOUX_DECL_SYSCALL_NAME(DIRENT) - NOUX_DECL_SYSCALL_NAME(EXECVE) - NOUX_DECL_SYSCALL_NAME(SELECT) - NOUX_DECL_SYSCALL_NAME(FORK) - NOUX_DECL_SYSCALL_NAME(GETPID) - NOUX_DECL_SYSCALL_NAME(WAIT4) - NOUX_DECL_SYSCALL_NAME(PIPE) - NOUX_DECL_SYSCALL_NAME(DUP2) - NOUX_DECL_SYSCALL_NAME(UNLINK) - NOUX_DECL_SYSCALL_NAME(READLINK) - NOUX_DECL_SYSCALL_NAME(RENAME) - NOUX_DECL_SYSCALL_NAME(MKDIR) - NOUX_DECL_SYSCALL_NAME(SYMLINK) - NOUX_DECL_SYSCALL_NAME(SOCKET) - NOUX_DECL_SYSCALL_NAME(GETSOCKOPT) - NOUX_DECL_SYSCALL_NAME(SETSOCKOPT) - NOUX_DECL_SYSCALL_NAME(ACCEPT) - NOUX_DECL_SYSCALL_NAME(BIND) - NOUX_DECL_SYSCALL_NAME(LISTEN) - NOUX_DECL_SYSCALL_NAME(SEND) - NOUX_DECL_SYSCALL_NAME(SENDTO) - NOUX_DECL_SYSCALL_NAME(RECV) - NOUX_DECL_SYSCALL_NAME(RECVFROM) - NOUX_DECL_SYSCALL_NAME(GETPEERNAME) - NOUX_DECL_SYSCALL_NAME(SHUTDOWN) - NOUX_DECL_SYSCALL_NAME(CONNECT) - NOUX_DECL_SYSCALL_NAME(USERINFO) - NOUX_DECL_SYSCALL_NAME(GETTIMEOFDAY) - NOUX_DECL_SYSCALL_NAME(CLOCK_GETTIME) - NOUX_DECL_SYSCALL_NAME(UTIMES) - NOUX_DECL_SYSCALL_NAME(SYNC) - NOUX_DECL_SYSCALL_NAME(KILL) - NOUX_DECL_SYSCALL_NAME(GETDTABLESIZE) - case SYSCALL_INVALID: return 0; - } - return 0; - } - - /** - * Perform syscall - * - * The syscall arguments and results are communicated via the shared - * sysio dataspace. - * - * \return true on success - */ - virtual bool syscall(Syscall syscall) = 0; - - /* - * Return the next open file descriptor, starting from (and including) - * 'start_fd'. - * - * \return the next open file descriptor or -1 - */ - virtual int next_open_fd(int start_fd) = 0; - - /********************* - ** RPC declaration ** - *********************/ - - GENODE_RPC(Rpc_sysio_dataspace, Dataspace_capability, sysio_dataspace); - GENODE_RPC(Rpc_lookup_region_map, Capability, - lookup_region_map, addr_t); - GENODE_RPC(Rpc_syscall, bool, syscall, Syscall); - GENODE_RPC(Rpc_next_open_fd, int, next_open_fd, int); - - GENODE_RPC_INTERFACE(Rpc_sysio_dataspace, Rpc_lookup_region_map, - Rpc_syscall, Rpc_next_open_fd); - }; -} - -#undef NOUX_DECL_SYSCALL_NAME - -#endif /* _INCLUDE__NOUX_SESSION__NOUX_SESSION_H_ */ - diff --git a/repos/ports/include/noux_session/sysio.h b/repos/ports/include/noux_session/sysio.h deleted file mode 100644 index 9ec3f8d54..000000000 --- a/repos/ports/include/noux_session/sysio.h +++ /dev/null @@ -1,495 +0,0 @@ -/* - * \brief Facility for passing system-call arguments - * \author Norman Feske - * \date 2011-02-15 - * - * The 'Sysio' data structure is shared between the noux environment - * and the child. It is used to pass system-call arguments that would - * traditionally be transferred via 'copy_from_user' and 'copy_to_user'. - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _INCLUDE__NOUX_SESSION__SYSIO_H_ -#define _INCLUDE__NOUX_SESSION__SYSIO_H_ - -/* Genode includes */ -#include -#include -#include - - -#define SYSIO_DECL(syscall_name, args, results) \ - struct args syscall_name##_in; \ - struct results syscall_name##_out; - - -namespace Noux { - using namespace Genode; - struct Sysio; -} - - -struct Noux::Sysio -{ - /* signal numbers must match with libc signal numbers */ - enum Signal { - SIG_INT = 2, - SIG_CHLD = 20, - SIG_WINCH = 28 - }; - - enum { SIGNAL_QUEUE_SIZE = 32 }; - Ring_buffer pending_signals; - - enum { MAX_PATH_LEN = 512 }; - typedef char Path[MAX_PATH_LEN]; - - enum { CHUNK_SIZE = 64*1024 }; - typedef char Chunk[CHUNK_SIZE]; - - enum { ARGS_MAX_LEN = 16*1024 }; - typedef char Args[ARGS_MAX_LEN]; - - enum { ENV_MAX_LEN = 6*1024 }; - typedef char Env[ENV_MAX_LEN]; - - typedef __SIZE_TYPE__ size_t; - typedef long int ssize_t; - - /** - * Flags of 'mode' argument of open syscall - */ - enum { - OPEN_MODE_RDONLY = 0, - OPEN_MODE_WRONLY = 1, - OPEN_MODE_RDWR = 2, - OPEN_MODE_ACCMODE = 3, - OPEN_MODE_CREATE = 0x0800, /* libc O_EXCL */ - }; - - typedef Vfs::Directory_service::Stat Stat; - - /** - * Argument structure used for ioctl syscall - */ - struct Ioctl_in - { - typedef Vfs::File_io_service::Ioctl_opcode Opcode; - - typedef Vfs::File_io_service::Ioctl_value Value; - - Opcode request; - int argp; - }; - - /** - * Structure carrying the result values of 'ioctl' syscalls - */ - typedef Vfs::File_io_service::Ioctl_out Ioctl_out; - - enum Lseek_whence { LSEEK_SET, LSEEK_CUR, LSEEK_END }; - - enum { DIRENT_MAX_NAME_LEN = Vfs::Directory_service::Dirent::Name::MAX_LEN }; - - typedef Vfs::Directory_service::Dirent_type Dirent_type; - - /* - * Must be POD (in contrast to the VFS type) because it's used in a union - */ - struct Dirent - { - unsigned long fileno; - Dirent_type type; - char name[DIRENT_MAX_NAME_LEN]; - - Dirent & operator= (Vfs::Directory_service::Dirent const &dirent) - { - fileno = dirent.fileno; - type = dirent.type; - memcpy(name, dirent.name.buf, DIRENT_MAX_NAME_LEN); - - return *this; - } - }; - - enum Fcntl_cmd { - FCNTL_CMD_GET_FILE_STATUS_FLAGS, - FCNTL_CMD_SET_FILE_STATUS_FLAGS, - FCNTL_CMD_SET_FD_FLAGS, - FCNTL_CMD_GET_FD_FLAGS - }; - - enum { - FCNTL_FILE_STATUS_FLAG_NONBLOCK = 4 - }; - - /** - * Input and output argument type of select syscall - */ - struct Select_fds - { - /** - * Maximum number of file descriptors supported - */ - enum { MAX_FDS = 32U }; - - /** - * Number of file descriptors to watch for read operations (rd), - * write operations (wr), or exceptions (ex). - */ - size_t num_rd, - num_wr, - num_ex; - - /** - * Array containing the file descriptors, starting with those - * referring to rd, followed by wr, and finally ex - */ - int array[MAX_FDS]; - - /** - * Return total number of file descriptors contained in the array - */ - size_t total_fds() const { - return min(num_rd + num_wr + num_ex, (size_t)MAX_FDS); } - - /** - * Check for maximum population of fds array - */ - bool max_fds_exceeded() const - { - /* - * Note that even though the corner case of num_rd + num_wr + - * num_ex == MAX_FDS is technically valid, this condition hints - * at a possible attempt to over popupate the array (see the - * implementation of 'select' in the Noux libc plugin). Hence, - * we regard this case as an error, too. - */ - return total_fds() >= MAX_FDS; - } - - /** - * Return true of fd set index should be watched for reading - */ - bool watch_for_rd(unsigned i) const { return i < num_rd; } - - /** - * Return true if fd set index should be watched for writing - */ - bool watch_for_wr(unsigned i) const { - return (i >= num_rd) && (i < num_rd + num_wr); } - - /** - * Return true if fd set index should be watched for exceptions - */ - bool watch_for_ex(unsigned i) const { - return (i >= num_rd + num_wr) && (i < total_fds()); } - }; - - struct Select_timeout - { - long sec, usec; - - /** - * Set timeout to infinity - */ - void set_infinite() { sec = -1; usec = -1; } - - /** - * Return true if the timeout is infinite - */ - bool infinite() const { return (sec == -1) && (usec == -1); } - - /** - * Return true if the timeout is zero - */ - bool zero() const { return (sec == 0) && (usec == 0); } - }; - - /** - * Socket related structures - */ - enum { MAX_HOSTNAME_LEN = 255 }; - typedef char Hostname[MAX_HOSTNAME_LEN]; - - enum { MAX_SERVNAME_LEN = 255 }; - typedef char Servname[MAX_SERVNAME_LEN]; - - enum { MAX_ADDRINFO_RESULTS = 4 }; - - struct in_addr - { - unsigned int s_addr; - }; - - struct sockaddr - { - unsigned char sa_len; - unsigned char sa_family; - char sa_data[14]; - }; - - struct sockaddr_in { - unsigned char sin_len; - unsigned char sin_family; - unsigned short sin_port; - struct in_addr sin_addr; - char sin_zero[8]; - }; - - typedef unsigned socklen_t; - - struct addrinfo { - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - socklen_t ai_addrlen; - struct sockaddr *ai_addr; - char *ai_canonname; - struct addrinfo *ai_next; - }; - - struct Addrinfo { - struct addrinfo addrinfo; - struct sockaddr ai_addr; - char ai_canonname[255]; - }; - - /** - * user info defintions - */ - enum { USERINFO_GET_ALL = 0, USERINFO_GET_UID, USERINFO_GET_GID }; - enum { MAX_USERNAME_LEN = 32 }; - typedef char User[MAX_USERNAME_LEN]; - enum { MAX_SHELL_LEN = 16 }; - typedef char Shell[MAX_SHELL_LEN]; - enum { MAX_HOME_LEN = 128 }; - typedef char Home[MAX_HOME_LEN]; - typedef unsigned int Uid; - - /** - * time/clock definitions - */ - enum Clock_Id { CLOCK_ID_SECOND }; - - enum Fcntl_error { FCNTL_ERR_CMD_INVALID = Vfs::Directory_service::NUM_GENERAL_ERRORS }; - enum Mkdir_error { MKDIR_ERR_EXISTS, MKDIR_ERR_NO_ENTRY, - MKDIR_ERR_NO_SPACE, MKDIR_ERR_NO_PERM, - MKDIR_ERR_NAME_TOO_LONG }; - enum Readlink_error { READLINK_ERR_NO_ENTRY, READLINK_ERR_NO_PERM }; - enum Symlink_error { SYMLINK_ERR_EXISTS, SYMLINK_ERR_NO_ENTRY, - SYMLINK_ERR_NO_SPACE, SYMLINK_ERR_NO_PERM, - SYMLINK_ERR_NAME_TOO_LONG }; - - enum Execve_error { EXECVE_ERR_NO_ENTRY = Vfs::Directory_service::NUM_GENERAL_ERRORS, - EXECVE_ERR_NO_MEMORY, - EXECVE_ERR_NO_EXEC, - EXECVE_ERR_ACCESS}; - enum Fork_error { FORK_NOMEM = Vfs::Directory_service::NUM_GENERAL_ERRORS }; - enum Select_error { SELECT_ERR_INTERRUPT }; - - /** - * Socket related errors - */ - enum Accept_error { ACCEPT_ERR_AGAIN, ACCEPT_ERR_WOULD_BLOCK, - ACCEPT_ERR_INVALID, ACCEPT_ERR_NO_MEMORY, - ACCEPT_ERR_NOT_SUPPORTED }; - - enum Bind_error { BIND_ERR_ACCESS, BIND_ERR_ADDR_IN_USE, - BIND_ERR_INVALID, BIND_ERR_NO_MEMORY }; - - enum Connect_error { CONNECT_ERR_ACCESS, CONNECT_ERR_AGAIN, - CONNECT_ERR_ALREADY, CONNECT_ERR_CONN_REFUSED, - CONNECT_ERR_NO_PERM, CONNECT_ERR_ADDR_IN_USE, - CONNECT_ERR_IN_PROGRESS, CONNECT_ERR_IS_CONNECTED, - CONNECT_ERR_RESET, CONNECT_ERR_ABORTED, - CONNECT_ERR_NO_ROUTE }; - - enum Listen_error { LISTEN_ERR_ADDR_IN_USE, LISTEN_ERR_NOT_SUPPORTED }; - - enum Recv_error { RECV_ERR_AGAIN, RECV_ERR_WOULD_BLOCK, - RECV_ERR_CONN_REFUSED, RECV_ERR_INVALID, - RECV_ERR_NOT_CONNECTED, RECV_ERR_NO_MEMORY }; - - enum Send_error { SEND_ERR_AGAIN, SEND_ERR_WOULD_BLOCK, - SEND_ERR_CONNECTION_RESET, SEND_ERR_INVALID, - SEND_ERR_IS_CONNECTED, SEND_ERR_NO_MEMORY }; - - enum Shutdown_error { SHUTDOWN_ERR_NOT_CONNECTED }; - - enum Socket_error { SOCKET_ERR_ACCESS, SOCKET_ERR_NO_AF_SUPPORT, - SOCKET_ERR_INVALID, SOCKET_ERR_NO_MEMORY }; - - enum Clock_error { CLOCK_ERR_INVALID, CLOCK_ERR_FAULT, CLOCK_ERR_NO_PERM }; - - enum Utimes_error { UTIMES_ERR_ACCESS, UTIMES_ERR_FAUL, UTIMES_ERR_EIO, - UTIMES_ERR_NAME_TOO_LONG, UTIMES_ERR_NO_ENTRY, - UTIMES_ERR_NOT_DIRECTORY, UTIMES_ERR_NO_PERM, - UTIMES_ERR_READ_ONLY }; - - enum Wait4_error { WAIT4_ERR_INTERRUPT }; - - enum Kill_error { KILL_ERR_SRCH }; - - union { - Vfs::Directory_service::General_error general; - Vfs::Directory_service::Stat_result stat; - Vfs::File_io_service::Ftruncate_result ftruncate; - Vfs::Directory_service::Open_result open; - Vfs::Directory_service::Unlink_result unlink; - Vfs::Directory_service::Rename_result rename; - Vfs::File_io_service::Read_result read; - Vfs::File_io_service::Write_result write; - Vfs::File_io_service::Ioctl_result ioctl; - - Fcntl_error fcntl; - Mkdir_error mkdir; - Readlink_error readlink; - Symlink_error symlink; - Execve_error execve; - Select_error select; - Accept_error accept; - Bind_error bind; - Connect_error connect; - Listen_error listen; - Recv_error recv; - Send_error send; - Shutdown_error shutdown; - Socket_error socket; - Clock_error clock; - Utimes_error utimes; - Wait4_error wait4; - Kill_error kill; - Fork_error fork; - - } error; - - union { - - SYSIO_DECL(write, { int fd; size_t count; Chunk chunk; }, - { size_t count; }); - - SYSIO_DECL(stat, { Path path; }, { Stat st; }); - - SYSIO_DECL(symlink, { Path oldpath; Path newpath; }, { }); - - SYSIO_DECL(fstat, { int fd; }, { Stat st; }); - - SYSIO_DECL(ftruncate, { int fd; off_t length; }, { }); - - SYSIO_DECL(fcntl, { int fd; long long_arg; Fcntl_cmd cmd; }, - { int result; }); - - SYSIO_DECL(open, { Path path; int mode; }, { int fd; }); - - SYSIO_DECL(close, { int fd; }, { }); - - SYSIO_DECL(ioctl, : Ioctl_in { int fd; }, : Ioctl_out { }); - - SYSIO_DECL(lseek, { int fd; off_t offset; Lseek_whence whence; }, - { off_t offset; }); - - SYSIO_DECL(dirent, { int fd; }, { Dirent entry; }); - - SYSIO_DECL(read, { int fd; size_t count; }, - { Chunk chunk; size_t count; }); - - SYSIO_DECL(readlink, { Path path; size_t bufsiz; }, - { Chunk chunk; size_t count; }); - - SYSIO_DECL(execve, { Path filename; Args args; Env env; }, { }); - - SYSIO_DECL(select, { Select_fds fds; Select_timeout timeout; }, - { Select_fds fds; }); - - SYSIO_DECL(fork, { addr_t ip; addr_t sp; - addr_t parent_cap_addr; }, - { int pid; }); - - SYSIO_DECL(getpid, { }, { int pid; }); - - SYSIO_DECL(wait4, { int pid; bool nohang; }, - { int pid; int status; }); - SYSIO_DECL(pipe, { }, { int fd[2]; }); - - SYSIO_DECL(dup2, { int fd; int to_fd; }, { int fd; }); - - SYSIO_DECL(unlink, { Path path; }, { }); - - SYSIO_DECL(rename, { Path from_path; Path to_path; }, { }); - - SYSIO_DECL(mkdir, { Path path; int mode; }, { }); - - SYSIO_DECL(socket, { int domain; int type; int protocol; }, - { int fd; }); - - /* XXX for now abuse Chunk for passing optval */ - SYSIO_DECL(getsockopt, { int fd; int level; int optname; Chunk optval; - socklen_t optlen; }, { int result; }); - - SYSIO_DECL(setsockopt, { int fd; int level; - int optname; Chunk optval; - socklen_t optlen; }, { }); - - SYSIO_DECL(accept, { int fd; struct sockaddr addr; socklen_t addrlen; }, - { int fd; }); - - SYSIO_DECL(bind, { int fd; struct sockaddr addr; - socklen_t addrlen; }, { int result; }); - - SYSIO_DECL(getpeername, { int fd; struct sockaddr addr; - socklen_t addrlen; }, { }); - - SYSIO_DECL(listen, { int fd; int type; int backlog; }, - { int result; }); - - SYSIO_DECL(send, { int fd; Chunk buf; size_t len; int flags; }, - { ssize_t len; }); - - SYSIO_DECL(sendto, { int fd; Chunk buf; size_t len; int flags; - struct sockaddr dest_addr; socklen_t addrlen; }, - { ssize_t len; }); - - SYSIO_DECL(recv, { int fd; Chunk buf; size_t len; int flags; }, - { size_t len; }); - - SYSIO_DECL(recvfrom, { int fd; Chunk buf; size_t len; int flags; - struct sockaddr src_addr; socklen_t addrlen; }, - { size_t len; }); - - SYSIO_DECL(shutdown, { int fd; int how; }, { }); - - SYSIO_DECL(connect, { int fd; struct sockaddr addr; socklen_t addrlen; }, - { int result; }); - - SYSIO_DECL(userinfo, { int request; Uid uid; }, - { User name; Uid uid; Uid gid; Shell shell; - Home home; }); - - SYSIO_DECL(gettimeofday, { }, { unsigned long sec; unsigned int usec; }); - - SYSIO_DECL(clock_gettime, { Clock_Id clock_id; }, - { unsigned long sec; unsigned long nsec; }); - - SYSIO_DECL(utimes, { Path path; unsigned long sec; unsigned long usec; }, - { }); - - SYSIO_DECL(sync, { }, { }); - - SYSIO_DECL(kill, { int pid; Signal sig; }, { }); - - SYSIO_DECL(getdtablesize, { }, { int n; }); - }; -}; - -#undef SYSIO_DECL - -#endif /* _INCLUDE__NOUX_SESSION__SYSIO_H_ */ diff --git a/repos/ports/lib/mk/libc_noux.mk b/repos/ports/lib/mk/libc_noux.mk deleted file mode 100644 index 4f385ce5e..000000000 --- a/repos/ports/lib/mk/libc_noux.mk +++ /dev/null @@ -1,11 +0,0 @@ -SRC_CC = plugin.cc - -LIBS += libc - -REP_INC_DIR += src/lib/libc - -vpath %.cc $(REP_DIR)/src/lib/libc_noux - -SHARED_LIB = yes - -CC_CXX_WARN_STRICT = diff --git a/repos/ports/lib/symbols/libc_noux b/repos/ports/lib/symbols/libc_noux deleted file mode 100644 index 5ab5212c4..000000000 --- a/repos/ports/lib/symbols/libc_noux +++ /dev/null @@ -1,35 +0,0 @@ -_Z14init_libc_nouxv T -_Z15noux_connectionv T -_Z4nouxv T -_Z5sysiov T -_ZN4Libc10vfs_configEv T -_ZN4Libc6configEv T -_sigaction T -_sigprocmask T -_wait4 T -chmod T -clock_gettime T -endpwent T -fork T -fork_trampoline T -getdtablesize T -getegid T -geteuid T -getgid T -getpid T -getppid T -getpwuid T -getrlimit T -getrusage T -gettimeofday T -getuid T -kill T -nanosleep T -sbrk T -select T -sigaction T -sigprocmask T -sleep T -sync T -utimes T -vfork T diff --git a/repos/ports/recipes/api/noux/content.mk b/repos/ports/recipes/api/noux/content.mk index 30efcec87..4aab8870f 100644 --- a/repos/ports/recipes/api/noux/content.mk +++ b/repos/ports/recipes/api/noux/content.mk @@ -1,4 +1,4 @@ -MIRROR_FROM_REP_DIR := lib/symbols/libc_noux mk/noux.mk mk/gnu_build.mk +MIRROR_FROM_REP_DIR := mk/noux.mk mk/gnu_build.mk content:$(MIRROR_FROM_REP_DIR) LICENSE diff --git a/repos/ports/recipes/api/noux_session/content.mk b/repos/ports/recipes/api/noux_session/content.mk deleted file mode 100644 index 97581bfa9..000000000 --- a/repos/ports/recipes/api/noux_session/content.mk +++ /dev/null @@ -1,2 +0,0 @@ -MIRRORED_FROM_REP_DIR := include/noux_session -include $(GENODE_DIR)/repos/os/recipes/api/session.inc diff --git a/repos/ports/recipes/api/noux_session/hash b/repos/ports/recipes/api/noux_session/hash deleted file mode 100644 index b943ee6cc..000000000 --- a/repos/ports/recipes/api/noux_session/hash +++ /dev/null @@ -1 +0,0 @@ -2020-03-25 5b839717ad8acc5742ac2e7f78f2c50d3d77b1ca diff --git a/repos/ports/recipes/pkg/system_shell/archives b/repos/ports/recipes/pkg/system_shell/archives index f1f1e86fc..60d547d8f 100644 --- a/repos/ports/recipes/pkg/system_shell/archives +++ b/repos/ports/recipes/pkg/system_shell/archives @@ -1,5 +1,4 @@ _/raw/system_shell -_/src/noux _/src/bash-minimal _/src/vim-minimal _/src/coreutils-minimal diff --git a/repos/ports/recipes/src/noux/content.mk b/repos/ports/recipes/src/noux/content.mk deleted file mode 100644 index d710e432d..000000000 --- a/repos/ports/recipes/src/noux/content.mk +++ /dev/null @@ -1,31 +0,0 @@ -MIRROR_FROM_REP_DIR := src/noux src/lib/libc_noux lib/mk/libc_noux.mk - -content: $(MIRROR_FROM_REP_DIR) - -$(MIRROR_FROM_REP_DIR): - $(mirror_from_rep_dir) - -MIRROR_FROM_LIBPORTS := include/libc-plugin \ - src/lib/libc/internal/mem_alloc.h \ - src/lib/libc/internal/types.h \ - src/lib/libc/internal/legacy.h - -content: $(MIRROR_FROM_LIBPORTS) - -$(MIRROR_FROM_LIBPORTS): - mkdir -p $(dir $@) - cp -r $(GENODE_DIR)/repos/libports/$@ $@ - -MIRROR_FROM_OS := include/init/child_policy.h - -content: $(MIRROR_FROM_OS) - -$(MIRROR_FROM_OS): - mkdir -p $(dir $@) - cp -r $(GENODE_DIR)/repos/os/$@ $@ - -content: LICENSE - -LICENSE: - cp $(GENODE_DIR)/LICENSE $@ - diff --git a/repos/ports/recipes/src/noux/hash b/repos/ports/recipes/src/noux/hash deleted file mode 100644 index 93dd6ba7b..000000000 --- a/repos/ports/recipes/src/noux/hash +++ /dev/null @@ -1 +0,0 @@ -2020-03-25 d13b8d86250ac0f22c9ea71fc4cfce2759aeba18 diff --git a/repos/ports/recipes/src/noux/used_apis b/repos/ports/recipes/src/noux/used_apis deleted file mode 100644 index ddb9ebeff..000000000 --- a/repos/ports/recipes/src/noux/used_apis +++ /dev/null @@ -1,10 +0,0 @@ -base -os -vfs -libc -noux -noux_session -terminal_session -timer_session -posix -rtc_session diff --git a/repos/ports/src/lib/libc_noux/plugin.cc b/repos/ports/src/lib/libc_noux/plugin.cc deleted file mode 100644 index a2d6b7b60..000000000 --- a/repos/ports/src/lib/libc_noux/plugin.cc +++ /dev/null @@ -1,2434 +0,0 @@ -/* - * \brief Noux libc plugin - * \author Norman Feske - * \date 2011-02-14 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* noux includes */ -#include -#include - -/* libc plugin includes */ -#include -#include - -/* libc component includes */ -#include - -/* libc includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * There is a off_t typedef clash between sys/socket.h - * and base/stdint.h. We define the macro here to circumvent - * this issue. - */ -#undef DIOCGMEDIASIZE -#define DIOCGMEDIASIZE _IOR('d', 129, int64_t) - - -/* libc-internal includes */ -#include -#include - - -using Genode::log; -using Genode::error; -using Genode::warning; -using Genode::Hex; - - -enum { verbose = false }; -enum { verbose_signals = false }; - - -/* - * Customize libc VFS - */ -namespace Libc { - - /* - * Override the weak function interface of the libc and VFS plugin as Noux - * programs do not obtain such configuration via Genode's config mechanism. - */ - Genode::Xml_node config() { return Xml_node(""); } - Genode::Xml_node vfs_config() { return Xml_node(""); } - - /* - * Enhance main-thread stack - * - * This is done because we ran into a stack overflow while compiling - * Genodes core with GCC in Noux. - */ - enum { STACK_SIZE = 64UL * 1024 * sizeof(Genode::addr_t) }; - Genode::size_t Component::stack_size() { return STACK_SIZE; } -} - - - -class Noux_connection -{ - private: - - Genode::Env &_env; - - Noux::Connection _connection; - - Genode::Attached_dataspace _sysio_ds { _env.rm(), _connection.sysio_dataspace() }; - - public: - - Noux_connection(Genode::Env &env) : _env(env), _connection(env) { } - - /** - * Return the capability of the local stack-area region map - * - * \param ptr some address within the stack-area - */ - Genode::Capability stack_area_region_map(void * const ptr) - { - return _connection.lookup_region_map((Genode::addr_t)ptr); - } - - Noux::Session *session() { return &_connection; } - Noux::Sysio *sysio() { return _sysio_ds.local_addr(); } - - void reconnect() - { - using namespace Genode; - - /* - * Release Id_space::Element of the local ID space. - */ - _connection.discard_session_id(); - - /* - * Obtain new noux connection. Note that we cannot reconstruct - * the connection via a 'Reconstructible' because this would - * result in an inconsistent referernce count when attempting - * to destruct the session capability in the just-cleared - * capability space. - */ - construct_at(this, _env); - } -}; - - -/* - * Defined by Libc::Plugin::init - */ -static Genode::Env *_env_ptr = nullptr; - -Noux_connection *noux_connection() -{ - if (!_env_ptr) { - Genode::error("missing call of 'Libc::Plugin::init'"); - return nullptr; - } - - static Noux_connection inst(*_env_ptr); - return &inst; -} - - -Noux::Session *noux() { return noux_connection()->session(); } -Noux::Sysio *sysio() { return noux_connection()->sysio(); } - - -/* - * Array of signal handlers, initialized with 0 (SIG_DFL) - * TODO: preserve ignored signals across 'execve()' - */ -static struct sigaction signal_action[NSIG+1]; - -/* - * Signal mask functionality is not fully implemented yet. - * TODO: - actually block delivery of to be blocked signals - * - preserve signal mask across 'execve()' - */ -static sigset_t signal_mask; - - -static bool noux_syscall(Noux::Session::Syscall opcode) -{ - /* - * Signal handlers might do syscalls themselves, so the 'sysio' object - * needs to be saved before and restored after calling the signal handler. - * There is only one global 'saved_sysio' buffer as signals are not checked - * in nested calls of 'noux_syscall' from signal handlers. - */ - static Noux::Sysio saved_sysio; - - bool ret = noux()->syscall(opcode); - - static bool in_sigh = false; /* true if called from signal handler */ - - if (in_sigh) - return ret; - - /* handle signals */ - while (!sysio()->pending_signals.empty()) { - in_sigh = true; - Noux::Sysio::Signal signal = sysio()->pending_signals.get(); - if (verbose_signals) - log(__func__, ": received signal ", (int)signal); - if (signal_action[signal].sa_flags & SA_SIGINFO) { - memcpy(&saved_sysio, sysio(), sizeof(Noux::Sysio)); - /* TODO: pass siginfo_t struct */ - signal_action[signal].sa_sigaction(signal, 0, 0); - memcpy(sysio(), &saved_sysio, sizeof(Noux::Sysio)); - } else { - if (signal_action[signal].sa_handler == SIG_DFL) { - switch (signal) { - case SIGCHLD: - case SIGWINCH: - /* ignore */ - break; - default: - /* terminate the process */ - exit((signal << 8) | EXIT_FAILURE); - } - } else if (signal_action[signal].sa_handler == SIG_IGN) { - /* do nothing */ - } else { - memcpy(&saved_sysio, sysio(), sizeof(Noux::Sysio)); - signal_action[signal].sa_handler(signal); - memcpy(sysio(), &saved_sysio, sizeof(Noux::Sysio)); - } - } - } - in_sigh = false; - - return ret; -} - - -enum { FS_BLOCK_SIZE = 4096 }; - - -/*********************************************** - ** Overrides of libc default implementations ** - ***********************************************/ - -/** - * User information related functions - */ -extern "C" struct passwd *getpwuid(uid_t uid) -{ - static char name[Noux::Sysio::MAX_USERNAME_LEN]; - static char shell[Noux::Sysio::MAX_SHELL_LEN]; - static char home[Noux::Sysio::MAX_HOME_LEN]; - - static char *empty = strdup(""); - - static struct passwd pw = { - /* .pw_name = */ name, - /* .pw_passwd = */ empty, - /* .pw_uid = */ 0, - /* .pw_gid = */ 0, - /* .pw_change = */ 0, - /* .pw_class = */ empty, - /* .pw_gecos = */ empty, - /* .pw_dir = */ home, - /* .pw_shell = */ shell, - /* .pw_expire = */ 0, - /* .pw_fields = */ 0 - }; - - sysio()->userinfo_in.uid = uid; - sysio()->userinfo_in.request = Noux::Sysio::USERINFO_GET_ALL; - - if (!noux_syscall(Noux::Session::SYSCALL_USERINFO)) { - return (struct passwd *)0; - } - - /* SYSCALL_USERINFO assures that strings are always '\0' terminated */ - Genode::memcpy(name, sysio()->userinfo_out.name, sizeof (sysio()->userinfo_out.name)); - Genode::memcpy(home, sysio()->userinfo_out.home, sizeof (sysio()->userinfo_out.home)); - Genode::memcpy(shell, sysio()->userinfo_out.shell, sizeof (sysio()->userinfo_out.shell)); - - pw.pw_uid = sysio()->userinfo_out.uid; - pw.pw_gid = sysio()->userinfo_out.gid; - - return &pw; -} - - -extern "C" int getdtablesize() -{ - if (!noux_syscall(Noux::Session::SYSCALL_GETDTABLESIZE)) { - warning("getdtablesize syscall failed"); - errno = ENOSYS; - return -1; - } - - int n = sysio()->getdtablesize_out.n; - return n; -} - - -extern "C" uid_t getgid() -{ - sysio()->userinfo_in.request = Noux::Sysio::USERINFO_GET_GID; - - if (!noux_syscall(Noux::Session::SYSCALL_USERINFO)) - return 0; - - uid_t gid = sysio()->userinfo_out.gid; - return gid; -} - - -extern "C" uid_t getegid() -{ - return getgid(); -} - - -extern "C" uid_t getuid() -{ - sysio()->userinfo_in.request = Noux::Sysio::USERINFO_GET_UID; - - if (!noux_syscall(Noux::Session::SYSCALL_USERINFO)) - return 0; - - uid_t uid = sysio()->userinfo_out.uid; - - return uid; -} - - -extern "C" uid_t geteuid() -{ - return getuid(); -} - - -void *sbrk(intptr_t increment) -{ - if (verbose) - warning(__func__, " not implemented ", (long int)increment); - errno = ENOMEM; - return reinterpret_cast(-1); -} - - -extern "C" int getrlimit(int resource, struct rlimit *rlim) -{ - switch (resource) { - case RLIMIT_STACK: - { - using namespace Genode; - - Thread * me = Thread::myself(); - - if (!me) - break; - - addr_t top = reinterpret_cast(me->stack_top()); - addr_t cur = reinterpret_cast(me->stack_base()); - - rlim->rlim_cur = rlim->rlim_max = top - cur; - return 0; - } - case RLIMIT_AS: - #ifdef __x86_64__ - rlim->rlim_cur = rlim->rlim_max = 0x800000000000UL; - #else - rlim->rlim_cur = rlim->rlim_max = 0xc0000000UL; - #endif - return 0; - case RLIMIT_RSS: - rlim->rlim_cur = rlim->rlim_max = _env_ptr->pd().ram_quota().value; - return 0; - case RLIMIT_NPROC: - case RLIMIT_NOFILE: - rlim->rlim_cur = rlim->rlim_max = RLIM_INFINITY; - return 0; - } - errno = ENOSYS; - return -1; -} - - -/** - * Utility to copy-out syscall results to buf struct - * - * Code shared between 'stat' and 'fstat'. - */ -static void _sysio_to_stat_struct(Noux::Sysio const *sysio, struct stat *buf) -{ - unsigned const readable_bits = S_IRUSR, - writeable_bits = S_IWUSR, - executable_bits = S_IXUSR; - - auto type = [] (Vfs::Node_type type) - { - switch (type) { - case Vfs::Node_type::DIRECTORY: return S_IFDIR; - case Vfs::Node_type::CONTINUOUS_FILE: return S_IFREG; - case Vfs::Node_type::TRANSACTIONAL_FILE: return S_IFSOCK; - case Vfs::Node_type::SYMLINK: return S_IFLNK; - } - return 0; - }; - - Vfs::Directory_service::Stat const &src = sysio->stat_out.st; - - *buf = { }; - - buf->st_uid = 0; - buf->st_gid = 0; - buf->st_mode = (src.rwx.readable ? readable_bits : 0) - | (src.rwx.writeable ? writeable_bits : 0) - | (src.rwx.executable ? executable_bits : 0) - | type(src.type); - buf->st_size = src.size; - buf->st_blksize = FS_BLOCK_SIZE; - buf->st_blocks = (src.size + FS_BLOCK_SIZE - 1) / FS_BLOCK_SIZE; - buf->st_ino = src.inode; - buf->st_dev = src.device; - - if (src.modification_time.value != Vfs::Timestamp::INVALID) - buf->st_mtime = src.modification_time.value; -} - - -static bool serialize_string_array(char const * const * array, char *dst, Genode::size_t dst_len) -{ - for (unsigned i = 0; array[i]; i++) - { - Genode::size_t const curr_len = Genode::strlen(array[i]) + 1; - if (curr_len + 1 >= dst_len) - return false; - - Genode::strncpy(dst, array[i], dst_len); - dst += curr_len; - dst_len -= curr_len; - } - - dst[0] = 0; - return true; -} - - -/** - * Return number of marhalled file descriptors into select argument buffer - * - * \return number of marshalled file descriptors, this value is guaranteed to - * not exceed the 'dst_fds_len' argument - */ -static size_t marshal_fds(fd_set *src_fds, int nfds, - int *dst_fds, size_t dst_fds_len) -{ - if (!src_fds) return 0; - - size_t num_fds = 0; - - for (int fd = 0; (fd < nfds) && (num_fds < dst_fds_len); fd++) - if (FD_ISSET(fd, src_fds)) - dst_fds[num_fds++] = fd; - - return num_fds; -} - - -/** - * Unmarshal result of select syscall into fd set - */ -static void unmarshal_fds(int nfds, int *src_fds, size_t src_fds_len, fd_set *dst_fds) -{ - if (!dst_fds) return; - - /** - * Calling FD_ZERO will not work because it will try to reset sizeof (fd_set) - * which is typically 128 bytes but dst_fds might by even less bytes large if - * it was allocated dynamically. So we will reset the fd_set manually which - * will work fine as long as we are using FreeBSDs libc - another libc however - * might use a different struct. - * - * Note: The fds are actually stored in a bit-array. So we need to calculate - * how many array entries we have to reset. sizeof (fd_mask) will return the - * size of one entry in bytes. - */ - int _ = nfds / (sizeof (fd_mask) * 8) + 1; - for (int i = 0; i < _; i++) - dst_fds->__fds_bits[i] = 0; - - for (size_t i = 0; i < src_fds_len; i++) - FD_SET(src_fds[i], dst_fds); -} - - -extern "C" int select(int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, struct timeval *timeout) -{ - - /* - * Marshal file descriptor into sysio page - */ - Noux::Sysio::Select_fds &in_fds = sysio()->select_in.fds; - - int *dst = in_fds.array; - size_t dst_len = Noux::Sysio::Select_fds::MAX_FDS; - - /** - * These variables are used in max_fds_exceeded() calculation, so - * they need to be proper initialized. - */ - in_fds.num_rd = 0; - in_fds.num_wr = 0; - in_fds.num_ex = 0; - - if (readfds != NULL) { - in_fds.num_rd = marshal_fds(readfds, nfds, dst, dst_len); - - dst += in_fds.num_rd; - dst_len -= in_fds.num_rd; - } - - if (writefds != NULL) { - in_fds.num_wr = marshal_fds(writefds, nfds, dst, dst_len); - - dst += in_fds.num_wr; - dst_len -= in_fds.num_wr; - } - - if (exceptfds != NULL) { - in_fds.num_ex = marshal_fds(exceptfds, nfds, dst, dst_len); - } - - if (in_fds.max_fds_exceeded()) { - errno = ENOMEM; - return -1; - } - - /* - * Marshal timeout - */ - if (timeout) { - sysio()->select_in.timeout.sec = timeout->tv_sec; - sysio()->select_in.timeout.usec = timeout->tv_usec; - } else { - sysio()->select_in.timeout.set_infinite(); - } - - /* - * Perform syscall - */ - if (!noux_syscall(Noux::Session::SYSCALL_SELECT)) { - switch (sysio()->error.select) { - case Noux::Sysio::SELECT_ERR_INTERRUPT: errno = EINTR; break; - } - return -1; - } - - /* - * Unmarshal file selectors reported by the select syscall - */ - Noux::Sysio::Select_fds &out_fds = sysio()->select_out.fds; - - int *src = out_fds.array; - int total_fds = 0; - - if (readfds != NULL) { - unmarshal_fds(nfds, src, out_fds.num_rd, readfds); - src += out_fds.num_rd; - total_fds += out_fds.num_rd; - } - - if (writefds != NULL) { - unmarshal_fds(nfds, src, out_fds.num_wr, writefds); - src += out_fds.num_wr; - total_fds += out_fds.num_wr; - } - - if (exceptfds != NULL) { - unmarshal_fds(nfds, src, out_fds.num_ex, exceptfds); - /* exceptfds are currently ignored */ - } - - return total_fds; -} - - -#include - - -static void * in_stack_area; -static jmp_buf fork_jmp_buf; -static Genode::Capability::Raw new_parent; - -extern "C" void stdout_reconnect(Genode::Parent &); /* provided by 'default_log.cc' */ - - -/* - * The new process created via fork will start its execution here. - */ -extern "C" void fork_trampoline() -{ - /* reinitialize environment */ - using namespace Genode; - _env_ptr->reinit(new_parent); - - /* reinitialize standard-output connection */ - stdout_reconnect(_env_ptr->parent()); - - /* reinitialize noux connection */ - noux_connection()->reconnect(); - - /* reinitialize main-thread object which implies reinit of stack area */ - auto stack_area_rm = noux_connection()->stack_area_region_map(in_stack_area); - _env_ptr->reinit_main_thread(stack_area_rm); - - /* apply processor state that the forker had when he did the fork */ - longjmp(fork_jmp_buf, 1); -} - - -static pid_t fork_result; - - -/** - * Called once the component has left the entrypoint and exited the signal - * dispatch loop. - * - * This function is called from the context of the initial thread. - */ -static void suspended_callback() -{ - /* stack used for executing 'fork_trampoline' */ - enum { STACK_SIZE = 8 * 1024 }; - static long stack[STACK_SIZE]; - - if (setjmp(fork_jmp_buf)) { - - /* - * We got here via longjmp from 'fork_trampoline'. - */ - fork_result = 0; - - } else { - - /* - * save the current stack address used for re-initializing - * the stack area during process bootstrap - */ - int dummy; - in_stack_area = &dummy; - - /* got here during the normal control flow of the fork call */ - sysio()->fork_in.ip = (Genode::addr_t)(&fork_trampoline); - sysio()->fork_in.sp = Abi::stack_align((Genode::addr_t)&stack[STACK_SIZE]); - sysio()->fork_in.parent_cap_addr = (Genode::addr_t)(&new_parent); - - if (!noux_syscall(Noux::Session::SYSCALL_FORK)) { - error("fork error ", (int)sysio()->error.general); - switch (sysio()->error.fork) { - case Noux::Sysio::FORK_NOMEM: errno = ENOMEM; break; - default: errno = EAGAIN; - } - fork_result = -1; - return; - } - - fork_result = sysio()->fork_out.pid; - } -} - - -namespace Libc { void schedule_suspend(void (*suspended) ()); } - - -extern "C" pid_t fork(void) -{ - Libc::schedule_suspend(suspended_callback); - - return fork_result; -} - - -extern "C" pid_t vfork(void) { return fork(); } - - -extern "C" pid_t getpid(void) -{ - noux_syscall(Noux::Session::SYSCALL_GETPID); - return sysio()->getpid_out.pid; -} - - -extern "C" pid_t getppid(void) { return getpid(); } - - -extern "C" int chmod(char const *path, mode_t mode) -{ - if (verbose) - warning(__func__, ": chmod '", path, "' to ", Hex(mode), " not implemented"); - return 0; -} - - -extern "C" pid_t wait4(pid_t pid, int *status, int options, - struct rusage *rusage) -{ - sysio()->wait4_in.pid = pid; - sysio()->wait4_in.nohang = !!(options & WNOHANG); - if (!noux_syscall(Noux::Session::SYSCALL_WAIT4)) { - switch (sysio()->error.wait4) { - case Noux::Sysio::WAIT4_ERR_INTERRUPT: errno = EINTR; break; - } - return -1; - } - - /* - * The libc expects status information in bits 0..6 and the exit value - * in bits 8..15 (according to 'wait.h'). - */ - if (status) - *status = ((sysio()->wait4_out.status >> 8) & 0177) | - ((sysio()->wait4_out.status & 0xff) << 8); - - return sysio()->wait4_out.pid; -} - - -extern "C" __attribute__((alias("wait4"))) -pid_t _wait4(pid_t, int *, int, struct rusage *); - - -extern "C" __attribute__((alias("wait4"))) -pid_t __sys_wait4(pid_t, int *, int, struct rusage *); - - -extern "C" pid_t waitpid(pid_t pid, int *istat, int options) -{ - return wait4(pid, istat, options, NULL); -} - - -extern "C" int execve(char const *filename, char *const argv[], - char *const envp[]) -{ - if (verbose) { - log(__func__, ": filename=", filename); - - for (int i = 0; argv[i]; i++) - log(__func__, "argv[", i, "]='", Genode::Cstring(argv[i]), "'"); - - for (int i = 0; envp[i]; i++) - log(__func__, "envp[", i, "]='", Genode::Cstring(envp[i]), "'"); - } - - Libc::Absolute_path resolved_path; - try { - Libc::resolve_symlinks(filename, resolved_path); - } catch (Libc::Symlink_resolve_error) { - return -1; - } - - Genode::strncpy(sysio()->execve_in.filename, resolved_path.string(), - sizeof(sysio()->execve_in.filename)); - if (!serialize_string_array(argv, sysio()->execve_in.args, - sizeof(sysio()->execve_in.args))) { - error("execve: argument buffer exceeded"); - errno = E2BIG; - return -1; - } - - /* communicate the current working directory as environment variable */ - - size_t noux_cwd_len = Genode::snprintf(sysio()->execve_in.env, - sizeof(sysio()->execve_in.env), - "NOUX_CWD="); - - if (!getcwd(&(sysio()->execve_in.env[noux_cwd_len]), - sizeof(sysio()->execve_in.env) - noux_cwd_len)) { - error("execve: environment buffer exceeded"); - errno = E2BIG; - return -1; - } - - noux_cwd_len = strlen(sysio()->execve_in.env) + 1; - - if (!serialize_string_array(envp, &(sysio()->execve_in.env[noux_cwd_len]), - sizeof(sysio()->execve_in.env) - noux_cwd_len)) { - error("execve: environment buffer exceeded"); - errno = E2BIG; - return -1; - } - - if (!noux_syscall(Noux::Session::SYSCALL_EXECVE)) { - warning("exec syscall failed for path \"", filename, "\""); - switch (sysio()->error.execve) { - case Noux::Sysio::EXECVE_ERR_NO_ENTRY: errno = ENOENT; break; - case Noux::Sysio::EXECVE_ERR_NO_MEMORY: errno = ENOMEM; break; - case Noux::Sysio::EXECVE_ERR_NO_EXEC: errno = ENOEXEC; break; - case Noux::Sysio::EXECVE_ERR_ACCESS: errno = EACCES; break; - } - return -1; - } - - /* - * In the success case, we never return from execve, the execution is - * resumed in the new program. - */ - Genode::sleep_forever(); - return 0; -} - - -extern "C" int _execve(char const *, char *const[], char *const[]) __attribute__((alias("execve"))); - - -int getrusage(int who, struct rusage *usage) -{ - if (verbose) - warning(__func__, " not implemented"); - - errno = ENOSYS; - return -1; -} - - -void endpwent(void) -{ - if (verbose) - warning(__func__, " not implemented"); -} - - -extern "C" void sync(void) -{ - noux_syscall(Noux::Session::SYSCALL_SYNC); -} - - -extern "C" int kill(__pid_t pid, int sig) -{ - if (verbose_signals) - log(__func__, ": pid=", pid, ", sig=", sig); - - sysio()->kill_in.pid = pid; - sysio()->kill_in.sig = Noux::Sysio::Signal(sig); - - if (!noux_syscall(Noux::Session::SYSCALL_KILL)) { - switch (sysio()->error.kill) { - case Noux::Sysio::KILL_ERR_SRCH: errno = ESRCH; break; - } - return -1; - } - - return 0; -} - - -extern "C" int raise(int sig) -{ - return kill(getpid(), sig); -} - - -extern "C" int nanosleep(const struct timespec *timeout, - struct timespec *remainder) -{ - Noux::Sysio::Select_fds &in_fds = sysio()->select_in.fds; - - in_fds.num_rd = 0; - in_fds.num_wr = 0; - in_fds.num_ex = 0; - - sysio()->select_in.timeout.sec = timeout->tv_sec; - sysio()->select_in.timeout.usec = timeout->tv_nsec / 1000; - - /* - * Perform syscall - */ - if (!noux_syscall(Noux::Session::SYSCALL_SELECT)) { - switch (sysio()->error.select) { - case Noux::Sysio::SELECT_ERR_INTERRUPT: errno = EINTR; break; - } - - return -1; - } - - if (remainder) { - remainder->tv_sec = 0; - remainder->tv_nsec = 0; - } - - return 0; -} - - -extern "C" unsigned int sleep(unsigned int seconds) -{ - struct timespec dummy = { Genode::min(seconds, __INT_MAX__), 0 }; - - /* - * Always return 0 because our nanosleep() cannot not be interrupted. - */ - nanosleep(&dummy, 0); - return 0; -} - - -/******************** - ** Time functions ** - ********************/ - -/* - * The default implementations as provided by the libc rely on a dedicated - * thread. But on Noux, no thread other than the main thread is allowed. For - * this reason, we need to override the default implementations here. - */ - -extern "C" int clock_gettime(clockid_t clk_id, struct timespec *tp) -{ - /* we currently only support CLOCK_SECOND */ - switch (clk_id) { - case CLOCK_SECOND: - sysio()->clock_gettime_in.clock_id = Noux::Sysio::CLOCK_ID_SECOND; - break; - default: - /* let's save the trip to noux and return directly */ - errno = EINVAL; - return -1; - } - - if (!noux_syscall(Noux::Session::SYSCALL_CLOCK_GETTIME)) { - switch (sysio()->error.clock) { - case Noux::Sysio::CLOCK_ERR_INVALID: errno = EINVAL; break; - default: errno = 0; break; - } - - return -1; - } - - tp->tv_sec = sysio()->clock_gettime_out.sec; - tp->tv_nsec = sysio()->clock_gettime_out.nsec; - - return 0; -} - - -extern "C" int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - if (!noux_syscall(Noux::Session::SYSCALL_GETTIMEOFDAY)) { - errno = EINVAL; - return -1; - } - - tv->tv_sec = sysio()->gettimeofday_out.sec; - tv->tv_usec = sysio()->gettimeofday_out.usec; - - return 0; -} - - -extern "C" int utimes(const char* path, const struct timeval *times) -{ - char * const dst = sysio()->utimes_in.path; - size_t const max_len = sizeof(sysio()->utimes_in.path); - Genode::strncpy(dst, path, max_len); - - sysio()->utimes_in.sec = times ? times->tv_sec : 0; - sysio()->utimes_in.usec = times ? times->tv_usec : 0; - - if (!noux_syscall(Noux::Session::SYSCALL_UTIMES)) { - errno = EINVAL; - return -1; - } - - return 0; -} - - -/********************* - ** Signal handling ** - *********************/ - -extern "C" int sigprocmask(int how, const sigset_t *set, sigset_t *oldset) -{ - if (oldset) - *oldset = signal_mask; - - if (!set) - return 0; - - switch (how) { - case SIG_BLOCK: - for (int sig = 1; sig < NSIG; sig++) - if (sigismember(set, sig)) { - if (verbose_signals) - log(__func__, ": signal ", sig, " requested to get blocked"); - sigaddset(&signal_mask, sig); - } - break; - case SIG_UNBLOCK: - for (int sig = 1; sig < NSIG; sig++) - if (sigismember(set, sig)) { - if (verbose_signals) - log(__func__, ": signal ", sig, " requested to get unblocked"); - sigdelset(&signal_mask, sig); - } - break; - case SIG_SETMASK: - if (verbose_signals) - for (int sig = 1; sig < NSIG; sig++) - if (sigismember(set, sig)) - log(__func__, ": signal ", sig, " requested to get blocked"); - signal_mask = *set; - break; - default: - errno = EINVAL; - return -1; - } - - return 0; -} - - -extern "C" int _sigprocmask(int how, const sigset_t *set, sigset_t *oldset) __attribute__((alias("sigprocmask"))); - - -extern "C" int _sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) -{ - if (verbose_signals) - log("signum=", signum, ", handler=", act ? act->sa_handler : nullptr); - - if ((signum < 1) || (signum > NSIG)) { - errno = EINVAL; - return -1; - } - - if (oldact) - *oldact = signal_action[signum]; - - if (act) - signal_action[signum] = *act; - - return 0; -} - - -extern "C" int sigaction(int, const struct sigaction *, struct sigaction *) __attribute__((alias("_sigaction"))); -extern "C" int __libc_sigaction(int, const struct sigaction *, struct sigaction *) __attribute__((alias("_sigaction"))); - - -/********************* - ** File operations ** - *********************/ - -static int noux_fd(Libc::Plugin_context *context) -{ - /* - * We use the 'context' pointer only as container for an int value. It is - * never used as a pointer. To make 64-bit compilers happy, we need to keep - * the bit width of the cast intact. The upper 32 bit are discarded when - * leaving the function. - */ - return (long)context; -} - - -static Libc::Plugin_context *noux_context(int noux_fd) -{ - return reinterpret_cast(noux_fd); -} - - -namespace { - - class Plugin : public Libc::Plugin - { - private: - - /* - * Override the libc's default VFS plugin - */ - enum { PLUGIN_PRIORITY = 1 }; - - public: - - /** - * Constructor - */ - Plugin() : Libc::Plugin(PLUGIN_PRIORITY) { } - - void init(Genode::Env &); - - bool supports_access(const char *, int) { return true; } - bool supports_open(char const *, int) { return true; } - bool supports_stat(char const *) { return true; } - bool supports_symlink(char const *, char const*) { return true; } - bool supports_pipe() { return true; } - bool supports_unlink(char const *) { return true; } - bool supports_readlink(const char *, char *, ::size_t) { return true; } - bool supports_rename(const char *, const char *) { return true; } - bool supports_rmdir(char const *) { return true; } - bool supports_mkdir(const char *, mode_t) { return true; } - bool supports_socket(int, int, int) { return true; } - bool supports_mmap() { return true; } - - int access(char const *, int); - Libc::File_descriptor *open(char const *, int); - ssize_t write(Libc::File_descriptor *, const void *, ::size_t); - int close(Libc::File_descriptor *); - Libc::File_descriptor *dup(Libc::File_descriptor*); - int dup2(Libc::File_descriptor *, Libc::File_descriptor *); - int fstat(Libc::File_descriptor *, struct stat *); - int fsync(Libc::File_descriptor *); - int fstatfs(Libc::File_descriptor *, struct statfs *); - int ftruncate(Libc::File_descriptor *, ::off_t); - int fcntl(Libc::File_descriptor *, int, long); - ssize_t getdirentries(Libc::File_descriptor *, char *, ::size_t, ::off_t *); - ::off_t lseek(Libc::File_descriptor *, ::off_t offset, int whence); - ssize_t read(Libc::File_descriptor *, void *, ::size_t); - ssize_t readlink(const char *path, char *buf, ::size_t bufsiz); - int rename(const char *oldpath, const char *newpath); - int rmdir(char const *path); - int stat(char const *, struct stat *); - int symlink(const char *, const char *); - int ioctl(Libc::File_descriptor *, int request, char *argp); - int pipe(Libc::File_descriptor *pipefd[2]); - int unlink(char const *path); - int mkdir(const char *path, mode_t mode); - void *mmap(void *addr, ::size_t length, int prot, int flags, - Libc::File_descriptor *, ::off_t offset); - int munmap(void *addr, ::size_t length); - - /* Network related functions */ - Libc::File_descriptor *socket(int, int, int); - Libc::File_descriptor *accept(Libc::File_descriptor *, - struct sockaddr *, socklen_t *); - int bind(Libc::File_descriptor *, const struct sockaddr *, - socklen_t); - int connect(Libc::File_descriptor *, const struct sockaddr *addr, - socklen_t addrlen); - int getpeername(Libc::File_descriptor *, struct sockaddr *, - socklen_t *); - int listen(Libc::File_descriptor *, int); - ssize_t send(Libc::File_descriptor *, const void *, ::size_t, - int flags); - ssize_t sendto(Libc::File_descriptor *, const void *, size_t, int, - const struct sockaddr *, socklen_t); - ssize_t recv(Libc::File_descriptor *, void *, ::size_t, int); - ssize_t recvfrom(Libc::File_descriptor *, void *, ::size_t, int, - struct sockaddr *, socklen_t*); - int getsockopt(Libc::File_descriptor *, int, int, void *, - socklen_t *); - int setsockopt(Libc::File_descriptor *, int , int , const void *, - socklen_t); - int shutdown(Libc::File_descriptor *, int how); - }; - - - int Plugin::access(char const *pathname, int mode) - { - if (verbose) - log(__func__, ": access '", pathname, "' (mode=", Hex(mode), ") " - "called, not implemented"); - - struct stat stat; - if (::stat(pathname, &stat) == 0) - return 0; - - errno = ENOENT; - return -1; - } - - - int Plugin::stat(char const *path, struct stat *buf) - { - if (verbose) - log(__func__, ": path=", path); - - if ((path == NULL) or (buf == NULL)) { - errno = EFAULT; - return -1; - } - - Genode::strncpy(sysio()->stat_in.path, path, sizeof(sysio()->stat_in.path)); - - if (!noux_syscall(Noux::Session::SYSCALL_STAT)) { - if (verbose) - warning("stat syscall failed for path \"", path, "\""); - switch (sysio()->error.stat) { - case Vfs::Directory_service::STAT_ERR_NO_ENTRY: errno = ENOENT; return -1; - case Vfs::Directory_service::STAT_ERR_NO_PERM: errno = EACCES; return -1; - case Vfs::Directory_service::STAT_OK: break; /* never reached */ - } - } - - _sysio_to_stat_struct(sysio(), buf); - return 0; - } - - - Libc::File_descriptor *Plugin::open(char const *pathname, int flags) - { - if (Genode::strlen(pathname) + 1 > sizeof(sysio()->open_in.path)) { - log(__func__, ": ENAMETOOLONG"); - errno = ENAMETOOLONG; - return 0; - } - - bool opened = false; - while (!opened) { - Genode::strncpy(sysio()->open_in.path, pathname, sizeof(sysio()->open_in.path)); - sysio()->open_in.mode = flags; - if (noux_syscall(Noux::Session::SYSCALL_OPEN)) - opened = true; - else - switch (sysio()->error.open) { - case Vfs::Directory_service::OPEN_ERR_UNACCESSIBLE: - if (!(flags & O_CREAT)) { - errno = ENOENT; - return 0; - } - /* O_CREAT is set, so try to create the file */ - Genode::strncpy(sysio()->open_in.path, pathname, sizeof(sysio()->open_in.path)); - sysio()->open_in.mode = flags | O_EXCL; - if (noux_syscall(Noux::Session::SYSCALL_OPEN)) - opened = true; - else - switch (sysio()->error.open) { - case Vfs::Directory_service::OPEN_ERR_EXISTS: - /* file has been created by someone else in the meantime */ - break; - case Vfs::Directory_service::OPEN_ERR_NO_PERM: - errno = EPERM; return 0; - default: - errno = ENOENT; return 0; - } - break; - case Vfs::Directory_service::OPEN_ERR_NO_PERM: errno = EPERM; return 0; - case Vfs::Directory_service::OPEN_ERR_EXISTS: errno = EEXIST; return 0; - default: errno = ENOENT; return 0; - } - } - - Libc::Plugin_context *context = noux_context(sysio()->open_out.fd); - Libc::File_descriptor *fd = - Libc::file_descriptor_allocator()->alloc(this, context, sysio()->open_out.fd); - if ((flags & O_TRUNC) && (ftruncate(fd, 0) == -1)) { - Plugin::close(fd); - return 0; - } - return fd; - } - - - int Plugin::symlink(const char *oldpath, const char *newpath) - { - if (verbose) - log(__func__, ": ", newpath, " -> ", oldpath); - - if ((Genode::strlen(oldpath) + 1 > sizeof(sysio()->symlink_in.oldpath)) || - (Genode::strlen(newpath) + 1 > sizeof(sysio()->symlink_in.newpath))) { - log(__func__, ": ENAMETOOLONG"); - errno = ENAMETOOLONG; - return 0; - } - - Genode::strncpy(sysio()->symlink_in.oldpath, oldpath, sizeof(sysio()->symlink_in.oldpath)); - Genode::strncpy(sysio()->symlink_in.newpath, newpath, sizeof(sysio()->symlink_in.newpath)); - if (!noux_syscall(Noux::Session::SYSCALL_SYMLINK)) { - warning("symlink syscall failed for path \"", newpath, "\""); - switch (sysio()->error.symlink) { - case Noux::Sysio::SYMLINK_ERR_NO_ENTRY: errno = ENOENT; return -1; - case Noux::Sysio::SYMLINK_ERR_EXISTS: errno = EEXIST; return -1; - case Noux::Sysio::SYMLINK_ERR_NO_SPACE: errno = ENOSPC; return -1; - case Noux::Sysio::SYMLINK_ERR_NO_PERM: errno = EPERM; return -1; - case Noux::Sysio::SYMLINK_ERR_NAME_TOO_LONG: errno = ENAMETOOLONG; return -1; - } - } - - return 0; - } - - - int Plugin::fstatfs(Libc::File_descriptor *, struct statfs *buf) - { - buf->f_flags = MNT_UNION; - return 0; - } - - - ssize_t Plugin::write(Libc::File_descriptor *fd, const void *buf, - ::size_t count) - { - if (!buf) { errno = EFAULT; return -1; } - - /* remember original len for the return value */ - size_t const orig_count = count; - - char *src = (char *)buf; - while (count > 0) { - - Genode::size_t curr_count = Genode::min((::size_t)Noux::Sysio::CHUNK_SIZE, count); - - sysio()->write_in.fd = noux_fd(fd->context); - sysio()->write_in.count = curr_count; - Genode::memcpy(sysio()->write_in.chunk, src, curr_count); - - if (!noux_syscall(Noux::Session::SYSCALL_WRITE)) { - switch (sysio()->error.write) { - case Vfs::File_io_service::WRITE_ERR_AGAIN: errno = EAGAIN; break; - case Vfs::File_io_service::WRITE_ERR_WOULD_BLOCK: errno = EWOULDBLOCK; break; - case Vfs::File_io_service::WRITE_ERR_INVALID: errno = EINVAL; break; - case Vfs::File_io_service::WRITE_ERR_IO: errno = EIO; break; - case Vfs::File_io_service::WRITE_ERR_INTERRUPT: errno = EINTR; break; - default: - if (sysio()->error.general == Vfs::Directory_service::ERR_FD_INVALID) - errno = EBADF; - else - errno = 0; - break; - } - - /* try again */ - bool const retry = (errno == EINTR - || errno == EAGAIN - || errno == EWOULDBLOCK); - if (errno && retry) - continue; - - /* leave writing loop on error */ - if (errno) - break; - } - - count -= sysio()->write_out.count; - src += sysio()->write_out.count; - } - return orig_count - count; - } - - - ssize_t Plugin::read(Libc::File_descriptor *fd, void *buf, ::size_t count) - { - if (!buf) { errno = EFAULT; return -1; } - - Genode::size_t sum_read_count = 0; - - while (count > 0) { - - Genode::size_t curr_count = - Genode::min(count, sizeof(sysio()->read_out.chunk)); - - sysio()->read_in.fd = noux_fd(fd->context); - sysio()->read_in.count = curr_count; - - if (!noux_syscall(Noux::Session::SYSCALL_READ)) { - - switch (sysio()->error.read) { - case Vfs::File_io_service::READ_ERR_AGAIN: errno = EAGAIN; break; - case Vfs::File_io_service::READ_ERR_WOULD_BLOCK: errno = EWOULDBLOCK; break; - case Vfs::File_io_service::READ_ERR_INVALID: errno = EINVAL; break; - case Vfs::File_io_service::READ_ERR_IO: errno = EIO; break; - case Vfs::File_io_service::READ_ERR_INTERRUPT: errno = EINTR; break; - default: - if (sysio()->error.general == Vfs::Directory_service::ERR_FD_INVALID) - errno = EBADF; - else - errno = 0; - break; - } - - /* try again */ - bool const retry = (errno == EINTR - || errno == EAGAIN - || errno == EWOULDBLOCK); - if (errno && retry) - continue; - - return -1; - } - - Genode::memcpy((char*)buf + sum_read_count, - sysio()->read_out.chunk, - sysio()->read_out.count); - - sum_read_count += sysio()->read_out.count; - - if (sysio()->read_out.count < curr_count) - break; /* end of file */ - - if (sysio()->read_out.count <= count) - count -= sysio()->read_out.count; - else - break; /* should not happen */ - } - - return sum_read_count; - } - - - int Plugin::close(Libc::File_descriptor *fd) - { - sysio()->close_in.fd = noux_fd(fd->context); - if (!noux_syscall(Noux::Session::SYSCALL_CLOSE)) { - error("close error"); - /* XXX set errno */ - return -1; - } - Libc::file_descriptor_allocator()->free(fd); - return 0; - } - - - int Plugin::ioctl(Libc::File_descriptor *fd, int request, char *argp) - { - /* - * Marshal ioctl arguments - */ - sysio()->ioctl_in.fd = noux_fd(fd->context); - sysio()->ioctl_in.request = Vfs::File_io_service::IOCTL_OP_UNDEFINED; - - switch (request) { - - case TIOCGWINSZ: - sysio()->ioctl_in.request = Vfs::File_io_service::IOCTL_OP_TIOCGWINSZ; - break; - - case TIOCGETA: - { - if (verbose) - log(__func__, ": TIOCGETA - argp=", (void *)argp); - ::termios *termios = (::termios *)argp; - - termios->c_iflag = 0; - termios->c_oflag = 0; - termios->c_cflag = 0; - /* - * Set 'ECHO' flag, needed by libreadline. Otherwise, echoing - * user input doesn't work in bash. - */ - termios->c_lflag = ECHO; - memset(termios->c_cc, _POSIX_VDISABLE, sizeof(termios->c_cc)); - termios->c_ispeed = 0; - termios->c_ospeed = 0; - - return 0; - } - - break; - - case TIOCSETAF: - { - sysio()->ioctl_in.request = Vfs::File_io_service::IOCTL_OP_TIOCSETAF; - - ::termios *termios = (::termios *)argp; - - /** - * For now only enabling/disabling of ECHO is supported - */ - if (termios->c_lflag & (ECHO | ECHONL)) { - sysio()->ioctl_in.argp = (Vfs::File_io_service::IOCTL_VAL_ECHO | - Vfs::File_io_service::IOCTL_VAL_ECHONL); - } - else { - sysio()->ioctl_in.argp = Vfs::File_io_service::IOCTL_VAL_NULL; - } - - break; - } - - case TIOCSETAW: - { - sysio()->ioctl_in.request = Vfs::File_io_service::IOCTL_OP_TIOCSETAW; - sysio()->ioctl_in.argp = argp ? *(int*)argp : 0; - - break; - } - - case FIONBIO: - { - if (verbose) - log(__func__, ": FIONBIO - *argp=", *argp); - - sysio()->ioctl_in.request = Vfs::File_io_service::IOCTL_OP_FIONBIO; - sysio()->ioctl_in.argp = argp ? *(int*)argp : 0; - - break; - } - - case DIOCGMEDIASIZE: - { - sysio()->ioctl_in.request = Vfs::File_io_service::IOCTL_OP_DIOCGMEDIASIZE; - sysio()->ioctl_in.argp = 0; - - break; - } - - case TIOCSETA: - { - /* not implemented but used by e.g. vim */ - break; - } - - - default: - - warning("unsupported ioctl (request=", Hex(request), ")"); - break; - } - - if (sysio()->ioctl_in.request == Vfs::File_io_service::IOCTL_OP_UNDEFINED) { - errno = ENOTTY; - return -1; - } - - /* perform syscall */ - if (!noux_syscall(Noux::Session::SYSCALL_IOCTL)) { - switch (sysio()->error.ioctl) { - case Vfs::File_io_service::IOCTL_ERR_INVALID: errno = EINVAL; break; - case Vfs::File_io_service::IOCTL_ERR_NOTTY: errno = ENOTTY; break; - default: errno = 0; break; - } - - return -1; - } - - /* - * Unmarshal ioctl results - */ - switch (request) { - - case TIOCGWINSZ: - { - ::winsize *winsize = (::winsize *)argp; - winsize->ws_row = sysio()->ioctl_out.tiocgwinsz.rows; - winsize->ws_col = sysio()->ioctl_out.tiocgwinsz.columns; - return 0; - } - case TIOCSETAF: - case TIOCSETAW: - return 0; - - case FIONBIO: - return 0; - case DIOCGMEDIASIZE: - { - int64_t *disk_size = (int64_t*)argp; - *disk_size = sysio()->ioctl_out.diocgmediasize.size; - return 0; - } - - default: - return -1; - } - } - - - int Plugin::pipe(Libc::File_descriptor *pipefd[2]) - { - /* perform syscall */ - if (!noux_syscall(Noux::Session::SYSCALL_PIPE)) { - error("pipe error"); - /* XXX set errno */ - return -1; - } - - for (int i = 0; i < 2; i++) { - Libc::Plugin_context *context = noux_context(sysio()->pipe_out.fd[i]); - pipefd[i] = Libc::file_descriptor_allocator()->alloc(this, context, sysio()->pipe_out.fd[i]); - } - return 0; - } - - - Libc::File_descriptor *Plugin::dup(Libc::File_descriptor* fd) - { - sysio()->dup2_in.fd = noux_fd(fd->context); - sysio()->dup2_in.to_fd = -1; - - if (!noux_syscall(Noux::Session::SYSCALL_DUP2)) { - error("dup error"); - /* XXX set errno */ - return 0; - } - - Libc::Plugin_context *context = noux_context(sysio()->dup2_out.fd); - return Libc::file_descriptor_allocator()->alloc(this, context, - sysio()->dup2_out.fd); - } - - - int Plugin::dup2(Libc::File_descriptor *fd, Libc::File_descriptor *new_fd) - { - /* - * We use a one-to-one mapping of libc fds and Noux fds. - */ - new_fd->context = noux_context(new_fd->libc_fd); - - sysio()->dup2_in.fd = noux_fd(fd->context); - sysio()->dup2_in.to_fd = noux_fd(new_fd->context); - - /* perform syscall */ - if (!noux_syscall(Noux::Session::SYSCALL_DUP2)) { - error("dup2 error"); - /* XXX set errno */ - return -1; - } - - return noux_fd(new_fd->context); - } - - - int Plugin::fstat(Libc::File_descriptor *fd, struct stat *buf) - { - sysio()->fstat_in.fd = noux_fd(fd->context); - if (!noux_syscall(Noux::Session::SYSCALL_FSTAT)) { - error("fstat error"); - /* XXX set errno */ - return -1; - } - - _sysio_to_stat_struct(sysio(), buf); - return 0; - } - - - int Plugin::fsync(Libc::File_descriptor *fd) - { - if (verbose) - warning(__func__, ": not implemented"); - return 0; - } - - - int Plugin::ftruncate(Libc::File_descriptor *fd, ::off_t length) - { - sysio()->ftruncate_in.fd = noux_fd(fd->context); - sysio()->ftruncate_in.length = length; - if (!noux_syscall(Noux::Session::SYSCALL_FTRUNCATE)) { - switch (sysio()->error.ftruncate) { - case Vfs::File_io_service::FTRUNCATE_OK: /* never reached */ - case Vfs::File_io_service::FTRUNCATE_ERR_NO_PERM: errno = EPERM; break; - case Vfs::File_io_service::FTRUNCATE_ERR_INTERRUPT: errno = EINTR; break; - case Vfs::File_io_service::FTRUNCATE_ERR_NO_SPACE: errno = ENOSPC; break; - } - return -1; - } - - return 0; - } - - - int Plugin::fcntl(Libc::File_descriptor *fd, int cmd, long arg) - { - /* copy arguments to sysio */ - sysio()->fcntl_in.fd = noux_fd(fd->context); - switch (cmd) { - - case F_DUPFD_CLOEXEC: - case F_DUPFD: - { - /* - * Allocate free file descriptor locally. Noux FDs are expected - * to correspond one-to-one to libc FDs. - */ - Libc::File_descriptor *new_fd = - Libc::file_descriptor_allocator()->alloc(this, 0); - new_fd->path(fd->fd_path); - - /* - * Use new allocated number as name of file descriptor - * duplicate. - */ - if (dup2(fd, new_fd) == -1) { - error("Plugin::fcntl: dup2 unexpectedly failed"); - errno = EINVAL; - return -1; - } - - return new_fd->libc_fd; - } - - case F_GETFD: - sysio()->fcntl_in.cmd = Noux::Sysio::FCNTL_CMD_GET_FD_FLAGS; - break; - - case F_SETFD: - sysio()->fcntl_in.cmd = Noux::Sysio::FCNTL_CMD_SET_FD_FLAGS; - sysio()->fcntl_in.long_arg = arg; - break; - - case F_GETFL: - if (verbose) - log("fcntl: F_GETFL for libc_fd=", fd->libc_fd); - sysio()->fcntl_in.cmd = Noux::Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS; - break; - - case F_SETFL: - if (verbose) - log("fcntl: F_SETFL for libc_fd=", fd->libc_fd); - sysio()->fcntl_in.cmd = Noux::Sysio::FCNTL_CMD_SET_FILE_STATUS_FLAGS; - sysio()->fcntl_in.long_arg = arg; - break; - - default: - error("fcntl: unsupported command ", cmd); - errno = EINVAL; - return -1; - }; - - /* invoke system call */ - if (!noux_syscall(Noux::Session::SYSCALL_FCNTL)) { - warning("fcntl failed (libc_fd=", fd->libc_fd, ", cmd=", Hex(cmd), ")"); - switch (sysio()->error.fcntl) { - case Noux::Sysio::FCNTL_ERR_CMD_INVALID: errno = EINVAL; break; - default: - switch (sysio()->error.general) { - case Vfs::Directory_service::ERR_FD_INVALID: errno = EINVAL; break; - case Vfs::Directory_service::NUM_GENERAL_ERRORS: break; - } - } - return -1; - } - - /* read result from sysio */ - return sysio()->fcntl_out.result; - } - - - ssize_t Plugin::getdirentries(Libc::File_descriptor *fd, char *buf, - ::size_t nbytes, ::off_t *basep) - { - if (nbytes < sizeof(struct dirent)) { - error("buf too small"); - return -1; - } - - sysio()->dirent_in.fd = noux_fd(fd->context); - - if (!noux_syscall(Noux::Session::SYSCALL_DIRENT)) { - switch (sysio()->error.general) { - - case Vfs::Directory_service::ERR_FD_INVALID: - errno = EBADF; - error("dirent: ERR_FD_INVALID"); - return -1; - - case Vfs::Directory_service::NUM_GENERAL_ERRORS: return -1; - } - } - - using Dirent_type = Vfs::Directory_service::Dirent_type; - - if (sysio()->dirent_out.entry.type == Dirent_type::END) - return 0; - - auto d_type = [] (Dirent_type const &type) - { - switch (sysio()->dirent_out.entry.type) { - case Dirent_type::DIRECTORY: return DT_DIR; - case Dirent_type::CONTINUOUS_FILE: return DT_REG; - case Dirent_type::TRANSACTIONAL_FILE: return DT_REG; - case Dirent_type::SYMLINK: return DT_LNK; - case Dirent_type::END: return 0; - } - return 0; - }; - - struct dirent &dirent = *(struct dirent *)buf; - - dirent = { }; - - dirent.d_type = d_type(sysio()->dirent_out.entry.type); - dirent.d_fileno = sysio()->dirent_out.entry.fileno; - dirent.d_reclen = sizeof(struct dirent); - - Genode::strncpy(dirent.d_name, sysio()->dirent_out.entry.name, - sizeof(dirent.d_name)); - - dirent.d_namlen = Genode::strlen(dirent.d_name); - - *basep += sizeof(struct dirent); - return sizeof(struct dirent); - } - - - ::off_t Plugin::lseek(Libc::File_descriptor *fd, - ::off_t offset, int whence) - { - sysio()->lseek_in.fd = noux_fd(fd->context); - sysio()->lseek_in.offset = offset; - - switch (whence) { - default: - case SEEK_SET: sysio()->lseek_in.whence = Noux::Sysio::LSEEK_SET; break; - case SEEK_CUR: sysio()->lseek_in.whence = Noux::Sysio::LSEEK_CUR; break; - case SEEK_END: sysio()->lseek_in.whence = Noux::Sysio::LSEEK_END; break; - } - - if (!noux_syscall(Noux::Session::SYSCALL_LSEEK)) { - switch (sysio()->error.general) { - - case Vfs::Directory_service::ERR_FD_INVALID: - errno = EBADF; - error("lseek: ERR_FD_INVALID"); - return -1; - - case Vfs::Directory_service::NUM_GENERAL_ERRORS: return -1; - } - } - - return sysio()->lseek_out.offset; - } - - - int Plugin::unlink(char const *path) - { - Genode::strncpy(sysio()->unlink_in.path, path, sizeof(sysio()->unlink_in.path)); - - if (!noux_syscall(Noux::Session::SYSCALL_UNLINK)) { - warning("unlink syscall failed for path \"", path, "\""); - typedef Vfs::Directory_service::Unlink_result Result; - switch (sysio()->error.unlink) { - case Result::UNLINK_ERR_NO_ENTRY: errno = ENOENT; break; - case Result::UNLINK_ERR_NOT_EMPTY: errno = ENOTEMPTY; break; - case Result::UNLINK_ERR_NO_PERM: errno = EPERM; break; - case Result::UNLINK_OK: break; /* only here to complete the enumeration */ - } - return -1; - } - - return 0; - } - - - int Plugin::rmdir(char const *path) - { - return Plugin::unlink(path); - } - - - ssize_t Plugin::readlink(const char *path, char *buf, ::size_t bufsiz) - { - if (verbose) - log(__func__, ": path=", path, ", bufsiz=", bufsiz); - - Genode::strncpy(sysio()->readlink_in.path, path, sizeof(sysio()->readlink_in.path)); - sysio()->readlink_in.bufsiz = bufsiz; - - if (!noux_syscall(Noux::Session::SYSCALL_READLINK)) { - warning("readlink syscall failed for path \"", path, "\""); - switch (sysio()->error.readlink) { - case Noux::Sysio::READLINK_ERR_NO_ENTRY: errno = ENOENT; return -1; - case Noux::Sysio::READLINK_ERR_NO_PERM: errno = EPERM; return -1; - } - } - - ssize_t size = Genode::min((size_t)sysio()->readlink_out.count, bufsiz); - - Genode::memcpy(buf, sysio()->readlink_out.chunk, size); - - if (verbose) - log(__func__, ": result=", Genode::Cstring(buf)); - - return size; - } - - - int Plugin::rename(char const *from_path, char const *to_path) - { - Genode::strncpy(sysio()->rename_in.from_path, from_path, sizeof(sysio()->rename_in.from_path)); - Genode::strncpy(sysio()->rename_in.to_path, to_path, sizeof(sysio()->rename_in.to_path)); - - if (!noux_syscall(Noux::Session::SYSCALL_RENAME)) { - warning("rename syscall failed for \"", from_path, "\" -> \"", to_path, "\""); - switch (sysio()->error.rename) { - case Vfs::Directory_service::RENAME_ERR_NO_ENTRY: errno = ENOENT; break; - case Vfs::Directory_service::RENAME_ERR_CROSS_FS: errno = EXDEV; break; - case Vfs::Directory_service::RENAME_ERR_NO_PERM: errno = EPERM; break; - default: errno = EPERM; break; - } - return -1; - } - - return 0; - } - - - int Plugin::mkdir(const char *path, mode_t mode) - { - Genode::strncpy(sysio()->mkdir_in.path, path, sizeof(sysio()->mkdir_in.path)); - - if (!noux_syscall(Noux::Session::SYSCALL_MKDIR)) { - warning("mkdir syscall failed for \"", path, "\" mode=", Hex(mode)); - switch (sysio()->error.mkdir) { - case Noux::Sysio::MKDIR_ERR_EXISTS: errno = EEXIST; break; - case Noux::Sysio::MKDIR_ERR_NO_ENTRY: errno = ENOENT; break; - case Noux::Sysio::MKDIR_ERR_NO_SPACE: errno = ENOSPC; break; - case Noux::Sysio::MKDIR_ERR_NAME_TOO_LONG: errno = ENAMETOOLONG; break; - case Noux::Sysio::MKDIR_ERR_NO_PERM: errno = EPERM; break; - default: errno = EPERM; break; - } - return -1; - } - return 0; - } - - - void *Plugin::mmap(void *addr_in, ::size_t length, int prot, int flags, - Libc::File_descriptor *fd, ::off_t offset) - { - if (prot != PROT_READ) { - error("mmap for prot=", Hex(prot), " not supported"); - errno = EACCES; - return (void *)-1; - } - - if (addr_in != 0) { - error("mmap for predefined address not supported"); - errno = EINVAL; - return (void *)-1; - } - - void *addr = Libc::mem_alloc()->alloc(length, PAGE_SHIFT); - if (addr == (void *)-1) { - errno = ENOMEM; - return (void *)-1; - } - - if (::pread(fd->libc_fd, addr, length, offset) < 0) { - error("mmap could not obtain file content"); - ::munmap(addr, length); - errno = EACCES; - return (void *)-1; - } - - return addr; - } - - - int Plugin::munmap(void *addr, ::size_t) - { - Libc::mem_alloc()->free(addr); - return 0; - } - - - Libc::File_descriptor *Plugin::socket(int domain, int type, int protocol) - { - sysio()->socket_in.domain = domain; - sysio()->socket_in.type = type; - sysio()->socket_in.protocol = protocol; - - if (!noux_syscall(Noux::Session::SYSCALL_SOCKET)) - return 0; - - Libc::Plugin_context *context = noux_context(sysio()->socket_out.fd); - return Libc::file_descriptor_allocator()->alloc(this, context, - sysio()->socket_out.fd); - } - - - int Plugin::getsockopt(Libc::File_descriptor *fd, int level, int optname, - void *optval, socklen_t *optlen) - { - sysio()->getsockopt_in.fd = noux_fd(fd->context); - sysio()->getsockopt_in.level = level; - sysio()->getsockopt_in.optname = optname; - - /* wipe-old state */ - sysio()->getsockopt_in.optlen = *optlen; - Genode::memset(sysio()->getsockopt_in.optval, 0, - sizeof (sysio()->getsockopt_in.optval)); - - if (!noux_syscall(Noux::Session::SYSCALL_GETSOCKOPT)) - return -1; - - Genode::memcpy(optval, sysio()->setsockopt_in.optval, - sysio()->getsockopt_in.optlen); - - return 0; - } - - - int Plugin::setsockopt(Libc::File_descriptor *fd, int level, int optname, - const void *optval, socklen_t optlen) - { - if (optlen > sizeof(sysio()->setsockopt_in.optval)) { - /* XXX */ - return -1; - } - - sysio()->setsockopt_in.fd = noux_fd(fd->context); - sysio()->setsockopt_in.level = level; - sysio()->setsockopt_in.optname = optname; - sysio()->setsockopt_in.optlen = optlen; - - Genode::memcpy(sysio()->setsockopt_in.optval, optval, optlen); - - if (!noux_syscall(Noux::Session::SYSCALL_SETSOCKOPT)) { - /* XXX */ - return -1; - } - - return 0; - } - - - Libc::File_descriptor *Plugin::accept(Libc::File_descriptor *fd, struct sockaddr *addr, - socklen_t *addrlen) - { - sysio()->accept_in.fd = noux_fd(fd->context); - - if (addr != NULL) { - Genode::memcpy(&sysio()->accept_in.addr, addr, sizeof (struct sockaddr)); - sysio()->accept_in.addrlen = *addrlen; - } - else { - Genode::memset(&sysio()->accept_in.addr, 0, sizeof (struct sockaddr)); - sysio()->accept_in.addrlen = 0; - } - - if (!noux_syscall(Noux::Session::SYSCALL_ACCEPT)) { - switch (sysio()->error.accept) { - case Noux::Sysio::ACCEPT_ERR_AGAIN: errno = EAGAIN; break; - case Noux::Sysio::ACCEPT_ERR_NO_MEMORY: errno = ENOMEM; break; - case Noux::Sysio::ACCEPT_ERR_INVALID: errno = EINVAL; break; - case Noux::Sysio::ACCEPT_ERR_NOT_SUPPORTED: errno = EOPNOTSUPP; break; - case Noux::Sysio::ACCEPT_ERR_WOULD_BLOCK: errno = EWOULDBLOCK; break; - default: errno = 0; break; - } - - return 0; - } - - if (addr != NULL) - *addrlen = sysio()->accept_in.addrlen; - - Libc::Plugin_context *context = noux_context(sysio()->accept_out.fd); - return Libc::file_descriptor_allocator()->alloc(this, context, - sysio()->accept_out.fd); - } - - - int Plugin::bind(Libc::File_descriptor *fd, const struct sockaddr *addr, - socklen_t addrlen) - { - sysio()->bind_in.fd = noux_fd(fd->context); - - Genode::memcpy(&sysio()->bind_in.addr, addr, sizeof (struct sockaddr)); - sysio()->bind_in.addrlen = addrlen; - - if (!noux_syscall(Noux::Session::SYSCALL_BIND)) { - switch (sysio()->error.bind) { - case Noux::Sysio::BIND_ERR_ACCESS: errno = EACCES; break; - case Noux::Sysio::BIND_ERR_ADDR_IN_USE: errno = EADDRINUSE; break; - case Noux::Sysio::BIND_ERR_INVALID: errno = EINVAL; break; - case Noux::Sysio::BIND_ERR_NO_MEMORY: errno = ENOMEM; break; - default: errno = 0; break; - } - return -1; - } - - return 0; - } - - - int Plugin::connect(Libc::File_descriptor *fd, const struct sockaddr *addr, - socklen_t addrlen) - { - sysio()->connect_in.fd = noux_fd(fd->context); - - Genode::memcpy(&sysio()->connect_in.addr, addr, sizeof (struct sockaddr)); - sysio()->connect_in.addrlen = addrlen; - - if (!noux_syscall(Noux::Session::SYSCALL_CONNECT)) { - switch (sysio()->error.connect) { - case Noux::Sysio::CONNECT_ERR_AGAIN: errno = EAGAIN; break; - case Noux::Sysio::CONNECT_ERR_ALREADY: errno = EALREADY; break; - case Noux::Sysio::CONNECT_ERR_ADDR_IN_USE: errno = EADDRINUSE; break; - case Noux::Sysio::CONNECT_ERR_IN_PROGRESS: errno = EINPROGRESS; break; - case Noux::Sysio::CONNECT_ERR_IS_CONNECTED: errno = EISCONN; break; - case Noux::Sysio::CONNECT_ERR_RESET: errno = ECONNRESET; break; - case Noux::Sysio::CONNECT_ERR_ABORTED: errno = ECONNABORTED; break; - case Noux::Sysio::CONNECT_ERR_NO_ROUTE: errno = EHOSTUNREACH; break; - default: errno = 0; break; - } - return -1; - } - - return 0; - } - - - int Plugin::getpeername(Libc::File_descriptor *fd, struct sockaddr *addr, - socklen_t *addrlen) - { - sysio()->getpeername_in.fd = noux_fd(fd->context); - sysio()->getpeername_in.addrlen = *addrlen; - - if (!noux_syscall(Noux::Session::SYSCALL_GETPEERNAME)) { - /* errno */ - return -1; - } - - Genode::memcpy(addr, &sysio()->getpeername_in.addr, - sizeof (struct sockaddr)); - *addrlen = sysio()->getpeername_in.addrlen; - - return 0; - } - - - int Plugin::listen(Libc::File_descriptor *fd, int backlog) - { - sysio()->listen_in.fd = noux_fd(fd->context); - sysio()->listen_in.backlog = backlog; - - if (!noux_syscall(Noux::Session::SYSCALL_LISTEN)) { - switch (sysio()->error.listen) { - case Noux::Sysio::LISTEN_ERR_ADDR_IN_USE: errno = EADDRINUSE; break; - case Noux::Sysio::LISTEN_ERR_NOT_SUPPORTED: errno = EOPNOTSUPP; break; - default: errno = 0; break; - } - return -1; - } - - return 0; - } - - - ssize_t Plugin::recv(Libc::File_descriptor *fd, void *buf, ::size_t len, int flags) - { - if (!buf) { errno = EFAULT; return -1; } - - Genode::size_t sum_recv_count = 0; - - while (len > 0) { - Genode::size_t curr_len = - Genode::min(len, sizeof(sysio()->recv_in.buf)); - - sysio()->recv_in.fd = noux_fd(fd->context); - sysio()->recv_in.len = curr_len; - - if (!noux_syscall(Noux::Session::SYSCALL_RECV)) { - switch (sysio()->error.recv) { - case Noux::Sysio::RECV_ERR_AGAIN: errno = EAGAIN; break; - case Noux::Sysio::RECV_ERR_WOULD_BLOCK: errno = EWOULDBLOCK; break; - case Noux::Sysio::RECV_ERR_INVALID: errno = EINVAL; break; - case Noux::Sysio::RECV_ERR_NOT_CONNECTED: errno = ENOTCONN; break; - default: errno = 0; break; - } - return -1; - } - - Genode::memcpy((char *)buf + sum_recv_count, - sysio()->recv_in.buf, sysio()->recv_out.len); - - sum_recv_count += sysio()->recv_out.len; - - if (sysio()->recv_out.len < curr_len) - break; - - if (sysio()->recv_out.len <= len) - len -= sysio()->recv_out.len; - else - break; - } - - return sum_recv_count; - } - - - ssize_t Plugin::recvfrom(Libc::File_descriptor *fd, void *buf, ::size_t len, int flags, - struct sockaddr *src_addr, socklen_t *addrlen) - { - if (!buf) { errno = EFAULT; return -1; } - - Genode::size_t sum_recvfrom_count = 0; - - while (len > 0) { - Genode::size_t curr_len = Genode::min(len, sizeof(sysio()->recvfrom_in.buf)); - - sysio()->recv_in.fd = noux_fd(fd->context); - sysio()->recv_in.len = curr_len; - - if (addrlen == NULL) - sysio()->recvfrom_in.addrlen = 0; - else - sysio()->recvfrom_in.addrlen = *addrlen; - - if (!noux_syscall(Noux::Session::SYSCALL_RECVFROM)) { - switch (sysio()->error.recv) { - case Noux::Sysio::RECV_ERR_AGAIN: errno = EAGAIN; break; - case Noux::Sysio::RECV_ERR_WOULD_BLOCK: errno = EWOULDBLOCK; break; - case Noux::Sysio::RECV_ERR_INVALID: errno = EINVAL; break; - case Noux::Sysio::RECV_ERR_NOT_CONNECTED: errno = ENOTCONN; break; - default: errno = 0; break; - } - return -1; - } - - if (src_addr != NULL && addrlen != NULL) - Genode::memcpy(src_addr, &sysio()->recvfrom_in.src_addr, - sysio()->recvfrom_in.addrlen); - - - Genode::memcpy((char *)buf + sum_recvfrom_count, - sysio()->recvfrom_in.buf, sysio()->recvfrom_out.len); - - sum_recvfrom_count += sysio()->recvfrom_out.len; - - if (sysio()->recvfrom_out.len < curr_len) - break; - - if (sysio()->recvfrom_out.len <= len) - len -= sysio()->recvfrom_out.len; - else - break; - } - - return sum_recvfrom_count; - } - - - ssize_t Plugin::send(Libc::File_descriptor *fd, const void *buf, ::size_t len, int flags) - { - if (!buf) { errno = EFAULT; return -1; } - - /* remember original len for the return value */ - int const orig_count = len; - char *src = (char *)buf; - - while (len > 0) { - - Genode::size_t curr_len = Genode::min(sizeof (sysio()->send_in.buf), len); - - sysio()->send_in.fd = noux_fd(fd->context); - sysio()->send_in.len = curr_len; - Genode::memcpy(sysio()->send_in.buf, src, curr_len); - - if (!noux_syscall(Noux::Session::SYSCALL_SEND)) { - error("write error ", (int)sysio()->error.general); - switch (sysio()->error.send) { - case Noux::Sysio::SEND_ERR_AGAIN: errno = EAGAIN; break; - case Noux::Sysio::SEND_ERR_WOULD_BLOCK: errno = EWOULDBLOCK; break; - case Noux::Sysio::SEND_ERR_CONNECTION_RESET: errno = ECONNRESET; break; - case Noux::Sysio::SEND_ERR_INVALID: errno = EINVAL; break; - case Noux::Sysio::SEND_ERR_IS_CONNECTED: errno = EISCONN; break; - case Noux::Sysio::SEND_ERR_NO_MEMORY: errno = ENOMEM; break; - default: errno = 0; break; - } - /* return foo */ - } - - len -= curr_len; - src += curr_len; - } - return orig_count; - } - - - ssize_t Plugin::sendto(Libc::File_descriptor *fd, const void *buf, size_t len, int flags, - const struct sockaddr *dest_addr, socklen_t addrlen) - { - if (!buf) { errno = EFAULT; return -1; } - - int const orig_count = len; - - if (addrlen > sizeof (sysio()->sendto_in.dest_addr)) { - errno = 0; /* XXX */ - return -1; - } - - /* wipe-out sendto buffer */ - Genode::memset(sysio()->sendto_in.buf, 0, sizeof (sysio()->sendto_in.buf)); - - char *src = (char *)buf; - while (len > 0) { - size_t curr_len = Genode::min(sizeof (sysio()->sendto_in.buf), len); - - sysio()->sendto_in.fd = noux_fd(fd->context); - sysio()->sendto_in.len = curr_len; - Genode::memcpy(sysio()->sendto_in.buf, src, curr_len); - - if (addrlen == 0) { - sysio()->sendto_in.addrlen = 0; - Genode::memset(&sysio()->sendto_in.dest_addr, 0, sizeof (struct sockaddr)); - } - else { - sysio()->sendto_in.addrlen = addrlen; - Genode::memcpy(&sysio()->sendto_in.dest_addr, dest_addr, addrlen); - } - - if (!noux_syscall(Noux::Session::SYSCALL_SENDTO)) { - switch (sysio()->error.send) { - case Noux::Sysio::SEND_ERR_AGAIN: errno = EAGAIN; break; - case Noux::Sysio::SEND_ERR_WOULD_BLOCK: errno = EWOULDBLOCK; break; - case Noux::Sysio::SEND_ERR_CONNECTION_RESET: errno = ECONNRESET; break; - case Noux::Sysio::SEND_ERR_INVALID: errno = EINVAL; break; - case Noux::Sysio::SEND_ERR_IS_CONNECTED: errno = EISCONN; break; - case Noux::Sysio::SEND_ERR_NO_MEMORY: errno = ENOMEM; break; - default: errno = 0; break; - } - return -1; - } - - len -= curr_len; - src += curr_len; - } - - return orig_count; - } - - - int Plugin::shutdown(Libc::File_descriptor *fd, int how) - { - sysio()->shutdown_in.fd = noux_fd(fd->context); - sysio()->shutdown_in.how = how; - - if (!noux_syscall(Noux::Session::SYSCALL_SHUTDOWN)) { - switch (sysio()->error.shutdown) { - case Noux::Sysio::SHUTDOWN_ERR_NOT_CONNECTED: errno = ENOTCONN; break; - default: errno = 0; break; - } - return -1; - } - - return 0; - } - -} /* unnamed namespace */ - - -/************************************** - ** Obtaining command-line arguments ** - **************************************/ - -/* external symbols provided by Genode's startup code */ -extern char **genode_argv; -extern int genode_argc; -extern char **genode_envp; - -/* pointer to environment, provided by libc */ -extern char **environ; - - -/* register noux libc plugin at libc */ -static Plugin noux_plugin; - - -void Plugin::init(Genode::Env &env) -{ - _env_ptr = &env; - noux_connection(); - - /* register inherited open file descriptors */ - int fd = 0; - while ((fd = noux()->next_open_fd(fd)) != -1) { - Libc::file_descriptor_allocator()->alloc(this, noux_context(fd), fd); - fd++; - } - - sigemptyset(&signal_mask); - - /* copy command-line arguments from 'args' ROM dataspace */ - enum { MAX_ARGS = 256, ARG_BUF_SIZE = sizeof(Noux::Sysio::Args) }; - static char *argv[MAX_ARGS]; - static char arg_buf[ARG_BUF_SIZE]; - { - Genode::Attached_rom_dataspace ds(env, "args"); - Genode::memcpy(arg_buf, ds.local_addr(), - Genode::min((size_t)ARG_BUF_SIZE, ds.size())); - } - - int argc = 0; - for (unsigned i = 0; arg_buf[i] && (i < ARG_BUF_SIZE - 2); ) { - - if (i >= ARG_BUF_SIZE - 2) { - warning("command-line argument buffer exceeded"); - break; - } - - if (argc >= MAX_ARGS - 1) { - warning("number of command-line arguments exceeded"); - break; - } - - argv[argc] = &arg_buf[i]; - i += Genode::strlen(&arg_buf[i]) + 1; /* skip null-termination */ - argc++; - } - - /* register command-line arguments at Genode's startup code */ - genode_argv = argv; - genode_argc = argc; - - /* - * Make environment variables from 'env' ROM dataspace available to libc's - * 'environ'. - */ - enum { ENV_MAX_ENTRIES = 128, ENV_BUF_SIZE = 8*1024 }; - static char *env_array[ENV_MAX_ENTRIES]; - static char env_buf[ENV_BUF_SIZE]; - { - Genode::Attached_rom_dataspace ds(env, "env"); - Genode::memcpy(env_buf, ds.local_addr(), - Genode::min((size_t)ENV_BUF_SIZE, ds.size())); - } - char *env_string = &env_buf[0]; - - unsigned num_entries = 0; /* index within 'env_array' */ - - static Libc::Absolute_path noux_cwd("/"); - - while (*env_string && (num_entries < ENV_MAX_ENTRIES - 1)) { - if ((strlen(env_string) >= strlen("NOUX_CWD=")) && - (strncmp(env_string, "NOUX_CWD=", strlen("NOUX_CWD=")) == 0)) { - noux_cwd.import(&env_string[strlen("NOUX_CWD=")]); - } else { - env_array[num_entries++] = env_string; - } - env_string += (strlen(env_string) + 1); - } - env_array[num_entries] = 0; - - /* register list of environment variables at libc 'environ' pointer */ - environ = env_array; - - /* define env pointer to be passed to main function (in '_main.cc') */ - genode_envp = environ; - - chdir(noux_cwd.base()); -} - - diff --git a/repos/ports/src/lib/libc_noux/target.mk b/repos/ports/src/lib/libc_noux/target.mk deleted file mode 100644 index 402046338..000000000 --- a/repos/ports/src/lib/libc_noux/target.mk +++ /dev/null @@ -1,4 +0,0 @@ -TARGET = libc_noux -LIBS = posix libc_noux - -CC_CXX_WARN_STRICT = diff --git a/repos/ports/src/noux/args.h b/repos/ports/src/noux/args.h deleted file mode 100644 index 3eb4209e1..000000000 --- a/repos/ports/src/noux/args.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * \brief Handling command-line for Noux processes - * \author Norman Feske - * \date 2011-01-17 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__ARGS_H_ -#define _NOUX__ARGS_H_ - -/* Genode includes */ -#include -#include -#include - -namespace Noux { - class Args; - class Args_dataspace; -} - - -class Noux::Args -{ - protected: - - char * const _buf; - size_t const _buf_size; - size_t _len; - - size_t _free_size() const - { - /* - * Keep space for two trailing zeros, indicating the end of the - * stream of strings. - */ - return _buf_size - _len - 2; - } - - public: - - class Overrun { }; - - /** - * Constructor - * - * \param buf argument buffer - * \param buf_size size of argument buffer in character, - * must be at least 2 - */ - Args(char *buf, size_t buf_size) - : _buf(buf), _buf_size(buf_size), _len(0) - { - if (buf_size <= 2) - throw Overrun(); - - /* search end of string stream (two subsequent zeros) */ - for (; (_buf[_len] || _buf[_len + 1]) && (_len < _buf_size - 2); _len++); - - /* ensure termination of argument buffer */ - _buf[_buf_size - 1] = 0; - _buf[_buf_size - 2] = 0; - } - - Args() : _buf(0), _buf_size(0), _len(0) { } - - bool valid() const { return _buf_size > 0; } - - size_t len() const { return _len; } - - char const *base() const { return _buf; } - - void append(char const *arg) - { - size_t const arg_len = strlen(arg); - - if (arg_len > _free_size()) - throw Overrun(); - - strncpy(_buf + _len, arg, _buf_size - _len); - - _len += arg_len + 1; /* keep null termination between strings */ - - /* mark end of stream of strings */ - _buf[_len] = 0; - } - - void dump() - { - for (unsigned i = 0, j = 0; _buf[i] && (i < _buf_size - 2); - i += strlen(&_buf[i]) + 1, j++) - log("arg(", j, "): \"", Cstring(&_buf[i]), "\""); - } -}; - - -struct Noux::Args_dataspace : private Attached_ram_dataspace, Args -{ - Args_dataspace(Ram_allocator &ram, Region_map &rm, - size_t size, Args const &from = Args()) - : - Attached_ram_dataspace(ram, rm, size), - Args(local_addr(), size) - { - if (from.len() > size - 2) - throw Overrun(); - - memcpy(_buf, from.base(), from.len() + 1); - } - - using Attached_ram_dataspace::cap; -}; - -#endif /* _NOUX__ARGS_H_ */ diff --git a/repos/ports/src/noux/armed_timeout.h b/repos/ports/src/noux/armed_timeout.h deleted file mode 100644 index ad1e2d4bc..000000000 --- a/repos/ports/src/noux/armed_timeout.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * \brief Timeout mechanism for 'select' - * \author Norman Feske - * \date 2011-02-14 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__ARMED_TIMEOUT_H_ -#define _NOUX__ARMED_TIMEOUT_H_ - -#include - -namespace Noux { class Armed_timeout; } - - -class Noux::Armed_timeout : Noncopyable -{ - public: - - struct State : Noncopyable - { - State() { } - bool timed_out { }; - }; - - private: - - State &_state; - Lock &_blocker; - - Timer::One_shot_timeout _one_shot_timeout; - - void _handle_one_shot_timeout(Duration) - { - _state.timed_out = true; - _blocker.unlock(); - } - - public: - - Armed_timeout(State &state, Lock &blocker, - Timer::Connection &timer, Microseconds microseconds) - : - _state(state), _blocker(blocker), - _one_shot_timeout(timer, *this, &Armed_timeout::_handle_one_shot_timeout) - { - _state.timed_out = false; - _one_shot_timeout.schedule(microseconds); - } - - void discard() { _one_shot_timeout.discard(); } -}; - -#endif /* _NOUX__ARMED_TIMEOUT_H_ */ diff --git a/repos/ports/src/noux/child.h b/repos/ports/src/noux/child.h deleted file mode 100644 index 06acf98b0..000000000 --- a/repos/ports/src/noux/child.h +++ /dev/null @@ -1,586 +0,0 @@ -/* - * \brief Noux child process - * \author Norman Feske - * \date 2011-02-17 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__CHILD_H_ -#define _NOUX__CHILD_H_ - -/* Genode includes */ -#include -#include -#include - -/* Noux includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 - */ -class Noux::Pid_allocator -{ - private: - - Lock _lock { }; - int _num_pids { 0 }; - - public: - - int alloc() - { - Lock::Guard guard(_lock); - return _num_pids++; - } -}; - - -struct Noux::Child_config : Attached_ram_dataspace -{ - enum { CONFIG_DS_SIZE = 4096 }; - - Child_config(Ram_allocator &ram, Region_map &local_rm, Verbose const &verbose) - : - Attached_ram_dataspace(ram, local_rm, CONFIG_DS_SIZE) - { - Xml_generator xml(local_addr(), CONFIG_DS_SIZE, "config", [&] () - { - if (verbose.ld()) - xml.attribute("ld_verbose", "yes"); - - xml.node("ld", [&] () { - xml.node("library", [&] () { - xml.attribute("rom", "libc_noux.lib.so"); }); }); - }); - } -}; - - -class Noux::Child : public Rpc_object, - public File_descriptor_registry, - public Family_member, - public Destruct_queue::Element, - public Interrupt_handler -{ - private: - - /* - * Noncopyable - */ - Child(Child const &); - Child &operator = (Child const &); - - Child_policy::Name const _name; - - Verbose const &_verbose; - - User_info const &_user_info; - - Time_info const &_time_info; - - Parent_exit *_parent_exit; - Kill_broadcaster &_kill_broadcaster; - Timer::Connection &_timer_connection; - Parent_execve &_parent_execve; - Pid_allocator &_pid_allocator; - - Env &_env; - - Vfs::File_system &_root_dir; - - Vfs_io_waiter_registry &_vfs_io_waiter_registry; - Vfs_handle_context _vfs_handle_context { }; - - Destruct_queue &_destruct_queue; - - void _handle_destruct() { _destruct_queue.insert(this); } - - Signal_handler _destruct_handler { - _env.ep(), *this, &Child::_handle_destruct }; - - Allocator &_heap; - - /** - * Entrypoint used to serve the RPC interfaces of the - * locally-provided services - */ - enum { STACK_SIZE = 64*1024 }; - Rpc_entrypoint _ep { &_env.pd(), STACK_SIZE, "noux_process", false }; - - Pd_session &_ref_pd; - Pd_session_capability const _ref_pd_cap; - - /** - * Registry of dataspaces owned by the Noux process - */ - Dataspace_registry _ds_registry { _heap }; - - /** - * Locally-provided PD service - */ - typedef Local_service Pd_service; - Pd_session_component _pd { _heap, _env, _ep, _name, _ds_registry }; - Pd_service::Single_session_factory _pd_factory { _pd }; - Pd_service _pd_service { _pd_factory }; - - /** - * Locally-provided CPU service - */ - typedef Local_service Cpu_service; - Cpu_session_component _cpu { _env, _ep, _name, false, _ds_registry }; - Cpu_service::Single_session_factory _cpu_factory { _cpu }; - Cpu_service _cpu_service { _cpu_factory }; - - /* - * Locally-provided Noux service - */ - Capability_guard _cap_guard { _ep, *this }; - - typedef Local_service > Noux_service; - Noux_service::Single_session_factory _noux_factory { *this }; - Noux_service _noux_service { _noux_factory }; - - /* - * Locally-provided ROM service - */ - Empty_rom_factory _empty_rom_factory { _heap, _ep }; - Empty_rom_service _empty_rom_service { _empty_rom_factory }; - Local_rom_factory _rom_factory { _heap, _env, _ep, _root_dir, - _vfs_io_waiter_registry, _ds_registry }; - Local_rom_service _rom_service { _rom_factory }; - - /** - * Command line arguments - */ - enum { ARGS_DS_SIZE = sizeof(Sysio::Args) }; - - Args_dataspace _args; - - /** - * Environment variables - */ - Environment _sysio_env; - - /* - * Child configuration - */ - Child_config _config { _ref_pd, _env.rm(), _verbose }; - - enum { PAGE_SIZE = 4096, PAGE_MASK = ~(PAGE_SIZE - 1) }; - enum { SYSIO_DS_SIZE = PAGE_MASK & (sizeof(Sysio) + PAGE_SIZE - 1) }; - - Attached_ram_dataspace _sysio_ds { _ref_pd, _env.rm(), SYSIO_DS_SIZE }; - Sysio &_sysio = *_sysio_ds.local_addr(); - - typedef Ring_buffer - Signal_queue; - Signal_queue _pending_signals { }; - - Parent_services &_parent_services; - - Static_dataspace_info _sysio_ds_info; - Static_dataspace_info _args_ds_info; - Static_dataspace_info _sysio_env_ds_info; - Static_dataspace_info _config_ds_info; - - Child_policy _child_policy; - - Genode::Child _child; - - /** - * Exception type for failed file-descriptor lookup - */ - class Invalid_fd { }; - - Shared_pointer _lookup_channel(int fd) const - { - Shared_pointer channel = io_channel_by_fd(fd); - - if (channel) - return channel; - - throw Invalid_fd(); - } - - /** - * Let specified child inherit our file descriptors - */ - void _assign_io_channels_to(Child *child, bool skip_when_close_on_execve_set) - { - for (int fd = 0; fd < MAX_FILE_DESCRIPTORS; fd++) - if (fd_in_use(fd)) { - if (skip_when_close_on_execve_set && close_fd_on_execve(fd)) - continue; - child->add_io_channel(io_channel_by_fd(fd), fd); - child->close_fd_on_execve(fd, close_fd_on_execve(fd)); - } - } - - /** - * Block until the IO channel is ready for reading or writing or an - * exception occured. - * - * \param io the IO channel - * \param rd check for data available for reading - * \param wr check for readiness for writing - * \param ex check for exceptions - */ - void _block_for_io_channel(Shared_pointer &io, - bool rd, bool wr, bool ex) - { - /* reset the blocker lock to the 'locked' state */ - _blocker.unlock(); - _blocker.lock(); - - Wake_up_notifier notifier(&_blocker); - io->register_wake_up_notifier(¬ifier); - - for (;;) { - if (io->check_unblock(rd, wr, ex) || - !_pending_signals.empty()) - break; - - /* block (unless the lock got unlocked in the meantime) */ - _blocker.lock(); - } - - io->unregister_wake_up_notifier(¬ifier); - } - - void _destruct() - { - _ep.dissolve(this); - - if (init_process(this)) - init_process_exited(_child_policy.exit_value()); - } - - public: - - struct Insufficient_memory : Exception { }; - - /** - * Constructor - * - * \param forked false if the child is spawned directly from - * an executable binary (i.e., the init process, - * or children created via execve, or - * true if the child is a fork from another child - * - * \throw Insufficent_memory if the child could not be started by - * the parent - */ - Child(Child_policy::Name const &name, - Verbose const &verbose, - User_info const &user_info, - Time_info const &time_info, - Parent_exit *parent_exit, - Kill_broadcaster &kill_broadcaster, - Timer::Connection &timer_connection, - Parent_execve &parent_execve, - Pid_allocator &pid_allocator, - int pid, - Env &env, - Vfs::File_system &root_dir, - Vfs_io_waiter_registry &vfs_io_waiter_registry, - Args const &args, - Sysio::Env const &sysio_env, - Allocator &heap, - Pd_session &ref_pd, - Pd_session_capability ref_pd_cap, - Parent_services &parent_services, - bool forked, - Destruct_queue &destruct_queue) - : - Family_member(pid), - Destruct_queue::Element(heap), - _name(name), - _verbose(verbose), - _user_info(user_info), - _time_info(time_info), - _parent_exit(parent_exit), - _kill_broadcaster(kill_broadcaster), - _timer_connection(timer_connection), - _parent_execve(parent_execve), - _pid_allocator(pid_allocator), - _env(env), - _root_dir(root_dir), - _vfs_io_waiter_registry(vfs_io_waiter_registry), - _destruct_queue(destruct_queue), - _heap(heap), - _ref_pd (ref_pd), _ref_pd_cap (ref_pd_cap), - _args(ref_pd, _env.rm(), ARGS_DS_SIZE, args), - _sysio_env(_ref_pd, _env.rm(), sysio_env), - _parent_services(parent_services), - _sysio_ds_info(_ds_registry, _sysio_ds.cap()), - _args_ds_info(_ds_registry, _args.cap()), - _sysio_env_ds_info(_ds_registry, _sysio_env.cap()), - _config_ds_info(_ds_registry, _config.cap()), - _child_policy(name, forked, - _args.cap(), _sysio_env.cap(), _config.cap(), - _ep, _pd_service, _cpu_service, - _noux_service, _empty_rom_service, - _rom_service, _parent_services, - *this, parent_exit, *this, _destruct_handler, - ref_pd, ref_pd_cap, - _verbose.enabled()), - _child(_env.rm(), _ep, _child_policy) - { - if (_verbose.enabled()) - _args.dump(); - - if (!_child.main_thread_cap().valid()) { - _destruct(); - throw Insufficient_memory(); - } - } - - ~Child() { _destruct(); } - - void start() { _ep.activate(); } - - void start_forked_main_thread(addr_t ip, addr_t sp, addr_t parent_cap_addr) - { - /* poke parent_cap_addr into child's address space */ - Capability::Raw const raw = _child.parent_cap().raw(); - - _pd.poke(_env.rm(), parent_cap_addr, (char *)&raw, sizeof(raw)); - - /* start execution of new main thread at supplied trampoline */ - _cpu.start_main_thread(ip, sp); - } - - void submit_exit_signal() - { - if (init_process(this)) { - log("init process exited"); - - /* trigger exit of main event loop */ - init_process_exited(_child_policy.exit_value()); - } else { - Signal_transmitter(_destruct_handler).submit(); - } - } - - Pd_session_component &pd() { return _pd; } - - Dataspace_registry &ds_registry() { return _ds_registry; } - - - /**************************** - ** Noux session interface ** - ****************************/ - - Dataspace_capability sysio_dataspace() override - { - return _sysio_ds.cap(); - } - - Capability lookup_region_map(addr_t const addr) override - { - return _pd.lookup_region_map(addr); - } - - bool syscall(Syscall sc) override; - - int next_open_fd(int start_fd) override - { - if (start_fd >= 0) - for (int fd = start_fd; fd < MAX_FILE_DESCRIPTORS; fd++) - if (fd_in_use(fd)) - return fd; - return -1; - } - - - /**************************************** - ** File_descriptor_registry overrides ** - ****************************************/ - - /** - * Find out if the IO channel associated with 'fd' has more file - * descriptors associated with it - */ - bool _is_the_only_fd_for_io_channel(int fd, - Shared_pointer io_channel) - { - for (int f = 0; f < MAX_FILE_DESCRIPTORS; f++) { - if ((f != fd) && - fd_in_use(f) && - (io_channel_by_fd(f) == io_channel)) - return false; - } - - return true; - } - - int add_io_channel(Shared_pointer io_channel, int fd = -1) override - { - fd = File_descriptor_registry::add_io_channel(io_channel, fd); - - /* Register the interrupt handler only once per IO channel */ - if (_is_the_only_fd_for_io_channel(fd, io_channel)) { - Io_channel_listener *l = new (_heap) Io_channel_listener(this); - io_channel->register_interrupt_handler(l); - } - - return fd; - } - - void remove_io_channel(int fd) override - { - Shared_pointer io_channel = _lookup_channel(fd); - - /* - * Unregister the interrupt handler only if there are no other - * file descriptors associated with the 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->unregister_interrupt_handler(l); - Genode::destroy(_heap, l); - } - - File_descriptor_registry::remove_io_channel(fd); - } - - void flush() override - { - for (int fd = 0; fd < MAX_FILE_DESCRIPTORS; fd++) - try { - remove_io_channel(fd); - } catch (Invalid_fd) { } - } - - - /***************************** - ** Family_member interface ** - *****************************/ - - void submit_signal(Noux::Sysio::Signal sig) override - { - try { - _pending_signals.add(sig); - } catch (Signal_queue::Overflow) { - error("signal queue is full - signal dropped"); - } - - _blocker.unlock(); - } - - Family_member *do_execve(const char *filename, - Args const &args, - Sysio::Env const &env) override - { - Lock::Guard signal_lock_guard(signal_lock()); - - Child *child = new (_heap) Child(filename, - _verbose, - _user_info, - _time_info, - _parent_exit, - _kill_broadcaster, - _timer_connection, - _parent_execve, - _pid_allocator, - pid(), - _env, - _root_dir, - _vfs_io_waiter_registry, - args, - env, - _heap, - _ref_pd, _ref_pd_cap, - _parent_services, - false, - _destruct_queue); - - _assign_io_channels_to(child, true); - - /* move the signal queue */ - while (!_pending_signals.empty()) - child->_pending_signals.add(_pending_signals.get()); - - /* - * Close all open files. - * - * This action is not part of the child destructor, - * because in the case that a child exits itself, - * it may need to close all files to unblock the - * parent (which might be reading from a pipe) before - * the parent can destroy the child object. - */ - flush(); - - /* signal main thread to remove ourself */ - Signal_transmitter(_destruct_handler).submit(); - - /* start executing the new process */ - child->start(); - - /* this child will be removed by the execve_finalization_dispatcher */ - - return child; - } - - - /********************************* - ** Interrupt_handler interface ** - *********************************/ - - void handle_interrupt(Sysio::Signal signal) override - { - submit_signal(signal); - } -}; - -#endif /* _NOUX__CHILD_H_ */ diff --git a/repos/ports/src/noux/child_env.h b/repos/ports/src/noux/child_env.h deleted file mode 100644 index fc44663fe..000000000 --- a/repos/ports/src/noux/child_env.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * \brief Noux child environment - * \author Christian Prochaska - * \author Norman Feske - * \date 2012-07-19 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__CHILD_ENV_H_ -#define _NOUX__CHILD_ENV_H_ - -/* Genode includes */ -#include - -/* Noux includes */ -#include -#include - -namespace Noux { - template class Child_env; - using namespace Genode; -} - - -/** - * \param ARGS_SIZE size of the argument buffer given - * to the constructor - */ -template -class Noux::Child_env -{ - private: - - static unsigned constexpr MAX_LEN_INTERPRETER_LINE = 128; - - char const *_binary_name { nullptr }; - char _args[ARGS_SIZE + MAX_LEN_INTERPRETER_LINE]; - Sysio::Env _env; - - void _process_env(Sysio::Env env) - { - memcpy(_env, env, sizeof(Sysio::Env)); - } - - /** - * Verify that the file exists and return its size - */ - Vfs::file_size _file_size(Vfs::File_system &root_dir, - char const *binary_name) - { - Vfs::Directory_service::Stat stat_out; - Vfs::Directory_service::Stat_result stat_result; - - stat_result = root_dir.stat(binary_name, stat_out); - - switch (stat_result) { - case Vfs::Directory_service::STAT_OK: - break; - case Vfs::Directory_service::STAT_ERR_NO_ENTRY: - throw Binary_does_not_exist(); - case Vfs::Directory_service::STAT_ERR_NO_PERM: - throw Binary_is_not_accessible(); - } - - return stat_out.size; - } - - /** - * Verify that the file is a valid ELF executable - */ - void _verify_elf(char const *file) - { - if ((file[0] != 0x7f) || - (file[1] != 'E') || - (file[2] != 'L') || - (file[3] != 'F')) - throw Binary_is_not_executable(); - } - - /** - * Handle the case that the given binary needs an interpreter - */ - void _process_binary_name_and_args(char const *binary_name, - char const *args, - Vfs::File_system &root_dir, - Vfs_io_waiter_registry &vfs_io_waiter_registry, - Ram_allocator &ram, - Region_map &rm, - Allocator &alloc) - { - Vfs::file_size binary_size = _file_size(root_dir, binary_name); - - if (binary_size == 0) - throw Binary_is_not_executable(); - - /* - * We may have to check the dataspace twice because the binary - * could be a script that uses an interpreter which might not - * exist. - */ - Reconstructible binary_ds { - root_dir, vfs_io_waiter_registry, - binary_name, ram, rm, alloc - }; - - if (!binary_ds->ds.valid()) - throw Binary_is_not_executable(); - - Reconstructible attached_binary_ds(rm, binary_ds->ds); - - char const *binary_addr = attached_binary_ds->local_addr(); - - /* look for '#!' */ - if ((binary_addr[0] != '#') || (binary_addr[1] != '!')) { - _binary_name = binary_name; - Genode::memcpy(_args, args, ARGS_SIZE); - _verify_elf(binary_addr); - return; - } - - /* find end of line */ - Range_checked_index - eol(2, min(binary_size, MAX_LEN_INTERPRETER_LINE)); - - try { - while (binary_addr[eol] != '\n') eol++; - } catch (Index_out_of_range) { } - - /* skip leading spaces */ - Range_checked_index - interpreter_line_cursor(2, eol); - - try { - while (binary_addr[interpreter_line_cursor] == ' ') - interpreter_line_cursor++; - } catch (Index_out_of_range) { } - - /* no interpreter name found */ - if (interpreter_line_cursor == eol) - throw Binary_does_not_exist(); - - int interpreter_name_start = interpreter_line_cursor; - - /* find end of interpreter name */ - try { - while (binary_addr[interpreter_line_cursor] != ' ') - interpreter_line_cursor++; - } catch (Index_out_of_range) { } - - size_t interpreter_name_len = - interpreter_line_cursor - interpreter_name_start; - - /* copy interpreter name into argument buffer */ - unsigned int args_buf_cursor = 0; - Genode::strncpy(&_args[args_buf_cursor], - &binary_addr[interpreter_name_start], - interpreter_name_len + 1); - _binary_name = &_args[args_buf_cursor]; - args_buf_cursor += interpreter_name_len + 1; - - /* skip more spaces */ - try { - while (binary_addr[interpreter_line_cursor] == ' ') - interpreter_line_cursor++; - } catch (Index_out_of_range) { } - - /* append interpreter arguments to argument buffer */ - size_t interpreter_args_len = eol - interpreter_line_cursor; - if (interpreter_args_len > 0) { - Genode::strncpy(&_args[args_buf_cursor], - &binary_addr[interpreter_line_cursor], - interpreter_args_len + 1); - args_buf_cursor += interpreter_args_len + 1; - } - - /* append script arguments to argument buffer */ - Genode::memcpy(&_args[args_buf_cursor], - args, ARGS_SIZE); - - /* check if interpreter exists and is executable */ - - binary_size = _file_size(root_dir, _binary_name); - - if (binary_size == 0) - throw Binary_is_not_executable(); - - binary_ds.construct(root_dir, vfs_io_waiter_registry, - _binary_name, ram, - rm, alloc); - - if (!binary_ds->ds.valid()) - throw Binary_is_not_executable(); - - attached_binary_ds.construct(rm, binary_ds->ds); - - _verify_elf(attached_binary_ds->local_addr()); - } - - public: - - struct Binary_does_not_exist : Exception { }; - struct Binary_is_not_accessible : Exception { }; - struct Binary_is_not_executable : Exception { }; - - Child_env(char const *binary_name, - char const *args, Sysio::Env env, - Vfs::File_system &root_dir, - Vfs_io_waiter_registry &vfs_io_waiter_registry, - Ram_allocator &ram, - Region_map &rm, - Allocator &alloc) - { - _process_env(env); - _process_binary_name_and_args(binary_name, args, root_dir, - vfs_io_waiter_registry, - ram, rm, alloc); - } - - char const *binary_name() const { return _binary_name; } - - Args args() { return Args(_args, sizeof(_args)); } - - Sysio::Env const &env() const { return _env; } -}; - -#endif /* _NOUX__CHILD_ENV_H_ */ diff --git a/repos/ports/src/noux/child_policy.h b/repos/ports/src/noux/child_policy.h deleted file mode 100644 index 82dde8356..000000000 --- a/repos/ports/src/noux/child_policy.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * \brief Noux child policy - * \author Norman Feske - * \date 2012-02-25 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__CHILD_POLICY_H_ -#define _NOUX__CHILD_POLICY_H_ - -/* Genode includes */ -#include - -/* Noux includes */ -#include -#include -#include -#include -#include - -namespace Noux { - - typedef Registered Parent_service; - typedef Registry Parent_services; - - typedef Local_service Pd_service; - typedef Local_service Cpu_service; - typedef Local_service > Noux_service; - - class Child_policy; -} - - -class Noux::Child_policy : public Genode::Child_policy -{ - private: - - /** - * Noncopyable - */ - Child_policy(Child_policy const &); - Child_policy &operator = (Child_policy const &); - - Name const _name; - bool _forked; - Init::Child_policy_provide_rom_file _args_policy; - Init::Child_policy_provide_rom_file _env_policy; - Init::Child_policy_provide_rom_file _config_policy; - Pd_service &_pd_service; - Cpu_service &_cpu_service; - Noux_service &_noux_service; - Empty_rom_service &_empty_rom_service; - Local_rom_service &_rom_service; - Parent_services &_parent_services; - Family_member &_family_member; - Parent_exit *_parent_exit; - File_descriptor_registry &_file_descriptor_registry; - Signal_context_capability _destruct_context_cap; - Pd_session &_ref_pd; - Pd_session_capability _ref_pd_cap; - int _exit_value; - bool _verbose; - - template - static Genode::Service *_find_service(Genode::Registry &services, - Genode::Service::Name const &name) - { - Genode::Service *service = nullptr; - services.for_each([&] (T &s) { - if (!service && (s.name() == name)) - service = &s; }); - return service; - } - - /** - * Find suitable service for a given session request - * - * \throw Service_denied - */ - Service &_matching_service(Service::Name const &service_name, - Session_label const &label) - { - /* - * Route initial ROM requests (binary and linker) of a forked child - * to the empty ROM service, since the ROMs are already attached in - * the replayed region map. - */ - if (_forked && (service_name == Genode::Rom_session::service_name())) { - if (label.last_element() == name()) return _empty_rom_service; - if (label.last_element() == linker_name()) return _empty_rom_service; - } - - Genode::Service *service = nullptr; - - /* check for local ROM requests */ - if ((service = _args_policy .resolve_session_request_with_label(service_name, label)) - || (service = _env_policy .resolve_session_request_with_label(service_name, label)) - || (service = _config_policy.resolve_session_request_with_label(service_name, label))) - return *service; - - /* check for local services */ - if (service_name == Genode::Cpu_session::service_name()) return _cpu_service; - if (service_name == Genode::Rom_session::service_name()) return _rom_service; - if (service_name == Genode::Pd_session::service_name()) return _pd_service; - if (service_name == Noux::Session::service_name()) return _noux_service; - - /* check for parent services */ - if ((service = _find_service(_parent_services, service_name))) - return *service; - - throw Service_denied(); - } - - public: - - Child_policy(Name const &name, - bool forked, - Dataspace_capability args_ds, - Dataspace_capability env_ds, - Dataspace_capability config_ds, - Rpc_entrypoint &entrypoint, - Pd_service &pd_service, - Cpu_service &cpu_service, - Noux_service &noux_service, - Empty_rom_service &empty_rom_service, - Local_rom_service &rom_service, - Parent_services &parent_services, - Family_member &family_member, - Parent_exit *parent_exit, - File_descriptor_registry &file_descriptor_registry, - Signal_context_capability destruct_context_cap, - Pd_session &ref_pd, - Pd_session_capability ref_pd_cap, - bool verbose) - : - _name(name), _forked(forked), - _args_policy( "args", args_ds, &entrypoint), - _env_policy( "env", env_ds, &entrypoint), - _config_policy("config", config_ds, &entrypoint), - _pd_service(pd_service), - _cpu_service(cpu_service), - _noux_service(noux_service), - _empty_rom_service(empty_rom_service), - _rom_service(rom_service), - _parent_services(parent_services), - _family_member(family_member), - _parent_exit(parent_exit), - _file_descriptor_registry(file_descriptor_registry), - _destruct_context_cap(destruct_context_cap), - _ref_pd (ref_pd), _ref_pd_cap (ref_pd_cap), - _exit_value(~0), - _verbose(verbose) - { } - - int exit_value() const { return _exit_value; } - - /**************************** - ** Child policy interface ** - ****************************/ - - Name name() const override { return _name; } - - Pd_session &ref_pd() override { return _ref_pd; } - Pd_session_capability ref_pd_cap() const override { return _ref_pd_cap; } - - void init(Pd_session &session, Pd_session_capability) override - { - session.ref_account(_ref_pd_cap); - } - - Route resolve_session_request(Service::Name const &service_name, - Session_label const &label) override - { - return Route { .service = _matching_service(service_name, label), - .label = label, - .diag = Session::Diag() }; - } - - void exit(int exit_value) override - { - _exit_value = exit_value; - - if (_verbose || (exit_value != 0)) - log("child ", _name, " exited with exit value ", exit_value); - - /* - * Close all open file descriptors. This is necessary to unblock - * the parent if it is trying to read from a pipe (connected to - * the child) before calling 'wait4()'. - */ - _file_descriptor_registry.flush(); - - _family_member.exit(exit_value); - - /* notify the parent */ - if (_parent_exit) - _parent_exit->exit_child(); - else { - /* handle exit of the init process */ - Signal_transmitter(_destruct_context_cap).submit(); - } - } - - Region_map *address_space(Pd_session &pd) override - { - return &static_cast(pd).address_space_region_map(); - } - - bool forked() const override { return _forked; } -}; - -#endif /* _NOUX__CHILD_POLICY_H_ */ diff --git a/repos/ports/src/noux/cpu_session_component.h b/repos/ports/src/noux/cpu_session_component.h deleted file mode 100644 index 6435c9ce2..000000000 --- a/repos/ports/src/noux/cpu_session_component.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * \brief CPU session provided to Noux processes - * \author Norman Feske - * \date 2012-02-22 - * - * The custom implementation of the CPU session interface is used to tweak - * the startup procedure as performed by the 'Process' class. Normally, - * processes start execution immediately at creation time at the ELF entry - * point. For implementing fork semantics, however, this default behavior - * does not work. Instead, we need to defer the start of the main thread - * until we have finished copying the address space of the forking process. - * Furthermore, we need to start the main thread at a custom trampoline - * function rather than at the ELF entry point. Those customizations are - * possible by wrapping core's CPU service. - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__CPU_SESSION_COMPONENT_H_ -#define _NOUX__CPU_SESSION_COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include -#include - -/* Noux includes */ -#include - -namespace Noux { - class Cpu_session_component; - using namespace Genode; -} - - -class Noux::Cpu_session_component : public Rpc_object -{ - private: - - Rpc_entrypoint &_ep; - bool const _forked; - Cpu_connection _cpu; - - enum { MAX_THREADS = 8, MAIN_THREAD_IDX = 0 }; - - Thread_capability _threads[MAX_THREADS]; - Dataspace_capability _trace_control { }; - Dataspace_registry &_registry; - - Constructible _ds_info { }; - - public: - - /** - * Constructor - * - * \param forked false if the CPU session belongs to a child - * created via execve or to the init process, or - * true if the CPU session belongs to a newly - * forked process. - * - * The 'forked' parameter controls the policy applied to the - * startup of the main thread. - */ - Cpu_session_component(Env &env, - Rpc_entrypoint &ep, - Child_policy::Name const &label, - bool forked, - Dataspace_registry ®istry) - : - _ep(ep), _forked(forked), _cpu(env, label.string()), _registry(registry) - { - _ep.manage(this); - } - - ~Cpu_session_component() - { - _ep.dissolve(this); - - if (!_trace_control.valid()) - return; - } - - /** - * Explicitly start main thread, only meaningful when - * 'forked' is true - */ - void start_main_thread(addr_t ip, addr_t sp) - { - Capability main_thread = _threads[MAIN_THREAD_IDX]; - Cpu_thread_client(main_thread).start(ip, sp); - } - - Cpu_session_capability cpu_cap() { return _cpu.cap(); } - - - /*************************** - ** Cpu_session interface ** - ***************************/ - - Thread_capability create_thread(Capability pd_cap, - Name const &name, - Affinity::Location affinity, - Weight weight, - addr_t utcb) override - { - /* create thread at core, keep local copy (needed on NOVA) */ - for (unsigned i = 0; i < MAX_THREADS; i++) { - if (_threads[i].valid()) - continue; - - auto lambda = [&] (Pd_session_component *pd) - { - if (!pd) - throw Thread_creation_failed(); - - return _cpu.create_thread(pd->core_pd_cap(), name, - affinity, weight, utcb); - }; - - Thread_capability cap = _ep.apply(pd_cap, lambda); - _threads[i] = cap; - return cap; - } - - error("maximum number of threads per session reached"); - throw Thread_creation_failed(); - } - - void kill_thread(Thread_capability thread) override - { - /* purge local copy of thread capability */ - for (unsigned i = 0; i < MAX_THREADS; i++) - if (_threads[i].local_name() == thread.local_name()) - _threads[i] = Thread_capability(); - - _cpu.kill_thread(thread); - } - - void exception_sigh(Signal_context_capability handler) override { - _cpu.exception_sigh(handler); } - - Affinity::Space affinity_space() const override { - return _cpu.affinity_space(); } - - Dataspace_capability trace_control() override - { - if (!_trace_control.valid()) { - _trace_control = _cpu.trace_control(); - _ds_info.construct(_registry, _trace_control); - } - return _trace_control; - } - - Quota quota() override { return _cpu.quota(); } - - int ref_account(Cpu_session_capability c) override { - return _cpu.ref_account(c); } - - int transfer_quota(Cpu_session_capability c, size_t q) override { - return _cpu.transfer_quota(c, q); } - - Capability native_cpu() override { - return _cpu.native_cpu(); } -}; - -#endif /* _NOUX__CPU_SESSION_COMPONENT_H_ */ diff --git a/repos/ports/src/noux/dataspace_registry.h b/repos/ports/src/noux/dataspace_registry.h deleted file mode 100644 index 3c02eeb70..000000000 --- a/repos/ports/src/noux/dataspace_registry.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * \brief Registry for dataspaces used by noux processes - * \author Norman Feske - * \date 2012-02-22 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__DATASPACE_REGISTRY_H_ -#define _NOUX__DATASPACE_REGISTRY_H_ - -/* Genode includes */ -#include -#include - -namespace Noux { - class Dataspace_user; - class Dataspace_info; - class Dataspace_registry; - - struct Static_dataspace_info; - - using namespace Genode; -} - - -struct Noux::Dataspace_user : Interface, private List::Element -{ - friend class Dataspace_info; - friend class List; - - virtual void dissolve(Dataspace_info &ds) = 0; -}; - - -class Noux::Dataspace_info : public Object_pool::Entry -{ - private: - - size_t _size; - Dataspace_capability _ds_cap; - Lock _users_lock { }; - List _users { }; - - public: - - Dataspace_info(Dataspace_capability ds_cap) - : - Object_pool::Entry(ds_cap), - _size(ds_cap.valid() ? Dataspace_client(ds_cap).size() : 0), - _ds_cap(ds_cap) - { } - - virtual ~Dataspace_info() { } - - size_t size() const { return _size; } - Dataspace_capability ds_cap() const { return _ds_cap; } - - void register_user(Dataspace_user &user) - { - Lock::Guard guard(_users_lock); - _users.insert(&user); - } - - void unregister_user(Dataspace_user &user) - { - Lock::Guard guard(_users_lock); - _users.remove(&user); - } - - void dissolve_users() - { - for (;;) { - Dataspace_user *user = 0; - { - Lock::Guard guard(_users_lock); - user = _users.first(); - if (!user) - break; - - _users.remove(user); - } - user->dissolve(*this); - } - } - - /** - * 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 - * the new dataspace - * \param ep entrypoint used to serve the RPC - * interface of the new dataspace - * (used if the dataspace is a sub - * RM session) - * \return capability for the new dataspace - */ - virtual Dataspace_capability fork(Ram_allocator &ram, - Region_map &local_rm, - Allocator &alloc, - Dataspace_registry &ds_registry, - Rpc_entrypoint &ep) = 0; - - /** - * 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 src data source buffer - * \param len length of source buffer in bytes - */ - 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 - * - * \param addr address that is covered by the requested region map - */ - virtual Capability lookup_region_map(addr_t) - { - /* by default a dataspace is no sub region map, so return invalid */ - return Capability(); - } -}; - - -class Noux::Dataspace_registry : public Object_pool -{ - private: - - Allocator &_alloc; - - public: - - Dataspace_registry(Allocator &alloc) : _alloc(alloc) { } - - ~Dataspace_registry() - { - /* - * At the time the destructor is called, most 'Dataspace_info' - * objects are expected to be gone already because - * 'Child::_resources' and 'Child::_child' are destructed - * before the 'Child::_ds_registry'. However, RM dataspaces - * created via 'Rm_dataspace_info::fork', are not handled by - * those destructors. So we have to clean them up here. - */ - remove_all([&] (Dataspace_info *info) { destroy(_alloc, info); }); - } -}; - - -struct Noux::Static_dataspace_info : Dataspace_info -{ - Dataspace_registry &_ds_registry; - - Static_dataspace_info(Dataspace_registry &ds_registry, - Dataspace_capability ds) - : Dataspace_info(ds), _ds_registry(ds_registry) - { - _ds_registry.insert(this); - } - - ~Static_dataspace_info() - { - auto lambda = [this] (Static_dataspace_info *info) { - - if (!info) { - error("lookup of binary ds info failed"); - return; - } - - _ds_registry.remove(info); - - info->dissolve_users(); - }; - _ds_registry.apply(ds_cap(), lambda); - } - - Dataspace_capability fork(Ram_allocator &, - Region_map &, - Allocator &, - Dataspace_registry &, - Rpc_entrypoint &) override - { - return ds_cap(); - } - - void poke(Region_map &, addr_t, char const *, size_t) override - { - error("attempt to poke onto a static dataspace"); - } -}; - -#endif /* _NOUX__DATASPACE_REGISTRY_H_ */ diff --git a/repos/ports/src/noux/destruct_queue.h b/repos/ports/src/noux/destruct_queue.h deleted file mode 100644 index 084878f88..000000000 --- a/repos/ports/src/noux/destruct_queue.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * \brief Queue for delayed object destruction - * \author Christian Prochaska - * \date 2013-01-03 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__DESTRUCT_QUEUE_H_ -#define _NOUX__DESTRUCT_QUEUE_H_ - -/* Genode includes */ -#include -#include - -namespace Noux { class Destruct_queue; } - - -class Noux::Destruct_queue -{ - public: - - struct Element_base : Interface, private Genode::List::Element - { - friend class List; - virtual void destroy() = 0; - }; - - /* - * When a pointer to an object which inherits 'Element' among other - * base classes gets static-casted to a pointer to the 'Element' - * base object, the resulting address can differ from the start - * address of the inherited object. To be able to pass the start - * address of the inherited object to the allocator, a static-cast - * back to the inherited class needs to be performed. Therefore the - * type of the class inheriting from 'Element' needs to be given as - * template parameter. - */ - template - class Element : public Element_base - { - private: - - Genode::Allocator &_alloc; - - public: - - /** - * Constructor - * - * \param alloc the allocator which was used to allocate - * the element - */ - Element(Genode::Allocator &alloc) : _alloc(alloc) { } - - virtual ~Element() { }; - - void destroy() override - { - Genode::destroy(_alloc, static_cast(this)); - } - }; - - private: - - Genode::List _destruct_list { }; - Genode::Lock _destruct_list_lock { }; - Signal_context_capability _sigh; - - public: - - Destruct_queue(Signal_context_capability sigh) : _sigh(sigh) { } - - void insert(Element_base *element) - { - Genode::Lock::Guard guard(_destruct_list_lock); - _destruct_list.insert(element); - - Signal_transmitter(_sigh).submit(); - } - - void flush() - { - Genode::Lock::Guard guard(_destruct_list_lock); - - Element_base *element; - while ((element = _destruct_list.first())) { - _destruct_list.remove(element); - element->destroy(); - } - } -}; - -#endif /* _NOUX__DESTRUCT_QUEUE_H_ */ diff --git a/repos/ports/src/noux/empty_rom_service.h b/repos/ports/src/noux/empty_rom_service.h deleted file mode 100644 index 79ce17a4f..000000000 --- a/repos/ports/src/noux/empty_rom_service.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * \brief ROM service provided to Noux processes for initial ROMs - * \author Christian Prochaska - * \date 2017-01-31 - * - * The initial ROMs (binary and linker) are already attached in a forked - * child and don't need a new ROM dataspace. - */ - -/* - * 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__EMPTY_ROM_SERVICE_H_ -#define _NOUX__EMPTY_ROM_SERVICE_H_ - -/* Genode includes */ -#include - -/* Noux includes */ -#include - -namespace Noux { - - typedef Local_service Empty_rom_service; - class Empty_rom_factory; -} - - -class Noux::Empty_rom_factory : public Empty_rom_service::Factory -{ - private: - - Allocator &_alloc; - Rpc_entrypoint &_ep; - - public: - - Empty_rom_factory(Allocator &alloc, Rpc_entrypoint &ep) - : _alloc(alloc), _ep(ep) { } - - Empty_rom_session_component &create(Args const &, Affinity) override - { - try { - return *new (_alloc) Empty_rom_session_component(_ep); } - catch (Rom_connection::Rom_connection_failed) { - throw Service_denied(); } - } - - void upgrade(Empty_rom_session_component &, Args const &) override { } - - void destroy(Empty_rom_session_component &session) override - { - Genode::destroy(_alloc, &session); - } -}; - -#endif /* _NOUX__EMPTY_ROM_SERVICE_H_ */ diff --git a/repos/ports/src/noux/empty_rom_session_component.h b/repos/ports/src/noux/empty_rom_session_component.h deleted file mode 100644 index ae5cf82ab..000000000 --- a/repos/ports/src/noux/empty_rom_session_component.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * \brief ROM session implementation used by Noux processes for initial ROMs - * \author Christian Prochaska - * \date 2017-01-31 - * - * The initial ROMs (binary and linker) are already attached in a forked - * child and don't need a new ROM dataspace. The invalid dataspace returned - * by this component is handled in 'Child::Process'. - */ - -/* - * 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__EMPTY_ROM_SESSION_COMPONENT_H_ -#define _NOUX__EMPTY_ROM_SESSION_COMPONENT_H_ - -/* Genode includes */ -#include - -namespace Noux { class Empty_rom_session_component; } - -class Noux::Empty_rom_session_component : public Rpc_object -{ - private: - - Rpc_entrypoint &_ep; - - public: - - Empty_rom_session_component(Rpc_entrypoint &ep) - : _ep(ep) - { - _ep.manage(this); - } - - ~Empty_rom_session_component() - { - _ep.dissolve(this); - } - - - /*************************** - ** ROM session interface ** - ***************************/ - - Rom_dataspace_capability dataspace() override - { - return Rom_dataspace_capability(); - } - - void sigh(Signal_context_capability) override { } -}; - -#endif /* _NOUX__EMPTY_ROM_SESSION_COMPONENT_H_ */ diff --git a/repos/ports/src/noux/environment.h b/repos/ports/src/noux/environment.h deleted file mode 100644 index 98da6c7e4..000000000 --- a/repos/ports/src/noux/environment.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * \brief Process environment utility - * \author Norman Feske - * \date 2011-02-17 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__ENVIRONMENT_H_ -#define _NOUX__ENVIRONMENT_H_ - -/* Genode includes */ -#include -#include - -/* Noux includes */ -#include - -namespace Noux { - class Environment; - using namespace Genode; -} - - -class Noux::Environment : Noncopyable -{ - private: - - Attached_ram_dataspace _ds; - - Sysio::Env &_env { *_ds.local_addr() }; - - public: - - /** - * Constructor - * - * \param env comma-separated list of environment variables - */ - Environment(Ram_allocator &ram, Region_map &local_rm, Sysio::Env const &env) - : _ds(ram, local_rm, sizeof(Sysio::Env)) - { - memcpy(&_env, &env, sizeof(Sysio::Env)); - } - - Dataspace_capability cap() { return _ds.cap(); } - - /** - * Return list of environment variables as zero-separated list - */ - Sysio::Env const &env() { return _env; } -}; - -#endif /* _NOUX__ENVIRONMENT_H_ */ diff --git a/repos/ports/src/noux/family_member.h b/repos/ports/src/noux/family_member.h deleted file mode 100644 index 1d00d0b01..000000000 --- a/repos/ports/src/noux/family_member.h +++ /dev/null @@ -1,177 +0,0 @@ -/* - * \brief Helper for handling the relationship between Noux processes - * \author Norman Feske - * \date 2012-02-25 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__FAMILY_MEMBER_H_ -#define _NOUX__FAMILY_MEMBER_H_ - -/* Genode includes */ -#include -#include - -/* Noux includes */ -#include -#include - -namespace Noux { class Family_member; } - - -class Noux::Family_member : private List::Element, - public Parent_exit, - public Parent_execve -{ - private: - - friend class List; - - int const _pid; - Lock _lock { }; - List _list { }; - bool _has_exited { false }; - int _exit_status { 0 }; - - protected: - - /** - * Lock used for implementing blocking syscalls, - * i.e., select, wait4, ... - */ - Lock _blocker { }; - - public: - - Family_member(int pid) : _pid(pid) { } - - virtual ~Family_member() { } - - int pid() const { return _pid; } - - int exit_status() const { return _exit_status; } - - /** - * Called by the parent at creation time of the process - */ - void insert(Family_member *member) - { - Lock::Guard guard(_lock); - _list.insert(member); - } - - /** - * Called by the parent from the return path of the wait4 syscall - */ - void remove(Family_member *member) - { - Lock::Guard guard(_lock); - _list.remove(member); - } - - virtual void submit_signal(Noux::Sysio::Signal sig) = 0; - - /** - * Called by the parent (originates from Kill_broadcaster) - */ - bool deliver_kill(int pid, Noux::Sysio::Signal sig) - { - Lock::Guard guard(_lock); - - if (pid == _pid) { - submit_signal(sig); - return true; - } - - bool result = false; - - for (Family_member *child = _list.first(); child; child = child->next()) - if (child->deliver_kill(pid, sig)) - result = true; - - return result; - } - - /** - * Parent_exit interface - */ - - /* Called by the child on the parent (via Parent_exit) */ - void exit_child() override - { - submit_signal(Sysio::Signal::SIG_CHLD); - } - - /** - * Parent_execve interface - */ - - /* Called by the parent from 'execve_child()' */ - virtual Family_member *do_execve(const char *filename, - Args const &args, - Sysio::Env const &env) = 0; - - /* Called by the child on the parent (via Parent_execve) */ - void execve_child(Family_member &child, - const char *filename, - Args const &args, - Sysio::Env const &env) override - { - Lock::Guard guard(_lock); - Family_member *new_child = child.do_execve(filename, - args, - env); - _list.insert(new_child); - _list.remove(&child); - } - - - /** - * Tell the parent that we exited - */ - void exit(int exit_status) - { - _exit_status = exit_status; - _has_exited = true; - } - - Family_member *poll4() - { - Lock::Guard guard(_lock); - - /* check if any of our children has exited */ - Family_member *curr = _list.first(); - for (; curr; curr = curr->next()) { - if (curr->_has_exited) - return curr; - } - return 0; - } - - /** - * Wait for the exit of any of our children - */ - Family_member *wait4() - { - /* reset the blocker lock to the 'locked' state */ - _blocker.unlock(); - _blocker.lock(); - - Family_member *result = poll4(); - if (result) - return result; - - _blocker.lock(); - - /* either a child exited or a signal occurred */ - return poll4(); - } -}; - -#endif /* _NOUX__FAMILY_MEMBER_H_ */ diff --git a/repos/ports/src/noux/file_descriptor_registry.h b/repos/ports/src/noux/file_descriptor_registry.h deleted file mode 100644 index e698152c1..000000000 --- a/repos/ports/src/noux/file_descriptor_registry.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * \brief Manager for file descriptors of one child - * \author Norman Feske - * \date 2011-02-17 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__FILE_DESCRIPTOR_REGISTRY_H_ -#define _NOUX__FILE_DESCRIPTOR_REGISTRY_H_ - -/* Noux includes */ -#include - -namespace Noux { class File_descriptor_registry; } - - -class Noux::File_descriptor_registry -{ - public: - - enum { MAX_FILE_DESCRIPTORS = 64 }; - - private: - - struct { - bool allocated; - bool close_on_execve; - Shared_pointer io_channel; - } _fds[MAX_FILE_DESCRIPTORS] { }; - - bool _valid_fd(int fd) const - { - return (fd >= 0) && (fd < MAX_FILE_DESCRIPTORS); - } - - bool _find_available_fd(int *fd) const - { - /* allocate the first free file descriptor */ - for (unsigned i = 0; i < MAX_FILE_DESCRIPTORS; i++) - if (_fds[i].allocated == false) { - *fd = i; - return true; - } - return false; - } - - void _assign_fd(int fd, Shared_pointer &io_channel) - { - _fds[fd].io_channel = io_channel; - _fds[fd].allocated = true; - _fds[fd].close_on_execve = false; - } - - void _reset_fd(int fd) - { - _fds[fd].io_channel = Shared_pointer(); - _fds[fd].allocated = false; - _fds[fd].close_on_execve = false; - } - - public: - - File_descriptor_registry() - { - flush(); - } - - virtual ~File_descriptor_registry() { } - - /** - * Associate I/O channel with file descriptor - * - * \return noux file descriptor used for the I/O channel - */ - virtual int add_io_channel(Shared_pointer io_channel, int fd = -1) - { - if ((fd == -1) && !_find_available_fd(&fd)) { - error("could not allocate file descriptor"); - return -1; - } - - if (!_valid_fd(fd)) { - error("file descriptor ", fd, " is out of range"); - return -2; - } - - _assign_fd(fd, io_channel); - return fd; - } - - virtual void remove_io_channel(int fd) - { - if (!_valid_fd(fd)) - error("file descriptor ", fd, " is out of range"); - else - _reset_fd(fd); - } - - bool fd_in_use(int fd) const - { - return (_valid_fd(fd) && _fds[fd].io_channel); - } - - Shared_pointer io_channel_by_fd(int fd) const - { - if (!fd_in_use(fd)) - return Shared_pointer(); - - return _fds[fd].io_channel; - } - - void close_fd_on_execve(int fd, bool close_on_execve) - { - if (!_valid_fd(fd)) - error("file descriptor ", fd, " is out of range"); - else - _fds[fd].close_on_execve = close_on_execve; - } - - bool close_fd_on_execve(int fd) - { - if (!_valid_fd(fd)) { - error("file descriptor ", fd, " is out of range"); - return false; - } - - return _fds[fd].close_on_execve; - } - - virtual void flush() - { - /* close all file descriptors */ - for (unsigned i = 0; i < MAX_FILE_DESCRIPTORS; i++) - _reset_fd(i); - } -}; - -#endif /* _NOUX__FILE_DESCRIPTOR_REGISTRY_H_ */ diff --git a/repos/ports/src/noux/interrupt_handler.h b/repos/ports/src/noux/interrupt_handler.h deleted file mode 100644 index 86132e89e..000000000 --- a/repos/ports/src/noux/interrupt_handler.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * \brief Interrupt handler interface - * \author Christian Prochaska - * \date 2013-10-08 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__INTERRUPT_HANDLER__H_ -#define _NOUX__INTERRUPT_HANDLER__H_ - -#include - -namespace Noux { - - struct Interrupt_handler : Genode::Interface - { - virtual void handle_interrupt(Sysio::Signal) = 0; - }; -}; - -#endif /* _NOUX__INTERRUPT_HANDLER__H_ */ - diff --git a/repos/ports/src/noux/io_channel.h b/repos/ports/src/noux/io_channel.h deleted file mode 100644 index 02e625d75..000000000 --- a/repos/ports/src/noux/io_channel.h +++ /dev/null @@ -1,201 +0,0 @@ -/* - * \brief I/O channel - * \author Norman Feske - * \date 2011-02-17 - * - * An 'Io_channel' is the interface for the operations on an open file - * descriptor. - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__IO_CHANNEL_H_ -#define _NOUX__IO_CHANNEL_H_ - -/* Genode includes */ -#include -#include - -/* Noux includes */ -#include -#include -#include -#include - -namespace Noux { - 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 - * different methods, which does not belong to the original - * interface, e.g. network methods. - */ -struct Noux::Io_channel_backend -{ - virtual ~Io_channel_backend() { } - - virtual int type() const { return -1; } -}; - - -/** - * Input/output channel interface - */ -class Noux::Io_channel : private Reference_counter -{ - private: - - friend class Shared_pointer; - - /** - * List of notifiers (i.e., processes) used by threads that block - * for an I/O-channel event - */ - List _notifiers { }; - Lock _notifiers_lock { }; - List _interrupt_handlers { }; - Lock _interrupt_handlers_lock { }; - - public: - - virtual ~Io_channel() { } - - virtual Io_channel_backend *backend() { return nullptr; } - - virtual bool write(Sysio &) { return false; } - virtual bool read(Sysio &) { return false; } - virtual bool fstat(Sysio &) { return false; } - virtual bool ftruncate(Sysio &) { return false; } - virtual bool fcntl(Sysio &) { return false; } - virtual bool dirent(Sysio &) { return false; } - virtual bool ioctl(Sysio &) { return false; } - virtual bool lseek(Sysio &) { return false; } - - /** - * Return true if an unblocking condition of the channel is satisfied - * - * \param rd if true, check for data available for reading - * \param wr if true, check for readiness for writing - * \param ex if true, check for exceptions - */ - virtual bool check_unblock(bool /* rd */, bool /* wr */, bool /* ex */) const { - return false; } - - /** - * Return true if the channel is set to non-blocking mode - */ - virtual bool nonblocking() { return false; } - - /** - * Register blocker for getting waked up on an I/O channel event - * - * This function is normally called by the to-be-blocked thread - * prior blocking itself, e.g., during a 'select' syscall. - */ - void register_wake_up_notifier(Wake_up_notifier *notifier) - { - Lock::Guard guard(_notifiers_lock); - - _notifiers.insert(notifier); - } - - /** - * Unregister wake-up notifier - * - * This function is normally called after a blocker has left the - * blocking condition, e.g., during the return from the 'select' - * syscall'. - */ - void unregister_wake_up_notifier(Wake_up_notifier *notifier) - { - Lock::Guard guard(_notifiers_lock); - - _notifiers.remove(notifier); - } - - /** - * Tell all registered notifiers about an occurred I/O event - * - * This function is called by I/O channel implementations that - * respond to external signals, e.g., the availability of new - * input from a terminal session. - */ - void invoke_all_notifiers() - { - Lock::Guard guard(_notifiers_lock); - - for (Wake_up_notifier *n = _notifiers.first(); n; n = n->next()) - n->wake_up(); - } - - /** - * Register interrupt handler - * - * This function is called by Child objects to get woken up if the - * terminal sends, for example, Ctrl-C. - */ - void register_interrupt_handler(Io_channel_listener *handler) - { - Lock::Guard guard(_interrupt_handlers_lock); - - _interrupt_handlers.insert(handler); - } - - /** - * Unregister interrupt handler - */ - void unregister_interrupt_handler(Io_channel_listener *handler) - { - Lock::Guard guard(_interrupt_handlers_lock); - - _interrupt_handlers.remove(handler); - } - - /** - * Find the 'Io_channel_listener' object which contains the given - * 'Interrupt_handler' pointer - */ - Io_channel_listener *lookup_io_channel_listener(Interrupt_handler *handler) - { - for (Io_channel_listener *l = _interrupt_handlers.first(); - l; l = l->next()) - if (l->object() == handler) - return l; - return 0; - } - - /** - * Tell all registered handlers about an interrupt event - */ - void invoke_all_interrupt_handlers(Sysio::Signal signal) - { - Lock::Guard signal_lock_guard(signal_lock()); - Lock::Guard guard(_interrupt_handlers_lock); - - for (Io_channel_listener *l = _interrupt_handlers.first(); - l; l = l->next()) - l->object()->handle_interrupt(signal); - } - - /** - * Get the path of the file associated with the I/O channel - * - * This function is used to simplify the implemenation of SYSCALL_FSTAT - * and is only implemented by Vfs_io_channel. - */ - virtual bool path(char * /* path */, size_t /* len */) { return false; } -}; - -#endif /* _NOUX__IO_CHANNEL_H_ */ diff --git a/repos/ports/src/noux/io_channel_listener.h b/repos/ports/src/noux/io_channel_listener.h deleted file mode 100644 index c80dadb78..000000000 --- a/repos/ports/src/noux/io_channel_listener.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * \brief IO channel listener - * \author Christian Prochaska - * \date 2014-01-23 - */ - -/* - * Copyright (C) 2014-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__IO_CHANNEL_LISTENER__H_ -#define _NOUX__IO_CHANNEL_LISTENER__H_ - -/* Genode includes */ -#include - -/* Noux includes */ -#include - -namespace Noux { typedef List_element Io_channel_listener; } - -#endif /* _NOUX__IO_CHANNEL_LISTENER__H_ */ - diff --git a/repos/ports/src/noux/io_receptor_registry.h b/repos/ports/src/noux/io_receptor_registry.h deleted file mode 100644 index 727702847..000000000 --- a/repos/ports/src/noux/io_receptor_registry.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * \brief Io receptor registry - * \author Josef Soentgen - * \date 2012-10-05 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__IO_RECEPTOR_REGISTRY_H_ -#define _NOUX__IO_RECEPTOR_REGISTRY_H_ - -/* Genode includes */ -#include -#include - - -namespace Noux { - struct Io_receptor; - struct Io_receptor_registry; -} - - -struct Noux::Io_receptor : List::Element -{ - private: - - Lock *_lock; - - public: - - Io_receptor(Lock *lock) : _lock(lock) { } - - void check_and_wakeup() - { - if (_lock) - _lock->unlock(); - } -}; - - -class Noux::Io_receptor_registry -{ - private: - - List _receptors { }; - Lock _receptors_lock { }; - - public: - - Io_receptor_registry() { } - - ~Io_receptor_registry() - { - Io_receptor *receptor; - while ((receptor = _receptors.first()) != 0) - _receptors.remove(receptor); - } - - void register_receptor(Io_receptor *receptor) - { - Lock::Guard guard(_receptors_lock); - - _receptors.insert(receptor); - } - - void unregister_receptor(Io_receptor *receptor) - { - Lock::Guard guard(_receptors_lock); - - _receptors.remove(receptor); - } - - Io_receptor *first() { return _receptors.first(); } -}; - -#endif /* _NOUX__IO_RECEPTOR_REGISTRY_H_ */ diff --git a/repos/ports/src/noux/kill_broadcaster.h b/repos/ports/src/noux/kill_broadcaster.h deleted file mode 100644 index 91c45a67b..000000000 --- a/repos/ports/src/noux/kill_broadcaster.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * \brief Kill_broadcaster interface - * \author Christian Prochaska - * \date 2014-01-13 - */ - -/* - * Copyright (C) 2014-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__KILL_BROADCASTER__H_ -#define _NOUX__KILL_BROADCASTER__H_ - -/* Noux includes */ -#include - -namespace Noux { - - struct Kill_broadcaster : Genode::Interface - { - virtual bool kill(int pid, Noux::Sysio::Signal sig) = 0; - }; -}; - -#endif /* _NOUX__KILL_BROADCASTER__H_ */ - diff --git a/repos/ports/src/noux/local_rom_service.h b/repos/ports/src/noux/local_rom_service.h deleted file mode 100644 index ec53a7ad5..000000000 --- a/repos/ports/src/noux/local_rom_service.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * \brief ROM service provided to Noux processes - * \author Norman Feske - * \date 2013-07-18 - * - * The local ROM service has the sole purpose of tracking ROM dataspaces - * so that they are properly detached from RM sessions when the corresponding - * ROM sessions are closed. - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__LOCAL_ROM_SERVICE_H_ -#define _NOUX__LOCAL_ROM_SERVICE_H_ - -/* Genode includes */ -#include - -/* Noux includes */ -#include -#include - -namespace Noux { - - typedef Local_service Local_rom_service; - class Local_rom_factory; -} - - -class Noux::Local_rom_factory : public Local_rom_service::Factory -{ - private: - - Allocator &_alloc; - Env &_env; - Rpc_entrypoint &_ep; - Vfs::File_system &_root_dir; - Vfs_io_waiter_registry &_vfs_io_waiter_registry; - Dataspace_registry &_registry; - - public: - - Local_rom_factory(Allocator &alloc, Env &env, Rpc_entrypoint &ep, - Vfs::File_system &root_dir, - Vfs_io_waiter_registry &vfs_io_waiter_registry, - Dataspace_registry ®istry) - : - _alloc(alloc), _env(env), _ep(ep), _root_dir(root_dir), - _vfs_io_waiter_registry(vfs_io_waiter_registry), - _registry(registry) - { } - - Rom_session_component &create(Args const &args, Affinity) override - { - try { - Rom_session_component::Name const rom_name = - label_from_args(args.string()).last_element(); - - return *new (_alloc) - Rom_session_component(_alloc, _env, _ep, _root_dir, - _vfs_io_waiter_registry, _registry, - rom_name); - } - catch (Rom_connection::Rom_connection_failed) { - throw Service_denied(); } - } - - void upgrade(Rom_session_component &, Args const &) override { } - - void destroy(Rom_session_component &session) override - { - Genode::destroy(_alloc, &session); - } -}; - -#endif /* _NOUX__LOCAL_ROM_SERVICE_H_ */ diff --git a/repos/ports/src/noux/main.cc b/repos/ports/src/noux/main.cc deleted file mode 100644 index 3fc8b2359..000000000 --- a/repos/ports/src/noux/main.cc +++ /dev/null @@ -1,340 +0,0 @@ -/* - * \brief Unix emulation environment for Genode - * \author Norman Feske - * \date 2011-02-14 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Genode includes */ -#include -#include -#include - -/* Noux includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Noux { - - static Noux::Child *init_child; - static int exit_value = ~0; - - bool init_process(Child *child) { return child == init_child; } - void init_process_exited(int exit) { init_child = 0; exit_value = exit; } -} - - -Noux::Io_receptor_registry * Noux::io_receptor_registry() -{ - static Noux::Io_receptor_registry _inst; - return &_inst; -} - - -/** - * Return string containing the environment variables of init - * - * The variable definitions are separated by zeros. The end of the string is - * marked with another zero. - */ -static Noux::Sysio::Env &env_string_of_init_process(Genode::Xml_node config) -{ - static Noux::Sysio::Env env; - int index = 0; - - /* read environment variables for init process from config */ - Genode::Xml_node start_node = config.sub_node("start"); - try { - Genode::Xml_node node = start_node.sub_node("env"); - for (; ; node = node.next("env")) { - - typedef Genode::String<256> Var; - Var const var(node.attribute_value("name", Var()), "=", - node.attribute_value("value", Var())); - - bool const env_exeeded = index + var.length() >= sizeof(env); - bool const var_exeeded = (var.length() == var.capacity()); - - if (env_exeeded || var_exeeded) { - warning("truncated environment variable: ", node); - env[index] = 0; - break; - } - - Genode::strncpy(&env[index], var.string(), var.length()); - index += var.length(); - } - } - catch (Genode::Xml_node::Nonexistent_sub_node) { } - - return env; -} - - -namespace Noux { class Stdio_unavailable : Genode::Exception { }; } - - -/* - * \throw Stdio_unavailable - */ -static Noux::Io_channel & -connect_stdio(Genode::Env &env, - Genode::Constructible &terminal, - Genode::Xml_node config, - Vfs::File_system &root, - Noux::Vfs_io_waiter_registry &vfs_io_waiter_registry, - Noux::Terminal_io_channel::Type type, - Genode::Allocator &alloc, - Noux::Time_info &time_info, - Timer::Connection &timer) -{ - using namespace Vfs; - using namespace Noux; - typedef Terminal_io_channel Tio; /* just a local abbreviation */ - - typedef Genode::String Path; - Vfs_handle *vfs_handle = nullptr; - char const *stdio_name = ""; - unsigned mode = 0; - - switch (type) { - case Tio::STDIN: - stdio_name = "stdin"; - mode = Directory_service::OPEN_MODE_RDONLY; - break; - case Tio::STDOUT: - stdio_name = "stdout"; - mode = Directory_service::OPEN_MODE_WRONLY; - break; - case Tio::STDERR: - stdio_name = "stderr"; - mode = Directory_service::OPEN_MODE_WRONLY; - break; - }; - - if (!config.has_attribute(stdio_name)) { - if (!terminal.constructed()) - terminal.construct(env); - warning(stdio_name, " VFS path not defined, connecting to terminal session"); - return *new (alloc) Tio(*terminal, type, env.ep()); - } - - Path const path = config.attribute_value(stdio_name, Path()); - - if (root.open(path.string(), mode, &vfs_handle, alloc) - != Directory_service::OPEN_OK) - { - error("failed to connect ", stdio_name, " to '", path, "'"); - throw Stdio_unavailable(); - } - - return *new (alloc) - Vfs_io_channel(path.string(), root.leaf_path(path.string()), - vfs_handle, vfs_io_waiter_registry, env.ep(), - time_info, timer); -} - - -/* - * This lock is needed to delay the insertion of signals into a child object. - * This is necessary during an 'execve()' syscall, when signals get copied from - * the old child object to the new one. Without the lock, an IO channel could - * insert a signal into both objects, which could lead to a duplicated signal - * in the new child object. - */ -Genode::Lock &Noux::signal_lock() -{ - static Genode::Lock inst; - return inst; -} - - -namespace Noux { struct Main; } - - -struct Noux::Main -{ - Env &_env; - - Heap _heap { _env.ram(), _env.rm() }; - - /* whitelist of service requests to be routed to the parent */ - Noux::Parent_services _parent_services { }; - - Noux::Parent_service _log_parent_service { _parent_services, _env, "LOG" }; - Noux::Parent_service _timer_parent_service { _parent_services, _env, "Timer" }; - - Attached_rom_dataspace _config { _env, "config" }; - - Verbose _verbose { _config.xml() }; - - /** - * Return name of init process as specified in the config - */ - Child_policy::Name _name_of_init_process() const - { - return _config.xml().sub_node("start").attribute_value("name", Child_policy::Name()); - } - - /** - * Read command-line arguments of init process from config - */ - Args const &_args_of_init_process() - { - static char args_buf[4096]; - static Args args(args_buf, sizeof(args_buf)); - - Xml_node start_node = _config.xml().sub_node("start"); - try { - /* the first argument is the program name */ - args.append(_name_of_init_process().string()); - - start_node.for_each_sub_node("arg", [&] (Xml_node arg_node) { - typedef String<512> Value; - args.append(arg_node.attribute_value("value", Value()).string()); - }); - - } catch (Args::Overrun) { error("argument buffer overrun"); } - - return args; - } - - /* initialize virtual file system */ - Vfs::Global_file_system_factory _global_file_system_factory { _heap }; - - struct Io_progress_handler : Genode::Entrypoint::Io_progress_handler - { - Vfs_io_waiter_registry io_waiter_registry { }; - - Io_progress_handler(Genode::Entrypoint &ep) - { - ep.register_io_progress_handler(*this); - } - - void handle_io_progress() override - { - io_waiter_registry.for_each([] (Vfs_io_waiter &r) { - r.wakeup(); - }); - } - - } _io_response_handler { _env.ep() }; - - Vfs::Simple_env _vfs_env { _env, _heap, _config.xml().sub_node("fstab") }; - - Vfs::File_system &_root_dir = _vfs_env.root_dir(); - - Pid_allocator _pid_allocator { }; - - Timer::Connection _timer_connection { _env }; - - User_info _user_info { _config.xml() }; - - Time_info _time_info { _env, _config.xml() }; - - Signal_handler
_destruct_handler { - _env.ep(), *this, &Main::_handle_destruct }; - - Destruct_queue _destruct_queue { _destruct_handler }; - - void _handle_destruct() - { - _destruct_queue.flush(); - - /* let noux exit if the init process exited */ - if (!init_child) { - _channel_0 = Shared_pointer(); - _channel_1 = Shared_pointer(); - _channel_2 = Shared_pointer(); - _env.parent().exit(exit_value); - } - } - - struct Kill_broadcaster_impl: Kill_broadcaster - { - Family_member *init_process = nullptr; - - bool kill(int pid, Noux::Sysio::Signal sig) override - { - return init_process->deliver_kill(pid, sig); - } - - } _kill_broadcaster { }; - - Noux::Child _init_child { _name_of_init_process(), - _verbose, - _user_info, - _time_info, - 0, - _kill_broadcaster, - _timer_connection, - _init_child, - _pid_allocator, - _pid_allocator.alloc(), - _env, - _root_dir, - _io_response_handler.io_waiter_registry, - _args_of_init_process(), - env_string_of_init_process(_config.xml()), - _heap, - _env.pd(), - _env.pd_session_cap(), - _parent_services, - false, - _destruct_queue }; - - Constructible _terminal { }; - - /* - * I/O channels must be dynamically allocated to handle cases where the - * init program closes one of these. - */ - typedef Terminal_io_channel Tio; /* just a local abbreviation */ - - Shared_pointer - _channel_0 { &connect_stdio(_env, _terminal, _config.xml(), _root_dir, - _io_response_handler.io_waiter_registry, - Tio::STDIN, _heap, _time_info, _timer_connection), _heap }, - _channel_1 { &connect_stdio(_env, _terminal, _config.xml(), _root_dir, - _io_response_handler.io_waiter_registry, - Tio::STDOUT, _heap, _time_info, _timer_connection), _heap }, - _channel_2 { &connect_stdio(_env, _terminal, _config.xml(), _root_dir, - _io_response_handler.io_waiter_registry, - Tio::STDERR, _heap, _time_info, _timer_connection), _heap }; - - Main(Env &env) : _env(env) - { - log("--- noux started ---"); - - _init_child.add_io_channel(_channel_0, 0); - _init_child.add_io_channel(_channel_1, 1); - _init_child.add_io_channel(_channel_2, 2); - - _kill_broadcaster.init_process = &_init_child; - - init_child = &_init_child; - - _init_child.start(); - } -}; - - -void Component::construct(Genode::Env &env) -{ - static Noux::Main main(env); -} diff --git a/repos/ports/src/noux/parent_execve.h b/repos/ports/src/noux/parent_execve.h deleted file mode 100644 index 6effe1d06..000000000 --- a/repos/ports/src/noux/parent_execve.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * \brief Parent_execve interface - * \author Christian Prochaska - * \date 2014-01-13 - */ - -/* - * Copyright (C) 2014-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__PARENT_EXECVE__H_ -#define _NOUX__PARENT_EXECVE__H_ - -/* Noux includes */ -#include - -namespace Noux { - struct Family_member; - struct Parent_execve; -} - - -struct Noux::Parent_execve : Genode::Interface -{ - virtual void execve_child(Family_member &child, - const char *filename, - Args const &args, - Sysio::Env const &env) = 0; -}; - -#endif /* _NOUX__PARENT_EXECVE__H_ */ - diff --git a/repos/ports/src/noux/parent_exit.h b/repos/ports/src/noux/parent_exit.h deleted file mode 100644 index 0cf672536..000000000 --- a/repos/ports/src/noux/parent_exit.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * \brief Parent_exit interface - * \author Christian Prochaska - * \date 2014-01-16 - */ - -/* - * Copyright (C) 2014-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__PARENT_EXIT__H_ -#define _NOUX__PARENT_EXIT__H_ - -#include - -namespace Noux { - - struct Family_member; - - struct Parent_exit : Genode::Interface - { - /* - * Handle the exiting of a child - */ - - virtual void exit_child() = 0; - }; - -}; - -#endif /* _NOUX__PARENT_EXIT__H_ */ - diff --git a/repos/ports/src/noux/path.h b/repos/ports/src/noux/path.h deleted file mode 100644 index 752b8eddd..000000000 --- a/repos/ports/src/noux/path.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief Path handling utility for Noux - * \author Norman Feske - * \date 2011-02-17 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__PATH_H_ -#define _NOUX__PATH_H_ - -/* Genode includes */ -#include - -namespace Noux { using Vfs::Absolute_path; } - -#endif /* _NOUX__PATH_H_ */ diff --git a/repos/ports/src/noux/pd_session_component.h b/repos/ports/src/noux/pd_session_component.h deleted file mode 100644 index 20ce93295..000000000 --- a/repos/ports/src/noux/pd_session_component.h +++ /dev/null @@ -1,327 +0,0 @@ -/* - * \brief PD service used by Noux processes - * \author Norman Feske - * \date 2016-04-20 - * - * The custom implementation of the PD session interface provides a pool of - * RAM shared by Noux and all Noux processes. The use of a shared pool - * alleviates the need to assign RAM quota to individual Noux processes. - * - * Furthermore, the custom implementation is needed to get hold of the RAM - * dataspaces allocated by each Noux process. When forking a process, the - * acquired information (in the form of 'Ram_dataspace_info' objects) is used - * to create a shadow copy of the forking address space. - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__PD_SESSION_COMPONENT_H_ -#define _NOUX__PD_SESSION_COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include - -/* Noux includes */ -#include -#include - -namespace Noux { - struct Ram_dataspace_info; - struct Pd_session_component; - using namespace Genode; -} - - -struct Noux::Ram_dataspace_info : Dataspace_info, - private List::Element -{ - friend class List; - - Ram_dataspace_info(Ram_dataspace_capability ds_cap) - : Dataspace_info(ds_cap) { } - - Dataspace_capability fork(Ram_allocator &ram, - Region_map &local_rm, - Allocator &alloc, - Dataspace_registry &ds_registry, - Rpc_entrypoint &) override - { - size_t const size = Dataspace_client(ds_cap()).size(); - Ram_dataspace_capability dst_ds_cap; - - try { - dst_ds_cap = ram.alloc(size); - - Attached_dataspace src_ds(local_rm, ds_cap()); - Attached_dataspace dst_ds(local_rm, dst_ds_cap); - memcpy(dst_ds.local_addr(), src_ds.local_addr(), size); - - ds_registry.insert(new (alloc) Ram_dataspace_info(dst_ds_cap)); - return dst_ds_cap; - - } catch (...) { - error("fork of RAM dataspace failed"); - - if (dst_ds_cap.valid()) - ram.free(dst_ds_cap); - - return Dataspace_capability(); - } - } - - 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())) { - error("illegal attemt to write beyond dataspace boundary"); - return; - } - - try { - Attached_dataspace ds(rm, ds_cap()); - memcpy(ds.local_addr() + dst_offset, src, len); - } catch (...) { warning("poke: failed to attach RAM dataspace"); } - } -}; - - -class Noux::Pd_session_component : public Rpc_object -{ - private: - - Rpc_entrypoint &_ep; - - Pd_connection _pd; - - Pd_session &_ref_pd; - - Region_map_component _address_space; - Region_map_component _stack_area; - Region_map_component _linker_area; - - Allocator &_alloc; - - Ram_allocator &_ram; - - Ram_quota _used_ram_quota { 0 }; - - List _ds_list { }; - - Dataspace_registry &_ds_registry; - - template - auto _with_automatic_cap_upgrade(FUNC func) -> decltype(func()) - { - Cap_quota upgrade { 10 }; - enum { NUM_ATTEMPTS = 3 }; - return retry( - [&] () { return func(); }, - [&] () { _ref_pd.transfer_quota(_pd.rpc_cap(), upgrade); }, - NUM_ATTEMPTS); - } - - public: - - /** - * Constructor - */ - Pd_session_component(Allocator &alloc, Env &env, Rpc_entrypoint &ep, - Child_policy::Name const &name, - Dataspace_registry &ds_registry) - : - _ep(ep), _pd(env, name.string()), _ref_pd(env.pd()), - _address_space(alloc, _ep, ds_registry, _pd, _pd.address_space()), - _stack_area (alloc, _ep, ds_registry, _pd, _pd.stack_area()), - _linker_area (alloc, _ep, ds_registry, _pd, _pd.linker_area()), - _alloc(alloc), _ram(env.ram()), _ds_registry(ds_registry) - { - _ep.manage(this); - - /* - * Equip the PD with an initial cap quota that suffices in the - * common case. Further capabilities are provisioned on demand - * via '_with_automatic_cap_upgrade'. - */ - _pd.ref_account(env.pd_session_cap()); - _ref_pd.transfer_quota(_pd.rpc_cap(), Cap_quota{10}); - } - - ~Pd_session_component() - { - _ep.dissolve(this); - - Ram_dataspace_info *info = 0; - while ((info = _ds_list.first())) - free(static_cap_cast(info->ds_cap())); - } - - Pd_session_capability core_pd_cap() { return _pd.cap(); } - - void poke(Region_map &rm, addr_t dst_addr, char const *src, size_t len) - { - _address_space.poke(rm, dst_addr, src, len); - } - - Capability lookup_region_map(addr_t const addr) - { - return _address_space.lookup_region_map(addr); - } - - Region_map &address_space_region_map() { return _address_space; } - Region_map &linker_area_region_map() { return _linker_area; } - Region_map &stack_area_region_map() { return _stack_area; } - - void replay(Pd_session_component &dst_pd, - Region_map &local_rm, - Allocator &alloc, - Dataspace_registry &ds_registry, - Rpc_entrypoint &ep) - { - /* replay region map into new protection domain */ - _stack_area .replay(dst_pd, dst_pd.stack_area_region_map(), local_rm, alloc, ds_registry, ep); - _linker_area .replay(dst_pd, dst_pd.linker_area_region_map(), local_rm, alloc, ds_registry, ep); - _address_space.replay(dst_pd, 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_stack_area = dst_pd.stack_area_region_map(); - Region_map &dst_linker_area = dst_pd.linker_area_region_map(); - - /* attach stack area */ - dst_address_space.attach(dst_stack_area.dataspace(), - Dataspace_client(dst_stack_area.dataspace()).size(), - 0, true, - _address_space.lookup_region_base(_stack_area.dataspace())); - - /* attach linker area */ - dst_address_space.attach(dst_linker_area.dataspace(), - Dataspace_client(dst_linker_area.dataspace()).size(), - 0, true, - _address_space.lookup_region_base(_linker_area.dataspace()), true); - } - - - /************************** - ** Pd_session interface ** - **************************/ - - void assign_parent(Capability parent) override { - _pd.assign_parent(parent); } - - bool assign_pci(addr_t addr, uint16_t bdf) override { - return _pd.assign_pci(addr, bdf); } - - void map(addr_t virt, addr_t size) override { - return _pd.map(virt, size); } - - Signal_source_capability alloc_signal_source() override - { - return _with_automatic_cap_upgrade([&] () { - return _pd.alloc_signal_source(); }); - } - - void free_signal_source(Signal_source_capability cap) override { - _pd.free_signal_source(cap); } - - Capability alloc_context(Signal_source_capability source, - unsigned long imprint) override - { - return _with_automatic_cap_upgrade([&] () { - return _pd.alloc_context(source, imprint); }); - } - - void free_context(Capability cap) override { - _pd.free_context(cap); } - - void submit(Capability context, unsigned cnt) override { - _pd.submit(context, cnt); } - - Native_capability alloc_rpc_cap(Native_capability ep) override - { - return _with_automatic_cap_upgrade([&] () { - return _pd.alloc_rpc_cap(ep); }); - } - - void free_rpc_cap(Native_capability cap) override { - _pd.free_rpc_cap(cap); } - - Capability address_space() override { - return _address_space.Rpc_object::cap(); } - - Capability stack_area() override { - return _stack_area.Rpc_object::cap(); } - - Capability linker_area() override { - return _linker_area.Rpc_object::cap(); } - - void ref_account(Capability) override { } - - void transfer_quota(Capability, Cap_quota) override { } - - Cap_quota cap_quota() const override { return _pd.cap_quota(); } - Cap_quota used_caps() const override { return _pd.used_caps(); } - - Ram_dataspace_capability alloc(size_t size, Cache_attribute cached) override - { - Ram_dataspace_capability ds_cap = _ram.alloc(size, cached); - - Ram_dataspace_info *ds_info = new (_alloc) Ram_dataspace_info(ds_cap); - - _ds_registry.insert(ds_info); - _ds_list.insert(ds_info); - - _used_ram_quota = Ram_quota { _used_ram_quota.value + size }; - - return ds_cap; - } - - void free(Ram_dataspace_capability ds_cap) override - { - Ram_dataspace_info *ds_info; - - auto lambda = [&] (Ram_dataspace_info *rdi) { - ds_info = rdi; - - if (!ds_info) { - error("RAM free: dataspace lookup failed"); - return; - } - - size_t const ds_size = rdi->size(); - - _ds_registry.remove(ds_info); - ds_info->dissolve_users(); - _ds_list.remove(ds_info); - _ram.free(ds_cap); - - _used_ram_quota = Ram_quota { _used_ram_quota.value - ds_size }; - }; - _ds_registry.apply(ds_cap, lambda); - destroy(_alloc, ds_info); - } - - size_t dataspace_size(Ram_dataspace_capability ds_cap) const override - { - size_t result = 0; - _ds_registry.apply(ds_cap, [&] (Ram_dataspace_info *rdi) { - if (rdi) - result = rdi->size(); }); - return result; - } - - void transfer_quota(Pd_session_capability, Ram_quota) override { } - Ram_quota ram_quota() const override { return _pd.ram_quota(); } - Ram_quota used_ram() const override { return Ram_quota{_used_ram_quota}; } - - Capability native_pd() override { - return _pd.native_pd(); } -}; - -#endif /* _NOUX__PD_SESSION_COMPONENT_H_ */ diff --git a/repos/ports/src/noux/pipe_io_channel.h b/repos/ports/src/noux/pipe_io_channel.h deleted file mode 100644 index 9d7f8d449..000000000 --- a/repos/ports/src/noux/pipe_io_channel.h +++ /dev/null @@ -1,353 +0,0 @@ -/* - * \brief I/O channels for pipe input/output - * \author Norman Feske - * \date 2012-03-19 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__PIPE_IO_CHANNEL_H_ -#define _NOUX__PIPE_IO_CHANNEL_H_ - -/* Noux includes */ -#include - -namespace Noux { - class Pipe; - class Pipe_sink_io_channel; - class Pipe_source_io_channel; -} - - -class Noux::Pipe : public Reference_counter -{ - private: - - Lock mutable _lock { }; - - enum { BUFFER_SIZE = 4096 }; - char _buffer[BUFFER_SIZE]; - - unsigned _read_offset { 0 }; - unsigned _write_offset { 0 }; - - Signal_context_capability _read_ready_sigh { }; - Signal_context_capability _write_ready_sigh { }; - - bool _writer_is_gone { false }; - - /** - * Return space available in the buffer for writing, in bytes - */ - size_t _avail_buffer_space() const - { - if (_read_offset < _write_offset) - return (BUFFER_SIZE - _write_offset) + _read_offset - 1; - - if (_read_offset > _write_offset) - return _read_offset - _write_offset - 1; - - /* _read_offset == _write_offset */ - return BUFFER_SIZE - 1; - } - - bool _any_space_avail_for_writing() const - { - return _avail_buffer_space() > 0;; - } - - void _wake_up_reader() - { - if (_read_ready_sigh.valid()) - Signal_transmitter(_read_ready_sigh).submit(); - } - - void _wake_up_writer() - { - if (_write_ready_sigh.valid()) - Signal_transmitter(_write_ready_sigh).submit(); - } - - public: - - ~Pipe() - { - Lock::Guard guard(_lock); - } - - void writer_close() - { - Lock::Guard guard(_lock); - - _writer_is_gone = true; - _write_ready_sigh = Signal_context_capability(); - _wake_up_reader(); - } - - void reader_close() - { - Lock::Guard guard(_lock); - _read_ready_sigh = Signal_context_capability(); - } - - bool writer_is_gone() const - { - Lock::Guard guard(_lock); - return _writer_is_gone; - } - - bool any_space_avail_for_writing() const - { - Lock::Guard guard(_lock); - return _any_space_avail_for_writing(); - } - - bool data_avail_for_reading() const - { - Lock::Guard guard(_lock); - - return _read_offset != _write_offset; - } - - size_t read(char *dst, size_t dst_len) - { - Lock::Guard guard(_lock); - - if (_read_offset < _write_offset) { - - size_t len = min(dst_len, _write_offset - _read_offset); - memcpy(dst, &_buffer[_read_offset], len); - - _read_offset += len; - _wake_up_writer(); - - return len; - } - - if (_read_offset > _write_offset) { - - size_t const upper_len = min(dst_len, BUFFER_SIZE - _read_offset); - memcpy(dst, &_buffer[_read_offset], upper_len); - - size_t const lower_len = min(dst_len - upper_len, _write_offset); - if (lower_len) { - memcpy(dst + upper_len, &_buffer[0], lower_len); - _read_offset = lower_len; - } else { - _read_offset += upper_len; - } - _wake_up_writer(); - - return upper_len + lower_len; - } - - /* _read_offset == _write_offset */ - return 0; - } - - /** - * Write to pipe buffer - * - * \return number of written bytes (may be less than 'len') - */ - size_t write(char *src, size_t len) - { - Lock::Guard guard(_lock); - - /* trim write request to the available buffer space */ - size_t const trimmed_len = min(len, _avail_buffer_space()); - - /* - * Remember pipe state prior writing to see whether a reader - * must be unblocked after writing. - */ - bool const pipe_was_empty = (_read_offset == _write_offset); - - /* write data up to the upper boundary of the pipe buffer */ - size_t const upper_len = min(BUFFER_SIZE - _write_offset, trimmed_len); - memcpy(&_buffer[_write_offset], src, upper_len); - - _write_offset += upper_len; - - /* - * Determine number of remaining bytes beyond the buffer boundary. - * The buffer wraps. So this data will end up in the lower part - * of the pipe buffer. - */ - size_t const lower_len = trimmed_len - upper_len; - - if (lower_len > 0) { - - /* pipe buffer wrap-around, write remaining data to the lower part */ - memcpy(&_buffer[0], src + upper_len, lower_len); - _write_offset = lower_len; - } - - /* - * Wake up reader who may block for incoming data. - */ - if (pipe_was_empty || !_any_space_avail_for_writing()) - _wake_up_reader(); - - /* return number of written bytes */ - return trimmed_len; - } - - void register_write_ready_sigh(Signal_context_capability sigh) - { - Lock::Guard guard(_lock); - _write_ready_sigh = sigh; - } - - void register_read_ready_sigh(Signal_context_capability sigh) - { - Lock::Guard guard(_lock); - _read_ready_sigh = sigh; - } -}; - - -class Noux::Pipe_sink_io_channel : public Io_channel -{ - private: - - Signal_handler _write_ready_handler; - - void _handle_write_ready() { Io_channel::invoke_all_notifiers(); } - - Shared_pointer _pipe; - - bool _nonblocking { false }; - - public: - - Pipe_sink_io_channel(Shared_pointer pipe, Entrypoint &ep) - : - _write_ready_handler(ep, *this, &Pipe_sink_io_channel::_handle_write_ready), - _pipe(pipe) - { - pipe->register_write_ready_sigh(_write_ready_handler); - } - - ~Pipe_sink_io_channel() { _pipe->writer_close(); } - - bool check_unblock(bool, bool wr, bool) const override - { - return wr && _pipe->any_space_avail_for_writing(); - } - - bool nonblocking() override { return _nonblocking; } - - bool write(Sysio &sysio) override - { - sysio.write_out.count = _pipe->write(sysio.write_in.chunk, - sysio.write_in.count); - return true; - } - - bool fcntl(Sysio &sysio) override - { - switch (sysio.fcntl_in.cmd) { - - case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: - sysio.fcntl_out.result = Sysio::OPEN_MODE_WRONLY; - return true; - - case Sysio::FCNTL_CMD_SET_FILE_STATUS_FLAGS: - _nonblocking = (sysio.fcntl_in.long_arg & - Sysio::FCNTL_FILE_STATUS_FLAG_NONBLOCK); - sysio.fcntl_out.result = 0; - return true; - - default: - return false; - } - } - - bool fstat(Sysio &sysio) override - { - sysio.fstat_out.st.type = Vfs::Node_type::CONTINUOUS_FILE; - return true; - } -}; - - -class Noux::Pipe_source_io_channel : public Io_channel -{ - private: - - Signal_handler _read_avail_handler; - - void _handle_read_avail() { Io_channel::invoke_all_notifiers(); } - - Shared_pointer _pipe; - - bool _nonblocking { false }; - - public: - - Pipe_source_io_channel(Shared_pointer pipe, Entrypoint &ep) - : - _read_avail_handler(ep, *this, &Pipe_source_io_channel::_handle_read_avail), - _pipe(pipe) - { - _pipe->register_read_ready_sigh(_read_avail_handler); - } - - ~Pipe_source_io_channel() { _pipe->reader_close(); } - - bool check_unblock(bool rd, bool, bool) const override - { - /* unblock if the writer has already closed its pipe end */ - if (_pipe->writer_is_gone()) - return true; - - return (rd && _pipe->data_avail_for_reading()); - } - - bool nonblocking() override { return _nonblocking; } - - bool read(Sysio &sysio) override - { - size_t const max_count = - min(sysio.read_in.count, - sizeof(sysio.read_out.chunk)); - - sysio.read_out.count = - _pipe->read(sysio.read_out.chunk, max_count); - - return true; - } - - bool fcntl(Sysio &sysio) override - { - switch (sysio.fcntl_in.cmd) { - - case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: - sysio.fcntl_out.result = Sysio::OPEN_MODE_RDONLY; - return true; - - case Sysio::FCNTL_CMD_SET_FILE_STATUS_FLAGS: - _nonblocking = (sysio.fcntl_in.long_arg & - Sysio::FCNTL_FILE_STATUS_FLAG_NONBLOCK); - sysio.fcntl_out.result = 0; - return true; - - default: - return false; - } - } - - bool fstat(Sysio &sysio) override - { - sysio.fstat_out.st.type = Vfs::Node_type::CONTINUOUS_FILE; - return true; - } -}; - -#endif /* _NOUX__PIPE_IO_CHANNEL_H_ */ diff --git a/repos/ports/src/noux/range_checked_index.h b/repos/ports/src/noux/range_checked_index.h deleted file mode 100644 index c3de0fdc1..000000000 --- a/repos/ports/src/noux/range_checked_index.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * \brief Utility for checking array bounds - * \author Norman Feske - * \date 2011-02-18 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__RANGE_CHECKED_INDEX_H_ -#define _NOUX__RANGE_CHECKED_INDEX_H_ - -namespace Noux { - - class Index_out_of_range { }; - template struct Range_checked_index; -} - - -template -struct Noux::Range_checked_index -{ - T value; - T const max; - - Range_checked_index(T value, T max) : value(value), max(max) { } - - Range_checked_index operator++ (int) - { - T old_value = value; - - if (++value >= max) - throw Index_out_of_range(); - - return Range_checked_index(old_value, max); - } - - operator T () { return value; } -}; - -#endif /* _NOUX__RANGE_CHECKED_INDEX_H_ */ diff --git a/repos/ports/src/noux/region_map_component.h b/repos/ports/src/noux/region_map_component.h deleted file mode 100644 index 89a94535f..000000000 --- a/repos/ports/src/noux/region_map_component.h +++ /dev/null @@ -1,425 +0,0 @@ -/* - * \brief Region map implementation used by Noux processes - * \author Norman Feske - * \author Martin Stein - * \date 2012-02-22 - * - * The custom region-map implementation is used for recording all regions - * attached to the region map. Using the recorded information, the address- - * space layout can then be replayed onto a new process created via fork. - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__REGION_MAP_COMPONENT_H_ -#define _NOUX__REGION_MAP_COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include -#include - -/* Noux includes */ -#include - -namespace Noux { class Region_map_component; } - - -class Noux::Region_map_component : public Rpc_object, - public Dataspace_info -{ - private: - - static constexpr bool verbose_attach = false; - static constexpr bool verbose_replay = false; - - Allocator &_alloc; - - Rpc_entrypoint &_ep; - - /** - * Record of an attached dataspace - */ - struct Region : private List::Element, private Dataspace_user - { - friend class Region_map_component; /* list operations */ - friend class List; - - Region_map_component &rm; - Dataspace_capability ds; - size_t size; - off_t offset; - addr_t local_addr; - bool executable; - - Region(Region_map_component &rm, - Dataspace_capability ds, size_t size, - off_t offset, addr_t local_addr, bool exec) - : - rm(rm), ds(ds), size(size), offset(offset), - local_addr(local_addr), executable(exec) - { } - - /** - * Return true if region contains specified address - */ - bool contains(addr_t addr) const - { - return (addr >= local_addr) && (addr < local_addr + size); - } - - Region *next_region() - { - return List::Element::next(); - } - - void dissolve(Dataspace_info &ds) override; - }; - - Lock _region_lock { }; - List _regions { }; - - Region *_lookup_region_by_addr(addr_t local_addr) - { - Region *curr = _regions.first(); - for (; curr; curr = curr->next_region()) { - if (curr->contains(local_addr)) - return curr; - } - return 0; - } - - /** - * Wrapped region map at core - */ - Region_map_client _rm; - - Pd_connection &_pd; - - Dataspace_registry &_ds_registry; - - public: - - /** - * Constructor - * - * \param pd protection domain the region map belongs to, used for - * quota upgrades - * \param rm region map at core - */ - Region_map_component(Allocator &alloc, Rpc_entrypoint &ep, - Dataspace_registry &ds_registry, - Pd_connection &pd, - Capability rm) - : - Dataspace_info(Region_map_client(rm).dataspace()), - _alloc(alloc), _ep(ep), _rm(rm), _pd(pd), _ds_registry(ds_registry) - { - _ep.manage(this); - _ds_registry.insert(this); - } - - /** - * Destructor - */ - ~Region_map_component() - { - _ds_registry.remove(this); - _ep.dissolve(this); - - Region *curr; - while ((curr = _regions.first())) - detach(curr->local_addr); - } - - /** - * Return address where the specified dataspace is attached - * - * This function is used by the 'Pd_session_component' to look up - * the base addresses for the stack area and linker area. - */ - addr_t lookup_region_base(Dataspace_capability ds) - { - Lock::Guard guard(_region_lock); - - Region *curr = _regions.first(); - for (; curr; curr = curr->next_region()) { - if (curr->ds.local_name() == ds.local_name()) - return curr->local_addr; - } - return 0; - } - - /** - * Replay attachments onto specified region map - * - * \param dst_ram backing store used for allocating the - * the copies of RAM dataspaces - * \param ds_registry dataspace registry used for keeping track - * of newly created dataspaces - * \param ep entrypoint used to serve the RPC interface - * of forked managed dataspaces - */ - void replay(Ram_allocator &dst_ram, - Region_map &dst_rm, - Region_map &local_rm, - Allocator &alloc, - Dataspace_registry &ds_registry, - Rpc_entrypoint &ep) - { - Lock::Guard guard(_region_lock); - for (Region *curr = _regions.first(); curr; curr = curr->next_region()) { - - auto lambda = [&] (Dataspace_info *info) - { - Dataspace_capability ds; - if (info) { - - ds = info->fork(dst_ram, local_rm, alloc, ds_registry, ep); - - /* - * XXX We could detect dataspaces that are attached - * more than once. For now, we create a new fork - * for each attachment. - */ - - } else { - - warning("replay: missing ds_info for dataspace at addr ", - Hex(curr->local_addr)); - - /* - * If the dataspace is not a RAM dataspace, assume that - * it's a ROM dataspace. - * - * XXX Handle ROM dataspaces explicitly. For once, we - * need to make sure that they remain available - * until the child process exits even if the parent - * process exits earlier. Furthermore, we would - * like to detect unexpected dataspaces. - */ - ds = curr->ds; - } - - /* - * The call of 'info->fork' returns a invalid dataspace - * capability for the stack area and linker area. Those - * region maps are directly replayed and attached in - * 'Pd_session_component::replay'. So we can skip them - * here. - */ - if (!ds.valid()) { - if (verbose_replay) - warning("replay: skip dataspace of region ", - Hex(curr->local_addr)); - return; - } - - enum { USE_LOCAL_ADDR = true }; - dst_rm.attach(ds, curr->size, curr->offset, USE_LOCAL_ADDR, - curr->local_addr, curr->executable); - }; - _ds_registry.apply(curr->ds, lambda); - }; - } - - - /************************** - ** Region_map interface ** - **************************/ - - Local_addr attach(Dataspace_capability ds, - size_t size, off_t offset, - bool use_local_addr, - Local_addr local_addr, - bool executable, - bool writeable) override - { - /* - * Region map subtracts offset from size if size is 0 - */ - if (size == 0) size = Dataspace_client(ds).size() - offset; - - for (;;) { - try { - local_addr = _rm.attach(ds, size, offset, use_local_addr, - local_addr, executable, writeable); - break; - } - catch (Out_of_ram) { _pd.upgrade_ram(8*1024); } - catch (Out_of_caps) { _pd.upgrade_caps(2); } - } - - Region * region = new (_alloc) Region(*this, ds, size, offset, - local_addr, executable); - - /* register region as user of RAM dataspaces */ - auto lambda = [&] (Dataspace_info *info) - { - if (info) { - info->register_user(*region); - } else { - if (verbose_attach) { - warning("trying to attach unknown dataspace type " - "ds=", ds.local_name(), " " - "info@", info, " " - "local_addr=", Hex(local_addr), " " - "size=", Dataspace_client(ds).size(), " " - "offset=", Hex(offset)); - } - } - }; - _ds_registry.apply(ds, lambda); - - /* - * Record attachment for later replay (needed during fork) - */ - Lock::Guard guard(_region_lock); - _regions.insert(region); - - return local_addr; - } - - void detach(Local_addr local_addr) override - { - Region * region = 0; - { - Lock::Guard guard(_region_lock); - region = _lookup_region_by_addr(local_addr); - if (!region) { - warning("attempt to detach unknown region at ", (void *)local_addr); - return; - } - - _regions.remove(region); - } - - _ds_registry.apply(region->ds, [&] (Dataspace_info *info) { - if (info) info->unregister_user(*region); }); - - destroy(_alloc, region); - - _rm.detach(local_addr); - } - - void fault_handler(Signal_context_capability handler) override - { - return _rm.fault_handler(handler); - } - - State state() override - { - return _rm.state(); - } - - Dataspace_capability dataspace() override - { - /* - * We cannot call '_rm.dataspace()' here because NOVA would - * hand out a capability that is unequal to the one we got - * during the construction of the 'Dataspace_info' base class. - * To work around this problem, we return the capability - * that is kept in the 'Dataspace_info'. - */ - return ds_cap(); - } - - - /****************************** - ** Dataspace_info interface ** - ******************************/ - - Dataspace_capability fork(Ram_allocator &, - Region_map &, - Allocator &, - Dataspace_registry &, - Rpc_entrypoint &) override - { - return Dataspace_capability(); - } - - /** - * Return leaf region map that covers a given address - * - * \param addr address that is covered by the requested region map - */ - Capability lookup_region_map(addr_t const addr) override - { - /* if there's no region that could be a sub RM then we're a leaf */ - Region * const region = _lookup_region_by_addr(addr); - if (!region) { return Rpc_object::cap(); } - - auto lambda = [&] (Dataspace_info *info) - { - /* if there is no info for the region it can't be a sub RM */ - if (!info) { return Rpc_object::cap(); } - - /* ask the dataspace info for an appropriate sub RM */ - addr_t const region_base = region->local_addr; - addr_t const region_off = region->offset; - addr_t const sub_addr = addr - region_base + region_off; - Capability sub_rm = info->lookup_region_map(sub_addr); - - /* if the result is invalid the dataspace is no sub RM */ - if (!sub_rm.valid()) { return Rpc_object::cap(); } - return sub_rm; - }; - return _ds_registry.apply(region->ds, lambda); - } - - void poke(Region_map &rm, addr_t dst_addr, char const *src, size_t len) override - { - Dataspace_capability ds_cap; - addr_t local_addr; - - { - Lock::Guard guard(_region_lock); - - Region *region = _lookup_region_by_addr(dst_addr); - if (!region) { - error("poke: no region at ", Hex(dst_addr)); - return; - } - - /* - * Test if start and end address occupied by the object - * type refers to the same region. - */ - if (region != _lookup_region_by_addr(dst_addr + len - 1)) { - error("attempt to write beyond region boundary"); - return; - } - - if (region->offset) { - error("poke: writing to region with offset is not supported"); - return; - } - - ds_cap = region->ds; - local_addr = region->local_addr; - } - - _ds_registry.apply(ds_cap, [&] (Dataspace_info *info) { - if (!info) { - error("attempt to write to unknown dataspace type"); - for (;;); - } - info->poke(rm, dst_addr - local_addr, src, len); - }); - } -}; - - -inline void Noux::Region_map_component::Region::dissolve(Dataspace_info &) -{ - rm.detach(local_addr); -} - - -#endif /* _NOUX__REGION_MAP_COMPONENT_H_ */ diff --git a/repos/ports/src/noux/rom_session_component.h b/repos/ports/src/noux/rom_session_component.h deleted file mode 100644 index a46e0aa5b..000000000 --- a/repos/ports/src/noux/rom_session_component.h +++ /dev/null @@ -1,261 +0,0 @@ -/* - * \brief ROM session implementation used by Noux processes - * \author Norman Feske - * \date 2013-07-18 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__ROM_SESSION_COMPONENT_H_ -#define _NOUX__ROM_SESSION_COMPONENT_H_ - -/* Genode includes */ -#include -#include - -/* Noux includes */ -#include "vfs_io_channel.h" - -namespace Noux { - - struct Vfs_dataspace; - struct Rom_dataspace_info; - class Rom_session_component; -} - - -/** - * Dataspace obtained from the VFS - */ -struct Noux::Vfs_dataspace -{ - typedef Child_policy::Name Name; - Name const name; - - Vfs::File_system &root_dir; - Vfs_io_waiter_registry &vfs_io_waiter_registry; - Genode::Ram_allocator &ram; - Genode::Region_map &rm; - Genode::Allocator &alloc; - - Dataspace_capability ds { }; - bool got_ds_from_vfs { true }; - - Vfs_dataspace(Vfs::File_system &root_dir, - Vfs_io_waiter_registry &vfs_io_waiter_registry, - Name const &name, - Genode::Ram_allocator &ram, Genode::Region_map &rm, - Genode::Allocator &alloc) - : - name(name), - root_dir(root_dir), vfs_io_waiter_registry(vfs_io_waiter_registry), - ram(ram), rm(rm), alloc(alloc) - { - ds = root_dir.dataspace(name.string()); - - if (!ds.valid()) { - - got_ds_from_vfs = false; - - Vfs::Directory_service::Stat stat_out; - - if (root_dir.stat(name.string(), stat_out) != Vfs::Directory_service::STAT_OK) - return; - - if (stat_out.size == 0) - return; - - Vfs::Vfs_handle *file; - if (root_dir.open(name.string(), - Vfs::Directory_service::OPEN_MODE_RDONLY, - &file, - alloc) != Vfs::Directory_service::OPEN_OK) - return; - - Vfs_handle_context read_context; - Vfs::Vfs_handle::Guard guard(file); - file->handler(&read_context); - - ds = ram.alloc(stat_out.size); - - char *addr = rm.attach(static_cap_cast(ds)); - - for (Vfs::file_size bytes_read = 0; bytes_read < stat_out.size; ) { - - Registered_no_delete - vfs_io_waiter(vfs_io_waiter_registry); - - while (!file->fs().queue_read(file, stat_out.size - bytes_read)) - vfs_io_waiter.wait_for_io(); - - Vfs::File_io_service::Read_result read_result; - - Vfs::file_size out_count; - - for (;;) { - read_result = file->fs().complete_read(file, addr + bytes_read, - stat_out.size, - out_count); - if (read_result != Vfs::File_io_service::READ_QUEUED) - break; - - read_context.vfs_io_waiter.wait_for_io(); - } - - /* wake up threads blocking for 'queue_*()' or 'write()' */ - vfs_io_waiter_registry.for_each([] (Vfs_io_waiter &r) { - r.wakeup(); - }); - - if (read_result != Vfs::File_io_service::READ_OK) { - Genode::error("Error reading dataspace from VFS"); - rm.detach(addr); - ram.free(static_cap_cast(ds)); - root_dir.close(file); - return; - } - - bytes_read += out_count; - file->advance_seek(out_count); - } - - rm.detach(addr); - } - } - - ~Vfs_dataspace() - { - if (got_ds_from_vfs) - root_dir.release(name.string(), ds); - else - ram.free(static_cap_cast(ds)); - } -}; - - -struct Noux::Rom_dataspace_info : Dataspace_info -{ - Rom_dataspace_info(Dataspace_capability ds) : Dataspace_info(ds) { } - - ~Rom_dataspace_info() { } - - Dataspace_capability fork(Ram_allocator &, - Region_map &, - Allocator &alloc, - Dataspace_registry &ds_registry, - Rpc_entrypoint &) override - { - ds_registry.insert(new (alloc) Rom_dataspace_info(ds_cap())); - return ds_cap(); - } - - void poke(Region_map &, addr_t, char const *, size_t) override - { - error("attempt to poke onto a ROM dataspace"); - } -}; - - -/** - * Local ROM service - * - * Depending on the ROM name, the data is provided by the VFS (if the name - * starts with a '/' or the parent's ROM service. If the name empty, an - * invalid dataspace capability is returned (this is used for the binary - * ROM session of a forked process). - */ -class Noux::Rom_session_component : public Rpc_object -{ - public: - - typedef Child_policy::Name Name; - - private: - - Allocator &_alloc; - Rpc_entrypoint &_ep; - Vfs::File_system &_root_dir; - Vfs_io_waiter_registry &_vfs_io_waiter_registry; - Dataspace_registry &_ds_registry; - - Constructible _rom_from_vfs { }; - - /** - * Wrapped ROM session at core - */ - Constructible _rom_from_parent { }; - - Dataspace_capability _init_ds_cap(Env &env, Name const &name) - { - if (name.string()[0] == '/') { - _rom_from_vfs.construct(_root_dir, _vfs_io_waiter_registry, - name, env.ram(), env.rm(), _alloc); - return _rom_from_vfs->ds; - } - - _rom_from_parent.construct(env, name.string()); - Dataspace_capability ds = _rom_from_parent->dataspace(); - return ds; - } - - Dataspace_capability const _ds_cap; - - public: - - Rom_session_component(Allocator &alloc, Env &env, Rpc_entrypoint &ep, - Vfs::File_system &root_dir, - Vfs_io_waiter_registry &vfs_io_waiter_registry, - Dataspace_registry &ds_registry, Name const &name) - : - _alloc(alloc), _ep(ep), _root_dir(root_dir), - _vfs_io_waiter_registry(vfs_io_waiter_registry), - _ds_registry(ds_registry), _ds_cap(_init_ds_cap(env, name)) - { - _ep.manage(this); - _ds_registry.insert(new (alloc) Rom_dataspace_info(_ds_cap)); - } - - ~Rom_session_component() - { - Rom_dataspace_info *ds_info = nullptr; - - /* - * Lookup and lock ds info instead of directly accessing - * the '_ds_info' member. - */ - _ds_registry.apply(_ds_cap, [&] (Rom_dataspace_info *info) { - - if (!info) { - error("~Rom_session_component: unexpected !info"); - return; - } - - _ds_registry.remove(info); - - info->dissolve_users(); - - ds_info = info; - }); - destroy(_alloc, ds_info); - _ep.dissolve(this); - } - - - /*************************** - ** ROM session interface ** - ***************************/ - - Rom_dataspace_capability dataspace() override - { - return static_cap_cast(_ds_cap); - } - - void sigh(Signal_context_capability) override { } -}; - -#endif /* _NOUX__ROM_SESSION_COMPONENT_H_ */ diff --git a/repos/ports/src/noux/shared_pointer.h b/repos/ports/src/noux/shared_pointer.h deleted file mode 100644 index 90297ddd1..000000000 --- a/repos/ports/src/noux/shared_pointer.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * \brief Reference-counting smart pointer - * \author Norman Feske - * \date 2011-02-17 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__SHARED_POINTER_PTR_H_ -#define _NOUX__SHARED_POINTER_PTR_H_ - -/* Genode includes */ -#include -#include -#include - -/* Noux includes */ -#include - -namespace Noux { - class Reference_counter; - class Shared_pointer_base; - template class Shared_pointer; -} - - -class Noux::Reference_counter -{ - private: - - Lock _lock { }; - long _value; - - friend class Shared_pointer_base; - - void _inc_ref_count() - { - Lock::Guard guard(_lock); - _value++; - } - - /** - * \return reference counter after decrement - */ - long _dec_ref_count() - { - Lock::Guard guard(_lock); - return --_value; - } - - public: - - Reference_counter() : _value(0) { } -}; - - -class Noux::Shared_pointer_base -{ - protected: - - Reference_counter *_ref_counter; - - Shared_pointer_base(Reference_counter *ref_counter) - : _ref_counter(ref_counter) { } - - void _inc_ref_count() { - if (_ref_counter) _ref_counter->_inc_ref_count(); } - - bool _dec_ref_count() { - return _ref_counter && (_ref_counter->_dec_ref_count() == 0); } - - long count() const { return _ref_counter ? _ref_counter->_value : -99; } -}; - - -template -class Noux::Shared_pointer : public Shared_pointer_base -{ - private: - - T *_ptr; - Allocator *_alloc; - - void _dec_ref_count() - { - if (Shared_pointer_base::_dec_ref_count()) { - - destroy(_alloc, _ptr); - _ptr = 0; - _alloc = 0; - _ref_counter = 0; - } - } - - public: - - Shared_pointer() : Shared_pointer_base(0), _ptr(0), _alloc(0) { } - - Shared_pointer(T *ptr, Allocator &alloc) - : Shared_pointer_base(ptr), _ptr(ptr), _alloc(&alloc) - { - _inc_ref_count(); - } - - Shared_pointer(Shared_pointer const & from) - : - Shared_pointer_base(from._ref_counter), - _ptr(from._ptr), _alloc(from._alloc) - { - _inc_ref_count(); - } - - Shared_pointer & operator=(const Shared_pointer& from) - { - /* check for self assignment */ - if (_ptr == from._ptr) - return *this; - - /* forget about original pointed-to object */ - _dec_ref_count(); - - _ref_counter = from._ref_counter; - _ptr = from._ptr; - _alloc = from._alloc; - - /* account for newly assigned pointed-to object */ - _inc_ref_count(); - - return *this; - } - - ~Shared_pointer() - { - _dec_ref_count(); - } - - T * operator -> () { return _ptr; } - T const* operator -> () const { return _ptr; } - - operator bool () const { return _ptr != 0; } - - bool operator== (const Shared_pointer &other) - { - return (_ptr == other._ptr); - } - - template - Shared_pointer dynamic_pointer_cast() - { - return Shared_pointer(dynamic_cast(_ptr), _alloc); - } -}; - -#endif /* _NOUX__SHARED_POINTER_H_ */ diff --git a/repos/ports/src/noux/syscall.cc b/repos/ports/src/noux/syscall.cc deleted file mode 100644 index 1d2722105..000000000 --- a/repos/ports/src/noux/syscall.cc +++ /dev/null @@ -1,1026 +0,0 @@ -/* - * \brief Noux syscall dispatcher - * \author Norman Feske - * \date 2011-02-14 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Noux includes */ -#include -#include -#include -#include - -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(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: - { - Shared_pointer 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' */ - result = io->write(_sysio); - } else { - if (io->nonblocking()) - _sysio.error.write = Vfs::File_io_service::WRITE_ERR_WOULD_BLOCK; - else - _sysio.error.write = Vfs::File_io_service::WRITE_ERR_INTERRUPT; - } - - break; - } - - case SYSCALL_READ: - { - Shared_pointer 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 { - if (io->nonblocking()) - _sysio.error.read = Vfs::File_io_service::READ_ERR_WOULD_BLOCK; - else - _sysio.error.read = Vfs::File_io_service::READ_ERR_INTERRUPT; - } - - break; - } - - case SYSCALL_FTRUNCATE: - { - Shared_pointer 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.inode = path_hash; - } - - _sysio.stat_out.st = stat_out; - - break; - } - - case SYSCALL_FSTAT: - { - Shared_pointer 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 */ - close_fd_on_execve(_sysio.fcntl_in.fd, !!_sysio.fcntl_in.long_arg); - result = true; - break; - } - - if (_sysio.fcntl_in.cmd == Sysio::FCNTL_CMD_GET_FD_FLAGS) { - - /* we assume that there is only the close-on-execve flag */ - _sysio.fcntl_out.result = close_fd_on_execve(_sysio.fcntl_in.fd); - result = true; - break; - } - - result = _lookup_channel(_sysio.fcntl_in.fd)->fcntl(_sysio); - break; - - case SYSCALL_OPEN: - { - Vfs::Vfs_handle *vfs_handle = 0; - - if (_root_dir.directory(_sysio.open_in.path)) { - - typedef Vfs::Directory_service::Opendir_result Opendir_result; - typedef Vfs::Directory_service::Open_result Open_result; - - Opendir_result opendir_result = - _root_dir.opendir(_sysio.open_in.path, false, - &vfs_handle, _heap); - - switch (opendir_result) { - case Opendir_result::OPENDIR_OK: - _sysio.error.open = Open_result::OPEN_OK; - break; - case Opendir_result::OPENDIR_ERR_LOOKUP_FAILED: - _sysio.error.open = Open_result::OPEN_ERR_UNACCESSIBLE; - break; - case Opendir_result::OPENDIR_ERR_NAME_TOO_LONG: - _sysio.error.open = Open_result::OPEN_ERR_NAME_TOO_LONG; - break; - case Opendir_result::OPENDIR_ERR_NODE_ALREADY_EXISTS: - _sysio.error.open = Open_result::OPEN_ERR_EXISTS; - break; - case Opendir_result::OPENDIR_ERR_NO_SPACE: - _sysio.error.open = Open_result::OPEN_ERR_NO_SPACE; - break; - case Opendir_result::OPENDIR_ERR_OUT_OF_RAM: - case Opendir_result::OPENDIR_ERR_OUT_OF_CAPS: - case Opendir_result::OPENDIR_ERR_PERMISSION_DENIED: - _sysio.error.open = Open_result::OPEN_ERR_NO_PERM; - break; - } - - } else { - - _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; - - if (!leaf_path) - break; - - Shared_pointer - channel(new (_heap) Vfs_io_channel(_sysio.open_in.path, - leaf_path, - vfs_handle, - _vfs_io_waiter_registry, - _env.ep(), - _time_info, - _timer_connection), - _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: - - typedef Child_env Execve_child_env; - - try { - - Execve_child_env child_env(_sysio.execve_in.filename, - _sysio.execve_in.args, - _sysio.execve_in.env, - _root_dir, _vfs_io_waiter_registry, - _env.ram(), _env.rm(), _heap); - - _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 (Execve_child_env::Binary_does_not_exist) { - _sysio.error.execve = Sysio::EXECVE_ERR_NO_ENTRY; } - catch (Execve_child_env::Binary_is_not_accessible) { - _sysio.error.execve = Sysio::EXECVE_ERR_ACCESS; } - catch (Execve_child_env::Binary_is_not_executable) { - _sysio.error.execve = Sysio::EXECVE_ERR_NO_EXEC; } - catch (Child::Insufficient_memory) { - _sysio.error.execve = Sysio::EXECVE_ERR_NO_MEMORY; } - - 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]; - - Genode::uint64_t timeout_sec = _sysio.select_in.timeout.sec; - Genode::uint64_t 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 = 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 = 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()) { - Microseconds const us { timeout_sec*1000U*1000U + timeout_usec }; - Armed_timeout::State ts { }; - Armed_timeout timeout(ts, _blocker, _timer_connection, us); - - /* 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 - */ - timeout.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 = 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, - _time_info, - this, - _kill_broadcaster, - _timer_connection, - *this, - _pid_allocator, - new_pid, - _env, - _root_dir, - _vfs_io_waiter_registry, - _args, - _sysio_env.env(), - _heap, - _ref_pd, _ref_pd_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, false); - - /* copy our address space into the new child */ - try { - _pd.replay(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(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 (new (_heap) Pipe, _heap); - Shared_pointer pipe_sink (new (_heap) Pipe_sink_io_channel (pipe, _env.ep()), _heap); - Shared_pointer 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::Vfs_handle *symlink_handle { 0 }; - - Vfs::Directory_service::Openlink_result openlink_result = - _root_dir.openlink(_sysio.readlink_in.path, false, &symlink_handle, _heap); - - switch (openlink_result) { - case Vfs::Directory_service::OPENLINK_OK: - result = true; - break; - case Vfs::Directory_service::OPENLINK_ERR_LOOKUP_FAILED: - _sysio.error.readlink = Sysio::READLINK_ERR_NO_ENTRY; - break; - case Vfs::Directory_service::OPENLINK_ERR_NAME_TOO_LONG: - case Vfs::Directory_service::OPENLINK_ERR_NODE_ALREADY_EXISTS: - case Vfs::Directory_service::OPENLINK_ERR_NO_SPACE: - case Vfs::Directory_service::OPENLINK_ERR_OUT_OF_RAM: - case Vfs::Directory_service::OPENLINK_ERR_OUT_OF_CAPS: - case Vfs::Directory_service::OPENLINK_ERR_PERMISSION_DENIED: - _sysio.error.readlink = Sysio::READLINK_ERR_NO_PERM; - } - - if (openlink_result != Vfs::Directory_service::OPENLINK_OK) - break; - - Vfs::file_size count = min(_sysio.readlink_in.bufsiz, - sizeof(_sysio.readlink_out.chunk)); - - Registered_no_delete - vfs_io_waiter(_vfs_io_waiter_registry); - - while (!symlink_handle->fs().queue_read(symlink_handle, count)) - vfs_io_waiter.wait_for_io(); - - Vfs_handle_context read_context; - Vfs::Vfs_handle::Guard guard(symlink_handle); - - symlink_handle->handler(&read_context); - - Vfs::file_size out_count = 0; - Vfs::File_io_service::Read_result read_result; - - for (;;) { - read_result = symlink_handle->fs().complete_read(symlink_handle, - _sysio.readlink_out.chunk, - count, - out_count); - - if (read_result != Vfs::File_io_service::READ_QUEUED) - break; - - read_context.vfs_io_waiter.wait_for_io(); - } - - /* wake up threads blocking for 'queue_*()' or 'write()' */ - _vfs_io_waiter_registry.for_each([] (Vfs_io_waiter &r) { - r.wakeup(); - }); - - _sysio.readlink_out.count = out_count; - - 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: - { - Vfs::Vfs_handle *dir_handle { 0 }; - - typedef Vfs::Directory_service::Opendir_result Opendir_result; - - Opendir_result opendir_result = - _root_dir.opendir(_sysio.mkdir_in.path, true, &dir_handle, _heap); - - switch (opendir_result) { - case Opendir_result::OPENDIR_OK: - dir_handle->ds().close(dir_handle); - result = true; - break; - case Opendir_result::OPENDIR_ERR_LOOKUP_FAILED: - _sysio.error.mkdir = Sysio::MKDIR_ERR_NO_ENTRY; - break; - case Opendir_result::OPENDIR_ERR_NAME_TOO_LONG: - _sysio.error.mkdir = Sysio::MKDIR_ERR_NAME_TOO_LONG; - break; - case Opendir_result::OPENDIR_ERR_NODE_ALREADY_EXISTS: - _sysio.error.mkdir = Sysio::MKDIR_ERR_EXISTS; - break; - case Opendir_result::OPENDIR_ERR_NO_SPACE: - _sysio.error.mkdir = Sysio::MKDIR_ERR_NO_SPACE; - break; - case Opendir_result::OPENDIR_ERR_OUT_OF_RAM: - case Opendir_result::OPENDIR_ERR_OUT_OF_CAPS: - case Opendir_result::OPENDIR_ERR_PERMISSION_DENIED: - _sysio.error.mkdir = Sysio::MKDIR_ERR_NO_PERM; - break; - } - - break; - } - - case SYSCALL_SYMLINK: - { - - Vfs::Vfs_handle *symlink_handle { 0 }; - - typedef Vfs::Directory_service::Openlink_result Openlink_result; - - Openlink_result openlink_result = - _root_dir.openlink(_sysio.symlink_in.newpath, true, - &symlink_handle, _heap); - - switch (openlink_result) { - case Openlink_result::OPENLINK_OK: - result = true; - break; - case Openlink_result::OPENLINK_ERR_LOOKUP_FAILED: - _sysio.error.symlink = Sysio::SYMLINK_ERR_NO_ENTRY; - break; - case Openlink_result::OPENLINK_ERR_NAME_TOO_LONG: - case Openlink_result::OPENLINK_ERR_NODE_ALREADY_EXISTS: - case Openlink_result::OPENLINK_ERR_NO_SPACE: - case Openlink_result::OPENLINK_ERR_OUT_OF_RAM: - case Openlink_result::OPENLINK_ERR_OUT_OF_CAPS: - case Openlink_result::OPENLINK_ERR_PERMISSION_DENIED: - _sysio.error.symlink = Sysio::SYMLINK_ERR_NO_PERM; - } - - if (openlink_result != Openlink_result::OPENLINK_OK) - break; - - Vfs::file_size count = strlen(_sysio.symlink_in.oldpath) + 1; - Vfs::file_size out_count; - - Registered_no_delete - vfs_io_waiter(_vfs_io_waiter_registry); - - for (;;) { - try { - symlink_handle->fs().write(symlink_handle, _sysio.symlink_in.oldpath, - strlen(_sysio.symlink_in.oldpath) + 1, - out_count); - break; - } catch (Vfs::File_io_service::Insufficient_buffer) { - vfs_io_waiter.wait_for_io(); - } - } - - /* wake up threads blocking for 'queue_*()' or 'write()' */ - _vfs_io_waiter_registry.for_each([] (Vfs_io_waiter &r) { - r.wakeup(); - }); - - if (out_count != count) { - _sysio.error.symlink = Sysio::SYMLINK_ERR_NAME_TOO_LONG; - result = false; - } - - while (!symlink_handle->fs().queue_sync(symlink_handle)) - vfs_io_waiter.wait_for_io(); - - Vfs_handle_context sync_context; - Vfs::Vfs_handle::Guard guard(symlink_handle); - - symlink_handle->handler(&sync_context); - - while (symlink_handle->fs().complete_sync(symlink_handle) == - Vfs::File_io_service::SYNC_QUEUED) - sync_context.vfs_io_waiter.wait_for_io(); - - /* wake up threads blocking for 'queue_*()' or 'write()' */ - _vfs_io_waiter_registry.for_each([] (Vfs_io_waiter &r) { - r.wakeup(); - }); - - 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: - { - Milliseconds const ms = - _timer_connection.curr_time().trunc_to_plain_ms(); - - _sysio.gettimeofday_out.sec = _time_info.initial_time(); - _sysio.gettimeofday_out.sec += (ms.value / 1000); - _sysio.gettimeofday_out.usec = (ms.value % 1000) * 1000; - - result = true; - break; - } - - case SYSCALL_CLOCK_GETTIME: - { - /** - * It's the same procedure as in SYSCALL_GETTIMEOFDAY. - */ - Milliseconds const ms = - _timer_connection.curr_time().trunc_to_plain_ms(); - - 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_info.initial_time(); - _sysio.clock_gettime_out.sec += (ms.value / 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: - { - /** - * Always return true, even if 'update_modification_timestamp' - * failed to keep programs, e.g. make, happy. - */ - result = true; - - char const *path = (char const *)_sysio.utimes_in.path; - unsigned long sec = _sysio.utimes_in.sec; - unsigned long usec = _sysio.utimes_in.usec; - (void)usec; - - Vfs::Vfs_handle *vfs_handle = 0; - _root_dir.open(path, 0, &vfs_handle, _heap); - if (!vfs_handle) { break; } - - if (!sec) { - Milliseconds const ms = - _timer_connection.curr_time().trunc_to_plain_ms(); - sec = _time_info.initial_time(); - sec += (ms.value / 1000); - usec = (ms.value % 1000) * 1000; - } - - Registered_no_delete - vfs_io_waiter(_vfs_io_waiter_registry); - - Vfs::Timestamp ts { .value = (long long)sec }; - - for (;;) { - if (vfs_handle->fs().update_modification_timestamp(vfs_handle, ts)) { - break; - } else { - vfs_io_waiter.wait_for_io(); - } - } - - _root_dir.close(vfs_handle); - break; - } - - case SYSCALL_SYNC: - { - /* no errors supported at this time */ - result = true; - - Vfs::Vfs_handle *sync_handle; - - Vfs::Directory_service::Opendir_result opendir_result = - _root_dir.opendir("/", false, &sync_handle, _heap); - - if (opendir_result != Vfs::Directory_service::OPENDIR_OK) - break; - - Registered_no_delete - vfs_io_waiter(_vfs_io_waiter_registry); - - while (!sync_handle->fs().queue_sync(sync_handle)) - vfs_io_waiter.wait_for_io(); - - Vfs_handle_context sync_context; - Vfs::Vfs_handle::Guard guard(sync_handle); - - sync_handle->handler(&sync_context); - - while (sync_handle->fs().complete_sync(sync_handle) == - Vfs::File_io_service::SYNC_QUEUED) - sync_context.vfs_io_waiter.wait_for_io(); - - /* wake up threads blocking for 'queue_*()' or 'write()' */ - _vfs_io_waiter_registry.for_each([] (Vfs_io_waiter &r) { - r.wakeup(); - }); - - 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: - - /* network support was removed */ - result = false; - 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; -} diff --git a/repos/ports/src/noux/target.mk b/repos/ports/src/noux/target.mk deleted file mode 100644 index f1323a308..000000000 --- a/repos/ports/src/noux/target.mk +++ /dev/null @@ -1,6 +0,0 @@ -TARGET = noux -LIBS = base vfs -SRC_CC = main.cc syscall.cc -INC_DIR += $(PRG_DIR) - -vpath %.cc $(PRG_DIR) diff --git a/repos/ports/src/noux/terminal_io_channel.h b/repos/ports/src/noux/terminal_io_channel.h deleted file mode 100644 index 71937f4b8..000000000 --- a/repos/ports/src/noux/terminal_io_channel.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * \brief I/O channel targeting Genode's terminal interface - * \author Norman Feske - * \date 2011-10-21 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__TERMINAL_IO_CHANNEL_H_ -#define _NOUX__TERMINAL_IO_CHANNEL_H_ - -/* Genode includes */ -#include -#include -#include -#include - -/* Noux includes */ -#include -#include - -namespace Noux { struct Terminal_io_channel; } - - -struct Noux::Terminal_io_channel : Io_channel -{ - Terminal::Session &_terminal; - - Signal_handler _read_avail_handler; - - Signal_handler _resize_handler; - - enum { EOF = 4 }; - - bool eof = false; - - enum Type { STDIN, STDOUT, STDERR } type; - - Ring_buffer read_buffer { }; - - Terminal_io_channel(Terminal::Session &terminal, Type type, - Entrypoint &ep) - : - _terminal(terminal), - _read_avail_handler(ep, *this, &Terminal_io_channel::_handle_read_avail), - _resize_handler (ep, *this, &Terminal_io_channel::_handle_resize), - type(type) - { - /* - * Enable wake up STDIN channel on the presence of new input - * - * By registering our I/O channel as signal handler, the Noux - * main loop will be unblocked on the arrival of new input. - * It will check if the received signal belongs to an I/O channel - * and invokes the 'handle_signal' function of the I/O channel. - * - * This gives us the opportunity to handle the unblocking of - * blocking system calls such as 'select'. - */ - if (type == STDIN) { - terminal.read_avail_sigh(_read_avail_handler); - terminal.size_changed_sigh(_resize_handler); - } - } - - bool write(Sysio &sysio) override - { - 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; - - return true; - } - - bool read(Sysio &sysio) override - { - if (type != STDIN) { - error("attempt to read from terminal output channel"); - return false; - } - - /* deliver EOF observed by the previous 'read' call */ - if (eof) { - sysio.read_out.count = 0; - eof = false; - return true; - } - - size_t const max_count = - min(sysio.read_in.count, - sizeof(sysio.read_out.chunk)); - - for (sysio.read_out.count = 0; - (sysio.read_out.count < max_count) && !read_buffer.empty(); - sysio.read_out.count++) { - - char c = read_buffer.get(); - - if (c == EOF) { - - /* - * If EOF was the only character of the batch, the count - * has reached zero. In this case the read result indicates - * the EOF condition as is. However, if count is greater - * than zero, we deliver the previous characters of the - * batch and return the zero result from the subsequent - * 'read' call. This condition is tracked by the 'eof' - * variable. - */ - if (sysio.read_out.count > 0) - eof = true; - - return true; - } - - sysio.read_out.chunk[sysio.read_out.count] = c; - } - - return true; - } - - bool fcntl(Sysio &sysio) override - { - /** - * Actually it is "inappropiate" to use fcntl() directly on terminals - * (atleast according to the Open Group Specification). We do it anyway - * since in our case stdout/in/err is directly connected to the terminal. - * - * Some GNU programms check if stdout is open by calling fcntl(stdout, F_GETFL, ...). - */ - switch (sysio.fcntl_in.cmd) { - - case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: - sysio.fcntl_out.result = 0; - return true; - - default: - return false; - } - - return false; - } - - bool fstat(Sysio &sysio) override - { - sysio.fstat_out.st.type = Vfs::Node_type::CONTINUOUS_FILE; - return true; - } - - bool check_unblock(bool rd, bool wr, bool) const override - { - /* never block for writing */ - if (wr) return true; - - /* - * Unblock I/O channel if the terminal has new user input. Channels - * otther than STDIN will never unblock. - */ - return (rd && (type == STDIN) && !read_buffer.empty()); - } - - bool ioctl(Sysio &sysio) override - { - switch (sysio.ioctl_in.request) { - - case Vfs::File_io_service::IOCTL_OP_TIOCGWINSZ: - { - Terminal::Session::Size size = _terminal.size(); - sysio.ioctl_out.tiocgwinsz.rows = size.lines(); - sysio.ioctl_out.tiocgwinsz.columns = size.columns(); - return true; - } - - case Vfs::File_io_service::IOCTL_OP_TIOCSETAF: - { - warning(__func__, ": OP_TIOCSETAF not implemented"); - return false; - } - - case Vfs::File_io_service::IOCTL_OP_TIOCSETAW: - { - warning(__func__, ": OP_TIOCSETAW not implemented"); - return false; - } - - default: - - warning("invalid ioctl request ", (int)sysio.ioctl_in.request); - return false; - }; - } - - void _handle_read_avail() - { - while ((read_buffer.avail_capacity() > 0) && - _terminal.avail()) { - - char c; - _terminal.read(&c, 1); - - enum { INTERRUPT = 3 }; - - if (c == INTERRUPT) { - Io_channel::invoke_all_interrupt_handlers(Sysio::SIG_INT); - } else { - read_buffer.add(c); - } - } - - Io_channel::invoke_all_notifiers(); - } - - void _handle_resize() - { - /* respond to terminal-close event */ - Terminal::Session::Size const size = _terminal.size(); - if (size.columns()*size.lines() == 0) - read_buffer.add(EOF); - - Io_channel::invoke_all_interrupt_handlers(Sysio::SIG_WINCH); - } -}; - -#endif /* _NOUX__TERMINAL_IO_CHANNEL_H_ */ diff --git a/repos/ports/src/noux/time_info.h b/repos/ports/src/noux/time_info.h deleted file mode 100644 index df666fa2e..000000000 --- a/repos/ports/src/noux/time_info.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * \brief Time information - * \author Josef Soentgen - * \date 2019-04-09 - */ - -/* - * Copyright (C) 2019 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__TIME_INFO_H_ -#define _NOUX__TIME_INFO_H_ - -/* Genode includes */ -#include -#include -#include - -/* Noux includes */ -#include - -namespace Noux { - class Time_info; - using namespace Genode; -} - - -class Noux::Time_info : Noncopyable -{ - private: - - Constructible _rtc { }; - - Genode::int64_t _initial_time { 0 }; - - static bool _leap(unsigned year) - { - return ((year % 4) == 0 - && ((year % 100) != 0 || (year % 400) == 0)); - } - - /** - * Convert RTC timestamp to UNIX epoch (UTC) - */ - static Genode::int64_t _convert(Rtc::Timestamp const &ts) - { - if (ts.year < 1970) { return 0; } - - /* - * Seconds per year lookup table - */ - static constexpr unsigned _secs_per_year[2] = { - 365 * 86400, 366 * 86400, - }; - - /* - * Seconds per month lookup table - */ - static constexpr unsigned _sec_per_month[13] = { - 0 * 86400, - 31 * 86400, 28 * 86400, 31 * 86400, 30 * 86400, - 31 * 86400, 30 * 86400, 31 * 86400, 31 * 86400, - 30 * 86400, 31 * 86400, 30 * 86400, 31 * 86400 - }; - - Genode::int64_t time = 0; - - for (unsigned i = 1970; i < ts.year; i++) { - /* abuse bool conversion for seconds look up */ - time += _secs_per_year[(int)_leap(i)]; - } - - for (unsigned i = 1; i < ts.month; i++) { - time += _sec_per_month[i]; - } - time += _leap(ts.year) * 86400LL; - - time += 86400LL * (ts.day-1); - time += 3600LL * ts.hour; - time += 60LL * ts.minute; - time += ts.second; - - return time; - } - - public: - - Time_info(Env &env, Xml_node config) - { - /* only try to establish the connection on demand */ - bool const rtc = config.attribute_value("rtc", false); - if (!rtc) { return; } - - _rtc.construct(env); - _initial_time = _convert(_rtc->current_time()); - } - - Genode::int64_t initial_time() const { return _initial_time; } -}; - -#endif /* _NOUX__TIME_INFO_H_ */ diff --git a/repos/ports/src/noux/user_info.h b/repos/ports/src/noux/user_info.h deleted file mode 100644 index 7884981d7..000000000 --- a/repos/ports/src/noux/user_info.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * \brief User information - * \author Josef Soentgen - * \author Norman Feske - * \date 2012-07-23 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__USER_INFO_H_ -#define _NOUX__USER_INFO_H_ - -/* Genode includes */ -#include -#include - -/* Noux includes */ -#include - -namespace Noux { - class User_info; - using namespace Genode; -} - - -class Noux::User_info : Noncopyable -{ - public: - - typedef String Name; - typedef String Shell; - typedef String Home; - - private: - - unsigned const _uid; - unsigned const _gid; - - Name const _name; - Shell const _shell; - Home const _home; - - template - 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: - - User_info(Xml_node node) - : - _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 uid() const { return _uid; } - unsigned gid() const { return _gid; } - - Name name() const { return _name; } - Shell shell() const { return _shell; } - Home home() const { return _home; } -}; - -#endif /* _NOUX__USER_INFO_H_ */ diff --git a/repos/ports/src/noux/verbose.h b/repos/ports/src/noux/verbose.h deleted file mode 100644 index 8122d5104..000000000 --- a/repos/ports/src/noux/verbose.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * \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 Affero General Public License version 3. - */ - -#ifndef _NOUX__VERBOSE_H_ -#define _NOUX__VERBOSE_H_ - -#include -#include - -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_ */ diff --git a/repos/ports/src/noux/vfs_io_channel.h b/repos/ports/src/noux/vfs_io_channel.h deleted file mode 100644 index e86babc29..000000000 --- a/repos/ports/src/noux/vfs_io_channel.h +++ /dev/null @@ -1,385 +0,0 @@ -/* - * \brief I/O channel for files opened via virtual directory service - * \author Norman Feske - * \date 2011-02-17 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__VFS_IO_CHANNEL_H_ -#define _NOUX__VFS_IO_CHANNEL_H_ - -/* Genode includes */ -#include - -/* Noux includes */ -#include -#include -#include - -namespace Noux { - class Vfs_io_waiter; - struct Vfs_handle_context; - struct Vfs_io_channel; - - typedef Registry> - Vfs_io_waiter_registry; -} - -class Noux::Vfs_io_waiter -{ - private: - - Genode::Semaphore _sem { }; - - public: - - void wait_for_io() { _sem.down(); } - - void wakeup() { _sem.up(); } -}; - -struct Noux::Vfs_handle_context : Vfs::Io_response_handler -{ - Vfs_io_waiter vfs_io_waiter { }; - - void read_ready_response() override { - vfs_io_waiter.wakeup(); } - - void io_progress_response() override { - vfs_io_waiter.wakeup(); } -}; - -struct Noux::Vfs_io_channel : Io_channel -{ - Signal_handler _read_avail_handler; - - void _handle_read_avail() - { - Io_channel::invoke_all_notifiers(); - } - - Vfs::Vfs_handle &_fh; - - Vfs_io_waiter_registry &_vfs_io_waiter_registry; - - Absolute_path _path; - Absolute_path _leaf_path; - - bool const _dir = _fh.ds().directory(_leaf_path.base()); - - Time_info const &_time_info; - Timer::Connection &_timer; - - void _sync() - { - Milliseconds const ms = - _timer.curr_time().trunc_to_plain_ms(); - uint64_t sec = _time_info.initial_time(); - sec += (ms.value / 1000); - - Vfs::Timestamp ts { .value = (long long)sec }; - - Registered_no_delete - vfs_io_waiter(_vfs_io_waiter_registry); - - if ((_fh.status_flags() & Sysio::OPEN_MODE_ACCMODE) != Sysio::OPEN_MODE_RDONLY) { - for (;;) { - if (_fh.fs().update_modification_timestamp(&_fh, ts)) { - break; - } else { - Genode::error("_sync: update_modification_timestamp failed"); - vfs_io_waiter.wait_for_io(); - } - } - } - - while (!_fh.fs().queue_sync(&_fh)) - vfs_io_waiter.wait_for_io(); - - while (_fh.fs().complete_sync(&_fh) == Vfs::File_io_service::SYNC_QUEUED) - vfs_io_waiter.wait_for_io(); - - /* wake up threads blocking for 'queue_*()' or 'write()' */ - _vfs_io_waiter_registry.for_each([] (Vfs_io_waiter &r) { - r.wakeup(); - }); - } - - Vfs_io_channel(char const *path, char const *leaf_path, - Vfs::Vfs_handle *vfs_handle, - Vfs_io_waiter_registry &vfs_io_waiter_registry, - Entrypoint &ep, - Time_info const &time_info, - Timer::Connection &timer) - : - _read_avail_handler(ep, *this, &Vfs_io_channel::_handle_read_avail), - _fh(*vfs_handle), _vfs_io_waiter_registry(vfs_io_waiter_registry), - _path(path), _leaf_path(leaf_path), _time_info(time_info), _timer(timer) - { - _fh.fs().register_read_ready_sigh(&_fh, _read_avail_handler); - } - - ~Vfs_io_channel() - { - _sync(); - - _fh.ds().close(&_fh); - } - - bool write(Sysio &sysio) override - { - if (_dir) { - sysio.error.write = Vfs::File_io_service::WRITE_ERR_INVALID; - return false; - } - - Vfs::file_size count = sysio.write_in.count; - Vfs::file_size out_count = 0; - - Registered_no_delete - vfs_io_waiter(_vfs_io_waiter_registry); - - for (;;) { - try { - sysio.error.write = _fh.fs().write(&_fh, sysio.write_in.chunk, - count, out_count); - break; - } catch (Vfs::File_io_service::Insufficient_buffer) { - vfs_io_waiter.wait_for_io(); - } - } - - /* wake up threads blocking for 'queue_*()' or 'write()' */ - _vfs_io_waiter_registry.for_each([] (Vfs_io_waiter &r) { - r.wakeup(); - }); - - if (sysio.error.write != Vfs::File_io_service::WRITE_OK) - return false; - - _fh.advance_seek(out_count); - - sysio.write_out.count = out_count; - - return true; - } - - bool read(Sysio &sysio) override - { - if (_dir) { - sysio.error.read = Vfs::File_io_service::READ_ERR_INVALID; - return false; - } - - size_t count = min(sysio.read_in.count, sizeof(sysio.read_out.chunk)); - - Vfs::file_size out_count = 0; - - Registered_no_delete - vfs_io_waiter(_vfs_io_waiter_registry); - - while (!_fh.fs().queue_read(&_fh, count)) - vfs_io_waiter.wait_for_io(); - - for (;;) { - - sysio.error.read = _fh.fs().complete_read(&_fh, sysio.read_out.chunk, count, out_count); - - if (sysio.error.read != Vfs::File_io_service::READ_QUEUED) - break; - - vfs_io_waiter.wait_for_io(); - } - - /* wake up threads blocking for 'queue_*()' or 'write()' */ - _vfs_io_waiter_registry.for_each([] (Vfs_io_waiter &r) { - r.wakeup(); - }); - - if (sysio.error.read != Vfs::File_io_service::READ_OK) - return false; - - sysio.read_out.count = out_count; - - _fh.advance_seek(out_count); - - return true; - } - - bool fstat(Sysio &sysio) override - { - _sync(); - - /* - * 'sysio.stat_in' is not used in '_fh.ds().stat()', - * so no 'sysio' member translation is needed here - */ - - Vfs::Directory_service::Stat stat; - sysio.error.stat = _fh.ds().stat(_leaf_path.base(), stat); - sysio.fstat_out.st = stat; - - return (sysio.error.stat == Vfs::Directory_service::STAT_OK); - } - - bool ftruncate(Sysio &sysio) override - { - _sync(); - - sysio.error.ftruncate = _fh.fs().ftruncate(&_fh, sysio.ftruncate_in.length); - - return (sysio.error.ftruncate == Vfs::File_io_service::FTRUNCATE_OK); - } - - bool fcntl(Sysio &sysio) override - { - switch (sysio.fcntl_in.cmd) { - - case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS: - - sysio.fcntl_out.result = _fh.status_flags(); - return true; - - case Sysio::FCNTL_CMD_SET_FILE_STATUS_FLAGS: - _fh.status_flags(sysio.fcntl_in.long_arg); - return true; - - default: - - warning("invalid fcntl command ", (int)sysio.fcntl_in.cmd); - sysio.error.fcntl = Sysio::FCNTL_ERR_CMD_INVALID; - return false; - }; - } - - /* - * The 'dirent' function for the root directory only (the - * 'Dir_file_system::open()' function handles all requests referring - * to directories). Hence, '_path' is the absolute path of the - * directory to inspect. - */ - bool dirent(Sysio &sysio) override - { - /* - * Return artificial dir entries for "." and ".." - */ - unsigned const index = _fh.seek() / sizeof(Sysio::Dirent); - if (index < 2) { - sysio.dirent_out.entry.type = Vfs::Directory_service::Dirent_type::DIRECTORY; - strncpy(sysio.dirent_out.entry.name, - index ? ".." : ".", - sizeof(sysio.dirent_out.entry.name)); - - sysio.dirent_out.entry.fileno = 1; - _fh.advance_seek(sizeof(Sysio::Dirent)); - return true; - } - - /* - * Delegate remaining dir-entry request to the actual file system. - * Align index range to zero when calling the directory service. - */ - - Vfs::file_size noux_dirent_seek = _fh.seek(); - _fh.seek((index - 2) * sizeof(Vfs::Directory_service::Dirent)); - - Vfs::file_size const count = sizeof(Vfs::Directory_service::Dirent); - - Registered_no_delete - vfs_io_waiter(_vfs_io_waiter_registry); - - while (!_fh.fs().queue_read(&_fh, count)) - vfs_io_waiter.wait_for_io(); - - Vfs::File_io_service::Read_result read_result; - Vfs::file_size out_count = 0; - Vfs::Directory_service::Dirent dirent { }; - - for (;;) { - read_result = _fh.fs().complete_read(&_fh, (char*)&dirent, - count, out_count); - - if (read_result != Vfs::File_io_service::READ_QUEUED) - break; - - vfs_io_waiter.wait_for_io(); - } - - /* wake up threads blocking for 'queue_*()' or 'write()' */ - _vfs_io_waiter_registry.for_each([] (Vfs_io_waiter &r) { - r.wakeup(); - }); - - if ((read_result != Vfs::File_io_service::READ_OK) || - (out_count != sizeof(dirent))) { - dirent = { }; - } - - _fh.seek(noux_dirent_seek); - - sysio.dirent_out.entry = dirent; - - _fh.advance_seek(sizeof(Sysio::Dirent)); - return true; - } - - /** - * Return size of file that the I/O channel refers to - * - * Note that this function overwrites the 'sysio' argument. Do not - * call it prior saving all input arguments from the original sysio - * structure. - */ - size_t size(Sysio &sysio) - { - if (fstat(sysio)) - return sysio.fstat_out.st.size; - - return 0; - } - - bool ioctl(Sysio &sysio) override - { - 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); - - return (sysio.error.ioctl == Vfs::File_io_service::IOCTL_OK); - } - - bool lseek(Sysio &sysio) override - { - switch (sysio.lseek_in.whence) { - 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_END: - off_t offset = sysio.lseek_in.offset; - sysio.fstat_in.fd = sysio.lseek_in.fd; - _fh.seek(size(sysio) + offset); - break; - } - sysio.lseek_out.offset = _fh.seek(); - return true; - } - - bool check_unblock(bool rd, bool wr, bool ex) const override - { - return _fh.fs().check_unblock(&_fh, rd, wr, ex); - } - - bool path(char *path, size_t len) override - { - strncpy(path, _path.base(), len); - path[len - 1] = '\0'; - - return true; - } -}; - -#endif /* _NOUX__VFS_IO_CHANNEL_H_ */ diff --git a/repos/ports/src/noux/wake_up_notifier.h b/repos/ports/src/noux/wake_up_notifier.h deleted file mode 100644 index aedebfcbb..000000000 --- a/repos/ports/src/noux/wake_up_notifier.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * \brief Utility for implementing blocking syscalls - * \author Norman Feske - * \date 2011-11-05 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _NOUX__WAKE_UP_NOTIFIER__H_ -#define _NOUX__WAKE_UP_NOTIFIER__H_ - -/* Genode includes */ -#include -#include - -namespace Noux { struct Wake_up_notifier; } - - -struct Noux::Wake_up_notifier : List::Element -{ - Lock *lock; - - Wake_up_notifier(Lock *lock = nullptr) : lock(lock) { } - - void wake_up() { if (lock) lock->unlock(); } -}; - -#endif /* _NOUX__WAKE_UP_NOTIFIER__H_ */ diff --git a/repos/ports/src/test/libc_noux/target.mk b/repos/ports/src/test/libc_noux/target.mk deleted file mode 100644 index 24ff82bd7..000000000 --- a/repos/ports/src/test/libc_noux/target.mk +++ /dev/null @@ -1,8 +0,0 @@ -TARGET = test-libc_noux -LIBS = libc -SRC_CC = main.cc - -# we re-use the libc_vfs test -vpath main.cc $(call select_from_repositories,src/test/libc_vfs) - -CC_CXX_WARN_STRICT = diff --git a/repos/ports/src/test/noux_signals/main.cc b/repos/ports/src/test/noux_signals/main.cc deleted file mode 100644 index 79da4d7dd..000000000 --- a/repos/ports/src/test/noux_signals/main.cc +++ /dev/null @@ -1,56 +0,0 @@ -/* - * \brief Noux SIGINT handler test - * \author Christian Prochaska - * \date 2013-10-17 - */ - -/* - * Copyright (C) 2013-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#include -#include -#include -#include -#include -#include - -void signal_handler(int signal) -{ - printf("%d: signal handler for signal %d called\n", - getpid(), signal); -} - -int main(int argc, char *argv[]) -{ - char c; - - struct sigaction sa; - - memset (&sa, '\0', sizeof(sa)); - - sa.sa_handler = signal_handler; - - sigaction(SIGINT, &sa, 0); - - int pid = fork(); - - if (pid == 0) - printf("test ready\n"); - - if ((read(0, &c, 1) == -1) && (errno = EINTR)) - printf("%d: 'read()' returned with error EINTR\n", getpid()); - else - printf("%d: 'read()' returned character 0x = %x\n", getpid(), c); - - if (pid > 0) { - waitpid(pid, 0, 0); - printf("test finished\n"); - } - - return 0; -} - diff --git a/repos/ports/src/test/noux_signals/target.mk b/repos/ports/src/test/noux_signals/target.mk deleted file mode 100644 index c17f57aa8..000000000 --- a/repos/ports/src/test/noux_signals/target.mk +++ /dev/null @@ -1,5 +0,0 @@ -TARGET = test-noux_signals -SRC_CC = main.cc -LIBS = posix - -CC_CXX_WARN_STRICT =