#include "base/files/file_path_watcher_inotify.h"
#include <errno.h>
#include <poll.h>
#include <stddef.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <unistd.h>
#include <algorithm>
#include <array>
#include <fstream>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <unordered_map>
#include <utility>
#include <vector>
#include "base/containers/contains.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_path_watcher.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/posix/eintr_wrapper.h"
#include "base/synchronization/lock.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/platform_thread.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/trace_event/base_tracing.h"
#include "build/build_config.h"
namespace base {
namespace {
#if !BUILDFLAG(IS_FUCHSIA)
constexpr char kInotifyMaxUserWatchesPath[] = …;
constexpr size_t kExpectedFilePathWatchers = …;
constexpr size_t kDefaultInotifyMaxUserWatches = …;
#endif
class FilePathWatcherImpl;
class InotifyReader;
size_t g_override_max_inotify_watches = …;
FilePathWatcher::ChangeType ToChangeType(const inotify_event* const event) { … }
class InotifyReaderThreadDelegate final : public PlatformThread::Delegate { … };
class InotifyReader { … };
class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate { … };
LazyInstance<InotifyReader>::Leaky g_inotify_reader = …;
void InotifyReaderThreadDelegate::ThreadMain() { … }
InotifyReader::InotifyReader()
: … { … }
bool InotifyReader::StartThread() { … }
InotifyReader::Watch InotifyReader::AddWatch(const FilePath& path,
FilePathWatcherImpl* watcher) { … }
void InotifyReader::RemoveWatch(Watch watch, FilePathWatcherImpl* watcher) { … }
void InotifyReader::OnInotifyEvent(const inotify_event* event) { … }
bool InotifyReader::HasWatches() { … }
FilePathWatcherImpl::FilePathWatcherImpl() = default;
FilePathWatcherImpl::~FilePathWatcherImpl() { … }
void FilePathWatcherImpl::OnFilePathChanged(
InotifyReader::Watch fired_watch,
const FilePath::StringType& child,
FilePathWatcher::ChangeInfo change_info,
bool created,
bool deleted) { … }
bool FilePathWatcherImpl::WouldExceedWatchLimit() const { … }
InotifyReader::WatcherEntry FilePathWatcherImpl::GetWatcherEntry() { … }
bool FilePathWatcherImpl::Watch(const FilePath& path,
Type type,
const FilePathWatcher::Callback& callback) { … }
bool FilePathWatcherImpl::WatchWithOptions(
const FilePath& path,
const WatchOptions& options,
const FilePathWatcher::Callback& callback) { … }
bool FilePathWatcherImpl::WatchWithChangeInfo(
const FilePath& path,
const WatchOptions& options,
const FilePathWatcher::CallbackWithChangeInfo& callback) { … }
void FilePathWatcherImpl::Cancel() { … }
bool FilePathWatcherImpl::UpdateWatches() { … }
bool FilePathWatcherImpl::UpdateRecursiveWatches(
InotifyReader::Watch fired_watch,
bool is_dir) { … }
bool FilePathWatcherImpl::UpdateRecursiveWatchesForPath(const FilePath& path) { … }
void FilePathWatcherImpl::TrackWatchForRecursion(InotifyReader::Watch watch,
const FilePath& path) { … }
void FilePathWatcherImpl::RemoveRecursiveWatches() { … }
bool FilePathWatcherImpl::AddWatchForBrokenSymlink(const FilePath& path,
WatchEntry* watch_entry) { … }
bool FilePathWatcherImpl::HasValidWatchVector() const { … }
}
size_t GetMaxNumberOfInotifyWatches() { … }
ScopedMaxNumberOfInotifyWatchesOverrideForTest::
ScopedMaxNumberOfInotifyWatchesOverrideForTest(size_t override_max) { … }
ScopedMaxNumberOfInotifyWatchesOverrideForTest::
~ScopedMaxNumberOfInotifyWatchesOverrideForTest() { … }
FilePathWatcher::FilePathWatcher()
: … { … }
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
bool FilePathWatcher::HasWatchesForTest() { … }
#endif
}