160 lines
3.9 KiB
C++
160 lines
3.9 KiB
C++
/*
|
|
* \brief Terminal file system
|
|
* \author Christian Prochaska
|
|
* \author Norman Feske
|
|
* \author Christian Helmuth
|
|
* \date 2012-05-23
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2012-2019 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 _INCLUDE__VFS__TERMINAL_FILE_SYSTEM_H_
|
|
#define _INCLUDE__VFS__TERMINAL_FILE_SYSTEM_H_
|
|
|
|
#include <terminal_session/connection.h>
|
|
#include <vfs/single_file_system.h>
|
|
#include <base/registry.h>
|
|
|
|
|
|
namespace Vfs { class Terminal_file_system; }
|
|
|
|
|
|
class Vfs::Terminal_file_system : public Single_file_system
|
|
{
|
|
private:
|
|
|
|
typedef Genode::String<64> Label;
|
|
Label _label;
|
|
|
|
Genode::Env &_env;
|
|
|
|
Terminal::Connection _terminal { _env, _label.string() };
|
|
|
|
struct Terminal_vfs_handle : Single_vfs_handle
|
|
{
|
|
Terminal::Connection &terminal;
|
|
bool notifying { false };
|
|
bool blocked { false };
|
|
|
|
Terminal_vfs_handle(Terminal::Connection &term,
|
|
Directory_service &ds,
|
|
File_io_service &fs,
|
|
Genode::Allocator &alloc,
|
|
int flags)
|
|
:
|
|
Single_vfs_handle(ds, fs, alloc, flags),
|
|
terminal(term)
|
|
{ }
|
|
|
|
bool read_ready() override {
|
|
return terminal.avail(); }
|
|
|
|
Read_result read(char *dst, file_size count,
|
|
file_size &out_count) override
|
|
{
|
|
if (!terminal.avail()) {
|
|
blocked = true;
|
|
return READ_QUEUED;
|
|
}
|
|
|
|
out_count = terminal.read(dst, count);
|
|
return READ_OK;
|
|
}
|
|
|
|
Write_result write(char const *src, file_size count,
|
|
file_size &out_count) override
|
|
{
|
|
out_count = terminal.write(src, count);
|
|
return WRITE_OK;
|
|
}
|
|
};
|
|
|
|
typedef Genode::Registered<Terminal_vfs_handle> Registered_handle;
|
|
typedef Genode::Registry<Registered_handle> Handle_registry;
|
|
|
|
Handle_registry _handle_registry { };
|
|
|
|
Genode::Io_signal_handler<Terminal_file_system> _read_avail_handler {
|
|
_env.ep(), *this, &Terminal_file_system::_handle_read_avail };
|
|
|
|
void _handle_read_avail()
|
|
{
|
|
_handle_registry.for_each([this] (Registered_handle &handle) {
|
|
if (handle.blocked) {
|
|
handle.blocked = false;
|
|
handle.io_progress_response();
|
|
}
|
|
|
|
if (handle.notifying) {
|
|
handle.notifying = false;
|
|
handle.read_ready_response();
|
|
}
|
|
});
|
|
}
|
|
|
|
public:
|
|
|
|
Terminal_file_system(Vfs::Env &env, Genode::Xml_node config)
|
|
:
|
|
Single_file_system(Node_type::TRANSACTIONAL_FILE, name(),
|
|
Node_rwx::rw(), config),
|
|
_label(config.attribute_value("label", Label())),
|
|
_env(env.env())
|
|
{
|
|
/* register for read-avail notification */
|
|
_terminal.read_avail_sigh(_read_avail_handler);
|
|
}
|
|
|
|
static const char *name() { return "terminal"; }
|
|
char const *type() override { return "terminal"; }
|
|
|
|
Open_result open(char const *path, unsigned flags,
|
|
Vfs_handle **out_handle,
|
|
Allocator &alloc) override
|
|
{
|
|
if (!_single_file(path))
|
|
return OPEN_ERR_UNACCESSIBLE;
|
|
|
|
try {
|
|
*out_handle = new (alloc)
|
|
Registered_handle(_handle_registry, _terminal, *this, *this, alloc, flags);
|
|
return OPEN_OK;
|
|
}
|
|
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
|
|
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
|
|
}
|
|
|
|
|
|
/********************************
|
|
** File I/O service interface **
|
|
********************************/
|
|
|
|
bool notify_read_ready(Vfs_handle *vfs_handle) override
|
|
{
|
|
Terminal_vfs_handle *handle =
|
|
static_cast<Terminal_vfs_handle*>(vfs_handle);
|
|
if (!handle)
|
|
return false;
|
|
|
|
handle->notifying = true;
|
|
return true;
|
|
}
|
|
|
|
Ftruncate_result ftruncate(Vfs_handle *, file_size) override
|
|
{
|
|
return FTRUNCATE_OK;
|
|
}
|
|
|
|
bool check_unblock(Vfs_handle *, bool rd, bool wr, bool) override
|
|
{
|
|
return ((rd && _terminal.avail()) || wr);
|
|
}
|
|
};
|
|
|
|
#endif /* _INCLUDE__VFS__TERMINAL_FILE_SYSTEM_H_ */
|