committed by
Christian Helmuth
parent
56ed7addbc
commit
e8336acafc
@@ -18,98 +18,98 @@
|
||||
#include <file_system_session/capability.h>
|
||||
#include <packet_stream_tx/client.h>
|
||||
|
||||
namespace File_system {
|
||||
|
||||
class Session_client : public Rpc_client<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
Packet_stream_tx::Client<Tx> _tx;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param session session capability
|
||||
* \param tx_buffer_alloc allocator used for managing the
|
||||
* transmission buffer
|
||||
*/
|
||||
Session_client(Session_capability session,
|
||||
Range_allocator &tx_buffer_alloc)
|
||||
:
|
||||
Rpc_client<Session>(session),
|
||||
_tx(call<Rpc_tx_cap>(), &tx_buffer_alloc)
|
||||
{ }
|
||||
namespace File_system { class Session_client; }
|
||||
|
||||
|
||||
/***********************************
|
||||
** File-system session interface **
|
||||
***********************************/
|
||||
class File_system::Session_client : public Rpc_client<Session>
|
||||
{
|
||||
private:
|
||||
|
||||
Tx::Source *tx() { return _tx.source(); }
|
||||
Packet_stream_tx::Client<Tx> _tx;
|
||||
|
||||
File_handle file(Dir_handle dir, Name const &name, Mode mode, bool create)
|
||||
{
|
||||
return call<Rpc_file>(dir, name, mode, create);
|
||||
}
|
||||
public:
|
||||
|
||||
Symlink_handle symlink(Dir_handle dir, Name const &name, bool create)
|
||||
{
|
||||
return call<Rpc_symlink>(dir, name, create);
|
||||
}
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param session session capability
|
||||
* \param tx_buffer_alloc allocator used for managing the
|
||||
* transmission buffer
|
||||
*/
|
||||
Session_client(Session_capability session,
|
||||
Range_allocator &tx_buffer_alloc)
|
||||
:
|
||||
Rpc_client<Session>(session),
|
||||
_tx(call<Rpc_tx_cap>(), &tx_buffer_alloc)
|
||||
{ }
|
||||
|
||||
Dir_handle dir(Path const &path, bool create)
|
||||
{
|
||||
return call<Rpc_dir>(path, create);
|
||||
}
|
||||
|
||||
Node_handle node(Path const &path)
|
||||
{
|
||||
return call<Rpc_node>(path);
|
||||
}
|
||||
/***********************************
|
||||
** File-system session interface **
|
||||
***********************************/
|
||||
|
||||
void close(Node_handle node)
|
||||
{
|
||||
call<Rpc_close>(node);
|
||||
}
|
||||
Tx::Source *tx() { return _tx.source(); }
|
||||
|
||||
Status status(Node_handle node)
|
||||
{
|
||||
return call<Rpc_status>(node);
|
||||
}
|
||||
File_handle file(Dir_handle dir, Name const &name, Mode mode, bool create) override
|
||||
{
|
||||
return call<Rpc_file>(dir, name, mode, create);
|
||||
}
|
||||
|
||||
void control(Node_handle node, Control control)
|
||||
{
|
||||
call<Rpc_control>(node, control);
|
||||
}
|
||||
Symlink_handle symlink(Dir_handle dir, Name const &name, bool create) override
|
||||
{
|
||||
return call<Rpc_symlink>(dir, name, create);
|
||||
}
|
||||
|
||||
void unlink(Dir_handle dir, Name const &name)
|
||||
{
|
||||
call<Rpc_unlink>(dir, name);
|
||||
}
|
||||
Dir_handle dir(Path const &path, bool create) override
|
||||
{
|
||||
return call<Rpc_dir>(path, create);
|
||||
}
|
||||
|
||||
void truncate(File_handle file, file_size_t size)
|
||||
{
|
||||
call<Rpc_truncate>(file, size);
|
||||
}
|
||||
Node_handle node(Path const &path) override
|
||||
{
|
||||
return call<Rpc_node>(path);
|
||||
}
|
||||
|
||||
void move(Dir_handle from_dir, Name const &from_name,
|
||||
Dir_handle to_dir, Name const &to_name)
|
||||
{
|
||||
call<Rpc_move>(from_dir, from_name, to_dir, to_name);
|
||||
}
|
||||
void close(Node_handle node) override
|
||||
{
|
||||
call<Rpc_close>(node);
|
||||
}
|
||||
|
||||
void sigh(Node_handle node, Signal_context_capability sigh)
|
||||
{
|
||||
call<Rpc_sigh>(node, sigh);
|
||||
}
|
||||
Status status(Node_handle node) override
|
||||
{
|
||||
return call<Rpc_status>(node);
|
||||
}
|
||||
|
||||
void sync()
|
||||
{
|
||||
call<Rpc_sync>();
|
||||
}
|
||||
};
|
||||
}
|
||||
void control(Node_handle node, Control control) override
|
||||
{
|
||||
call<Rpc_control>(node, control);
|
||||
}
|
||||
|
||||
void unlink(Dir_handle dir, Name const &name) override
|
||||
{
|
||||
call<Rpc_unlink>(dir, name);
|
||||
}
|
||||
|
||||
void truncate(File_handle file, file_size_t size) override
|
||||
{
|
||||
call<Rpc_truncate>(file, size);
|
||||
}
|
||||
|
||||
void move(Dir_handle from_dir, Name const &from_name,
|
||||
Dir_handle to_dir, Name const &to_name) override
|
||||
{
|
||||
call<Rpc_move>(from_dir, from_name, to_dir, to_name);
|
||||
}
|
||||
|
||||
void sigh(Node_handle node, Signal_context_capability sigh) override
|
||||
{
|
||||
call<Rpc_sigh>(node, sigh);
|
||||
}
|
||||
|
||||
void sync() override
|
||||
{
|
||||
call<Rpc_sync>();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__FILE_SYSTEM_SESSION__CLIENT_H_ */
|
||||
|
||||
@@ -18,26 +18,26 @@
|
||||
#include <base/connection.h>
|
||||
#include <base/allocator.h>
|
||||
|
||||
namespace File_system {
|
||||
namespace File_system { struct Connection; }
|
||||
|
||||
struct Connection : Genode::Connection<Session>, Session_client
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param tx_buffer_alloc allocator used for managing the
|
||||
* transmission buffer
|
||||
* \param tx_buf_size size of transmission buffer in bytes
|
||||
*/
|
||||
Connection(Range_allocator &tx_block_alloc,
|
||||
size_t tx_buf_size = 128*1024,
|
||||
const char *label = "")
|
||||
:
|
||||
Genode::Connection<Session>(
|
||||
session("ram_quota=%zd, tx_buf_size=%zd, label=\"%s\"",
|
||||
4*1024*sizeof(long) + tx_buf_size, tx_buf_size, label)),
|
||||
Session_client(cap(), tx_block_alloc) { }
|
||||
};
|
||||
}
|
||||
|
||||
struct File_system::Connection : Genode::Connection<Session>, Session_client
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param tx_buffer_alloc allocator used for managing the
|
||||
* transmission buffer
|
||||
* \param tx_buf_size size of transmission buffer in bytes
|
||||
*/
|
||||
Connection(Range_allocator &tx_block_alloc,
|
||||
size_t tx_buf_size = 128*1024,
|
||||
const char *label = "")
|
||||
:
|
||||
Genode::Connection<Session>(
|
||||
session("ram_quota=%zd, tx_buf_size=%zd, label=\"%s\"",
|
||||
4*1024*sizeof(long) + tx_buf_size, tx_buf_size, label)),
|
||||
Session_client(cap(), tx_block_alloc) { }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__FILE_SYSTEM_SESSION__CONNECTION_H_ */
|
||||
|
||||
@@ -23,37 +23,10 @@ namespace File_system {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
struct Node_handle
|
||||
{
|
||||
int value;
|
||||
|
||||
Node_handle() : value(-1) { }
|
||||
Node_handle(int v) : value(v) { }
|
||||
|
||||
bool valid() const { return value != -1; }
|
||||
};
|
||||
|
||||
|
||||
struct File_handle : Node_handle
|
||||
{
|
||||
File_handle() { }
|
||||
File_handle(int v) : Node_handle(v) { }
|
||||
};
|
||||
|
||||
|
||||
struct Dir_handle : Node_handle
|
||||
{
|
||||
Dir_handle() { }
|
||||
Dir_handle(int v) : Node_handle(v) { }
|
||||
};
|
||||
|
||||
|
||||
struct Symlink_handle : Node_handle
|
||||
{
|
||||
Symlink_handle() { }
|
||||
Symlink_handle(int v) : Node_handle(v) { }
|
||||
};
|
||||
|
||||
struct Node_handle;
|
||||
struct File_handle;
|
||||
struct Dir_handle;
|
||||
struct Symlink_handle;
|
||||
|
||||
/**
|
||||
* Type of client context embedded in each packet descriptor
|
||||
@@ -64,66 +37,10 @@ namespace File_system {
|
||||
*/
|
||||
struct Packet_ref;
|
||||
|
||||
|
||||
typedef uint64_t seek_off_t;
|
||||
typedef uint64_t file_size_t;
|
||||
|
||||
|
||||
class Packet_descriptor : public ::Packet_descriptor
|
||||
{
|
||||
public:
|
||||
|
||||
enum Opcode { READ, WRITE };
|
||||
|
||||
private:
|
||||
|
||||
Node_handle _handle; /* node handle */
|
||||
Opcode _op; /* requested operation */
|
||||
seek_off_t _position; /* seek offset in bytes */
|
||||
size_t _length; /* transaction length in bytes */
|
||||
bool _success; /* indicates success of operation */
|
||||
Packet_ref *_ref; /* opaque reference used at the client side
|
||||
for recognizing acknowledgements */
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Packet_descriptor(off_t offset = 0, size_t size = 0)
|
||||
:
|
||||
::Packet_descriptor(offset, size), _handle(-1),
|
||||
_op(READ), _position(0), _length(0), _success(false) { }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param position seek offset in bytes (by default, append)
|
||||
*/
|
||||
Packet_descriptor(Packet_descriptor p, Packet_ref *ref,
|
||||
Node_handle handle, Opcode op, size_t length,
|
||||
seek_off_t position = ~0)
|
||||
:
|
||||
::Packet_descriptor(p.offset(), p.size()),
|
||||
_handle(handle), _op(op),
|
||||
_position(position), _length(length), _success(false),
|
||||
_ref(ref)
|
||||
{ }
|
||||
|
||||
Node_handle handle() const { return _handle; }
|
||||
Opcode operation() const { return _op; }
|
||||
seek_off_t position() const { return _position; }
|
||||
size_t length() const { return _length; }
|
||||
bool succeeded() const { return _success; }
|
||||
Packet_ref *ref() const { return _ref; }
|
||||
|
||||
/*
|
||||
* Accessors called at the server side
|
||||
*/
|
||||
void succeeded(bool b) { _success = b ? 1 : 0; }
|
||||
void length(size_t length) { _length = length; }
|
||||
};
|
||||
|
||||
class Packet_descriptor;
|
||||
|
||||
/**
|
||||
* Flags as supplied to 'file', 'dir', and 'symlink' calls
|
||||
@@ -135,42 +52,9 @@ namespace File_system {
|
||||
typedef Rpc_in_buffer<MAX_NAME_LEN> Name;
|
||||
typedef Rpc_in_buffer<MAX_PATH_LEN> Path;
|
||||
|
||||
|
||||
struct Status
|
||||
{
|
||||
enum {
|
||||
MODE_SYMLINK = 0020000,
|
||||
MODE_FILE = 0100000,
|
||||
MODE_DIRECTORY = 0040000,
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX add access time
|
||||
* XXX add executable bit
|
||||
*/
|
||||
|
||||
file_size_t size;
|
||||
unsigned mode;
|
||||
unsigned long inode;
|
||||
|
||||
bool is_directory() const { return mode & MODE_DIRECTORY; }
|
||||
bool is_symlink() const { return mode & MODE_SYMLINK; }
|
||||
};
|
||||
|
||||
|
||||
struct Control { /* to manipulate the executable bit */ };
|
||||
|
||||
|
||||
/**
|
||||
* Data structure returned when reading from a directory node
|
||||
*/
|
||||
struct Directory_entry
|
||||
{
|
||||
enum Type { TYPE_FILE, TYPE_DIRECTORY, TYPE_SYMLINK };
|
||||
Type type;
|
||||
char name[MAX_NAME_LEN];
|
||||
};
|
||||
|
||||
struct Status;
|
||||
struct Control;
|
||||
struct Directory_entry;
|
||||
|
||||
/*
|
||||
* Exception types
|
||||
@@ -186,169 +70,295 @@ namespace File_system {
|
||||
class Invalid_name : Exception { };
|
||||
class Size_limit_reached : Exception { };
|
||||
|
||||
|
||||
struct Session : public Genode::Session
|
||||
{
|
||||
enum { TX_QUEUE_SIZE = 16 };
|
||||
|
||||
typedef Packet_stream_policy<File_system::Packet_descriptor,
|
||||
TX_QUEUE_SIZE, TX_QUEUE_SIZE,
|
||||
char> Tx_policy;
|
||||
|
||||
typedef Packet_stream_tx::Channel<Tx_policy> Tx;
|
||||
|
||||
static const char *service_name() { return "File_system"; }
|
||||
|
||||
virtual ~Session() { }
|
||||
|
||||
/**
|
||||
* Request client-side packet-stream interface of tx channel
|
||||
*/
|
||||
virtual Tx::Source *tx() { return 0; }
|
||||
|
||||
/**
|
||||
* Open or create file
|
||||
*
|
||||
* \throw Invalid_handle directory handle is invalid
|
||||
* \throw Node_already_exists file cannot be created because a
|
||||
* node with the same name already exists
|
||||
* \throw Invalid_name file name contains invalid characters
|
||||
* \throw Lookup_failed the name refers to a node other than a
|
||||
* file
|
||||
*/
|
||||
virtual File_handle file(Dir_handle, Name const &name, Mode, bool create) = 0;
|
||||
|
||||
/**
|
||||
* Open or create symlink
|
||||
*/
|
||||
virtual Symlink_handle symlink(Dir_handle, Name const &name, bool create) = 0;
|
||||
|
||||
/**
|
||||
* Open or create directory
|
||||
*
|
||||
* \throw Permission_denied
|
||||
* \throw Node_already_exists directory cannot be created because a
|
||||
* node with the same name already exists
|
||||
* \throw Lookup_failed path lookup failed because one element
|
||||
* of 'path' does not exist
|
||||
* \throw Name_too_long
|
||||
* \throw No_space
|
||||
*/
|
||||
virtual Dir_handle dir(Path const &path, bool create) = 0;
|
||||
|
||||
/**
|
||||
* Open existing node
|
||||
*
|
||||
* The returned node handle can be used merely as argument for
|
||||
* 'status'.
|
||||
*/
|
||||
virtual Node_handle node(Path const &path) = 0;
|
||||
|
||||
/**
|
||||
* Close file
|
||||
*/
|
||||
virtual void close(Node_handle) = 0;
|
||||
|
||||
/**
|
||||
* Request information about an open file or directory
|
||||
*/
|
||||
virtual Status status(Node_handle) = 0;
|
||||
|
||||
/**
|
||||
* Set information about an open file or directory
|
||||
*/
|
||||
virtual void control(Node_handle, Control) = 0;
|
||||
|
||||
/**
|
||||
* Delete file or directory
|
||||
*/
|
||||
virtual void unlink(Dir_handle, Name const &) = 0;
|
||||
|
||||
/**
|
||||
* Truncate or grow file to specified size
|
||||
*/
|
||||
virtual void truncate(File_handle, file_size_t size) = 0;
|
||||
|
||||
/**
|
||||
* Move and rename directory entry
|
||||
*/
|
||||
virtual void move(Dir_handle, Name const &from,
|
||||
Dir_handle, Name const &to) = 0;
|
||||
|
||||
/**
|
||||
* Register handler that should be notified on node changes
|
||||
*/
|
||||
virtual void sigh(Node_handle, Signal_context_capability sigh) = 0;
|
||||
|
||||
/**
|
||||
* Synchronize file system
|
||||
*
|
||||
* This is only needed by file systems that maintain an internal
|
||||
* cache, which needs to be flushed on certain occasions. Therefore,
|
||||
* the default implementation just serves as a reminder.
|
||||
*/
|
||||
virtual void sync() { PWRN("sync() not implemented!"); }
|
||||
|
||||
|
||||
/*******************
|
||||
** RPC interface **
|
||||
*******************/
|
||||
|
||||
GENODE_RPC(Rpc_tx_cap, Capability<Tx>, _tx_cap);
|
||||
GENODE_RPC_THROW(Rpc_file, File_handle, file,
|
||||
GENODE_TYPE_LIST(Invalid_handle, Node_already_exists,
|
||||
Invalid_name, Lookup_failed,
|
||||
Permission_denied),
|
||||
Dir_handle, Name const &, Mode, bool);
|
||||
GENODE_RPC_THROW(Rpc_symlink, Symlink_handle, symlink,
|
||||
GENODE_TYPE_LIST(Invalid_handle, Node_already_exists,
|
||||
Invalid_name, Lookup_failed, Permission_denied),
|
||||
Dir_handle, Name const &, bool);
|
||||
GENODE_RPC_THROW(Rpc_dir, Dir_handle, dir,
|
||||
GENODE_TYPE_LIST(Permission_denied, Node_already_exists,
|
||||
Lookup_failed, Name_too_long, No_space),
|
||||
Path const &, bool);
|
||||
GENODE_RPC_THROW(Rpc_node, Node_handle, node,
|
||||
GENODE_TYPE_LIST(Lookup_failed),
|
||||
Path const &);
|
||||
GENODE_RPC(Rpc_close, void, close, Node_handle);
|
||||
GENODE_RPC(Rpc_status, Status, status, Node_handle);
|
||||
GENODE_RPC(Rpc_control, void, control, Node_handle, Control);
|
||||
GENODE_RPC_THROW(Rpc_unlink, void, unlink,
|
||||
GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed),
|
||||
Dir_handle, Name const &);
|
||||
GENODE_RPC_THROW(Rpc_truncate, void, truncate,
|
||||
GENODE_TYPE_LIST(Permission_denied, Invalid_handle),
|
||||
File_handle, file_size_t);
|
||||
GENODE_RPC_THROW(Rpc_move, void, move,
|
||||
GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed),
|
||||
Dir_handle, Name const &, Dir_handle, Name const &);
|
||||
GENODE_RPC_THROW(Rpc_sigh, void, sigh,
|
||||
GENODE_TYPE_LIST(Invalid_handle),
|
||||
Node_handle, Signal_context_capability);
|
||||
GENODE_RPC(Rpc_sync, void, sync);
|
||||
|
||||
/*
|
||||
* Manual type-list definition, needed because the RPC interface
|
||||
* exceeds the maximum number of type-list elements supported by
|
||||
* 'Genode::Meta::Type_list<>'.
|
||||
*/
|
||||
typedef Meta::Type_tuple<Rpc_tx_cap,
|
||||
Meta::Type_tuple<Rpc_file,
|
||||
Meta::Type_tuple<Rpc_symlink,
|
||||
Meta::Type_tuple<Rpc_dir,
|
||||
Meta::Type_tuple<Rpc_node,
|
||||
Meta::Type_tuple<Rpc_close,
|
||||
Meta::Type_tuple<Rpc_status,
|
||||
Meta::Type_tuple<Rpc_control,
|
||||
Meta::Type_tuple<Rpc_unlink,
|
||||
Meta::Type_tuple<Rpc_truncate,
|
||||
Meta::Type_tuple<Rpc_move,
|
||||
Meta::Type_tuple<Rpc_sigh,
|
||||
Meta::Type_tuple<Rpc_sync,
|
||||
Meta::Empty>
|
||||
> > > > > > > > > > > > Rpc_functions;
|
||||
};
|
||||
struct Session;
|
||||
}
|
||||
|
||||
|
||||
struct File_system::Node_handle
|
||||
{
|
||||
int value;
|
||||
|
||||
Node_handle() : value(-1) { }
|
||||
Node_handle(int v) : value(v) { }
|
||||
|
||||
bool valid() const { return value != -1; }
|
||||
};
|
||||
|
||||
|
||||
struct File_system::File_handle : Node_handle
|
||||
{
|
||||
File_handle() { }
|
||||
File_handle(int v) : Node_handle(v) { }
|
||||
};
|
||||
|
||||
|
||||
struct File_system::Dir_handle : Node_handle
|
||||
{
|
||||
Dir_handle() { }
|
||||
Dir_handle(int v) : Node_handle(v) { }
|
||||
};
|
||||
|
||||
|
||||
struct File_system::Symlink_handle : Node_handle
|
||||
{
|
||||
Symlink_handle() { }
|
||||
Symlink_handle(int v) : Node_handle(v) { }
|
||||
};
|
||||
|
||||
|
||||
class File_system::Packet_descriptor : public ::Packet_descriptor
|
||||
{
|
||||
public:
|
||||
|
||||
enum Opcode { READ, WRITE };
|
||||
|
||||
private:
|
||||
|
||||
Node_handle _handle; /* node handle */
|
||||
Opcode _op; /* requested operation */
|
||||
seek_off_t _position; /* seek offset in bytes */
|
||||
size_t _length; /* transaction length in bytes */
|
||||
bool _success; /* indicates success of operation */
|
||||
Packet_ref *_ref; /* opaque reference used at the client side
|
||||
for recognizing acknowledgements */
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Packet_descriptor(off_t offset = 0, size_t size = 0)
|
||||
:
|
||||
::Packet_descriptor(offset, size), _handle(-1),
|
||||
_op(READ), _position(0), _length(0), _success(false) { }
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param position seek offset in bytes (by default, append)
|
||||
*/
|
||||
Packet_descriptor(Packet_descriptor p, Packet_ref *ref,
|
||||
Node_handle handle, Opcode op, size_t length,
|
||||
seek_off_t position = ~0)
|
||||
:
|
||||
::Packet_descriptor(p.offset(), p.size()),
|
||||
_handle(handle), _op(op),
|
||||
_position(position), _length(length), _success(false),
|
||||
_ref(ref)
|
||||
{ }
|
||||
|
||||
Node_handle handle() const { return _handle; }
|
||||
Opcode operation() const { return _op; }
|
||||
seek_off_t position() const { return _position; }
|
||||
size_t length() const { return _length; }
|
||||
bool succeeded() const { return _success; }
|
||||
Packet_ref *ref() const { return _ref; }
|
||||
|
||||
/*
|
||||
* Accessors called at the server side
|
||||
*/
|
||||
void succeeded(bool b) { _success = b ? 1 : 0; }
|
||||
void length(size_t length) { _length = length; }
|
||||
};
|
||||
|
||||
|
||||
struct File_system::Status
|
||||
{
|
||||
enum {
|
||||
MODE_SYMLINK = 0020000,
|
||||
MODE_FILE = 0100000,
|
||||
MODE_DIRECTORY = 0040000,
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX add access time
|
||||
* XXX add executable bit
|
||||
*/
|
||||
|
||||
file_size_t size;
|
||||
unsigned mode;
|
||||
unsigned long inode;
|
||||
|
||||
bool is_directory() const { return mode & MODE_DIRECTORY; }
|
||||
bool is_symlink() const { return mode & MODE_SYMLINK; }
|
||||
};
|
||||
|
||||
|
||||
struct File_system::Control { /* to manipulate the executable bit */ };
|
||||
|
||||
|
||||
/**
|
||||
* Data structure returned when reading from a directory node
|
||||
*/
|
||||
struct File_system::Directory_entry
|
||||
{
|
||||
enum Type { TYPE_FILE, TYPE_DIRECTORY, TYPE_SYMLINK };
|
||||
Type type;
|
||||
char name[MAX_NAME_LEN];
|
||||
};
|
||||
|
||||
|
||||
struct File_system::Session : public Genode::Session
|
||||
{
|
||||
enum { TX_QUEUE_SIZE = 16 };
|
||||
|
||||
typedef Packet_stream_policy<File_system::Packet_descriptor,
|
||||
TX_QUEUE_SIZE, TX_QUEUE_SIZE,
|
||||
char> Tx_policy;
|
||||
|
||||
typedef Packet_stream_tx::Channel<Tx_policy> Tx;
|
||||
|
||||
static const char *service_name() { return "File_system"; }
|
||||
|
||||
virtual ~Session() { }
|
||||
|
||||
/**
|
||||
* Request client-side packet-stream interface of tx channel
|
||||
*/
|
||||
virtual Tx::Source *tx() { return 0; }
|
||||
|
||||
/**
|
||||
* Open or create file
|
||||
*
|
||||
* \throw Invalid_handle directory handle is invalid
|
||||
* \throw Node_already_exists file cannot be created because a
|
||||
* node with the same name already exists
|
||||
* \throw Invalid_name file name contains invalid characters
|
||||
* \throw Lookup_failed the name refers to a node other than a
|
||||
* file
|
||||
*/
|
||||
virtual File_handle file(Dir_handle, Name const &name, Mode, bool create) = 0;
|
||||
|
||||
/**
|
||||
* Open or create symlink
|
||||
*/
|
||||
virtual Symlink_handle symlink(Dir_handle, Name const &name, bool create) = 0;
|
||||
|
||||
/**
|
||||
* Open or create directory
|
||||
*
|
||||
* \throw Permission_denied
|
||||
* \throw Node_already_exists directory cannot be created because a
|
||||
* node with the same name already exists
|
||||
* \throw Lookup_failed path lookup failed because one element
|
||||
* of 'path' does not exist
|
||||
* \throw Name_too_long
|
||||
* \throw No_space
|
||||
*/
|
||||
virtual Dir_handle dir(Path const &path, bool create) = 0;
|
||||
|
||||
/**
|
||||
* Open existing node
|
||||
*
|
||||
* The returned node handle can be used merely as argument for
|
||||
* 'status'.
|
||||
*/
|
||||
virtual Node_handle node(Path const &path) = 0;
|
||||
|
||||
/**
|
||||
* Close file
|
||||
*/
|
||||
virtual void close(Node_handle) = 0;
|
||||
|
||||
/**
|
||||
* Request information about an open file or directory
|
||||
*/
|
||||
virtual Status status(Node_handle) = 0;
|
||||
|
||||
/**
|
||||
* Set information about an open file or directory
|
||||
*/
|
||||
virtual void control(Node_handle, Control) = 0;
|
||||
|
||||
/**
|
||||
* Delete file or directory
|
||||
*/
|
||||
virtual void unlink(Dir_handle, Name const &) = 0;
|
||||
|
||||
/**
|
||||
* Truncate or grow file to specified size
|
||||
*/
|
||||
virtual void truncate(File_handle, file_size_t size) = 0;
|
||||
|
||||
/**
|
||||
* Move and rename directory entry
|
||||
*/
|
||||
virtual void move(Dir_handle, Name const &from,
|
||||
Dir_handle, Name const &to) = 0;
|
||||
|
||||
/**
|
||||
* Register handler that should be notified on node changes
|
||||
*/
|
||||
virtual void sigh(Node_handle, Signal_context_capability sigh) = 0;
|
||||
|
||||
/**
|
||||
* Synchronize file system
|
||||
*
|
||||
* This is only needed by file systems that maintain an internal
|
||||
* cache, which needs to be flushed on certain occasions. Therefore,
|
||||
* the default implementation just serves as a reminder.
|
||||
*/
|
||||
virtual void sync() { PWRN("sync() not implemented!"); }
|
||||
|
||||
|
||||
/*******************
|
||||
** RPC interface **
|
||||
*******************/
|
||||
|
||||
GENODE_RPC(Rpc_tx_cap, Capability<Tx>, _tx_cap);
|
||||
GENODE_RPC_THROW(Rpc_file, File_handle, file,
|
||||
GENODE_TYPE_LIST(Invalid_handle, Node_already_exists,
|
||||
Invalid_name, Lookup_failed,
|
||||
Permission_denied),
|
||||
Dir_handle, Name const &, Mode, bool);
|
||||
GENODE_RPC_THROW(Rpc_symlink, Symlink_handle, symlink,
|
||||
GENODE_TYPE_LIST(Invalid_handle, Node_already_exists,
|
||||
Invalid_name, Lookup_failed, Permission_denied),
|
||||
Dir_handle, Name const &, bool);
|
||||
GENODE_RPC_THROW(Rpc_dir, Dir_handle, dir,
|
||||
GENODE_TYPE_LIST(Permission_denied, Node_already_exists,
|
||||
Lookup_failed, Name_too_long, No_space),
|
||||
Path const &, bool);
|
||||
GENODE_RPC_THROW(Rpc_node, Node_handle, node,
|
||||
GENODE_TYPE_LIST(Lookup_failed),
|
||||
Path const &);
|
||||
GENODE_RPC(Rpc_close, void, close, Node_handle);
|
||||
GENODE_RPC(Rpc_status, Status, status, Node_handle);
|
||||
GENODE_RPC(Rpc_control, void, control, Node_handle, Control);
|
||||
GENODE_RPC_THROW(Rpc_unlink, void, unlink,
|
||||
GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed),
|
||||
Dir_handle, Name const &);
|
||||
GENODE_RPC_THROW(Rpc_truncate, void, truncate,
|
||||
GENODE_TYPE_LIST(Permission_denied, Invalid_handle),
|
||||
File_handle, file_size_t);
|
||||
GENODE_RPC_THROW(Rpc_move, void, move,
|
||||
GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed),
|
||||
Dir_handle, Name const &, Dir_handle, Name const &);
|
||||
GENODE_RPC_THROW(Rpc_sigh, void, sigh,
|
||||
GENODE_TYPE_LIST(Invalid_handle),
|
||||
Node_handle, Signal_context_capability);
|
||||
GENODE_RPC(Rpc_sync, void, sync);
|
||||
|
||||
/*
|
||||
* Manual type-list definition, needed because the RPC interface
|
||||
* exceeds the maximum number of type-list elements supported by
|
||||
* 'Genode::Meta::Type_list<>'.
|
||||
*/
|
||||
typedef Meta::Type_tuple<Rpc_tx_cap,
|
||||
Meta::Type_tuple<Rpc_file,
|
||||
Meta::Type_tuple<Rpc_symlink,
|
||||
Meta::Type_tuple<Rpc_dir,
|
||||
Meta::Type_tuple<Rpc_node,
|
||||
Meta::Type_tuple<Rpc_close,
|
||||
Meta::Type_tuple<Rpc_status,
|
||||
Meta::Type_tuple<Rpc_control,
|
||||
Meta::Type_tuple<Rpc_unlink,
|
||||
Meta::Type_tuple<Rpc_truncate,
|
||||
Meta::Type_tuple<Rpc_move,
|
||||
Meta::Type_tuple<Rpc_sigh,
|
||||
Meta::Type_tuple<Rpc_sync,
|
||||
Meta::Empty>
|
||||
> > > > > > > > > > > > Rpc_functions;
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__FILE_SYSTEM_SESSION__FILE_SYSTEM_SESSION_H_ */
|
||||
|
||||
@@ -18,36 +18,35 @@
|
||||
#include <packet_stream_tx/rpc_object.h>
|
||||
#include <base/rpc_server.h>
|
||||
|
||||
namespace File_system {
|
||||
namespace File_system { class Session_rpc_object; }
|
||||
|
||||
class Session_rpc_object : public Genode::Rpc_object<Session, Session_rpc_object>
|
||||
{
|
||||
protected:
|
||||
class File_system::Session_rpc_object : public Genode::Rpc_object<Session, Session_rpc_object>
|
||||
{
|
||||
protected:
|
||||
|
||||
Packet_stream_tx::Rpc_object<Tx> _tx;
|
||||
Packet_stream_tx::Rpc_object<Tx> _tx;
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param tx_ds dataspace used as communication buffer
|
||||
* for the tx packet stream
|
||||
* \param ep entry point used for packet-stream channel
|
||||
*/
|
||||
Session_rpc_object(Dataspace_capability tx_ds, Rpc_entrypoint &ep)
|
||||
: _tx(tx_ds, ep) { }
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param tx_ds dataspace used as communication buffer
|
||||
* for the tx packet stream
|
||||
* \param ep entry point used for packet-stream channel
|
||||
*/
|
||||
Session_rpc_object(Dataspace_capability tx_ds, Rpc_entrypoint &ep)
|
||||
: _tx(tx_ds, ep) { }
|
||||
|
||||
/**
|
||||
* Return capability to packet-stream channel
|
||||
*
|
||||
* This function is called by the client via an RPC call at session
|
||||
* construction time.
|
||||
*/
|
||||
Capability<Tx> _tx_cap() { return _tx.cap(); }
|
||||
/**
|
||||
* Return capability to packet-stream channel
|
||||
*
|
||||
* This function is called by the client via an RPC call at session
|
||||
* construction time.
|
||||
*/
|
||||
Capability<Tx> _tx_cap() { return _tx.cap(); }
|
||||
|
||||
Tx::Sink *tx_sink() { return _tx.sink(); }
|
||||
};
|
||||
}
|
||||
Tx::Sink *tx_sink() { return _tx.sink(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__FILE_SYSTEM_SESSION__SERVER_H_ */
|
||||
|
||||
Reference in New Issue
Block a user