mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-20 06:07:59 +00:00
parent
30948a4b0d
commit
547cc06976
@ -13,7 +13,6 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/open_node.h>
|
||||
#include <file_system_session/rpc_object.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <timer_session/connection.h>
|
||||
@ -29,6 +28,7 @@
|
||||
#include <sys/resource.h>
|
||||
#include "file_system.h"
|
||||
#include "directory.h"
|
||||
#include "open_node.h"
|
||||
|
||||
namespace Rump_fs {
|
||||
|
||||
|
95
repos/dde_rump/src/server/rump_fs/open_node.h
Normal file
95
repos/dde_rump/src/server/rump_fs/open_node.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* \brief Representation of an open file system node within the component (deprecated)
|
||||
* \author Christian Prochaska
|
||||
* \date 2017-06-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _OPEN_NODE_H_
|
||||
#define _OPEN_NODE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/listener.h>
|
||||
#include <file_system_session/file_system_session.h>
|
||||
|
||||
namespace File_system {
|
||||
/*
|
||||
* \param NODE component-specific node type
|
||||
*/
|
||||
template <typename NODE> class Open_node;
|
||||
}
|
||||
|
||||
template <typename NODE>
|
||||
class File_system::Open_node : public File_system::Node
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Id_space<File_system::Node>::Element _element;
|
||||
|
||||
NODE &_node;
|
||||
Genode::Constructible<File_system::Listener> _listener;
|
||||
|
||||
Listener::Version const _version_when_opened = _node.curr_version();
|
||||
|
||||
/*
|
||||
* Flag to track whether the underlying file-system node was
|
||||
* modified via this 'Open_node'. That is, if closing the 'Open_node'
|
||||
* should notify listeners of the file.
|
||||
*/
|
||||
bool _was_written = false;
|
||||
|
||||
public:
|
||||
|
||||
Open_node(NODE &node, Genode::Id_space<File_system::Node> &id_space)
|
||||
: _element(*this, id_space), _node(node) { }
|
||||
|
||||
~Open_node()
|
||||
{
|
||||
if (_listener.constructed()) {
|
||||
_node.remove_listener(&*_listener);
|
||||
_listener.destruct();
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify remaining listeners about the changed file
|
||||
*/
|
||||
if (_was_written)
|
||||
_node.notify_listeners();
|
||||
}
|
||||
|
||||
NODE &node() { return _node; }
|
||||
File_system::Listener &listener() { return *_listener; }
|
||||
|
||||
Genode::Id_space<File_system::Node>::Id id() { return _element.id(); }
|
||||
|
||||
/**
|
||||
* Register packet stream sink to be notified of node changes
|
||||
*/
|
||||
void register_notify(File_system::Sink &sink)
|
||||
{
|
||||
/*
|
||||
* If there was already a handler registered for the node,
|
||||
* remove the old handler.
|
||||
*/
|
||||
if (_listener.constructed()) {
|
||||
_node.remove_listener(&*_listener);
|
||||
_listener.destruct();
|
||||
}
|
||||
|
||||
/*
|
||||
* Register new handler
|
||||
*/
|
||||
_listener.construct(sink, id(), _version_when_opened);
|
||||
_node.add_listener(&*_listener);
|
||||
}
|
||||
|
||||
void mark_as_written() { _was_written = true; }
|
||||
};
|
||||
|
||||
#endif /* _OPEN_NODE_H_ */
|
@ -13,7 +13,6 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/component.h>
|
||||
#include <file_system/open_node.h>
|
||||
#include <file_system_session/rpc_object.h>
|
||||
#include <root/component.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
@ -25,6 +24,7 @@
|
||||
/* local includes */
|
||||
#include <directory.h>
|
||||
#include <file.h>
|
||||
#include <open_node.h>
|
||||
#include <util.h>
|
||||
|
||||
/* Genode block backend */
|
||||
|
95
repos/libports/src/server/fatfs_fs/open_node.h
Normal file
95
repos/libports/src/server/fatfs_fs/open_node.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* \brief Representation of an open file system node within the component (deprecated)
|
||||
* \author Christian Prochaska
|
||||
* \date 2017-06-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _OPEN_NODE_H_
|
||||
#define _OPEN_NODE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/listener.h>
|
||||
#include <file_system_session/file_system_session.h>
|
||||
|
||||
namespace File_system {
|
||||
/*
|
||||
* \param NODE component-specific node type
|
||||
*/
|
||||
template <typename NODE> class Open_node;
|
||||
}
|
||||
|
||||
template <typename NODE>
|
||||
class File_system::Open_node : public File_system::Node
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Id_space<File_system::Node>::Element _element;
|
||||
|
||||
NODE &_node;
|
||||
Genode::Constructible<File_system::Listener> _listener;
|
||||
|
||||
Listener::Version const _version_when_opened = _node.curr_version();
|
||||
|
||||
/*
|
||||
* Flag to track whether the underlying file-system node was
|
||||
* modified via this 'Open_node'. That is, if closing the 'Open_node'
|
||||
* should notify listeners of the file.
|
||||
*/
|
||||
bool _was_written = false;
|
||||
|
||||
public:
|
||||
|
||||
Open_node(NODE &node, Genode::Id_space<File_system::Node> &id_space)
|
||||
: _element(*this, id_space), _node(node) { }
|
||||
|
||||
~Open_node()
|
||||
{
|
||||
if (_listener.constructed()) {
|
||||
_node.remove_listener(&*_listener);
|
||||
_listener.destruct();
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify remaining listeners about the changed file
|
||||
*/
|
||||
if (_was_written)
|
||||
_node.notify_listeners();
|
||||
}
|
||||
|
||||
NODE &node() { return _node; }
|
||||
File_system::Listener &listener() { return *_listener; }
|
||||
|
||||
Genode::Id_space<File_system::Node>::Id id() { return _element.id(); }
|
||||
|
||||
/**
|
||||
* Register packet stream sink to be notified of node changes
|
||||
*/
|
||||
void register_notify(File_system::Sink &sink)
|
||||
{
|
||||
/*
|
||||
* If there was already a handler registered for the node,
|
||||
* remove the old handler.
|
||||
*/
|
||||
if (_listener.constructed()) {
|
||||
_node.remove_listener(&*_listener);
|
||||
_listener.destruct();
|
||||
}
|
||||
|
||||
/*
|
||||
* Register new handler
|
||||
*/
|
||||
_listener.construct(sink, id(), _version_when_opened);
|
||||
_node.add_listener(&*_listener);
|
||||
}
|
||||
|
||||
void mark_as_written() { _was_written = true; }
|
||||
};
|
||||
|
||||
#endif /* _OPEN_NODE_H_ */
|
@ -13,7 +13,6 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/heap.h>
|
||||
#include <file_system/open_node.h>
|
||||
#include <file_system_session/rpc_object.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <os/session_policy.h>
|
||||
@ -26,6 +25,7 @@
|
||||
|
||||
/* local includes */
|
||||
#include <directory.h>
|
||||
#include <open_node.h>
|
||||
#include <util.h>
|
||||
|
||||
|
||||
|
95
repos/libports/src/server/fuse_fs/open_node.h
Normal file
95
repos/libports/src/server/fuse_fs/open_node.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* \brief Representation of an open file system node within the component (deprecated)
|
||||
* \author Christian Prochaska
|
||||
* \date 2017-06-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _OPEN_NODE_H_
|
||||
#define _OPEN_NODE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/listener.h>
|
||||
#include <file_system_session/file_system_session.h>
|
||||
|
||||
namespace File_system {
|
||||
/*
|
||||
* \param NODE component-specific node type
|
||||
*/
|
||||
template <typename NODE> class Open_node;
|
||||
}
|
||||
|
||||
template <typename NODE>
|
||||
class File_system::Open_node : public File_system::Node
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Id_space<File_system::Node>::Element _element;
|
||||
|
||||
NODE &_node;
|
||||
Genode::Constructible<File_system::Listener> _listener;
|
||||
|
||||
Listener::Version const _version_when_opened = _node.curr_version();
|
||||
|
||||
/*
|
||||
* Flag to track whether the underlying file-system node was
|
||||
* modified via this 'Open_node'. That is, if closing the 'Open_node'
|
||||
* should notify listeners of the file.
|
||||
*/
|
||||
bool _was_written = false;
|
||||
|
||||
public:
|
||||
|
||||
Open_node(NODE &node, Genode::Id_space<File_system::Node> &id_space)
|
||||
: _element(*this, id_space), _node(node) { }
|
||||
|
||||
~Open_node()
|
||||
{
|
||||
if (_listener.constructed()) {
|
||||
_node.remove_listener(&*_listener);
|
||||
_listener.destruct();
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify remaining listeners about the changed file
|
||||
*/
|
||||
if (_was_written)
|
||||
_node.notify_listeners();
|
||||
}
|
||||
|
||||
NODE &node() { return _node; }
|
||||
File_system::Listener &listener() { return *_listener; }
|
||||
|
||||
Genode::Id_space<File_system::Node>::Id id() { return _element.id(); }
|
||||
|
||||
/**
|
||||
* Register packet stream sink to be notified of node changes
|
||||
*/
|
||||
void register_notify(File_system::Sink &sink)
|
||||
{
|
||||
/*
|
||||
* If there was already a handler registered for the node,
|
||||
* remove the old handler.
|
||||
*/
|
||||
if (_listener.constructed()) {
|
||||
_node.remove_listener(&*_listener);
|
||||
_listener.destruct();
|
||||
}
|
||||
|
||||
/*
|
||||
* Register new handler
|
||||
*/
|
||||
_listener.construct(sink, id(), _version_when_opened);
|
||||
_node.add_listener(&*_listener);
|
||||
}
|
||||
|
||||
void mark_as_written() { _was_written = true; }
|
||||
};
|
||||
|
||||
#endif /* _OPEN_NODE_H_ */
|
@ -32,10 +32,10 @@ class File_system::Open_node : public File_system::Node
|
||||
|
||||
Genode::Id_space<File_system::Node>::Element _element;
|
||||
|
||||
NODE &_node;
|
||||
Genode::Constructible<File_system::Listener> _listener;
|
||||
Genode::Weak_ptr<NODE> _node;
|
||||
Genode::Constructible<File_system::Listener> _listener;
|
||||
|
||||
Listener::Version const _version_when_opened = _node.curr_version();
|
||||
Listener::Version const _version_when_opened { _node_version(_node) };
|
||||
|
||||
/*
|
||||
* Flag to track whether the underlying file-system node was
|
||||
@ -44,15 +44,29 @@ class File_system::Open_node : public File_system::Node
|
||||
*/
|
||||
bool _was_written = false;
|
||||
|
||||
static Listener::Version const _node_version(Genode::Weak_ptr<NODE> node)
|
||||
{
|
||||
Genode::Locked_ptr<NODE> locked_node { node };
|
||||
|
||||
if (locked_node.valid())
|
||||
return locked_node->curr_version();
|
||||
else
|
||||
return Listener::Version { 0 };
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Open_node(NODE &node, Genode::Id_space<File_system::Node> &id_space)
|
||||
Open_node(Genode::Weak_ptr<NODE> node,
|
||||
Genode::Id_space<File_system::Node> &id_space)
|
||||
: _element(*this, id_space), _node(node) { }
|
||||
|
||||
~Open_node()
|
||||
{
|
||||
Genode::Locked_ptr<NODE> node { _node };
|
||||
|
||||
if (_listener.constructed()) {
|
||||
_node.remove_listener(&*_listener);
|
||||
if (node.valid())
|
||||
node->remove_listener(&*_listener);
|
||||
_listener.destruct();
|
||||
}
|
||||
|
||||
@ -60,10 +74,11 @@ class File_system::Open_node : public File_system::Node
|
||||
* Notify remaining listeners about the changed file
|
||||
*/
|
||||
if (_was_written)
|
||||
_node.notify_listeners();
|
||||
if (node.valid())
|
||||
node->notify_listeners();
|
||||
}
|
||||
|
||||
NODE &node() { return _node; }
|
||||
Genode::Weak_ptr<NODE>&node() { return _node; }
|
||||
File_system::Listener &listener() { return *_listener; }
|
||||
|
||||
Genode::Id_space<File_system::Node>::Id id() { return _element.id(); }
|
||||
@ -73,20 +88,25 @@ class File_system::Open_node : public File_system::Node
|
||||
*/
|
||||
void register_notify(File_system::Sink &sink)
|
||||
{
|
||||
Genode::Locked_ptr<NODE> node { _node };
|
||||
|
||||
/*
|
||||
* If there was already a handler registered for the node,
|
||||
* remove the old handler.
|
||||
*/
|
||||
if (_listener.constructed()) {
|
||||
_node.remove_listener(&*_listener);
|
||||
if (node.valid())
|
||||
node->remove_listener(&*_listener);
|
||||
_listener.destruct();
|
||||
}
|
||||
|
||||
/*
|
||||
* Register new handler
|
||||
*/
|
||||
_listener.construct(sink, id(), _version_when_opened);
|
||||
_node.add_listener(&*_listener);
|
||||
if (node.valid()) {
|
||||
_listener.construct(sink, id(), _version_when_opened);
|
||||
node->add_listener(&*_listener);
|
||||
}
|
||||
}
|
||||
|
||||
void mark_as_written() { _was_written = true; }
|
||||
|
@ -105,6 +105,7 @@ namespace File_system {
|
||||
class No_space : Exception { };
|
||||
class Not_empty : Exception { };
|
||||
class Permission_denied : Exception { };
|
||||
class Unavailable : Exception { };
|
||||
|
||||
struct Session;
|
||||
}
|
||||
@ -288,6 +289,7 @@ struct File_system::Session : public Genode::Session
|
||||
* \throw Out_of_ram server cannot allocate metadata
|
||||
* \throw Out_of_caps
|
||||
* \throw Permission_denied
|
||||
* \throw Unavailable directory vanished
|
||||
*/
|
||||
virtual File_handle file(Dir_handle, Name const &name, Mode, bool create) = 0;
|
||||
|
||||
@ -303,6 +305,7 @@ struct File_system::Session : public Genode::Session
|
||||
* \throw Out_of_ram server cannot allocate metadata
|
||||
* \throw Out_of_caps
|
||||
* \throw Permission_denied
|
||||
* \throw Unavailable directory vanished
|
||||
*/
|
||||
virtual Symlink_handle symlink(Dir_handle, Name const &name, bool create) = 0;
|
||||
|
||||
@ -345,6 +348,7 @@ struct File_system::Session : public Genode::Session
|
||||
* Request information about an open file or directory
|
||||
*
|
||||
* \throw Invalid_handle node handle is invalid
|
||||
* \throw Unavailable node vanished
|
||||
*/
|
||||
virtual Status status(Node_handle) = 0;
|
||||
|
||||
@ -352,6 +356,7 @@ struct File_system::Session : public Genode::Session
|
||||
* Set information about an open file or directory
|
||||
*
|
||||
* \throw Invalid_handle node handle is invalid
|
||||
* \throw Unavailable node vanished
|
||||
*/
|
||||
virtual void control(Node_handle, Control) = 0;
|
||||
|
||||
@ -364,6 +369,7 @@ struct File_system::Session : public Genode::Session
|
||||
* \throw Not_empty argument is a non-empty directory and
|
||||
* the backend does not support recursion
|
||||
* \throw Permission_denied
|
||||
* \throw Unavailable directory vanished
|
||||
*/
|
||||
virtual void unlink(Dir_handle dir, Name const &name) = 0;
|
||||
|
||||
@ -373,6 +379,7 @@ struct File_system::Session : public Genode::Session
|
||||
* \throw Invalid_handle node handle is invalid
|
||||
* \throw No_space new size exceeds free space
|
||||
* \throw Permission_denied node modification not allowed
|
||||
* \throw Unavailable node vanished
|
||||
*/
|
||||
virtual void truncate(File_handle, file_size_t size) = 0;
|
||||
|
||||
@ -383,6 +390,7 @@ struct File_system::Session : public Genode::Session
|
||||
* \throw Invalid_name 'to' contains invalid characters
|
||||
* \throw Lookup_failed 'from' not found
|
||||
* \throw Permission_denied node modification not allowed
|
||||
* \throw Unavailable a directory vanished
|
||||
*/
|
||||
virtual void move(Dir_handle, Name const &from,
|
||||
Dir_handle, Name const &to) = 0;
|
||||
@ -397,13 +405,13 @@ struct File_system::Session : public Genode::Session
|
||||
GENODE_TYPE_LIST(Invalid_handle, Invalid_name,
|
||||
Lookup_failed, Node_already_exists,
|
||||
No_space, Out_of_ram, Out_of_caps,
|
||||
Permission_denied),
|
||||
Permission_denied, Unavailable),
|
||||
Dir_handle, Name const &, Mode, bool);
|
||||
GENODE_RPC_THROW(Rpc_symlink, Symlink_handle, symlink,
|
||||
GENODE_TYPE_LIST(Invalid_handle, Invalid_name,
|
||||
Lookup_failed, Node_already_exists,
|
||||
No_space, Out_of_ram, Out_of_caps,
|
||||
Permission_denied),
|
||||
Permission_denied, Unavailable),
|
||||
Dir_handle, Name const &, bool);
|
||||
GENODE_RPC_THROW(Rpc_dir, Dir_handle, dir,
|
||||
GENODE_TYPE_LIST(Lookup_failed, Name_too_long,
|
||||
@ -417,23 +425,23 @@ struct File_system::Session : public Genode::Session
|
||||
GENODE_TYPE_LIST(Invalid_handle),
|
||||
Node_handle);
|
||||
GENODE_RPC_THROW(Rpc_status, Status, status,
|
||||
GENODE_TYPE_LIST(Invalid_handle),
|
||||
GENODE_TYPE_LIST(Invalid_handle, Unavailable),
|
||||
Node_handle);
|
||||
GENODE_RPC_THROW(Rpc_control, void, control,
|
||||
GENODE_TYPE_LIST(Invalid_handle),
|
||||
GENODE_TYPE_LIST(Invalid_handle, Unavailable),
|
||||
Node_handle, Control);
|
||||
GENODE_RPC_THROW(Rpc_unlink, void, unlink,
|
||||
GENODE_TYPE_LIST(Invalid_handle, Invalid_name,
|
||||
Lookup_failed, Not_empty,
|
||||
Permission_denied),
|
||||
Permission_denied, Unavailable),
|
||||
Dir_handle, Name const &);
|
||||
GENODE_RPC_THROW(Rpc_truncate, void, truncate,
|
||||
GENODE_TYPE_LIST(Invalid_handle, No_space,
|
||||
Permission_denied),
|
||||
Permission_denied, Unavailable),
|
||||
File_handle, file_size_t);
|
||||
GENODE_RPC_THROW(Rpc_move, void, move,
|
||||
GENODE_TYPE_LIST(Invalid_handle, Invalid_name,
|
||||
Lookup_failed, Permission_denied),
|
||||
Lookup_failed, Permission_denied, Unavailable),
|
||||
Dir_handle, Name const &, Dir_handle, Name const &);
|
||||
|
||||
GENODE_RPC_INTERFACE(Rpc_tx_cap, Rpc_file, Rpc_symlink, Rpc_dir, Rpc_node,
|
||||
|
@ -638,6 +638,7 @@ class Vfs::Fs_file_system : public File_system
|
||||
catch (::File_system::Lookup_failed) { return UNLINK_ERR_NO_ENTRY; }
|
||||
catch (::File_system::Not_empty) { return UNLINK_ERR_NOT_EMPTY; }
|
||||
catch (::File_system::Permission_denied) { return UNLINK_ERR_NO_PERM; }
|
||||
catch (::File_system::Unavailable) { return UNLINK_ERR_NO_ENTRY; }
|
||||
|
||||
return UNLINK_OK;
|
||||
}
|
||||
@ -765,6 +766,7 @@ class Vfs::Fs_file_system : public File_system
|
||||
catch (::File_system::No_space) { return OPEN_ERR_NO_SPACE; }
|
||||
catch (::File_system::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
|
||||
catch (::File_system::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
|
||||
catch (::File_system::Unavailable) { return OPEN_ERR_UNACCESSIBLE; }
|
||||
|
||||
return OPEN_OK;
|
||||
}
|
||||
@ -834,6 +836,7 @@ class Vfs::Fs_file_system : public File_system
|
||||
catch (::File_system::Out_of_ram) { return OPENLINK_ERR_OUT_OF_RAM; }
|
||||
catch (::File_system::Out_of_caps) { return OPENLINK_ERR_OUT_OF_CAPS; }
|
||||
catch (::File_system::Permission_denied) { return OPENLINK_ERR_PERMISSION_DENIED; }
|
||||
catch (::File_system::Unavailable) { return OPENLINK_ERR_LOOKUP_FAILED; }
|
||||
}
|
||||
|
||||
void close(Vfs_handle *vfs_handle) override
|
||||
@ -940,6 +943,7 @@ class Vfs::Fs_file_system : public File_system
|
||||
catch (::File_system::Invalid_handle) { return FTRUNCATE_ERR_NO_PERM; }
|
||||
catch (::File_system::Permission_denied) { return FTRUNCATE_ERR_NO_PERM; }
|
||||
catch (::File_system::No_space) { return FTRUNCATE_ERR_NO_SPACE; }
|
||||
catch (::File_system::Unavailable) { return FTRUNCATE_ERR_NO_PERM; }
|
||||
|
||||
return FTRUNCATE_OK;
|
||||
}
|
||||
|
@ -16,14 +16,13 @@
|
||||
#include <base/heap.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <root/component.h>
|
||||
#include <file_system/open_node.h>
|
||||
#include <file_system_session/rpc_object.h>
|
||||
#include <os/session_policy.h>
|
||||
#include <util/xml_node.h>
|
||||
|
||||
/* local includes */
|
||||
#include <directory.h>
|
||||
|
||||
#include <open_node.h>
|
||||
|
||||
namespace Lx_fs {
|
||||
|
||||
|
95
repos/os/src/server/lx_fs/open_node.h
Normal file
95
repos/os/src/server/lx_fs/open_node.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* \brief Representation of an open file system node within the component (deprecated)
|
||||
* \author Christian Prochaska
|
||||
* \date 2017-06-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _OPEN_NODE_H_
|
||||
#define _OPEN_NODE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system/listener.h>
|
||||
#include <file_system_session/file_system_session.h>
|
||||
|
||||
namespace File_system {
|
||||
/*
|
||||
* \param NODE component-specific node type
|
||||
*/
|
||||
template <typename NODE> class Open_node;
|
||||
}
|
||||
|
||||
template <typename NODE>
|
||||
class File_system::Open_node : public File_system::Node
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Id_space<File_system::Node>::Element _element;
|
||||
|
||||
NODE &_node;
|
||||
Genode::Constructible<File_system::Listener> _listener;
|
||||
|
||||
Listener::Version const _version_when_opened = _node.curr_version();
|
||||
|
||||
/*
|
||||
* Flag to track whether the underlying file-system node was
|
||||
* modified via this 'Open_node'. That is, if closing the 'Open_node'
|
||||
* should notify listeners of the file.
|
||||
*/
|
||||
bool _was_written = false;
|
||||
|
||||
public:
|
||||
|
||||
Open_node(NODE &node, Genode::Id_space<File_system::Node> &id_space)
|
||||
: _element(*this, id_space), _node(node) { }
|
||||
|
||||
~Open_node()
|
||||
{
|
||||
if (_listener.constructed()) {
|
||||
_node.remove_listener(&*_listener);
|
||||
_listener.destruct();
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify remaining listeners about the changed file
|
||||
*/
|
||||
if (_was_written)
|
||||
_node.notify_listeners();
|
||||
}
|
||||
|
||||
NODE &node() { return _node; }
|
||||
File_system::Listener &listener() { return *_listener; }
|
||||
|
||||
Genode::Id_space<File_system::Node>::Id id() { return _element.id(); }
|
||||
|
||||
/**
|
||||
* Register packet stream sink to be notified of node changes
|
||||
*/
|
||||
void register_notify(File_system::Sink &sink)
|
||||
{
|
||||
/*
|
||||
* If there was already a handler registered for the node,
|
||||
* remove the old handler.
|
||||
*/
|
||||
if (_listener.constructed()) {
|
||||
_node.remove_listener(&*_listener);
|
||||
_listener.destruct();
|
||||
}
|
||||
|
||||
/*
|
||||
* Register new handler
|
||||
*/
|
||||
_listener.construct(sink, id(), _version_when_opened);
|
||||
_node.add_listener(&*_listener);
|
||||
}
|
||||
|
||||
void mark_as_written() { _was_written = true; }
|
||||
};
|
||||
|
||||
#endif /* _OPEN_NODE_H_ */
|
@ -76,30 +76,47 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
switch (packet.operation()) {
|
||||
|
||||
case Packet_descriptor::READ:
|
||||
if (content && (packet.length() <= packet.size()))
|
||||
res_length = open_node.node().read((char *)content, length, packet.position());
|
||||
if (content && (packet.length() <= packet.size())) {
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
break;
|
||||
res_length = node->read((char *)content, length,
|
||||
packet.position());
|
||||
}
|
||||
break;
|
||||
|
||||
case Packet_descriptor::WRITE:
|
||||
if (content && (packet.length() <= packet.size()))
|
||||
res_length = open_node.node().write((char const *)content, length, packet.position());
|
||||
|
||||
if (content && (packet.length() <= packet.size())) {
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
break;
|
||||
res_length = node->write((char const *)content, length,
|
||||
packet.position());
|
||||
}
|
||||
open_node.mark_as_written();
|
||||
break;
|
||||
|
||||
case Packet_descriptor::CONTENT_CHANGED:
|
||||
case Packet_descriptor::CONTENT_CHANGED: {
|
||||
open_node.register_notify(*tx_sink());
|
||||
open_node.node().notify_listeners();
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
return;
|
||||
node->notify_listeners();
|
||||
return;
|
||||
}
|
||||
|
||||
case Packet_descriptor::READ_READY:
|
||||
/* not supported */
|
||||
break;
|
||||
|
||||
case Packet_descriptor::SYNC:
|
||||
open_node.node().notify_listeners();
|
||||
case Packet_descriptor::SYNC: {
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
break;
|
||||
node->notify_listeners();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
packet.length(res_length);
|
||||
packet.succeeded(res_length > 0);
|
||||
@ -207,7 +224,10 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
|
||||
auto file_fn = [&] (Open_node &open_node) {
|
||||
|
||||
Node &dir = open_node.node();
|
||||
Locked_ptr<Node> dir { open_node.node() };
|
||||
|
||||
if (!dir.valid())
|
||||
throw Unavailable();
|
||||
|
||||
if (!_writable)
|
||||
if (mode != STAT_ONLY && mode != READ_ONLY)
|
||||
@ -218,23 +238,23 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
if (!_writable)
|
||||
throw Permission_denied();
|
||||
|
||||
if (dir.has_sub_node_unsynchronized(name.string()))
|
||||
if (dir->has_sub_node_unsynchronized(name.string()))
|
||||
throw Node_already_exists();
|
||||
|
||||
try {
|
||||
File * const file = new (_alloc)
|
||||
File(_alloc, name.string());
|
||||
|
||||
dir.adopt_unsynchronized(file);
|
||||
dir->adopt_unsynchronized(file);
|
||||
open_node.mark_as_written();
|
||||
}
|
||||
catch (Allocator::Out_of_memory) { throw No_space(); }
|
||||
}
|
||||
|
||||
File *file = dir.lookup_file(name.string());
|
||||
File *file = dir->lookup_file(name.string());
|
||||
|
||||
Open_node *open_file =
|
||||
new (_alloc) Open_node(*file, _open_node_registry);
|
||||
new (_alloc) Open_node(file->weak_ptr(), _open_node_registry);
|
||||
|
||||
return open_file->id();
|
||||
};
|
||||
@ -255,29 +275,32 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
|
||||
auto symlink_fn = [&] (Open_node &open_node) {
|
||||
|
||||
Node &dir = open_node.node();
|
||||
Locked_ptr<Node> dir { open_node.node() };
|
||||
|
||||
if (!dir.valid())
|
||||
throw Unavailable();
|
||||
|
||||
if (create) {
|
||||
|
||||
if (!_writable)
|
||||
throw Permission_denied();
|
||||
|
||||
if (dir.has_sub_node_unsynchronized(name.string()))
|
||||
if (dir->has_sub_node_unsynchronized(name.string()))
|
||||
throw Node_already_exists();
|
||||
|
||||
try {
|
||||
Symlink * const symlink = new (_alloc)
|
||||
Symlink(name.string());
|
||||
|
||||
dir.adopt_unsynchronized(symlink);
|
||||
dir->adopt_unsynchronized(symlink);
|
||||
}
|
||||
catch (Allocator::Out_of_memory) { throw No_space(); }
|
||||
}
|
||||
|
||||
Symlink *symlink = dir.lookup_symlink(name.string());
|
||||
Symlink *symlink = dir->lookup_symlink(name.string());
|
||||
|
||||
Open_node *open_symlink =
|
||||
new (_alloc) Open_node(*symlink, _open_node_registry);
|
||||
new (_alloc) Open_node(symlink->weak_ptr(), _open_node_registry);
|
||||
|
||||
return open_symlink->id();
|
||||
};
|
||||
@ -325,7 +348,7 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
Directory *dir = _root.lookup_dir(path_str);
|
||||
|
||||
Open_node *open_dir =
|
||||
new (_alloc) Open_node(*dir, _open_node_registry);
|
||||
new (_alloc) Open_node(dir->weak_ptr(), _open_node_registry);
|
||||
|
||||
return Dir_handle { open_dir->id().value };
|
||||
}
|
||||
@ -337,7 +360,7 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
Node *node = _root.lookup(path.string() + 1);
|
||||
|
||||
Open_node *open_node =
|
||||
new (_alloc) Open_node(*node, _open_node_registry);
|
||||
new (_alloc) Open_node(node->weak_ptr(), _open_node_registry);
|
||||
|
||||
return open_node->id();
|
||||
}
|
||||
@ -345,7 +368,8 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
void close(Node_handle handle)
|
||||
{
|
||||
auto close_fn = [&] (Open_node &open_node) {
|
||||
destroy(_alloc, &open_node); };
|
||||
destroy(_alloc, &open_node);
|
||||
};
|
||||
|
||||
try {
|
||||
_open_node_registry.apply<Open_node>(handle, close_fn);
|
||||
@ -357,7 +381,11 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
Status status(Node_handle node_handle)
|
||||
{
|
||||
auto status_fn = [&] (Open_node &open_node) {
|
||||
return open_node.node().status(); };
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
throw Unavailable();
|
||||
return node->status();
|
||||
};
|
||||
|
||||
try {
|
||||
return _open_node_registry.apply<Open_node>(node_handle, status_fn);
|
||||
@ -378,14 +406,14 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
|
||||
auto unlink_fn = [&] (Open_node &open_node) {
|
||||
|
||||
Node &dir = open_node.node();
|
||||
Locked_ptr<Node> dir { open_node.node() };
|
||||
|
||||
Node *node = dir.lookup(name.string());
|
||||
if (!dir.valid())
|
||||
throw Unavailable();
|
||||
|
||||
dir.discard(node);
|
||||
Node *node = dir->lookup(name.string());
|
||||
|
||||
// XXX implement ref counting, do not destroy node that is
|
||||
// is still referenced by a node handle
|
||||
dir->discard(node);
|
||||
|
||||
destroy(_alloc, node);
|
||||
open_node.mark_as_written();
|
||||
@ -404,7 +432,10 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
throw Permission_denied();
|
||||
|
||||
auto truncate_fn = [&] (Open_node &open_node) {
|
||||
open_node.node().truncate(size);
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
throw Unavailable();
|
||||
node->truncate(size);
|
||||
open_node.mark_as_written();
|
||||
};
|
||||
|
||||
@ -431,17 +462,23 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
|
||||
auto inner_move_fn = [&] (Open_node &open_to_dir_node) {
|
||||
|
||||
Node &from_dir = open_from_dir_node.node();
|
||||
Locked_ptr<Node> from_dir { open_from_dir_node.node() };
|
||||
|
||||
Node *node = from_dir.lookup(from_name.string());
|
||||
if (!from_dir.valid())
|
||||
throw Unavailable();
|
||||
|
||||
Node *node = from_dir->lookup(from_name.string());
|
||||
node->name(to_name.string());
|
||||
|
||||
Node &to_dir = open_to_dir_node.node();
|
||||
if (!(open_to_dir_node.node() == open_from_dir_node.node())) {
|
||||
|
||||
if (&to_dir != &from_dir) {
|
||||
Locked_ptr<Node> to_dir { open_to_dir_node.node() };
|
||||
|
||||
from_dir.discard(node);
|
||||
to_dir.adopt_unsynchronized(node);
|
||||
if (!to_dir.valid())
|
||||
throw Unavailable();
|
||||
|
||||
from_dir->discard(node);
|
||||
to_dir->adopt_unsynchronized(node);
|
||||
|
||||
/*
|
||||
* If the file was moved from one directory to another we
|
||||
@ -449,13 +486,13 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object
|
||||
* directory 'from_dir' will always get notified (i.e.,
|
||||
* when just the file name was changed) below.
|
||||
*/
|
||||
to_dir.mark_as_updated();
|
||||
to_dir->mark_as_updated();
|
||||
open_to_dir_node.mark_as_written();
|
||||
to_dir.notify_listeners();
|
||||
to_dir->notify_listeners();
|
||||
|
||||
from_dir.mark_as_updated();
|
||||
from_dir->mark_as_updated();
|
||||
open_from_dir_node.mark_as_written();
|
||||
from_dir.notify_listeners();
|
||||
from_dir->notify_listeners();
|
||||
|
||||
node->mark_as_updated();
|
||||
node->notify_listeners();
|
||||
|
@ -29,7 +29,8 @@ namespace Ram_fs {
|
||||
}
|
||||
|
||||
|
||||
class Ram_fs::Node : public File_system::Node_base, public List<Node>::Element
|
||||
class Ram_fs::Node : public File_system::Node_base, public Weak_object<Node>,
|
||||
public List<Node>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
@ -56,6 +57,8 @@ class Ram_fs::Node : public File_system::Node_base, public List<Node>::Element
|
||||
: _ref_count(0), _inode(_unique_inode())
|
||||
{ _name[0] = 0; }
|
||||
|
||||
virtual ~Node() { lock_for_destruction(); }
|
||||
|
||||
unsigned long inode() const { return _inode; }
|
||||
char const *name() const { return _name; }
|
||||
|
||||
|
@ -658,22 +658,36 @@ class Trace_fs::Session_component : public Session_rpc_object
|
||||
switch (packet.operation()) {
|
||||
|
||||
case Packet_descriptor::READ:
|
||||
if (content && (packet.length() <= packet.size()))
|
||||
res_length = open_node.node().read((char *)content, length, packet.position());
|
||||
if (content && (packet.length() <= packet.size())) {
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
break;
|
||||
res_length = node->read((char *)content, length, packet.position());
|
||||
}
|
||||
break;
|
||||
|
||||
case Packet_descriptor::WRITE:
|
||||
if (content && (packet.length() <= packet.size()))
|
||||
res_length = open_node.node().write((char const *)content, length, packet.position());
|
||||
if (content && (packet.length() <= packet.size())) {
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
break;
|
||||
res_length = node->write((char const *)content, length, packet.position());
|
||||
}
|
||||
break;
|
||||
|
||||
case Packet_descriptor::CONTENT_CHANGED:
|
||||
case Packet_descriptor::CONTENT_CHANGED: {
|
||||
open_node.register_notify(*tx_sink());
|
||||
|
||||
/* notify_listeners may bounce the packet back*/
|
||||
open_node.node().notify_listeners();
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
return;
|
||||
node->notify_listeners();
|
||||
|
||||
/* otherwise defer acknowledgement of this packet */
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
case Packet_descriptor::READ_READY:
|
||||
/* not supported */
|
||||
break;
|
||||
@ -824,17 +838,20 @@ class Trace_fs::Session_component : public Session_rpc_object
|
||||
|
||||
auto file_fn = [&] (Open_node &open_node) {
|
||||
|
||||
Node &dir = open_node.node();
|
||||
Locked_ptr<Node> dir { open_node.node() };
|
||||
|
||||
if (!dir.valid())
|
||||
throw Invalid_handle();
|
||||
|
||||
if (create)
|
||||
throw Permission_denied();
|
||||
|
||||
File *file = dynamic_cast<File*>(dir.lookup(name.string()));
|
||||
File *file = dynamic_cast<File*>(dir->lookup(name.string()));
|
||||
if (!file)
|
||||
throw Invalid_name();
|
||||
|
||||
Open_node *open_file =
|
||||
new (_md_alloc) Open_node(*file, _open_node_registry);
|
||||
new (_md_alloc) Open_node(file->weak_ptr(), _open_node_registry);
|
||||
|
||||
return open_file->id();
|
||||
};
|
||||
@ -871,7 +888,7 @@ class Trace_fs::Session_component : public Session_rpc_object
|
||||
throw Invalid_name();
|
||||
|
||||
Open_node *open_dir =
|
||||
new (_md_alloc) Open_node(*dir, _open_node_registry);
|
||||
new (_md_alloc) Open_node(dir->weak_ptr(), _open_node_registry);
|
||||
|
||||
return Dir_handle { open_dir->id().value };
|
||||
}
|
||||
@ -885,7 +902,7 @@ class Trace_fs::Session_component : public Session_rpc_object
|
||||
Node *node = _root_dir.lookup(path_str + 1);
|
||||
|
||||
Open_node *open_node =
|
||||
new (_md_alloc) Open_node(*node, _open_node_registry);
|
||||
new (_md_alloc) Open_node(node->weak_ptr(), _open_node_registry);
|
||||
|
||||
return open_node->id();
|
||||
}
|
||||
@ -894,26 +911,29 @@ class Trace_fs::Session_component : public Session_rpc_object
|
||||
{
|
||||
auto close_fn = [&] (Open_node &open_node) {
|
||||
|
||||
Node &node = open_node.node();
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
|
||||
if (!node.valid())
|
||||
throw Invalid_handle();
|
||||
|
||||
/**
|
||||
* Acknowledge the change of the content of files which may be
|
||||
* modified by the user of the file system.
|
||||
*/
|
||||
Changeable_content *changeable = dynamic_cast<Changeable_content*>(&node);
|
||||
Changeable_content *changeable = dynamic_cast<Changeable_content*>(&*node);
|
||||
if (changeable) {
|
||||
if (changeable->changed()) {
|
||||
changeable->acknowledge_change();
|
||||
|
||||
/* let the trace fs perform the provoked actions */
|
||||
_trace_fs->handle_changed_node(&node);
|
||||
_trace_fs->handle_changed_node(&*node);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Notify listeners about the changed file.
|
||||
*/
|
||||
node.notify_listeners();
|
||||
node->notify_listeners();
|
||||
|
||||
/*
|
||||
* De-allocate handle
|
||||
@ -931,7 +951,10 @@ class Trace_fs::Session_component : public Session_rpc_object
|
||||
Status status(Node_handle node_handle)
|
||||
{
|
||||
auto status_fn = [&] (Open_node &open_node) {
|
||||
return open_node.node().status();
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
throw Invalid_handle();
|
||||
return node->status();
|
||||
};
|
||||
|
||||
try {
|
||||
@ -947,7 +970,10 @@ class Trace_fs::Session_component : public Session_rpc_object
|
||||
void truncate(File_handle handle, file_size_t size)
|
||||
{
|
||||
auto truncate_fn = [&] (Open_node &open_node) {
|
||||
open_node.node().truncate(size);
|
||||
Locked_ptr<Node> node { open_node.node() };
|
||||
if (!node.valid())
|
||||
throw Invalid_handle();
|
||||
node->truncate(size);
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -26,7 +26,8 @@ namespace Trace_fs {
|
||||
class Node;
|
||||
}
|
||||
|
||||
class Trace_fs::Node : public Node_base, public List<Node>::Element
|
||||
class Trace_fs::Node : public Node_base, public Weak_object<Node>,
|
||||
public List<Node>::Element
|
||||
{
|
||||
public:
|
||||
|
||||
@ -52,6 +53,8 @@ class Trace_fs::Node : public Node_base, public List<Node>::Element
|
||||
: _inode(_unique_inode())
|
||||
{ _name[0] = 0; }
|
||||
|
||||
virtual ~Node() { lock_for_destruction(); }
|
||||
|
||||
unsigned long inode() const { return _inode; }
|
||||
char const *name() const { return _name; }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user