FileWatcher.h 3.1 KB

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