mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-16 14:18:27 +00:00
committed by
Christian Helmuth
parent
eecb5cc300
commit
55c0a947e4
@ -9,11 +9,11 @@
|
||||
#define _DIRECTORY_H_
|
||||
|
||||
/* Genode include */
|
||||
#include <file_system/util.h>
|
||||
#include <os/path.h>
|
||||
|
||||
/* local includes */
|
||||
#include <node.h>
|
||||
#include <util.h>
|
||||
#include <file.h>
|
||||
|
||||
#include <lx_util.h>
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/node_handle_registry.h>
|
||||
#include <file_system_session/rpc_object.h>
|
||||
#include <root/component.h>
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
@ -22,7 +23,6 @@
|
||||
|
||||
/* local includes */
|
||||
#include <directory.h>
|
||||
#include <node_handle_registry.h>
|
||||
|
||||
|
||||
namespace File_system {
|
||||
@ -92,7 +92,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
|
||||
try {
|
||||
Node *node = _handle_registry.lookup_and_lock(packet.handle());
|
||||
Node_lock_guard guard(*node);
|
||||
Node_lock_guard guard(node);
|
||||
|
||||
_process_packet_op(packet, *node);
|
||||
}
|
||||
@ -191,7 +191,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
throw Invalid_name();
|
||||
|
||||
Directory *dir = _handle_registry.lookup_and_lock(dir_handle);
|
||||
Node_lock_guard dir_guard(*dir);
|
||||
Node_lock_guard dir_guard(dir);
|
||||
|
||||
if (!_writable)
|
||||
if (create || (mode != STAT_ONLY && mode != READ_ONLY))
|
||||
@ -199,7 +199,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
|
||||
File *file = dir->file(name.string(), mode, create);
|
||||
|
||||
Node_lock_guard file_guard(*file);
|
||||
Node_lock_guard file_guard(file);
|
||||
return _handle_registry.alloc(file);
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
throw Name_too_long();
|
||||
|
||||
Directory *dir = _root.subdir(path_str, create);
|
||||
Node_lock_guard guard(*dir);
|
||||
Node_lock_guard guard(dir);
|
||||
return _handle_registry.alloc(dir);
|
||||
}
|
||||
|
||||
@ -237,7 +237,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
|
||||
Node *node = _root.node(path_str + 1);
|
||||
|
||||
Node_lock_guard guard(*node);
|
||||
Node_lock_guard guard(node);
|
||||
return _handle_registry.alloc(node);
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
Status status(Node_handle node_handle)
|
||||
{
|
||||
Node *node = _handle_registry.lookup_and_lock(node_handle);
|
||||
Node_lock_guard guard(*node);
|
||||
Node_lock_guard guard(node);
|
||||
|
||||
Status s;
|
||||
s.inode = node->inode();
|
||||
@ -292,7 +292,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
throw Permission_denied();
|
||||
|
||||
File *file = _handle_registry.lookup_and_lock(file_handle);
|
||||
Node_lock_guard file_guard(*file);
|
||||
Node_lock_guard file_guard(file);
|
||||
file->truncate(size);
|
||||
}
|
||||
|
||||
|
@ -9,50 +9,13 @@
|
||||
#define _NODE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/signal.h>
|
||||
#include <file_system/listener.h>
|
||||
#include <file_system/node.h>
|
||||
|
||||
|
||||
namespace File_system {
|
||||
|
||||
class Listener : public List<Listener>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Lock _lock;
|
||||
Signal_context_capability _sigh;
|
||||
bool _marked_as_updated;
|
||||
|
||||
public:
|
||||
|
||||
Listener() : _marked_as_updated(false) { }
|
||||
|
||||
Listener(Signal_context_capability sigh)
|
||||
: _sigh(sigh), _marked_as_updated(false) { }
|
||||
|
||||
void notify()
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (_marked_as_updated && _sigh.valid())
|
||||
Signal_transmitter(_sigh).submit();
|
||||
|
||||
_marked_as_updated = false;
|
||||
}
|
||||
|
||||
void mark_as_updated()
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
_marked_as_updated = true;
|
||||
}
|
||||
|
||||
bool valid() const { return _sigh.valid(); }
|
||||
};
|
||||
|
||||
|
||||
class Node : public List<Node>::Element
|
||||
class Node : public Node_base
|
||||
{
|
||||
public:
|
||||
|
||||
@ -60,26 +23,13 @@ namespace File_system {
|
||||
|
||||
private:
|
||||
|
||||
Lock _lock;
|
||||
Name _name;
|
||||
unsigned long const _inode;
|
||||
|
||||
List<Listener> _listeners;
|
||||
|
||||
public:
|
||||
|
||||
Node(unsigned long inode) : _inode(inode) { _name[0] = 0; }
|
||||
|
||||
virtual ~Node()
|
||||
{
|
||||
/* propagate event to listeners */
|
||||
mark_as_updated();
|
||||
notify_listeners();
|
||||
|
||||
while (_listeners.first())
|
||||
_listeners.remove(_listeners.first());
|
||||
}
|
||||
|
||||
unsigned long inode() const { return _inode; }
|
||||
char const *name() const { return _name; }
|
||||
|
||||
@ -88,47 +38,10 @@ namespace File_system {
|
||||
*/
|
||||
void name(char const *name) { strncpy(_name, name, sizeof(_name)); }
|
||||
|
||||
void lock() { _lock.lock(); }
|
||||
void unlock() { _lock.unlock(); }
|
||||
|
||||
virtual size_t read(char *dst, size_t len, seek_off_t) = 0;
|
||||
virtual size_t write(char const *src, size_t len, seek_off_t) = 0;
|
||||
|
||||
void add_listener(Listener *listener)
|
||||
{
|
||||
_listeners.insert(listener);
|
||||
}
|
||||
|
||||
void remove_listener(Listener *listener)
|
||||
{
|
||||
_listeners.remove(listener);
|
||||
}
|
||||
|
||||
void notify_listeners()
|
||||
{
|
||||
for (Listener *curr = _listeners.first(); curr; curr = curr->next())
|
||||
curr->notify();
|
||||
}
|
||||
|
||||
void mark_as_updated()
|
||||
{
|
||||
for (Listener *curr = _listeners.first(); curr; curr = curr->next())
|
||||
curr->mark_as_updated();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Guard used for properly releasing node locks
|
||||
*/
|
||||
struct Node_lock_guard
|
||||
{
|
||||
Node &node;
|
||||
|
||||
Node_lock_guard(Node &node) : node(node) { }
|
||||
|
||||
~Node_lock_guard() { node.unlock(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _NODE_H_ */
|
||||
|
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* \brief Facility for managing the session-local node-handle namespace
|
||||
* \author Norman Feske
|
||||
* \date 2012-04-11
|
||||
*/
|
||||
|
||||
#ifndef _NODE_HANDLE_REGISTRY_H_
|
||||
#define _NODE_HANDLE_REGISTRY_H_
|
||||
|
||||
namespace File_system {
|
||||
|
||||
class Node;
|
||||
class Directory;
|
||||
class File;
|
||||
class Symlink;
|
||||
|
||||
/**
|
||||
* Type trait for determining the node type for a given handle type
|
||||
*/
|
||||
template<typename T> struct Node_type;
|
||||
template<> struct Node_type<Node_handle> { typedef Node Type; };
|
||||
template<> struct Node_type<Dir_handle> { typedef Directory Type; };
|
||||
template<> struct Node_type<File_handle> { typedef File Type; };
|
||||
template<> struct Node_type<Symlink_handle> { typedef Symlink Type; };
|
||||
|
||||
|
||||
/**
|
||||
* Type trait for determining the handle type for a given node type
|
||||
*/
|
||||
template<typename T> struct Handle_type;
|
||||
template<> struct Handle_type<Node> { typedef Node_handle Type; };
|
||||
template<> struct Handle_type<Directory> { typedef Dir_handle Type; };
|
||||
template<> struct Handle_type<File> { typedef File_handle Type; };
|
||||
template<> struct Handle_type<Symlink> { typedef Symlink_handle Type; };
|
||||
|
||||
|
||||
class Node_handle_registry
|
||||
{
|
||||
private:
|
||||
|
||||
/* maximum number of open nodes per session */
|
||||
enum { MAX_NODE_HANDLES = 128U };
|
||||
|
||||
Lock mutable _lock;
|
||||
|
||||
Node *_nodes[MAX_NODE_HANDLES];
|
||||
|
||||
/**
|
||||
* Each open node handle can act as a listener to be informed about
|
||||
* node changes.
|
||||
*/
|
||||
Listener _listeners[MAX_NODE_HANDLES];
|
||||
|
||||
/**
|
||||
* Allocate node handle
|
||||
*
|
||||
* \throw Out_of_node_handles
|
||||
*/
|
||||
int _alloc(Node *node)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
for (unsigned i = 0; i < MAX_NODE_HANDLES; i++)
|
||||
if (!_nodes[i]) {
|
||||
_nodes[i] = node;
|
||||
return i;
|
||||
}
|
||||
|
||||
throw Out_of_node_handles();
|
||||
}
|
||||
|
||||
bool _in_range(int handle) const
|
||||
{
|
||||
return ((handle >= 0) && (handle < MAX_NODE_HANDLES));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Node_handle_registry()
|
||||
{
|
||||
for (unsigned i = 0; i < MAX_NODE_HANDLES; i++)
|
||||
_nodes[i] = 0;
|
||||
}
|
||||
|
||||
template <typename NODE_TYPE>
|
||||
typename Handle_type<NODE_TYPE>::Type alloc(NODE_TYPE *node)
|
||||
{
|
||||
typedef typename Handle_type<NODE_TYPE>::Type Handle;
|
||||
return Handle(_alloc(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Release node handle
|
||||
*/
|
||||
void free(Node_handle handle)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_in_range(handle.value))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Notify listeners about the changed file.
|
||||
*/
|
||||
Node *node = dynamic_cast<Node *>(_nodes[handle.value]);
|
||||
if (!node) { return; }
|
||||
|
||||
node->lock();
|
||||
node->notify_listeners();
|
||||
|
||||
/*
|
||||
* De-allocate handle
|
||||
*/
|
||||
Listener &listener = _listeners[handle.value];
|
||||
|
||||
if (listener.valid())
|
||||
node->remove_listener(&listener);
|
||||
|
||||
_nodes[handle.value] = 0;
|
||||
listener = Listener();
|
||||
|
||||
node->unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup node using its handle as key
|
||||
*
|
||||
* The node returned by this function is in a locked state.
|
||||
*
|
||||
* \throw Invalid_handle
|
||||
*/
|
||||
template <typename HANDLE_TYPE>
|
||||
typename Node_type<HANDLE_TYPE>::Type *lookup_and_lock(HANDLE_TYPE handle)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_in_range(handle.value))
|
||||
throw Invalid_handle();
|
||||
|
||||
typedef typename Node_type<HANDLE_TYPE>::Type Node;
|
||||
Node *node = dynamic_cast<Node *>(_nodes[handle.value]);
|
||||
if (!node)
|
||||
throw Invalid_handle();
|
||||
|
||||
node->lock();
|
||||
return node;
|
||||
}
|
||||
|
||||
bool refer_to_same_node(Node_handle h1, Node_handle h2) const
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_in_range(h1.value) || !_in_range(h2.value)) {
|
||||
PDBG("refer_to_same_node -> Invalid_handle");
|
||||
throw Invalid_handle();
|
||||
}
|
||||
|
||||
return _nodes[h1.value] == _nodes[h2.value];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register signal handler to be notified of node changes
|
||||
*/
|
||||
void sigh(Node_handle handle, Signal_context_capability sigh)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_in_range(handle.value))
|
||||
throw Invalid_handle();
|
||||
|
||||
Node *node = dynamic_cast<Node *>(_nodes[handle.value]);
|
||||
if (!node) {
|
||||
PDBG("Invalid_handle");
|
||||
throw Invalid_handle();
|
||||
}
|
||||
|
||||
node->lock();
|
||||
Node_lock_guard node_lock_guard(*node);
|
||||
|
||||
Listener &listener = _listeners[handle.value];
|
||||
|
||||
/*
|
||||
* If there was already a handler registered for the node,
|
||||
* remove the old handler.
|
||||
*/
|
||||
if (listener.valid())
|
||||
node->remove_listener(&listener);
|
||||
|
||||
/*
|
||||
* Register new handler
|
||||
*/
|
||||
listener = Listener(sigh);
|
||||
node->add_listener(&listener);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _NODE_HANDLE_REGISTRY_H_ */
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* \brief Utilities
|
||||
* \author Norman Feske
|
||||
* \date 2012-04-11
|
||||
*/
|
||||
|
||||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
|
||||
/**
|
||||
* Return base-name portion of null-terminated path string
|
||||
*/
|
||||
static inline char const *basename(char const *path)
|
||||
{
|
||||
char const *start = path;
|
||||
|
||||
for (; *path; path++)
|
||||
if (*path == '/')
|
||||
start = path + 1;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if specified path is a base name (contains no path delimiters)
|
||||
*/
|
||||
static inline bool is_basename(char const *path)
|
||||
{
|
||||
for (; *path; path++)
|
||||
if (*path == '/')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if character 'c' occurs in null-terminated string 'str'
|
||||
*/
|
||||
static inline bool string_contains(char const *str, char c)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (*str == c)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if 'str' is a valid node name
|
||||
*/
|
||||
static inline bool valid_name(char const *str)
|
||||
{
|
||||
if (string_contains(str, '/')) return false;
|
||||
|
||||
/* must have at least one character */
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* _UTIL_H_ */
|
@ -7,9 +7,11 @@
|
||||
#ifndef _DIRECTORY_H_
|
||||
#define _DIRECTORY_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/util.h>
|
||||
|
||||
/* local includes */
|
||||
#include <node.h>
|
||||
#include <util.h>
|
||||
#include <file.h>
|
||||
#include <symlink.h>
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/node_handle_registry.h>
|
||||
#include <file_system_session/rpc_object.h>
|
||||
#include <root/component.h>
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
@ -22,7 +23,6 @@
|
||||
|
||||
/* local includes */
|
||||
#include <directory.h>
|
||||
#include <node_handle_registry.h>
|
||||
|
||||
|
||||
/*************************
|
||||
@ -90,7 +90,7 @@ namespace File_system {
|
||||
|
||||
try {
|
||||
Node *node = _handle_registry.lookup_and_lock(packet.handle());
|
||||
Node_lock_guard guard(*node);
|
||||
Node_lock_guard guard(node);
|
||||
|
||||
_process_packet_op(packet, *node);
|
||||
}
|
||||
@ -185,7 +185,7 @@ namespace File_system {
|
||||
throw Invalid_name();
|
||||
|
||||
Directory *dir = _handle_registry.lookup_and_lock(dir_handle);
|
||||
Node_lock_guard dir_guard(*dir);
|
||||
Node_lock_guard dir_guard(dir);
|
||||
|
||||
if (!_writable)
|
||||
if (mode != STAT_ONLY && mode != READ_ONLY)
|
||||
@ -209,7 +209,7 @@ namespace File_system {
|
||||
}
|
||||
|
||||
File *file = dir->lookup_and_lock_file(name.string());
|
||||
Node_lock_guard file_guard(*file);
|
||||
Node_lock_guard file_guard(file);
|
||||
return _handle_registry.alloc(file);
|
||||
}
|
||||
|
||||
@ -219,7 +219,7 @@ namespace File_system {
|
||||
throw Invalid_name();
|
||||
|
||||
Directory *dir = _handle_registry.lookup_and_lock(dir_handle);
|
||||
Node_lock_guard dir_guard(*dir);
|
||||
Node_lock_guard dir_guard(dir);
|
||||
|
||||
if (create) {
|
||||
|
||||
@ -239,7 +239,7 @@ namespace File_system {
|
||||
}
|
||||
|
||||
Symlink *symlink = dir->lookup_and_lock_symlink(name.string());
|
||||
Node_lock_guard file_guard(*symlink);
|
||||
Node_lock_guard file_guard(symlink);
|
||||
return _handle_registry.alloc(symlink);
|
||||
}
|
||||
|
||||
@ -262,7 +262,7 @@ namespace File_system {
|
||||
|
||||
Directory *parent = _root.lookup_and_lock_parent(path_str);
|
||||
|
||||
Node_lock_guard guard(*parent);
|
||||
Node_lock_guard guard(parent);
|
||||
|
||||
char const *name = basename(path_str);
|
||||
|
||||
@ -277,7 +277,7 @@ namespace File_system {
|
||||
}
|
||||
|
||||
Directory *dir = _root.lookup_and_lock_dir(path_str);
|
||||
Node_lock_guard guard(*dir);
|
||||
Node_lock_guard guard(dir);
|
||||
return _handle_registry.alloc(dir);
|
||||
}
|
||||
|
||||
@ -287,7 +287,7 @@ namespace File_system {
|
||||
|
||||
Node *node = _root.lookup_and_lock(path.string() + 1);
|
||||
|
||||
Node_lock_guard guard(*node);
|
||||
Node_lock_guard guard(node);
|
||||
return _handle_registry.alloc(node);
|
||||
}
|
||||
|
||||
@ -299,7 +299,7 @@ namespace File_system {
|
||||
Status status(Node_handle node_handle)
|
||||
{
|
||||
Node *node = _handle_registry.lookup_and_lock(node_handle);
|
||||
Node_lock_guard guard(*node);
|
||||
Node_lock_guard guard(node);
|
||||
|
||||
Status s;
|
||||
s.inode = node->inode();
|
||||
@ -338,7 +338,7 @@ namespace File_system {
|
||||
throw Permission_denied();
|
||||
|
||||
Directory *dir = _handle_registry.lookup_and_lock(dir_handle);
|
||||
Node_lock_guard dir_guard(*dir);
|
||||
Node_lock_guard dir_guard(dir);
|
||||
|
||||
Node *node = dir->lookup_and_lock(name.string());
|
||||
|
||||
@ -357,7 +357,7 @@ namespace File_system {
|
||||
throw Permission_denied();
|
||||
|
||||
File *file = _handle_registry.lookup_and_lock(file_handle);
|
||||
Node_lock_guard file_guard(*file);
|
||||
Node_lock_guard file_guard(file);
|
||||
file->truncate(size);
|
||||
}
|
||||
|
||||
@ -374,15 +374,15 @@ namespace File_system {
|
||||
throw Invalid_name();
|
||||
|
||||
Directory *from_dir = _handle_registry.lookup_and_lock(from_dir_handle);
|
||||
Node_lock_guard from_dir_guard(*from_dir);
|
||||
Node_lock_guard from_dir_guard(from_dir);
|
||||
|
||||
Node *node = from_dir->lookup_and_lock(from_name.string());
|
||||
Node_lock_guard node_guard(*node);
|
||||
Node_lock_guard node_guard(node);
|
||||
node->name(to_name.string());
|
||||
|
||||
if (!_handle_registry.refer_to_same_node(from_dir_handle, to_dir_handle)) {
|
||||
Directory *to_dir = _handle_registry.lookup_and_lock(to_dir_handle);
|
||||
Node_lock_guard to_dir_guard(*to_dir);
|
||||
Node_lock_guard to_dir_guard(to_dir);
|
||||
|
||||
from_dir->discard_unsynchronized(node);
|
||||
to_dir->adopt_unsynchronized(node);
|
||||
|
@ -8,49 +8,13 @@
|
||||
#define _NODE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/listener.h>
|
||||
#include <file_system/node.h>
|
||||
#include <util/list.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/signal.h>
|
||||
|
||||
namespace File_system {
|
||||
|
||||
class Listener : public List<Listener>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Lock _lock;
|
||||
Signal_context_capability _sigh;
|
||||
bool _marked_as_updated;
|
||||
|
||||
public:
|
||||
|
||||
Listener() : _marked_as_updated(false) { }
|
||||
|
||||
Listener(Signal_context_capability sigh)
|
||||
: _sigh(sigh), _marked_as_updated(false) { }
|
||||
|
||||
void notify()
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (_marked_as_updated && _sigh.valid())
|
||||
Signal_transmitter(_sigh).submit();
|
||||
|
||||
_marked_as_updated = false;
|
||||
}
|
||||
|
||||
void mark_as_updated()
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
_marked_as_updated = true;
|
||||
}
|
||||
|
||||
bool valid() const { return _sigh.valid(); }
|
||||
};
|
||||
|
||||
|
||||
class Node : public List<Node>::Element
|
||||
class Node : public Node_base, public List<Node>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
@ -58,12 +22,9 @@ namespace File_system {
|
||||
|
||||
private:
|
||||
|
||||
Lock _lock;
|
||||
int _ref_count;
|
||||
Name _name;
|
||||
unsigned long const _inode;
|
||||
List<Listener> _listeners;
|
||||
bool _modified;
|
||||
|
||||
/**
|
||||
* Generate unique inode number
|
||||
@ -77,19 +38,9 @@ namespace File_system {
|
||||
public:
|
||||
|
||||
Node()
|
||||
: _ref_count(0), _inode(_unique_inode()), _modified(false)
|
||||
: _ref_count(0), _inode(_unique_inode())
|
||||
{ _name[0] = 0; }
|
||||
|
||||
virtual ~Node()
|
||||
{
|
||||
/* propagate event to listeners */
|
||||
mark_as_updated();
|
||||
notify_listeners();
|
||||
|
||||
while (_listeners.first())
|
||||
_listeners.remove(_listeners.first());
|
||||
}
|
||||
|
||||
unsigned long inode() const { return _inode; }
|
||||
char const *name() const { return _name; }
|
||||
|
||||
@ -98,47 +49,10 @@ namespace File_system {
|
||||
*/
|
||||
void name(char const *name) { strncpy(_name, name, sizeof(_name)); }
|
||||
|
||||
void lock() { _lock.lock(); }
|
||||
void unlock() { _lock.unlock(); }
|
||||
|
||||
virtual size_t read(char *dst, size_t len, seek_off_t) = 0;
|
||||
virtual size_t write(char const *src, size_t len, seek_off_t) = 0;
|
||||
|
||||
void add_listener(Listener *listener)
|
||||
{
|
||||
_listeners.insert(listener);
|
||||
}
|
||||
|
||||
void remove_listener(Listener *listener)
|
||||
{
|
||||
_listeners.remove(listener);
|
||||
}
|
||||
|
||||
void notify_listeners()
|
||||
{
|
||||
for (Listener *curr = _listeners.first(); curr; curr = curr->next())
|
||||
curr->notify();
|
||||
}
|
||||
|
||||
void mark_as_updated()
|
||||
{
|
||||
for (Listener *curr = _listeners.first(); curr; curr = curr->next())
|
||||
curr->mark_as_updated();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Guard used for properly releasing node locks
|
||||
*/
|
||||
struct Node_lock_guard
|
||||
{
|
||||
Node &node;
|
||||
|
||||
Node_lock_guard(Node &node) : node(node) { }
|
||||
|
||||
~Node_lock_guard() { node.unlock(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _NODE_H_ */
|
||||
|
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* \brief Facility for managing the session-local node-handle namespace
|
||||
* \author Norman Feske
|
||||
* \date 2012-04-11
|
||||
*/
|
||||
|
||||
#ifndef _NODE_HANDLE_REGISTRY_H_
|
||||
#define _NODE_HANDLE_REGISTRY_H_
|
||||
|
||||
namespace File_system {
|
||||
|
||||
class Node;
|
||||
class Directory;
|
||||
class File;
|
||||
class Symlink;
|
||||
|
||||
/**
|
||||
* Type trait for determining the node type for a given handle type
|
||||
*/
|
||||
template<typename T> struct Node_type;
|
||||
template<> struct Node_type<Node_handle> { typedef Node Type; };
|
||||
template<> struct Node_type<Dir_handle> { typedef Directory Type; };
|
||||
template<> struct Node_type<File_handle> { typedef File Type; };
|
||||
template<> struct Node_type<Symlink_handle> { typedef Symlink Type; };
|
||||
|
||||
|
||||
/**
|
||||
* Type trait for determining the handle type for a given node type
|
||||
*/
|
||||
template<typename T> struct Handle_type;
|
||||
template<> struct Handle_type<Node> { typedef Node_handle Type; };
|
||||
template<> struct Handle_type<Directory> { typedef Dir_handle Type; };
|
||||
template<> struct Handle_type<File> { typedef File_handle Type; };
|
||||
template<> struct Handle_type<Symlink> { typedef Symlink_handle Type; };
|
||||
|
||||
|
||||
class Node_handle_registry
|
||||
{
|
||||
private:
|
||||
|
||||
/* maximum number of open nodes per session */
|
||||
enum { MAX_NODE_HANDLES = 128U };
|
||||
|
||||
Lock mutable _lock;
|
||||
|
||||
Node *_nodes[MAX_NODE_HANDLES];
|
||||
|
||||
/**
|
||||
* Each open node handle can act as a listener to be informed about
|
||||
* node changes.
|
||||
*/
|
||||
Listener _listeners[MAX_NODE_HANDLES];
|
||||
|
||||
/**
|
||||
* Allocate node handle
|
||||
*
|
||||
* \throw Out_of_node_handles
|
||||
*/
|
||||
int _alloc(Node *node)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
for (unsigned i = 0; i < MAX_NODE_HANDLES; i++)
|
||||
if (!_nodes[i]) {
|
||||
_nodes[i] = node;
|
||||
return i;
|
||||
}
|
||||
|
||||
throw Out_of_node_handles();
|
||||
}
|
||||
|
||||
bool _in_range(int handle) const
|
||||
{
|
||||
return ((handle >= 0) && (handle < MAX_NODE_HANDLES));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Node_handle_registry()
|
||||
{
|
||||
for (unsigned i = 0; i < MAX_NODE_HANDLES; i++)
|
||||
_nodes[i] = 0;
|
||||
}
|
||||
|
||||
template <typename NODE_TYPE>
|
||||
typename Handle_type<NODE_TYPE>::Type alloc(NODE_TYPE *node)
|
||||
{
|
||||
typedef typename Handle_type<NODE_TYPE>::Type Handle;
|
||||
return Handle(_alloc(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Release node handle
|
||||
*/
|
||||
void free(Node_handle handle)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_in_range(handle.value))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Notify listeners about the changed file.
|
||||
*/
|
||||
Node *node = dynamic_cast<Node *>(_nodes[handle.value]);
|
||||
if (!node) { return; }
|
||||
|
||||
node->lock();
|
||||
node->notify_listeners();
|
||||
|
||||
/*
|
||||
* De-allocate handle
|
||||
*/
|
||||
Listener &listener = _listeners[handle.value];
|
||||
|
||||
if (listener.valid())
|
||||
node->remove_listener(&listener);
|
||||
|
||||
_nodes[handle.value] = 0;
|
||||
listener = Listener();
|
||||
|
||||
node->unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup node using its handle as key
|
||||
*
|
||||
* The node returned by this function is in a locked state.
|
||||
*
|
||||
* \throw Invalid_handle
|
||||
*/
|
||||
template <typename HANDLE_TYPE>
|
||||
typename Node_type<HANDLE_TYPE>::Type *lookup_and_lock(HANDLE_TYPE handle)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_in_range(handle.value))
|
||||
throw Invalid_handle();
|
||||
|
||||
typedef typename Node_type<HANDLE_TYPE>::Type Node;
|
||||
Node *node = dynamic_cast<Node *>(_nodes[handle.value]);
|
||||
if (!node)
|
||||
throw Invalid_handle();
|
||||
|
||||
node->lock();
|
||||
return node;
|
||||
}
|
||||
|
||||
bool refer_to_same_node(Node_handle h1, Node_handle h2) const
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_in_range(h1.value) || !_in_range(h2.value)) {
|
||||
PDBG("refer_to_same_node -> Invalid_handle");
|
||||
throw Invalid_handle();
|
||||
}
|
||||
|
||||
return _nodes[h1.value] == _nodes[h2.value];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register signal handler to be notified of node changes
|
||||
*/
|
||||
void sigh(Node_handle handle, Signal_context_capability sigh)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_in_range(handle.value))
|
||||
throw Invalid_handle();
|
||||
|
||||
Node *node = dynamic_cast<Node *>(_nodes[handle.value]);
|
||||
if (!node) {
|
||||
PDBG("Invalid_handle");
|
||||
throw Invalid_handle();
|
||||
}
|
||||
|
||||
node->lock();
|
||||
Node_lock_guard node_lock_guard(*node);
|
||||
|
||||
Listener &listener = _listeners[handle.value];
|
||||
|
||||
/*
|
||||
* If there was already a handler registered for the node,
|
||||
* remove the old handler.
|
||||
*/
|
||||
if (listener.valid())
|
||||
node->remove_listener(&listener);
|
||||
|
||||
/*
|
||||
* Register new handler
|
||||
*/
|
||||
listener = Listener(sigh);
|
||||
node->add_listener(&listener);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _NODE_HANDLE_REGISTRY_H_ */
|
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* \brief Utilities
|
||||
* \author Norman Feske
|
||||
* \date 2012-04-11
|
||||
*/
|
||||
|
||||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
|
||||
/**
|
||||
* Return base-name portion of null-terminated path string
|
||||
*/
|
||||
static inline char const *basename(char const *path)
|
||||
{
|
||||
char const *start = path;
|
||||
|
||||
for (; *path; path++)
|
||||
if (*path == '/')
|
||||
start = path + 1;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if specified path is a base name (contains no path delimiters)
|
||||
*/
|
||||
static inline bool is_basename(char const *path)
|
||||
{
|
||||
for (; *path; path++)
|
||||
if (*path == '/')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if character 'c' occurs in null-terminated string 'str'
|
||||
*/
|
||||
static inline bool string_contains(char const *str, char c)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (*str == c)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if 'str' is a valid node name
|
||||
*/
|
||||
static inline bool valid_name(char const *str)
|
||||
{
|
||||
if (string_contains(str, '/')) return false;
|
||||
|
||||
/* must have at least one character */
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* _UTIL_H_ */
|
@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/node_handle_registry.h>
|
||||
#include <file_system_session/rpc_object.h>
|
||||
#include <root/component.h>
|
||||
#include <cap_session/connection.h>
|
||||
@ -24,7 +25,6 @@
|
||||
#include <directory.h>
|
||||
#include <file.h>
|
||||
#include <lookup.h>
|
||||
#include <node_handle_registry.h>
|
||||
#include <symlink.h>
|
||||
#include <util.h>
|
||||
|
||||
|
@ -15,12 +15,15 @@
|
||||
#ifndef _NODE_H_
|
||||
#define _NODE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/node.h>
|
||||
|
||||
/* local includes */
|
||||
#include <record.h>
|
||||
|
||||
namespace File_system {
|
||||
|
||||
class Node
|
||||
class Node : public Node_base
|
||||
{
|
||||
protected:
|
||||
|
||||
|
@ -1,137 +0,0 @@
|
||||
/*
|
||||
* \brief Facility for managing the session-local node-handle namespace
|
||||
* \author Norman Feske
|
||||
* \date 2012-04-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _NODE_HANDLE_REGISTRY_H_
|
||||
#define _NODE_HANDLE_REGISTRY_H_
|
||||
|
||||
namespace File_system {
|
||||
|
||||
class Node;
|
||||
class Directory;
|
||||
class File;
|
||||
class Symlink;
|
||||
|
||||
/**
|
||||
* Type trait for determining the node type for a given handle type
|
||||
*/
|
||||
template<typename T> struct Node_type;
|
||||
template<> struct Node_type<Node_handle> { typedef Node Type; };
|
||||
template<> struct Node_type<Dir_handle> { typedef Directory Type; };
|
||||
template<> struct Node_type<File_handle> { typedef File Type; };
|
||||
template<> struct Node_type<Symlink_handle> { typedef Symlink Type; };
|
||||
|
||||
|
||||
/**
|
||||
* Type trait for determining the handle type for a given node type
|
||||
*/
|
||||
template<typename T> struct Handle_type;
|
||||
template<> struct Handle_type<Node> { typedef Node_handle Type; };
|
||||
template<> struct Handle_type<Directory> { typedef Dir_handle Type; };
|
||||
template<> struct Handle_type<File> { typedef File_handle Type; };
|
||||
template<> struct Handle_type<Symlink> { typedef Symlink_handle Type; };
|
||||
|
||||
|
||||
class Node_handle_registry
|
||||
{
|
||||
private:
|
||||
|
||||
/* maximum number of open nodes per session */
|
||||
enum { MAX_NODE_HANDLES = 128U };
|
||||
|
||||
Lock mutable _lock;
|
||||
|
||||
Node *_nodes[MAX_NODE_HANDLES];
|
||||
|
||||
/**
|
||||
* Allocate node handle
|
||||
*
|
||||
* \throw Out_of_node_handles
|
||||
*/
|
||||
int _alloc(Node *node)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
for (unsigned i = 0; i < MAX_NODE_HANDLES; i++)
|
||||
if (!_nodes[i]) {
|
||||
_nodes[i] = node;
|
||||
return i;
|
||||
}
|
||||
|
||||
throw Out_of_node_handles();
|
||||
}
|
||||
|
||||
bool _in_range(int handle) const
|
||||
{
|
||||
return ((handle >= 0) && (handle < MAX_NODE_HANDLES));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Node_handle_registry()
|
||||
{
|
||||
for (unsigned i = 0; i < MAX_NODE_HANDLES; i++)
|
||||
_nodes[i] = 0;
|
||||
}
|
||||
|
||||
template <typename NODE_TYPE>
|
||||
typename Handle_type<NODE_TYPE>::Type alloc(NODE_TYPE *node)
|
||||
{
|
||||
typedef typename Handle_type<NODE_TYPE>::Type Handle;
|
||||
return Handle(_alloc(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Release node handle
|
||||
*/
|
||||
void free(Node_handle handle)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (_in_range(handle.value))
|
||||
_nodes[handle.value] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup node using its handle as key
|
||||
*
|
||||
* \throw Invalid_handle
|
||||
*/
|
||||
template <typename HANDLE_TYPE>
|
||||
typename Node_type<HANDLE_TYPE>::Type *lookup(HANDLE_TYPE handle)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_in_range(handle.value))
|
||||
throw Invalid_handle();
|
||||
|
||||
typedef typename Node_type<HANDLE_TYPE>::Type Node;
|
||||
Node *node = dynamic_cast<Node *>(_nodes[handle.value]);
|
||||
if (!node)
|
||||
throw Invalid_handle();
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
bool refer_to_same_node(Node_handle h1, Node_handle h2) const
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (!_in_range(h1.value) || !_in_range(h2.value))
|
||||
throw Invalid_handle();
|
||||
|
||||
return _nodes[h1.value] == _nodes[h2.value];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _NODE_HANDLE_REGISTRY_H_ */
|
@ -7,9 +7,11 @@
|
||||
#ifndef _DIRECTORY_H_
|
||||
#define _DIRECTORY_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/util.h>
|
||||
|
||||
/* local includes */
|
||||
#include <node.h>
|
||||
#include <util.h>
|
||||
#include <file.h>
|
||||
#include <symlink.h>
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/node_handle_registry.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <file_system_session/rpc_object.h>
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
@ -29,15 +30,30 @@
|
||||
#include <buffer.h>
|
||||
#include <directory.h>
|
||||
#include <followed_subject.h>
|
||||
#include <node_handle_registry.h>
|
||||
#include <trace_files.h>
|
||||
#include <util.h>
|
||||
|
||||
|
||||
static bool const verbose = false;
|
||||
#define PDBGV(...) if (verbose) PDBG(__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Return true if 'str' is a valid file name
|
||||
*/
|
||||
static inline bool valid_filename(char const *str)
|
||||
{
|
||||
if (!str) return false;
|
||||
|
||||
/* must have at least one character */
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
/* must not contain '/' or '\' or ':' */
|
||||
if (string_contains(str, '/') ||
|
||||
string_contains(str, '\\') ||
|
||||
string_contains(str, ':'))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class updates the file system
|
||||
|
@ -8,49 +8,14 @@
|
||||
#define _NODE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/node.h>
|
||||
#include <util/list.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/signal.h>
|
||||
|
||||
namespace File_system {
|
||||
|
||||
class Listener : public List<Listener>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Lock _lock;
|
||||
Signal_context_capability _sigh;
|
||||
bool _marked_as_updated;
|
||||
|
||||
public:
|
||||
|
||||
Listener() : _marked_as_updated(false) { }
|
||||
|
||||
Listener(Signal_context_capability sigh)
|
||||
: _sigh(sigh), _marked_as_updated(false) { }
|
||||
|
||||
void notify()
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
if (_marked_as_updated && _sigh.valid())
|
||||
Signal_transmitter(_sigh).submit();
|
||||
|
||||
_marked_as_updated = false;
|
||||
}
|
||||
|
||||
void mark_as_updated()
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
_marked_as_updated = true;
|
||||
}
|
||||
|
||||
bool valid() const { return _sigh.valid(); }
|
||||
};
|
||||
|
||||
|
||||
class Node : public List<Node>::Element
|
||||
class Node : public Node_base, public List<Node>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
@ -60,8 +25,6 @@ namespace File_system {
|
||||
|
||||
Name _name;
|
||||
unsigned long const _inode;
|
||||
List<Listener> _listeners;
|
||||
bool _modified;
|
||||
|
||||
/**
|
||||
* Generate unique inode number
|
||||
@ -75,19 +38,9 @@ namespace File_system {
|
||||
public:
|
||||
|
||||
Node()
|
||||
: _inode(_unique_inode()), _modified(false)
|
||||
: _inode(_unique_inode())
|
||||
{ _name[0] = 0; }
|
||||
|
||||
virtual ~Node()
|
||||
{
|
||||
/* propagate event to listeners */
|
||||
mark_as_updated();
|
||||
notify_listeners();
|
||||
|
||||
while (_listeners.first())
|
||||
_listeners.remove(_listeners.first());
|
||||
}
|
||||
|
||||
unsigned long inode() const { return _inode; }
|
||||
char const *name() const { return _name; }
|
||||
|
||||
@ -96,32 +49,10 @@ namespace File_system {
|
||||
*/
|
||||
void name(char const *name) { strncpy(_name, name, sizeof(_name)); }
|
||||
|
||||
virtual size_t read(char *dst, size_t len, seek_off_t) = 0;
|
||||
virtual size_t write(char const *src, size_t len, seek_off_t) = 0;
|
||||
|
||||
virtual Status status() const = 0;
|
||||
|
||||
void add_listener(Listener *listener)
|
||||
{
|
||||
_listeners.insert(listener);
|
||||
}
|
||||
|
||||
void remove_listener(Listener *listener)
|
||||
{
|
||||
_listeners.remove(listener);
|
||||
}
|
||||
|
||||
void notify_listeners()
|
||||
{
|
||||
for (Listener *curr = _listeners.first(); curr; curr = curr->next())
|
||||
curr->notify();
|
||||
}
|
||||
|
||||
void mark_as_updated()
|
||||
{
|
||||
for (Listener *curr = _listeners.first(); curr; curr = curr->next())
|
||||
curr->mark_as_updated();
|
||||
}
|
||||
virtual size_t read(char *dst, size_t len, seek_off_t) = 0;
|
||||
virtual size_t write(char const *src, size_t len, seek_off_t) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* \brief Facility for managing the session-local node-handle namespace
|
||||
* \author Norman Feske
|
||||
* \date 2012-04-11
|
||||
*/
|
||||
|
||||
#ifndef _NODE_HANDLE_REGISTRY_H_
|
||||
#define _NODE_HANDLE_REGISTRY_H_
|
||||
|
||||
namespace File_system {
|
||||
|
||||
class Node;
|
||||
class Directory;
|
||||
class File;
|
||||
class Symlink;
|
||||
|
||||
/**
|
||||
* Type trait for determining the node type for a given handle type
|
||||
*/
|
||||
template<typename T> struct Node_type;
|
||||
template<> struct Node_type<Node_handle> { typedef Node Type; };
|
||||
template<> struct Node_type<Dir_handle> { typedef Directory Type; };
|
||||
template<> struct Node_type<File_handle> { typedef File Type; };
|
||||
template<> struct Node_type<Symlink_handle> { typedef Symlink Type; };
|
||||
|
||||
|
||||
/**
|
||||
* Type trait for determining the handle type for a given node type
|
||||
*/
|
||||
template<typename T> struct Handle_type;
|
||||
template<> struct Handle_type<Node> { typedef Node_handle Type; };
|
||||
template<> struct Handle_type<Directory> { typedef Dir_handle Type; };
|
||||
template<> struct Handle_type<File> { typedef File_handle Type; };
|
||||
template<> struct Handle_type<Symlink> { typedef Symlink_handle Type; };
|
||||
|
||||
|
||||
class Node_handle_registry
|
||||
{
|
||||
private:
|
||||
|
||||
/* maximum number of open nodes per session */
|
||||
enum { MAX_NODE_HANDLES = 128U };
|
||||
|
||||
Lock mutable _lock;
|
||||
|
||||
Node *_nodes[MAX_NODE_HANDLES];
|
||||
|
||||
/**
|
||||
* Each open node handle can act as a listener to be informed about
|
||||
* node changes.
|
||||
*/
|
||||
Listener _listeners[MAX_NODE_HANDLES];
|
||||
|
||||
/**
|
||||
* Allocate node handle
|
||||
*
|
||||
* \throw Out_of_node_handles
|
||||
*/
|
||||
int _alloc(Node *node)
|
||||
{
|
||||
Lock::Guard guard(_lock);
|
||||
|
||||
for (unsigned i = 0; i < MAX_NODE_HANDLES; i++)
|
||||
if (!_nodes[i]) {
|
||||
_nodes[i] = node;
|
||||
return i;
|
||||
}
|
||||
|
||||
throw Out_of_node_handles();
|
||||
}
|
||||
|
||||
bool _in_range(int handle) const
|
||||
{
|
||||
return ((handle >= 0) && (handle < MAX_NODE_HANDLES));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Node_handle_registry()
|
||||
{
|
||||
for (unsigned i = 0; i < MAX_NODE_HANDLES; i++)
|
||||
_nodes[i] = 0;
|
||||
}
|
||||
|
||||
template <typename NODE_TYPE>
|
||||
typename Handle_type<NODE_TYPE>::Type alloc(NODE_TYPE *node)
|
||||
{
|
||||
typedef typename Handle_type<NODE_TYPE>::Type Handle;
|
||||
return Handle(_alloc(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Release node handle
|
||||
*/
|
||||
void free(Node_handle handle)
|
||||
{
|
||||
if (!_in_range(handle.value))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Notify listeners about the changed file.
|
||||
*/
|
||||
Node *node = dynamic_cast<Node *>(_nodes[handle.value]);
|
||||
if (!node) { return; }
|
||||
|
||||
node->notify_listeners();
|
||||
|
||||
/*
|
||||
* De-allocate handle
|
||||
*/
|
||||
Listener &listener = _listeners[handle.value];
|
||||
|
||||
if (listener.valid())
|
||||
node->remove_listener(&listener);
|
||||
|
||||
_nodes[handle.value] = 0;
|
||||
listener = Listener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup node using its handle as key
|
||||
*
|
||||
* \throw Invalid_handle
|
||||
*/
|
||||
template <typename HANDLE_TYPE>
|
||||
typename Node_type<HANDLE_TYPE>::Type *lookup(HANDLE_TYPE handle)
|
||||
{
|
||||
if (!_in_range(handle.value))
|
||||
throw Invalid_handle();
|
||||
|
||||
typedef typename Node_type<HANDLE_TYPE>::Type Node;
|
||||
Node *node = dynamic_cast<Node *>(_nodes[handle.value]);
|
||||
if (!node)
|
||||
throw Invalid_handle();
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
bool refer_to_same_node(Node_handle h1, Node_handle h2) const
|
||||
{
|
||||
if (!_in_range(h1.value) || !_in_range(h2.value)) {
|
||||
PDBG("refer_to_same_node -> Invalid_handle");
|
||||
throw Invalid_handle();
|
||||
}
|
||||
|
||||
return _nodes[h1.value] == _nodes[h2.value];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register signal handler to be notified of node changes
|
||||
*/
|
||||
void sigh(Node_handle handle, Signal_context_capability sigh)
|
||||
{
|
||||
if (!_in_range(handle.value))
|
||||
throw Invalid_handle();
|
||||
|
||||
Node *node = dynamic_cast<Node *>(_nodes[handle.value]);
|
||||
if (!node) {
|
||||
PDBG("Invalid_handle");
|
||||
throw Invalid_handle();
|
||||
}
|
||||
|
||||
Listener &listener = _listeners[handle.value];
|
||||
|
||||
/*
|
||||
* If there was already a handler registered for the node,
|
||||
* remove the old handler.
|
||||
*/
|
||||
if (listener.valid())
|
||||
node->remove_listener(&listener);
|
||||
|
||||
/*
|
||||
* Register new handler
|
||||
*/
|
||||
listener = Listener(sigh);
|
||||
node->add_listener(&listener);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _NODE_HANDLE_REGISTRY_H_ */
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* \brief Utilities
|
||||
* \author Norman Feske
|
||||
* \date 2012-04-11
|
||||
*/
|
||||
|
||||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
|
||||
/**
|
||||
* Return base-name portion of null-terminated path string
|
||||
*/
|
||||
static inline char const *basename(char const *path)
|
||||
{
|
||||
char const *start = path;
|
||||
|
||||
for (; *path; path++)
|
||||
if (*path == '/')
|
||||
start = path + 1;
|
||||
|
||||
return start;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if specified path is a base name (contains no path delimiters)
|
||||
*/
|
||||
static inline bool is_basename(char const *path)
|
||||
{
|
||||
for (; *path; path++)
|
||||
if (*path == '/')
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if character 'c' occurs in null-terminated string 'str'
|
||||
*/
|
||||
static inline bool string_contains(char const *str, char c)
|
||||
{
|
||||
for (; *str; str++)
|
||||
if (*str == c)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if 'str' is a valid node name
|
||||
*/
|
||||
static inline bool valid_name(char const *str)
|
||||
{
|
||||
if (string_contains(str, '/')) return false;
|
||||
|
||||
/* must have at least one character */
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if 'str' is a valid file name
|
||||
*/
|
||||
static inline bool valid_filename(char const *str)
|
||||
{
|
||||
if (!str) return false;
|
||||
|
||||
/* must have at least one character */
|
||||
if (str[0] == 0) return false;
|
||||
|
||||
/* must not contain '/' or '\' or ':' */
|
||||
if (string_contains(str, '/') ||
|
||||
string_contains(str, '\\') ||
|
||||
string_contains(str, ':'))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _UTIL_H_ */
|
Reference in New Issue
Block a user