genode/ports/include/noux_session/sysio.h
Norman Feske 66290ea46d Stacked file systems for Noux
This patch introduces support for stacked file systems alongside new
glue for accessing file-system implementations provided via Genode's
new file-system-session interface.

Using stacked file systems, an arbitrary number of file systems (such
as tar archives or file systems implemented as separate Genode
components) can be composed to form one merged virtual file system.

An example is given via the 'ports/run/noux_bash.run' script. This run
script creates a virtual file system out of multiple tar archives each
containing the content of a particular GNU package. In addition, one
'ram_fs' is mounted, which enables Noux to perform write operations.
This way, the shell output can be redirected to a file, or files can
be saved in VIM.

Fixes #103.
2012-05-17 20:34:00 +02:00

303 lines
7.1 KiB
C++

/*
* \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-2012 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 _INCLUDE__NOUX_SESSION__SYSIO_H_
#define _INCLUDE__NOUX_SESSION__SYSIO_H_
/* Genode includes */
#include <util/misc_math.h>
#define SYSIO_DECL(syscall_name, args, results) \
struct args syscall_name##_in; \
struct results syscall_name##_out;
namespace Noux {
using namespace Genode;
struct Sysio
{
/*
* Information about pending signals
*/
enum { SIG_MAX = 32 };
bool sig_mask[SIG_MAX];
/*
* Number of pending signals
*/
int sig_cnt;
enum { MAX_PATH_LEN = 512 };
typedef char Path[MAX_PATH_LEN];
enum { CHUNK_SIZE = 7*1024 };
typedef char Chunk[CHUNK_SIZE];
enum { ARGS_MAX_LEN = 3*1024 };
typedef char Args[ARGS_MAX_LEN];
enum { ENV_MAX_LEN = 3*1024 };
typedef char Env[ENV_MAX_LEN];
typedef __SIZE_TYPE__ size_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 = 0x0200,
};
enum {
STAT_MODE_SYMLINK = 0120000,
STAT_MODE_FILE = 0100000,
STAT_MODE_DIRECTORY = 0040000,
STAT_MODE_CHARDEV = 0020000,
};
struct Stat
{
size_t size;
unsigned mode;
unsigned uid;
unsigned gid;
unsigned long inode;
unsigned device;
};
/**
* Argument structure used for ioctl syscall
*/
struct Ioctl_in
{
enum Opcode { OP_UNDEFINED, OP_TIOCGWINSZ };
Opcode request;
};
/**
* Structure carrying the result values of 'ioctl' syscalls
*/
struct Ioctl_out
{
union
{
/* if request was 'OP_TIOCGSIZE' */
struct {
int rows;
int columns;
} tiocgwinsz;
};
};
enum Lseek_whence { LSEEK_SET, LSEEK_CUR, LSEEK_END };
enum { DIRENT_MAX_NAME_LEN = 128 };
enum Dirent_type {
DIRENT_TYPE_FILE,
DIRENT_TYPE_DIRECTORY,
DIRENT_TYPE_FIFO,
DIRENT_TYPE_SYMLINK,
DIRENT_TYPE_END
};
struct Dirent
{
int fileno;
Dirent_type type;
char name[DIRENT_MAX_NAME_LEN];
};
enum Fcntl_cmd {
FCNTL_CMD_GET_FILE_STATUS_FLAGS,
FCNTL_CMD_SET_FD_FLAGS
};
/**
* 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); }
};
enum General_error { ERR_FD_INVALID, NUM_GENERAL_ERRORS };
enum Stat_error { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS };
enum Fcntl_error { FCNTL_ERR_CMD_INVALID = NUM_GENERAL_ERRORS };
enum Open_error { OPEN_ERR_UNACCESSIBLE, OPEN_ERR_NO_PERM };
enum Execve_error { EXECVE_NONEXISTENT = NUM_GENERAL_ERRORS };
enum Unlink_error { UNLINK_ERR_NO_ENTRY, UNLINK_ERR_NO_PERM };
enum Rename_error { RENAME_ERR_NO_ENTRY, RENAME_ERR_CROSS_FS,
RENAME_ERR_NO_PERM };
enum Mkdir_error { MKDIR_ERR_EXISTS, MKDIR_ERR_NO_ENTRY,
MKDIR_ERR_NO_SPACE, MKDIR_ERR_NO_PERM,
MKDIR_ERR_NAME_TOO_LONG};
union {
General_error general;
Stat_error stat;
Fcntl_error fcntl;
Open_error open;
Execve_error execve;
Unlink_error unlink;
Rename_error rename;
Mkdir_error mkdir;
} error;
union {
SYSIO_DECL(getcwd, { }, { Path path; });
SYSIO_DECL(write, { int fd; size_t count; Chunk chunk; },
{ size_t count; });
SYSIO_DECL(stat, { Path path; }, { Stat st; });
SYSIO_DECL(fstat, { int fd; }, { Stat st; });
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(fchdir, { int fd; }, { });
SYSIO_DECL(read, { int fd; size_t count; },
{ 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; }, { });
SYSIO_DECL(unlink, { Path path; }, { });
SYSIO_DECL(rename, { Path from_path; Path to_path; }, { });
SYSIO_DECL(mkdir, { Path path; int mode; }, { });
};
};
};
#undef SYSIO_DECL
#endif /* _INCLUDE__NOUX_SESSION__SYSIO_H_ */