diff --git a/repos/os/src/lib/vfs/rom_file_system.h b/repos/os/src/lib/vfs/rom_file_system.h index 048aaafa4..7143a05e2 100644 --- a/repos/os/src/lib/vfs/rom_file_system.h +++ b/repos/os/src/lib/vfs/rom_file_system.h @@ -15,6 +15,7 @@ #define _INCLUDE__VFS__ROM_FILE_SYSTEM_H_ #include +#include #include namespace Vfs { class Rom_file_system; } @@ -26,13 +27,33 @@ class Vfs::Rom_file_system : public Single_file_system enum Rom_type { ROM_TEXT, ROM_BINARY }; + Genode::Env &_env; + typedef String<64> Label; Label const _label; bool const _binary; - Genode::Attached_rom_dataspace _rom; + Genode::Attached_rom_dataspace _rom { _env, _label.string() }; + + file_size _init_content_size() + { + if (!_binary) + for (file_size pos = 0; pos < _rom.size(); pos++) + if (_rom.local_addr()[pos] == 0x00) + return pos; + + return _rom.size(); + } + + file_size _content_size = _init_content_size(); + + void _update() + { + _rom.update(); + _content_size = _init_content_size(); + } class Rom_vfs_handle : public Single_vfs_handle { @@ -40,18 +61,7 @@ class Vfs::Rom_file_system : public Single_file_system Genode::Attached_rom_dataspace &_rom; - file_size const _content_size; - - file_size _init_content_size(Rom_type type) - { - if (type == ROM_TEXT) { - for (file_size pos = 0; pos < _rom.size(); pos++) - if (_rom.local_addr()[pos] == 0x00) - return pos; - } - - return _rom.size(); - } + file_size const &_content_size; public: @@ -59,10 +69,10 @@ class Vfs::Rom_file_system : public Single_file_system File_io_service &fs, Genode::Allocator &alloc, Genode::Attached_rom_dataspace &rom, - Rom_type type) + file_size const &content_size) : Single_vfs_handle(ds, fs, alloc, 0), - _rom(rom), _content_size(_init_content_size(type)) + _rom(rom), _content_size(content_size) { } Read_result read(char *dst, file_size count, @@ -105,6 +115,20 @@ class Vfs::Rom_file_system : public Single_file_system bool read_ready() override { return true; } }; + typedef Genode::Registered Registered_watch_handle; + typedef Genode::Registry Watch_handle_registry; + + Watch_handle_registry _handle_registry { }; + + void _handle_rom_changed() + { + _handle_registry.for_each([this] (Registered_watch_handle &handle) { + handle.watch_response(); }); + } + + Genode::Constructible> + _rom_changed_handler { }; + public: Rom_file_system(Vfs::Env &env, @@ -112,14 +136,13 @@ class Vfs::Rom_file_system : public Single_file_system : Single_file_system(Node_type::CONTINUOUS_FILE, name(), Node_rwx::ro(), config), + _env(env.env()), /* use 'label' attribute if present, fall back to 'name' if not */ _label(config.attribute_value("label", config.attribute_value("name", Label()))), - _binary(config.attribute_value("binary", true)), - - _rom(env.env(), _label.string()) + _binary(config.attribute_value("binary", true)) { } static char const *name() { return "rom"; } @@ -136,11 +159,11 @@ class Vfs::Rom_file_system : public Single_file_system if (!_single_file(path)) return OPEN_ERR_UNACCESSIBLE; - _rom.update(); + _update(); try { *out_handle = new (alloc) - Rom_vfs_handle(*this, *this, alloc, _rom, _binary ? ROM_BINARY : ROM_TEXT); + Rom_vfs_handle(*this, *this, alloc, _rom, _content_size); return OPEN_OK; } catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } @@ -166,8 +189,8 @@ class Vfs::Rom_file_system : public Single_file_system * version. */ if (out.type == Node_type::CONTINUOUS_FILE) { - _rom.update(); - out.size = _rom.valid() ? _rom.size() : 0; + _update(); + out.size = _content_size; out.rwx = { .readable = true, .writeable = false, .executable = true }; @@ -175,6 +198,34 @@ class Vfs::Rom_file_system : public Single_file_system return result; } + + Watch_result watch(char const *path, + Vfs_watch_handle **handle, + Allocator &alloc) override + { + if (!_single_file(path)) + return WATCH_ERR_UNACCESSIBLE; + + if (!_rom_changed_handler.constructed()) { + _rom_changed_handler.construct(_env.ep(), *this, + &Rom_file_system::_handle_rom_changed); + _rom.sigh(*_rom_changed_handler); + } + + try { + *handle = new (alloc) + Registered_watch_handle(_handle_registry, *this, alloc); + return WATCH_OK; + } + catch (Genode::Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } + catch (Genode::Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } + } + + void close(Vfs_watch_handle *handle) override + { + Genode::destroy(handle->alloc(), + static_cast(handle)); + } }; #endif /* _INCLUDE__VFS__ROM_FILE_SYSTEM_H_ */