/* * Copyright (c) 2018-2020, Andreas Kling * Copyright (c) 2021, sin-ack * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #include namespace Kernel { // A specific description of a watch. struct WatchDescription { int wd; Inode& inode; unsigned event_mask; static ErrorOr> create(int wd, Inode& inode, unsigned event_mask) { return adopt_nonnull_own_or_enomem(new (nothrow) WatchDescription(wd, inode, event_mask)); } private: WatchDescription(int wd, Inode& inode, unsigned event_mask) : wd(wd) , inode(inode) , event_mask(event_mask) { } }; class InodeWatcher final : public File { public: static ErrorOr> try_create(); virtual ~InodeWatcher() override; virtual bool can_read(OpenFileDescription const&, u64) const override; virtual ErrorOr read(OpenFileDescription&, u64, UserOrKernelBuffer&, size_t) override; // Can't write to an inode watcher. virtual bool can_write(OpenFileDescription const&, u64) const override { return true; } virtual ErrorOr write(OpenFileDescription&, u64, UserOrKernelBuffer const&, size_t) override { return EIO; } virtual ErrorOr close() override; virtual ErrorOr> pseudo_path(OpenFileDescription const&) const override; virtual StringView class_name() const override { return "InodeWatcher"sv; }; virtual bool is_inode_watcher() const override { return true; } void notify_inode_event(Badge, InodeIdentifier, InodeWatcherEvent::Type, StringView name = {}); ErrorOr register_inode(Inode&, unsigned event_mask); ErrorOr unregister_by_wd(int); void unregister_by_inode(Badge, InodeIdentifier); private: explicit InodeWatcher() { } mutable Mutex m_lock; struct Event { int wd { 0 }; InodeWatcherEvent::Type type { InodeWatcherEvent::Type::Invalid }; OwnPtr path; }; CircularQueue m_queue; Checked m_wd_counter { 1 }; // NOTE: These two hashmaps provide two different ways of reaching the same // watch description, so they will overlap. HashMap> m_wd_to_watches; HashMap m_inode_to_watches; }; }