chromium/content/browser/file_system_access/file_path_watcher/file_path_watcher_inotify.cc

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/file_system_access/file_path_watcher/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_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 "base/types/expected.h"
#include "build/build_config.h"
#include "content/browser/file_system_access/file_path_watcher/file_path_watcher.h"
#include "content/browser/file_system_access/file_path_watcher/file_path_watcher_histogram.h"

namespace content {

namespace {

#if !BUILDFLAG(IS_FUCHSIA)

// The /proc path to max_user_watches.
constexpr char kInotifyMaxUserWatchesPath[] =;

// This is a soft limit. If there are more than |kExpectedFilePathWatches|
// FilePathWatchers for a user, than they might affect each other's inotify
// watchers limit.
constexpr size_t kExpectedFilePathWatchers =;

// The default max inotify watchers limit per user, if reading
// /proc/sys/fs/inotify/max_user_watches fails.
constexpr size_t kDefaultInotifyMaxUserWatches =;

#endif  // !BUILDFLAG(IS_FUCHSIA)

class FilePathWatcherImpl;
class InotifyReader;

// Used by test to override inotify watcher limit.
size_t g_override_max_inotify_watches =;

class InotifyReaderThreadDelegate final
    : public base::PlatformThread::Delegate {};

// Singleton to manage all inotify watches.
// TODO(tony): It would be nice if this wasn't a singleton.
// http://crbug.com/38174
class InotifyReader {};

class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate {};

base::LazyInstance<InotifyReader>::Leaky g_inotify_reader =;

void InotifyReaderThreadDelegate::ThreadMain() {}

InotifyReader::InotifyReader()
    :{}

bool InotifyReader::StartThread() {}

InotifyReader::Watch InotifyReader::AddWatch(const base::FilePath& path,
                                             FilePathWatcherImpl* watcher) {}

void InotifyReader::RemoveWatch(Watch watch, FilePathWatcherImpl* watcher) {}

void InotifyReader::OnInotifyEvent(const inotify_event* event) {}

void InotifyReader::OnInotifyMatchingMoveEvents(
    const inotify_event* moved_from_event,
    const inotify_event* moved_to_event) {}

bool InotifyReader::HasWatches() {}

FilePathWatcherImpl::FilePathWatcherImpl() = default;

FilePathWatcherImpl::~FilePathWatcherImpl() {}

void FilePathWatcherImpl::OnFilePathChanged(
    InotifyReader::Watch fired_watch,
    const base::FilePath::StringType& child_name,
    uint32_t event_mask) {}

void FilePathWatcherImpl::OnFilePathChangedForMoveEvents(
    InotifyReader::Watch moved_from_watch,
    const base::FilePath::StringType& moved_from_child_name,
    InotifyReader::Watch moved_to_watch,
    const base::FilePath::StringType& moved_to_child_name,
    FilePathWatcher::FilePathType file_path_type) {}

base::expected<base::FilePath, FilePathWatcherImpl::ChangeProcessError>
FilePathWatcherImpl::FindChangedPathAndUpdateWatches(
    InotifyReader::Watch fired_watch,
    const base::FilePath::StringType& child,
    FilePathWatcher::FilePathType file_path_type,
    bool created,
    bool deleted) {}

void FilePathWatcherImpl::CancelAndRunCallbackOnExceededLimit() {}

bool FilePathWatcherImpl::WouldExceedWatchLimit() const {}

InotifyReader::WatcherEntry FilePathWatcherImpl::GetWatcherEntry() {}

bool FilePathWatcherImpl::Watch(const base::FilePath& path,
                                Type type,
                                const FilePathWatcher::Callback& callback) {}

bool FilePathWatcherImpl::WatchWithOptions(
    const base::FilePath& path,
    const WatchOptions& options,
    const FilePathWatcher::Callback& callback) {}

bool FilePathWatcherImpl::WatchWithChangeInfo(
    const base::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 base::FilePath& path) {}

void FilePathWatcherImpl::TrackWatchForRecursion(InotifyReader::Watch watch,
                                                 const base::FilePath& path) {}

void FilePathWatcherImpl::RemoveRecursiveWatches() {}

bool FilePathWatcherImpl::AddWatchForBrokenSymlink(const base::FilePath& path,
                                                   WatchEntry* watch_entry) {}

bool FilePathWatcherImpl::HasValidWatchVector() const {}

}  // namespace

size_t GetMaxNumberOfInotifyWatches() {}

ScopedMaxNumberOfInotifyWatchesOverrideForTest::
    ScopedMaxNumberOfInotifyWatchesOverrideForTest(size_t override_max) {}

ScopedMaxNumberOfInotifyWatchesOverrideForTest::
    ~ScopedMaxNumberOfInotifyWatchesOverrideForTest() {}

FilePathWatcher::FilePathWatcher()
    :{}

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// Put inside "BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)" because Android
// includes file_path_watcher_linux.cc.

// static
bool FilePathWatcher::HasWatchesForTest() {}
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)

}  // namespace content