summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibCore/FileWatcher.h
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries/LibCore/FileWatcher.h')
-rw-r--r--Userland/Libraries/LibCore/FileWatcher.h94
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);
+ }
};
}