mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +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),
|
||||
_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 };
|
||||
|
||||
struct Root { };
|
||||
|
||||
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 Subdir_handle_element;
|
||||
@ -92,7 +101,10 @@ class Vfs::Dir_file_system : public File_system
|
||||
*/
|
||||
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
|
||||
@ -165,10 +177,10 @@ class Vfs::Dir_file_system : public File_system
|
||||
char const *_sub_path(char const *path) const
|
||||
{
|
||||
/* do not strip anything from the path when we are root */
|
||||
if (_root())
|
||||
if (_vfs_root)
|
||||
return path;
|
||||
|
||||
if (strcmp(path, "/") == 0)
|
||||
if (_top_dir(path))
|
||||
return path;
|
||||
|
||||
/* 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));
|
||||
}
|
||||
|
||||
/* adjust base index for next file system */
|
||||
base += fs_num_dirent;
|
||||
};
|
||||
|
||||
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,
|
||||
File_system_factory &fs_factory)
|
||||
:
|
||||
_vfs_root(false),
|
||||
_first_file_system(0)
|
||||
{
|
||||
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 **
|
||||
@ -384,7 +409,7 @@ class Vfs::Dir_file_system : public File_system
|
||||
* If path equals directory name, return information about the
|
||||
* current directory.
|
||||
*/
|
||||
if (strlen(path) == 0 || (strcmp(path, "/") == 0)) {
|
||||
if (strlen(path) == 0 || _top_dir(path)) {
|
||||
out.size = 0;
|
||||
out.mode = STAT_MODE_DIRECTORY | 0755;
|
||||
out.uid = 0;
|
||||
@ -415,12 +440,12 @@ class Vfs::Dir_file_system : public File_system
|
||||
|
||||
file_size num_dirent(char const *path) override
|
||||
{
|
||||
if (_root()) {
|
||||
if (_vfs_root) {
|
||||
return _sum_dirents_of_file_systems(path);
|
||||
|
||||
} else {
|
||||
|
||||
if (strcmp(path, "/") == 0)
|
||||
if (_top_dir(path))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
@ -444,7 +469,7 @@ class Vfs::Dir_file_system : public File_system
|
||||
*/
|
||||
bool directory(char const *path) override
|
||||
{
|
||||
if (strcmp(path, "/") == 0)
|
||||
if (_top_dir(path))
|
||||
return true;
|
||||
|
||||
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,
|
||||
Dir_vfs_handle &dir_vfs_handle)
|
||||
{
|
||||
Opendir_result result = OPENDIR_OK;
|
||||
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;
|
||||
|
||||
Opendir_result r = fs->opendir(
|
||||
@ -556,9 +580,7 @@ class Vfs::Dir_file_system : public File_system
|
||||
case OPENDIR_OK:
|
||||
break;
|
||||
case OPENDIR_ERR_LOOKUP_FAILED:
|
||||
continue;
|
||||
default:
|
||||
result = r; /* loop will break */
|
||||
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_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
|
||||
return result;
|
||||
|
||||
return OPENDIR_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* path equals "/" (for reading the name of this directory) */
|
||||
if (strcmp(path, "/") == 0) {
|
||||
if (_top_dir(path)) {
|
||||
if (create)
|
||||
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(*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) {
|
||||
*out_handle = root_handle;
|
||||
} else {
|
||||
@ -622,6 +654,10 @@ class Vfs::Dir_file_system : public File_system
|
||||
Dir_vfs_handle *dir_vfs_handle = new (alloc)
|
||||
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);
|
||||
if (result == OPENDIR_OK) {
|
||||
*out_handle = dir_vfs_handle;
|
||||
@ -740,19 +776,19 @@ class Vfs::Dir_file_system : public File_system
|
||||
Dir_vfs_handle *dir_vfs_handle =
|
||||
static_cast<Dir_vfs_handle*>(vfs_handle);
|
||||
|
||||
if (_root())
|
||||
if (_vfs_root)
|
||||
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 _queue_read_of_file_systems(dir_vfs_handle);
|
||||
}
|
||||
|
||||
Read_result complete_read(Vfs_handle *vfs_handle,
|
||||
char *dst, file_size count,
|
||||
file_size &out_count) override
|
||||
{
|
||||
char *dst, file_size count,
|
||||
file_size &out_count) override
|
||||
{
|
||||
out_count = 0;
|
||||
|
||||
if (count < sizeof(Dirent))
|
||||
@ -761,10 +797,10 @@ class Vfs::Dir_file_system : public File_system
|
||||
Dir_vfs_handle *dir_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);
|
||||
|
||||
if (strcmp(dir_vfs_handle->path.base(), "/") == 0) {
|
||||
if (_top_dir(dir_vfs_handle->path.base())) {
|
||||
Dirent *dirent = (Dirent*)dst;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Ftruncate_result ftruncate(Vfs_handle *, file_size) override
|
||||
{
|
||||
|
@ -157,7 +157,7 @@ struct Cli_monitor::Main
|
||||
|
||||
/* initialize virtual file system */
|
||||
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() };
|
||||
|
||||
|
@ -202,7 +202,8 @@ class Fs_report::Root : public Genode::Root_component<Session_component>
|
||||
Vfs::Dir_file_system _vfs {
|
||||
_env, _heap, vfs_config(),
|
||||
_io_response_handler,
|
||||
_global_file_system_factory };
|
||||
_global_file_system_factory,
|
||||
Vfs::Dir_file_system::Root() };
|
||||
|
||||
Genode::Signal_handler<Root> _config_dispatcher {
|
||||
_env.ep(), *this, &Root::_config_update };
|
||||
|
@ -678,7 +678,7 @@ class Vfs_server::Root :
|
||||
|
||||
Vfs::Dir_file_system _vfs {
|
||||
_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 {
|
||||
_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"),
|
||||
io_response_handler,
|
||||
global_file_system_factory);
|
||||
global_file_system_factory,
|
||||
Vfs::Dir_file_system::Root());
|
||||
|
||||
Vfs::Vfs_handle *vfs_root_handle;
|
||||
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"),
|
||||
_io_response_handler,
|
||||
_global_file_system_factory };
|
||||
_global_file_system_factory,
|
||||
Vfs::Dir_file_system::Root() };
|
||||
|
||||
Vfs_handle_context _vfs_handle_context;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user