genode/ports/src/noux/vfs_io_channel.h
Norman Feske 66290ea46d Stacked file systems for Noux
This patch introduces support for stacked file systems alongside new
glue for accessing file-system implementations provided via Genode's
new file-system-session interface.

Using stacked file systems, an arbitrary number of file systems (such
as tar archives or file systems implemented as separate Genode
components) can be composed to form one merged virtual file system.

An example is given via the 'ports/run/noux_bash.run' script. This run
script creates a virtual file system out of multiple tar archives each
containing the content of a particular GNU package. In addition, one
'ram_fs' is mounted, which enables Noux to perform write operations.
This way, the shell output can be redirected to a file, or files can
be saved in VIM.

Fixes #103.
2012-05-17 20:34:00 +02:00

158 lines
3.5 KiB
C++

/*
* \brief I/O channel for files opened via virtual directory service
* \author Norman Feske
* \date 2011-02-17
*/
/*
* Copyright (C) 2011-2012 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 _NOUX__VFS_IO_CHANNEL_H_
#define _NOUX__VFS_IO_CHANNEL_H_
/* Noux includes */
#include <io_channel.h>
#include <file_system.h>
#include <dir_file_system.h>
#include <pwd.h>
namespace Noux {
struct Vfs_io_channel : public Io_channel
{
Vfs_handle *_fh;
Absolute_path _path;
Absolute_path _leaf_path;
Vfs_io_channel(char const *path, char const *leaf_path,
Dir_file_system *root_dir, Vfs_handle *vfs_handle)
: _fh(vfs_handle), _path(path), _leaf_path(leaf_path) { }
~Vfs_io_channel() { destroy(env()->heap(), _fh); }
bool write(Sysio *sysio, size_t &count)
{
if (!_fh->fs()->write(sysio, _fh))
return false;
count = sysio->write_out.count;
_fh->_seek += count;
return true;
}
bool read(Sysio *sysio)
{
if (!_fh->fs()->read(sysio, _fh))
return false;
_fh->_seek += sysio->read_out.count;
return true;
}
bool fstat(Sysio *sysio)
{
return _fh->ds()->stat(sysio, _leaf_path.base());
}
bool fcntl(Sysio *sysio)
{
switch (sysio->fcntl_in.cmd) {
case Sysio::FCNTL_CMD_GET_FILE_STATUS_FLAGS:
sysio->fcntl_out.result = _fh->status_flags();
return true;
default:
PWRN("invalid fcntl command %d", sysio->fcntl_in.cmd);
sysio->error.fcntl = Sysio::FCNTL_ERR_CMD_INVALID;
return false;
};
}
bool fchdir(Sysio *sysio, Pwd *pwd)
{
pwd->pwd(_path.base());
return true;
}
/*
* The 'dirent' function for the root directory only (the
* 'Dir_file_system::open()' function handles all requests referring
* to directories). Hence, '_path' is the absolute path of the
* directory to inspect.
*/
bool dirent(Sysio *sysio)
{
/*
* Return artificial dir entries for "." and ".."
*/
unsigned const index = _fh->seek() / sizeof(Sysio::Dirent);
if (index < 2) {
sysio->dirent_out.entry.type = Sysio::DIRENT_TYPE_DIRECTORY;
strncpy(sysio->dirent_out.entry.name,
index ? ".." : ".",
sizeof(sysio->dirent_out.entry.name));
sysio->dirent_out.entry.fileno = 1;
_fh->_seek += sizeof(Sysio::Dirent);
return true;
}
/*
* Delegate remaining dir-entry request to the actual file system.
* Align index range to zero when calling the directory service.
*/
if (!_fh->ds()->dirent(sysio, _path.base(), index - 2))
return false;
_fh->_seek += sizeof(Sysio::Dirent);
return true;
}
/**
* Return size of file that the I/O channel refers to
*
* Note that this function overwrites the 'sysio' argument. Do not
* call it prior saving all input arguments from the original sysio
* structure.
*/
size_t size(Sysio *sysio)
{
if (fstat(sysio))
return sysio->stat_out.st.size;
return 0;
}
bool lseek(Sysio *sysio)
{
switch (sysio->lseek_in.whence) {
case Sysio::LSEEK_SET: _fh->_seek = sysio->lseek_in.offset; break;
case Sysio::LSEEK_CUR: break;
case Sysio::LSEEK_END: _fh->_seek = size(sysio); break;
}
sysio->lseek_out.offset = _fh->_seek;
return true;
}
bool check_unblock(bool rd, bool wr, bool ex) const
{
/*
* XXX For now, we use the TAR fs only, which never blocks.
* However, real file systems may block.
*/
return true;
}
};
}
#endif /* _NOUX__VFS_IO_CHANNEL_H_ */