mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-11 15:33:04 +00:00
vfs: handle root directory explicitly
This makes '/' and the actual root of VFS distinguishable. A VFS root may contain one ore more '/' entries for each file system. 'opendir' for the VFS root opens all file systems via 'open_composite_dir', while 'opendir' for '/' only returns a VFS handle. Fixes #2569
This commit is contained in:
parent
66d5954fc5
commit
9c852c750a
@ -97,7 +97,7 @@ class Libc::Env_implementation : public Libc::Env
|
|||||||
:
|
:
|
||||||
_env(env), _file_system_factory(alloc),
|
_env(env), _file_system_factory(alloc),
|
||||||
_vfs(_env, alloc, _vfs_config(), io_response_handler,
|
_vfs(_env, alloc, _vfs_config(), io_response_handler,
|
||||||
_file_system_factory)
|
_file_system_factory, Vfs::Dir_file_system::Root())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,8 +30,17 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
|
|
||||||
enum { MAX_NAME_LEN = 128 };
|
enum { MAX_NAME_LEN = 128 };
|
||||||
|
|
||||||
|
struct Root { };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This instance is the root of VFS
|
||||||
|
*
|
||||||
|
* Additionally, the root has an empty _name.
|
||||||
|
*/
|
||||||
|
bool _vfs_root;
|
||||||
|
|
||||||
struct Dir_vfs_handle : Vfs_handle
|
struct Dir_vfs_handle : Vfs_handle
|
||||||
{
|
{
|
||||||
struct Subdir_handle_element;
|
struct Subdir_handle_element;
|
||||||
@ -92,7 +101,10 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
*/
|
*/
|
||||||
char _name[MAX_NAME_LEN];
|
char _name[MAX_NAME_LEN];
|
||||||
|
|
||||||
bool _root() const { return _name[0] == 0; }
|
/**
|
||||||
|
* Returns if path corresponds to top directory of file system
|
||||||
|
*/
|
||||||
|
bool _top_dir(char const *path) const { return strcmp(path, "/") == 0; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform operation on a file system
|
* Perform operation on a file system
|
||||||
@ -165,10 +177,10 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
char const *_sub_path(char const *path) const
|
char const *_sub_path(char const *path) const
|
||||||
{
|
{
|
||||||
/* do not strip anything from the path when we are root */
|
/* do not strip anything from the path when we are root */
|
||||||
if (_root())
|
if (_vfs_root)
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
if (strcmp(path, "/") == 0)
|
if (_top_dir(path))
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
/* skip heading slash in path if present */
|
/* skip heading slash in path if present */
|
||||||
@ -248,6 +260,9 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
|
|
||||||
result = vfs_handle.fs().queue_read(&vfs_handle, sizeof(Dirent));
|
result = vfs_handle.fs().queue_read(&vfs_handle, sizeof(Dirent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* adjust base index for next file system */
|
||||||
|
base += fs_num_dirent;
|
||||||
};
|
};
|
||||||
|
|
||||||
dir_vfs_handle->subdir_handle_registry.for_each(f);
|
dir_vfs_handle->subdir_handle_registry.for_each(f);
|
||||||
@ -297,6 +312,7 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
Io_response_handler &io_handler,
|
Io_response_handler &io_handler,
|
||||||
File_system_factory &fs_factory)
|
File_system_factory &fs_factory)
|
||||||
:
|
:
|
||||||
|
_vfs_root(false),
|
||||||
_first_file_system(0)
|
_first_file_system(0)
|
||||||
{
|
{
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
@ -337,6 +353,15 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dir_file_system(Genode::Env &env,
|
||||||
|
Genode::Allocator &alloc,
|
||||||
|
Genode::Xml_node node,
|
||||||
|
Io_response_handler &io_handler,
|
||||||
|
File_system_factory &fs_factory,
|
||||||
|
Dir_file_system::Root)
|
||||||
|
:
|
||||||
|
Dir_file_system(env, alloc, node, io_handler, fs_factory)
|
||||||
|
{ _vfs_root = true; }
|
||||||
|
|
||||||
/*********************************
|
/*********************************
|
||||||
** Directory-service interface **
|
** Directory-service interface **
|
||||||
@ -384,7 +409,7 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
* If path equals directory name, return information about the
|
* If path equals directory name, return information about the
|
||||||
* current directory.
|
* current directory.
|
||||||
*/
|
*/
|
||||||
if (strlen(path) == 0 || (strcmp(path, "/") == 0)) {
|
if (strlen(path) == 0 || _top_dir(path)) {
|
||||||
out.size = 0;
|
out.size = 0;
|
||||||
out.mode = STAT_MODE_DIRECTORY | 0755;
|
out.mode = STAT_MODE_DIRECTORY | 0755;
|
||||||
out.uid = 0;
|
out.uid = 0;
|
||||||
@ -415,12 +440,12 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
|
|
||||||
file_size num_dirent(char const *path) override
|
file_size num_dirent(char const *path) override
|
||||||
{
|
{
|
||||||
if (_root()) {
|
if (_vfs_root) {
|
||||||
return _sum_dirents_of_file_systems(path);
|
return _sum_dirents_of_file_systems(path);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (strcmp(path, "/") == 0)
|
if (_top_dir(path))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -444,7 +469,7 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
*/
|
*/
|
||||||
bool directory(char const *path) override
|
bool directory(char const *path) override
|
||||||
{
|
{
|
||||||
if (strcmp(path, "/") == 0)
|
if (_top_dir(path))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
path = _sub_path(path);
|
path = _sub_path(path);
|
||||||
@ -544,9 +569,8 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
Opendir_result open_composite_dirs(char const *sub_path,
|
Opendir_result open_composite_dirs(char const *sub_path,
|
||||||
Dir_vfs_handle &dir_vfs_handle)
|
Dir_vfs_handle &dir_vfs_handle)
|
||||||
{
|
{
|
||||||
Opendir_result result = OPENDIR_OK;
|
|
||||||
try {
|
try {
|
||||||
for (File_system *fs = _first_file_system; (fs && result == OPENDIR_OK); fs = fs->next) {
|
for (File_system *fs = _first_file_system; fs; fs = fs->next) {
|
||||||
Vfs_handle *sub_dir_handle = nullptr;
|
Vfs_handle *sub_dir_handle = nullptr;
|
||||||
|
|
||||||
Opendir_result r = fs->opendir(
|
Opendir_result r = fs->opendir(
|
||||||
@ -556,9 +580,7 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
case OPENDIR_OK:
|
case OPENDIR_OK:
|
||||||
break;
|
break;
|
||||||
case OPENDIR_ERR_LOOKUP_FAILED:
|
case OPENDIR_ERR_LOOKUP_FAILED:
|
||||||
continue;
|
|
||||||
default:
|
default:
|
||||||
result = r; /* loop will break */
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,7 +591,8 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
}
|
}
|
||||||
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
|
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
|
||||||
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
|
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
|
||||||
return result;
|
|
||||||
|
return OPENDIR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Opendir_result opendir(char const *path, bool create,
|
Opendir_result opendir(char const *path, bool create,
|
||||||
@ -577,13 +600,22 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
{
|
{
|
||||||
Opendir_result result = OPENDIR_OK;
|
Opendir_result result = OPENDIR_OK;
|
||||||
|
|
||||||
/* path equals "/" (for reading the name of this directory) */
|
if (_top_dir(path)) {
|
||||||
if (strcmp(path, "/") == 0) {
|
|
||||||
if (create)
|
if (create)
|
||||||
return OPENDIR_ERR_PERMISSION_DENIED;
|
return OPENDIR_ERR_PERMISSION_DENIED;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* opendir with '/' (called from 'open_composite_dirs' returns handle
|
||||||
|
* only, VFS root additionally calls 'open_composite_dirs' in order to
|
||||||
|
* open its file systems
|
||||||
|
*/
|
||||||
Dir_vfs_handle *root_handle = new (alloc)
|
Dir_vfs_handle *root_handle = new (alloc)
|
||||||
Dir_vfs_handle(*this, *this, alloc, path);
|
Dir_vfs_handle(*this, *this, alloc, path);
|
||||||
result = open_composite_dirs("/", *root_handle);
|
|
||||||
|
/* the VFS root may contain more file systems */
|
||||||
|
if (_vfs_root)
|
||||||
|
result = open_composite_dirs("/", *root_handle);
|
||||||
|
|
||||||
if (result == OPENDIR_OK) {
|
if (result == OPENDIR_OK) {
|
||||||
*out_handle = root_handle;
|
*out_handle = root_handle;
|
||||||
} else {
|
} else {
|
||||||
@ -622,6 +654,10 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
Dir_vfs_handle *dir_vfs_handle = new (alloc)
|
Dir_vfs_handle *dir_vfs_handle = new (alloc)
|
||||||
Dir_vfs_handle(*this, *this, alloc, path);
|
Dir_vfs_handle(*this, *this, alloc, path);
|
||||||
|
|
||||||
|
/* path equals "/" (for reading the name of this directory) */
|
||||||
|
if (strlen(sub_path) == 0)
|
||||||
|
sub_path = "/";
|
||||||
|
|
||||||
result = open_composite_dirs(sub_path, *dir_vfs_handle);
|
result = open_composite_dirs(sub_path, *dir_vfs_handle);
|
||||||
if (result == OPENDIR_OK) {
|
if (result == OPENDIR_OK) {
|
||||||
*out_handle = dir_vfs_handle;
|
*out_handle = dir_vfs_handle;
|
||||||
@ -740,19 +776,19 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
Dir_vfs_handle *dir_vfs_handle =
|
Dir_vfs_handle *dir_vfs_handle =
|
||||||
static_cast<Dir_vfs_handle*>(vfs_handle);
|
static_cast<Dir_vfs_handle*>(vfs_handle);
|
||||||
|
|
||||||
if (_root())
|
if (_vfs_root)
|
||||||
return _queue_read_of_file_systems(dir_vfs_handle);
|
return _queue_read_of_file_systems(dir_vfs_handle);
|
||||||
|
|
||||||
if (strcmp(dir_vfs_handle->path.base(), "/") == 0)
|
if (_top_dir(dir_vfs_handle->path.base()))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return _queue_read_of_file_systems(dir_vfs_handle);
|
return _queue_read_of_file_systems(dir_vfs_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Read_result complete_read(Vfs_handle *vfs_handle,
|
Read_result complete_read(Vfs_handle *vfs_handle,
|
||||||
char *dst, file_size count,
|
char *dst, file_size count,
|
||||||
file_size &out_count) override
|
file_size &out_count) override
|
||||||
{
|
{
|
||||||
out_count = 0;
|
out_count = 0;
|
||||||
|
|
||||||
if (count < sizeof(Dirent))
|
if (count < sizeof(Dirent))
|
||||||
@ -761,10 +797,10 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
Dir_vfs_handle *dir_vfs_handle =
|
Dir_vfs_handle *dir_vfs_handle =
|
||||||
static_cast<Dir_vfs_handle*>(vfs_handle);
|
static_cast<Dir_vfs_handle*>(vfs_handle);
|
||||||
|
|
||||||
if (_root())
|
if (_vfs_root)
|
||||||
return _complete_read_of_file_systems(dir_vfs_handle, dst, count, out_count);
|
return _complete_read_of_file_systems(dir_vfs_handle, dst, count, out_count);
|
||||||
|
|
||||||
if (strcmp(dir_vfs_handle->path.base(), "/") == 0) {
|
if (_top_dir(dir_vfs_handle->path.base())) {
|
||||||
Dirent *dirent = (Dirent*)dst;
|
Dirent *dirent = (Dirent*)dst;
|
||||||
file_offset index = vfs_handle->seek() / sizeof(Dirent);
|
file_offset index = vfs_handle->seek() / sizeof(Dirent);
|
||||||
|
|
||||||
@ -783,7 +819,7 @@ class Vfs::Dir_file_system : public File_system
|
|||||||
}
|
}
|
||||||
|
|
||||||
return _complete_read_of_file_systems(dir_vfs_handle, dst, count, out_count);
|
return _complete_read_of_file_systems(dir_vfs_handle, dst, count, out_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ftruncate_result ftruncate(Vfs_handle *, file_size) override
|
Ftruncate_result ftruncate(Vfs_handle *, file_size) override
|
||||||
{
|
{
|
||||||
|
@ -157,7 +157,7 @@ struct Cli_monitor::Main
|
|||||||
|
|
||||||
/* initialize virtual file system */
|
/* initialize virtual file system */
|
||||||
Vfs::Dir_file_system _root_dir { _env, _heap, _vfs_config(), io_response_handler,
|
Vfs::Dir_file_system _root_dir { _env, _heap, _vfs_config(), io_response_handler,
|
||||||
_global_file_system_factory };
|
_global_file_system_factory, Vfs::Dir_file_system::Root() };
|
||||||
|
|
||||||
Subsystem_config_registry _subsystem_config_registry { _root_dir, _heap, _env.ep() };
|
Subsystem_config_registry _subsystem_config_registry { _root_dir, _heap, _env.ep() };
|
||||||
|
|
||||||
|
@ -202,7 +202,8 @@ class Fs_report::Root : public Genode::Root_component<Session_component>
|
|||||||
Vfs::Dir_file_system _vfs {
|
Vfs::Dir_file_system _vfs {
|
||||||
_env, _heap, vfs_config(),
|
_env, _heap, vfs_config(),
|
||||||
_io_response_handler,
|
_io_response_handler,
|
||||||
_global_file_system_factory };
|
_global_file_system_factory,
|
||||||
|
Vfs::Dir_file_system::Root() };
|
||||||
|
|
||||||
Genode::Signal_handler<Root> _config_dispatcher {
|
Genode::Signal_handler<Root> _config_dispatcher {
|
||||||
_env.ep(), *this, &Root::_config_update };
|
_env.ep(), *this, &Root::_config_update };
|
||||||
|
@ -678,7 +678,7 @@ class Vfs_server::Root :
|
|||||||
|
|
||||||
Vfs::Dir_file_system _vfs {
|
Vfs::Dir_file_system _vfs {
|
||||||
_env, _vfs_heap, vfs_config(), _io_response_handler,
|
_env, _vfs_heap, vfs_config(), _io_response_handler,
|
||||||
_global_file_system_factory };
|
_global_file_system_factory, Vfs::Dir_file_system::Root() };
|
||||||
|
|
||||||
Genode::Signal_handler<Root> _config_handler {
|
Genode::Signal_handler<Root> _config_handler {
|
||||||
_env.ep(), *this, &Root::_config_update };
|
_env.ep(), *this, &Root::_config_update };
|
||||||
|
@ -533,7 +533,8 @@ void Component::construct(Genode::Env &env)
|
|||||||
|
|
||||||
Vfs::Dir_file_system vfs_root(env, heap, config_xml.sub_node("vfs"),
|
Vfs::Dir_file_system vfs_root(env, heap, config_xml.sub_node("vfs"),
|
||||||
io_response_handler,
|
io_response_handler,
|
||||||
global_file_system_factory);
|
global_file_system_factory,
|
||||||
|
Vfs::Dir_file_system::Root());
|
||||||
|
|
||||||
Vfs::Vfs_handle *vfs_root_handle;
|
Vfs::Vfs_handle *vfs_root_handle;
|
||||||
vfs_root.opendir("/", false, &vfs_root_handle, heap);
|
vfs_root.opendir("/", false, &vfs_root_handle, heap);
|
||||||
|
@ -237,7 +237,8 @@ struct Noux::Main
|
|||||||
|
|
||||||
Vfs::Dir_file_system _root_dir { _env, _heap, _config.xml().sub_node("fstab"),
|
Vfs::Dir_file_system _root_dir { _env, _heap, _config.xml().sub_node("fstab"),
|
||||||
_io_response_handler,
|
_io_response_handler,
|
||||||
_global_file_system_factory };
|
_global_file_system_factory,
|
||||||
|
Vfs::Dir_file_system::Root() };
|
||||||
|
|
||||||
Vfs_handle_context _vfs_handle_context;
|
Vfs_handle_context _vfs_handle_context;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user