LibCore+ConfigServer: Add FileWatcherFlags to replace InodeWatcherFlags

InodeWatcherFlags is an enumeration from the Kernel. To avoid using it
outside of Serenity, add a FileWatcherFlags for FileWatcher, much like
we already have FileWatcherEvent::Type.
This commit is contained in:
Timothy Flynn 2023-01-18 08:54:39 -05:00 committed by Tim Flynn
parent 98e6dbf50a
commit 142abc0b2e
5 changed files with 33 additions and 17 deletions

View file

@ -13,8 +13,6 @@
#include <AK/Noncopyable.h>
#include <AK/NonnullRefPtr.h>
#include <AK/RefCounted.h>
#include <Kernel/API/InodeWatcherEvent.h>
#include <Kernel/API/InodeWatcherFlags.h>
#include <LibCore/Notifier.h>
namespace Core {
@ -34,6 +32,14 @@ struct FileWatcherEvent {
AK_ENUM_BITWISE_OPERATORS(FileWatcherEvent::Type);
enum class FileWatcherFlags : u32 {
None = 0,
Nonblock = 1 << 0,
CloseOnExec = 1 << 1,
};
AK_ENUM_BITWISE_OPERATORS(FileWatcherFlags);
class FileWatcherBase {
public:
virtual ~FileWatcherBase() = default;
@ -57,7 +63,7 @@ class BlockingFileWatcher final : public FileWatcherBase {
AK_MAKE_NONCOPYABLE(BlockingFileWatcher);
public:
explicit BlockingFileWatcher(InodeWatcherFlags = InodeWatcherFlags::None);
explicit BlockingFileWatcher(FileWatcherFlags = FileWatcherFlags::None);
~BlockingFileWatcher();
Optional<FileWatcherEvent> wait_for_event();
@ -68,7 +74,7 @@ class FileWatcher final : public FileWatcherBase
AK_MAKE_NONCOPYABLE(FileWatcher);
public:
static ErrorOr<NonnullRefPtr<FileWatcher>> create(InodeWatcherFlags = InodeWatcherFlags::None);
static ErrorOr<NonnullRefPtr<FileWatcher>> create(FileWatcherFlags = FileWatcherFlags::None);
~FileWatcher();
Function<void(FileWatcherEvent const&)> on_change;

View file

@ -8,7 +8,6 @@
#include <AK/Debug.h>
#include <AK/DeprecatedString.h>
#include <AK/LexicalPath.h>
#include <Kernel/API/InodeWatcherFlags.h>
#include <LibCore/Notifier.h>
#include <errno.h>
#include <limits.h>
@ -23,13 +22,13 @@ static_assert(false, "This file must only be used for Linux");
namespace Core {
static constexpr unsigned inode_watcher_flags_to_inotify_flags(InodeWatcherFlags flags)
static constexpr unsigned file_watcher_flags_to_inotify_flags(FileWatcherFlags flags)
{
unsigned result = 0;
if ((flags & InodeWatcherFlags::Nonblock) != InodeWatcherFlags::None)
if (has_flag(flags, FileWatcherFlags::Nonblock))
result |= IN_NONBLOCK;
if ((flags & InodeWatcherFlags::CloseOnExec) != InodeWatcherFlags::None)
if (has_flag(flags, FileWatcherFlags::CloseOnExec))
result |= IN_CLOEXEC;
return result;
@ -92,9 +91,9 @@ static Optional<FileWatcherEvent> get_event_from_fd(int fd, HashMap<unsigned, De
return result;
}
ErrorOr<NonnullRefPtr<FileWatcher>> FileWatcher::create(InodeWatcherFlags flags)
ErrorOr<NonnullRefPtr<FileWatcher>> FileWatcher::create(FileWatcherFlags flags)
{
auto watcher_fd = ::inotify_init1(inode_watcher_flags_to_inotify_flags(flags | InodeWatcherFlags::CloseOnExec));
auto watcher_fd = ::inotify_init1(file_watcher_flags_to_inotify_flags(flags | FileWatcherFlags::CloseOnExec));
if (watcher_fd < 0)
return Error::from_errno(errno);

View file

@ -24,6 +24,18 @@ static_assert(false, "This file must only be used for SerenityOS");
namespace Core {
static constexpr unsigned file_watcher_flags_to_inode_watcher_flags(FileWatcherFlags flags)
{
auto result = InodeWatcherFlags::None;
if (has_flag(flags, FileWatcherFlags::Nonblock))
result |= InodeWatcherFlags::Nonblock;
if (has_flag(flags, FileWatcherFlags::CloseOnExec))
result |= InodeWatcherFlags::CloseOnExec;
return static_cast<unsigned>(result);
}
static Optional<FileWatcherEvent> get_event_from_fd(int fd, HashMap<unsigned, DeprecatedString> const& wd_to_path)
{
u8 buffer[MAXIMUM_EVENT_SIZE];
@ -139,8 +151,8 @@ ErrorOr<bool> FileWatcherBase::remove_watch(DeprecatedString path)
return true;
}
BlockingFileWatcher::BlockingFileWatcher(InodeWatcherFlags flags)
: FileWatcherBase(create_inode_watcher(static_cast<unsigned>(flags)))
BlockingFileWatcher::BlockingFileWatcher(FileWatcherFlags flags)
: FileWatcherBase(create_inode_watcher(file_watcher_flags_to_inode_watcher_flags(flags)))
{
VERIFY(m_watcher_fd != -1);
dbgln_if(FILE_WATCHER_DEBUG, "BlockingFileWatcher created with InodeWatcher {}", m_watcher_fd);
@ -170,9 +182,9 @@ Optional<FileWatcherEvent> BlockingFileWatcher::wait_for_event()
return event;
}
ErrorOr<NonnullRefPtr<FileWatcher>> FileWatcher::create(InodeWatcherFlags flags)
ErrorOr<NonnullRefPtr<FileWatcher>> FileWatcher::create(FileWatcherFlags flags)
{
auto watcher_fd = create_inode_watcher(static_cast<unsigned>(flags | InodeWatcherFlags::CloseOnExec));
auto watcher_fd = create_inode_watcher(file_watcher_flags_to_inode_watcher_flags(flags | FileWatcherFlags::CloseOnExec));
if (watcher_fd < 0)
return Error::from_errno(errno);

View file

@ -6,13 +6,12 @@
*/
#include "FileWatcher.h"
#include <Kernel/API/InodeWatcherFlags.h>
#include <LibCore/Notifier.h>
#include <errno.h>
namespace Core {
ErrorOr<NonnullRefPtr<FileWatcher>> FileWatcher::create(InodeWatcherFlags)
ErrorOr<NonnullRefPtr<FileWatcher>> FileWatcher::create(FileWatcherFlags)
{
return Error::from_errno(ENOTSUP);
}

View file

@ -39,7 +39,7 @@ static Core::ConfigFile& ensure_domain_config(DeprecatedString const& domain)
auto config = Core::ConfigFile::open_for_app(domain, Core::ConfigFile::AllowWriting::Yes).release_value_but_fixme_should_propagate_errors();
// FIXME: Use a single FileWatcher with multiple watches inside.
auto watcher_or_error = Core::FileWatcher::create(InodeWatcherFlags::Nonblock);
auto watcher_or_error = Core::FileWatcher::create(Core::FileWatcherFlags::Nonblock);
VERIFY(!watcher_or_error.is_error());
auto result = watcher_or_error.value()->add_watch(config->filename(), Core::FileWatcherEvent::Type::ContentModified);
VERIFY(!result.is_error());