file system: enhanced file status info

This patch extends the 'File_system::Status',
'File_system::Directory_entry', and the related 'Vfs' types with
the following additional information:

- Distinction between continuous and transactional files (Node_type)
  (issue #3507)
- Readable, writeable, and executable attributes (Node_rwx),
  replacing the former 'mode' bits
  (issue #3030)

The types 'Node_rwx', 'Node_type' are defined twice,
once for the VFS (vfs/types.h) and once for the 'File_system'
session (file_system_session/file_system_session.h).
Similarly, there is a direct correspondance between
'Vfs::Directory_service::Dirent' and 'File_system::Directory_entry'.

This duplication of types follows the existing pattern of keeping the
VFS and file-system session independent from each other.
This commit is contained in:
Norman Feske
2019-09-25 17:13:29 +02:00
committed by Christian Helmuth
parent 1297a8fb57
commit 5ab1505d43
52 changed files with 1049 additions and 668 deletions

View File

@ -69,6 +69,50 @@ class Vfs::Fs_file_system : public File_system
struct Fs_vfs_handle;
typedef Genode::Fifo<Fs_vfs_handle> Fs_vfs_handle_queue;
/**
* Convert 'File_system::Node_type' to 'Dirent_type'
*/
static Dirent_type _dirent_type(::File_system::Node_type type)
{
using ::File_system::Node_type;
switch (type) {
case Node_type::DIRECTORY: return Dirent_type::DIRECTORY;
case Node_type::CONTINUOUS_FILE: return Dirent_type::CONTINUOUS_FILE;
case Node_type::TRANSACTIONAL_FILE: return Dirent_type::TRANSACTIONAL_FILE;
case Node_type::SYMLINK: return Dirent_type::SYMLINK;
}
return Dirent_type::END;
}
/**
* Convert 'File_system::Node_type' to 'Vfs::Node_type'
*/
static Node_type _node_type(::File_system::Node_type type)
{
using Type = ::File_system::Node_type;
switch (type) {
case Type::DIRECTORY: return Node_type::DIRECTORY;
case Type::CONTINUOUS_FILE: return Node_type::CONTINUOUS_FILE;
case Type::TRANSACTIONAL_FILE: return Node_type::TRANSACTIONAL_FILE;
case Type::SYMLINK: return Node_type::SYMLINK;
}
Genode::error("invalid File_system::Node_type");
return Node_type::CONTINUOUS_FILE;
}
/**
* Convert 'File_system::Node_rwx' to 'Vfs::Node_rwx'
*/
static Node_rwx _node_rwx(::File_system::Node_rwx rwx)
{
return { .readable = rwx.readable,
.writeable = rwx.writeable,
.executable = rwx.executable };
}
struct Fs_vfs_handle : Vfs_handle,
private ::File_system::Node,
private Handle_space::Element,
@ -295,41 +339,38 @@ class Vfs::Fs_file_system : public File_system
using ::File_system::Directory_entry;
Directory_entry entry;
file_size entry_out_count;
Directory_entry entry { };
file_size entry_out_count = 0;
Read_result read_result =
Read_result const read_result =
_complete_read(&entry, DIRENT_SIZE, entry_out_count);
if (read_result != READ_OK)
return read_result;
Dirent *dirent = (Dirent*)dst;
entry.sanitize();
Dirent &dirent = *(Dirent*)dst;
if (entry_out_count < DIRENT_SIZE) {
/* no entry found for the given index, or error */
*dirent = Dirent();
dirent = Dirent {
.fileno = 0,
.type = Dirent_type::END,
.rwx = { },
.name = { }
};
out_count = sizeof(Dirent);
return READ_OK;
}
/*
* The default value has no meaning because the switch below
* assigns a value in each possible branch. But it is needed to
* keep the compiler happy.
*/
Dirent_type type = DIRENT_TYPE_END;
/* copy-out payload into destination buffer */
switch (entry.type) {
case Directory_entry::TYPE_DIRECTORY: type = DIRENT_TYPE_DIRECTORY; break;
case Directory_entry::TYPE_FILE: type = DIRENT_TYPE_FILE; break;
case Directory_entry::TYPE_SYMLINK: type = DIRENT_TYPE_SYMLINK; break;
}
dirent->fileno = entry.inode;
dirent->type = type;
strncpy(dirent->name, entry.name, sizeof(dirent->name));
dirent = Dirent {
.fileno = entry.inode,
.type = _dirent_type(entry.type),
.rwx = _node_rwx(entry.rwx),
.name = { entry.name.buf }
};
out_count = sizeof(Dirent);
@ -646,20 +687,13 @@ class Vfs::Fs_file_system : public File_system
out = Stat();
out.size = status.size;
out.mode = STAT_MODE_FILE | 0777;
if (status.symlink())
out.mode = STAT_MODE_SYMLINK | 0777;
if (status.directory())
out.mode = STAT_MODE_DIRECTORY | 0777;
out.uid = 0;
out.gid = 0;
out.inode = status.inode;
out.size = status.size;
out.type = _node_type(status.type);
out.rwx = _node_rwx(status.rwx);
out.inode = status.inode;
out.device = (Genode::addr_t)this;
out.modification_time.value = status.modification_time.value;
return STAT_OK;
}