diff options
Diffstat (limited to 'Userland/Libraries/LibCore/FileWatcher.h')
-rw-r--r-- | Userland/Libraries/LibCore/FileWatcher.h | 94 |
1 files changed, 79 insertions, 15 deletions
diff --git a/Userland/Libraries/LibCore/FileWatcher.h b/Userland/Libraries/LibCore/FileWatcher.h index 9e8a680397..c2a341afd7 100644 --- a/Userland/Libraries/LibCore/FileWatcher.h +++ b/Userland/Libraries/LibCore/FileWatcher.h @@ -7,54 +7,118 @@ #pragma once +#include <AK/EnumBits.h> #include <AK/Function.h> #include <AK/Noncopyable.h> #include <AK/NonnullRefPtr.h> #include <AK/RefCounted.h> #include <AK/Result.h> #include <AK/String.h> +#include <Kernel/API/InodeWatcherEvent.h> +#include <Kernel/API/InodeWatcherFlags.h> #include <LibCore/Notifier.h> namespace Core { struct FileWatcherEvent { enum class Type { - Modified, - ChildAdded, - ChildRemoved, + Invalid = 0, + MetadataModified = 1 << 0, + ContentModified = 1 << 1, + Deleted = 1 << 2, + ChildCreated = 1 << 3, + ChildDeleted = 1 << 4, }; Type type; - String child_path; + String event_path; }; -class BlockingFileWatcher { +AK_ENUM_BITWISE_OPERATORS(FileWatcherEvent::Type); + +class FileWatcherBase { +public: + virtual ~FileWatcherBase() { } + + Result<bool, String> add_watch(String path, FileWatcherEvent::Type event_mask); + Result<bool, String> remove_watch(String path); + bool is_watching(String const& path) const { return m_path_to_wd.find(path) != m_path_to_wd.end(); } + +protected: + FileWatcherBase(int watcher_fd) + : m_watcher_fd(watcher_fd) + { + } + + int m_watcher_fd { -1 }; + HashMap<String, unsigned> m_path_to_wd; + HashMap<unsigned, String> m_wd_to_path; +}; + +class BlockingFileWatcher final : public FileWatcherBase { AK_MAKE_NONCOPYABLE(BlockingFileWatcher); public: - explicit BlockingFileWatcher(const String& path); + explicit BlockingFileWatcher(InodeWatcherFlags = InodeWatcherFlags::None); ~BlockingFileWatcher(); Optional<FileWatcherEvent> wait_for_event(); - -private: - String m_path; - int m_watcher_fd { -1 }; }; -class FileWatcher : public RefCounted<FileWatcher> { +class FileWatcher final : public FileWatcherBase + , public RefCounted<FileWatcher> { AK_MAKE_NONCOPYABLE(FileWatcher); public: - static Result<NonnullRefPtr<FileWatcher>, String> watch(const String& path); + static Result<NonnullRefPtr<FileWatcher>, String> create(InodeWatcherFlags = InodeWatcherFlags::None); ~FileWatcher(); - Function<void(FileWatcherEvent)> on_change; + Function<void(FileWatcherEvent const&)> on_change; private: - FileWatcher(NonnullRefPtr<Notifier>, const String& path); + FileWatcher(int watcher_fd, NonnullRefPtr<Notifier>); NonnullRefPtr<Notifier> m_notifier; - String m_path; +}; + +} + +namespace AK { + +template<> +struct Formatter<Core::FileWatcherEvent> : Formatter<FormatString> { + void format(FormatBuilder& builder, const Core::FileWatcherEvent& value) + { + Formatter<FormatString>::format(builder, "FileWatcherEvent(\"{}\", {})", value.event_path, value.type); + } +}; + +template<> +struct Formatter<Core::FileWatcherEvent::Type> : Formatter<FormatString> { + void format(FormatBuilder& builder, const Core::FileWatcherEvent::Type& value) + { + char const* type; + switch (value) { + case Core::FileWatcherEvent::Type::ChildCreated: + type = "ChildCreated"; + break; + case Core::FileWatcherEvent::Type::ChildDeleted: + type = "ChildDeleted"; + break; + case Core::FileWatcherEvent::Type::Deleted: + type = "Deleted"; + break; + case Core::FileWatcherEvent::Type::ContentModified: + type = "ContentModified"; + break; + case Core::FileWatcherEvent::Type::MetadataModified: + type = "MetadataModified"; + break; + default: + VERIFY_NOT_REACHED(); + } + + builder.put_string(type); + } }; } |