FileWatcher.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
  3. * Copyright (c) 2021, the SerenityOS developers.
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #pragma once
  8. #include <AK/EnumBits.h>
  9. #include <AK/Function.h>
  10. #include <AK/Noncopyable.h>
  11. #include <AK/NonnullRefPtr.h>
  12. #include <AK/RefCounted.h>
  13. #include <AK/Result.h>
  14. #include <AK/String.h>
  15. #include <Kernel/API/InodeWatcherEvent.h>
  16. #include <Kernel/API/InodeWatcherFlags.h>
  17. #include <LibCore/Notifier.h>
  18. namespace Core {
  19. struct FileWatcherEvent {
  20. enum class Type {
  21. Invalid = 0,
  22. MetadataModified = 1 << 0,
  23. ContentModified = 1 << 1,
  24. Deleted = 1 << 2,
  25. ChildCreated = 1 << 3,
  26. ChildDeleted = 1 << 4,
  27. };
  28. Type type;
  29. String event_path;
  30. };
  31. AK_ENUM_BITWISE_OPERATORS(FileWatcherEvent::Type);
  32. class FileWatcherBase {
  33. public:
  34. virtual ~FileWatcherBase() { }
  35. Result<bool, String> add_watch(String path, FileWatcherEvent::Type event_mask);
  36. Result<bool, String> remove_watch(String path);
  37. bool is_watching(String const& path) const { return m_path_to_wd.find(path) != m_path_to_wd.end(); }
  38. protected:
  39. FileWatcherBase(int watcher_fd)
  40. : m_watcher_fd(watcher_fd)
  41. {
  42. }
  43. int m_watcher_fd { -1 };
  44. HashMap<String, unsigned> m_path_to_wd;
  45. HashMap<unsigned, String> m_wd_to_path;
  46. };
  47. class BlockingFileWatcher final : public FileWatcherBase {
  48. AK_MAKE_NONCOPYABLE(BlockingFileWatcher);
  49. public:
  50. explicit BlockingFileWatcher(InodeWatcherFlags = InodeWatcherFlags::None);
  51. ~BlockingFileWatcher();
  52. Optional<FileWatcherEvent> wait_for_event();
  53. };
  54. class FileWatcher final : public FileWatcherBase
  55. , public RefCounted<FileWatcher> {
  56. AK_MAKE_NONCOPYABLE(FileWatcher);
  57. public:
  58. static Result<NonnullRefPtr<FileWatcher>, String> create(InodeWatcherFlags = InodeWatcherFlags::None);
  59. ~FileWatcher();
  60. Function<void(FileWatcherEvent const&)> on_change;
  61. private:
  62. FileWatcher(int watcher_fd, NonnullRefPtr<Notifier>);
  63. NonnullRefPtr<Notifier> m_notifier;
  64. };
  65. }
  66. namespace AK {
  67. template<>
  68. struct Formatter<Core::FileWatcherEvent> : Formatter<FormatString> {
  69. void format(FormatBuilder& builder, const Core::FileWatcherEvent& value)
  70. {
  71. Formatter<FormatString>::format(builder, "FileWatcherEvent(\"{}\", {})", value.event_path, value.type);
  72. }
  73. };
  74. template<>
  75. struct Formatter<Core::FileWatcherEvent::Type> : Formatter<FormatString> {
  76. void format(FormatBuilder& builder, const Core::FileWatcherEvent::Type& value)
  77. {
  78. char const* type;
  79. switch (value) {
  80. case Core::FileWatcherEvent::Type::ChildCreated:
  81. type = "ChildCreated";
  82. break;
  83. case Core::FileWatcherEvent::Type::ChildDeleted:
  84. type = "ChildDeleted";
  85. break;
  86. case Core::FileWatcherEvent::Type::Deleted:
  87. type = "Deleted";
  88. break;
  89. case Core::FileWatcherEvent::Type::ContentModified:
  90. type = "ContentModified";
  91. break;
  92. case Core::FileWatcherEvent::Type::MetadataModified:
  93. type = "MetadataModified";
  94. break;
  95. default:
  96. VERIFY_NOT_REACHED();
  97. }
  98. builder.put_string(type);
  99. }
  100. };
  101. }