Move generic fs helpers to os/include/file_system

Fixes #1488
This commit is contained in:
Emery Hemingway
2015-04-23 15:26:54 -04:00
committed by Christian Helmuth
parent eecb5cc300
commit 55c0a947e4
35 changed files with 266 additions and 1722 deletions

View File

@ -18,10 +18,10 @@
/* Genode include */
#include <os/path.h>
#include <file_system/util.h>
/* local includes */
#include "node.h"
#include "util.h"
#include "file.h"
#include "symlink.h"

View File

@ -16,8 +16,10 @@
#ifndef _FILE_H_
#define _FILE_H_
/* Genode includes */
#include <file_system/util.h>
#include "node.h"
#include "util.h"
namespace File_system {
class File;

View File

@ -12,6 +12,9 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <file_system/node_handle_registry.h>
#include "undef.h"
#include <file_system_session/rpc_object.h>
@ -21,8 +24,6 @@
#include <rump_fs/fs.h>
#include "file_system.h"
#include "directory.h"
#include "node_handle_registry.h"
namespace File_system {
struct Main;

View File

@ -17,47 +17,16 @@
#define _NODE_H_
/* Genode includes */
#include <file_system/node.h>
#include <util/list.h>
#include <base/signal.h>
namespace File_system {
class Listener;
class Node;
}
class File_system::Listener : public List<Listener>::Element
{
private:
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()
{
if (_marked_as_updated && _sigh.valid())
Signal_transmitter(_sigh).submit();
_marked_as_updated = false;
}
void mark_as_updated()
{
_marked_as_updated = true;
}
bool valid() const { return _sigh.valid(); }
};
class File_system::Node : public List<Node>::Element
class File_system::Node : public Node_base, public List<Node>::Element
{
public:
@ -68,22 +37,10 @@ class File_system::Node : public List<Node>::Element
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; }
@ -94,28 +51,6 @@ class File_system::Node : public List<Node>::Element
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();
}
};
#endif /* _NODE_H_ */

View File

@ -1,184 +0,0 @@
/*
* \brief Facility for managing the session-local node-handle namespace
* \author Norman Feske
* \date 2012-04-11
*/
/*
* Copyright (C) 2012-2014 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 };
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)
{
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_ */

View File

@ -14,10 +14,11 @@
#ifndef _SYMLINK_H_
#define _SYMLINK_H_
/* Genode includes */
#include <file_system/util.h>
#include <os/path.h>
#include "node.h"
#include "util.h"
namespace File_system {
class Symlink;

View File

@ -1,70 +0,0 @@
/*
* \brief Utilities
* \author Norman Feske
* \date 2012-04-11
*/
/*
* Copyright (C) 2012-2014 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 _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_ */