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

#include "base/files/file_path_watcher.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 <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_inotify.h"
#include "base/files/file_util.h"
#include "base/functional/bind.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)

// The /proc path to max_user_watches.
constexpr char kInotifyMaxUserWatchesPath[] =
    "/proc/sys/fs/inotify/max_user_watches";

// 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 = 16u;

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

#endif  // !BUILDFLAG(IS_FUCHSIA)

class FilePathWatcherImpl;
class InotifyReader;

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

class InotifyReaderThreadDelegate final : public PlatformThread::Delegate {
 public:
  explicit InotifyReaderThreadDelegate(int inotify_fd)
      : inotify_fd_(inotify_fd) {}
  InotifyReaderThreadDelegate(const InotifyReaderThreadDelegate&) = delete;
  InotifyReaderThreadDelegate& operator=(const InotifyReaderThreadDelegate&) =
      delete;
  ~InotifyReaderThreadDelegate() override = default;

 private:
  void ThreadMain() override;

  const int inotify_fd_;
};

// Singleton to manage all inotify watches.
// TODO(tony): It would be nice if this wasn't a singleton.
// http://crbug.com/38174
class InotifyReader {
 public:
  // Watch descriptor used by AddWatch() and RemoveWatch().
#if BUILDFLAG(IS_ANDROID)
  using Watch = uint32_t;
#else
  using Watch = int;
#endif

  // Record of watchers tracked for watch descriptors.
  struct WatcherEntry {
    scoped_refptr<SequencedTaskRunner> task_runner;
    WeakPtr<FilePathWatcherImpl> watcher;
  };

  static constexpr Watch kInvalidWatch = static_cast<Watch>(-1);
  static constexpr Watch kWatchLimitExceeded = static_cast<Watch>(-2);

  InotifyReader(const InotifyReader&) = delete;
  InotifyReader& operator=(const InotifyReader&) = delete;

  // Watch directory |path| for changes. |watcher| will be notified on each
  // change. Returns |kInvalidWatch| on failure.
  Watch AddWatch(const FilePath& path, FilePathWatcherImpl* watcher);

  // Remove |watch| if it's valid.
  void RemoveWatch(Watch watch, FilePathWatcherImpl* watcher);

  // Invoked on "inotify_reader" thread to notify relevant watchers.
  void OnInotifyEvent(const inotify_event* event);

  // Returns true if any paths are actively being watched.
  bool HasWatches();

 private:
  friend struct LazyInstanceTraitsBase<InotifyReader>;

  InotifyReader();
  // There is no destructor because |g_inotify_reader| is a
  // base::LazyInstace::Leaky object. Having a destructor causes build
  // issues with GCC 6 (http://crbug.com/636346).

  // Returns true on successful thread creation.
  bool StartThread();

  Lock lock_;

  // Tracks which FilePathWatcherImpls to be notified on which watches.
  // The tracked FilePathWatcherImpl is keyed by raw pointers for fast look up
  // and mapped to a WatchEntry that is used to safely post a notification.
  std::unordered_map<Watch, std::map<FilePathWatcherImpl*, WatcherEntry>>
      watchers_ GUARDED_BY(lock_);

  // File descriptor returned by inotify_init.
  const int inotify_fd_;

  // Thread delegate for the Inotify thread.
  InotifyReaderThreadDelegate thread_delegate_;

  // Flag set to true when startup was successful.
  bool valid_ = false;
};

class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate {
 public:
  FilePathWatcherImpl();
  FilePathWatcherImpl(const FilePathWatcherImpl&) = delete;
  FilePathWatcherImpl& operator=(const FilePathWatcherImpl&) = delete;
  ~FilePathWatcherImpl() override;

  // Called for each event coming from the watch on the original thread.
  // |fired_watch| identifies the watch that fired, |child| indicates what has
  // changed, and is relative to the currently watched path for |fired_watch|.
  //
  // |created| is true if the object appears.
  // |deleted| is true if the object disappears.
  // |is_dir| is true if the object is a directory.
  void OnFilePathChanged(InotifyReader::Watch fired_watch,
                         const FilePath::StringType& child,
                         bool created,
                         bool deleted,
                         bool is_dir);

  // Returns whether the number of inotify watches of this FilePathWatcherImpl
  // would exceed the limit if adding one more.
  bool WouldExceedWatchLimit() const;

  // Returns a WatcherEntry for this, must be called on the original sequence.
  InotifyReader::WatcherEntry GetWatcherEntry();

 private:
  // Start watching |path| for changes and notify |delegate| on each change.
  // Returns true if watch for |path| has been added successfully.
  bool Watch(const FilePath& path,
             Type type,
             const FilePathWatcher::Callback& callback) override;

  // A generalized version. It extends |Type|.
  bool WatchWithOptions(const FilePath& path,
                        const WatchOptions& flags,
                        const FilePathWatcher::Callback& callback) override;

  // Cancel the watch. This unregisters the instance with InotifyReader.
  void Cancel() override;

  // Inotify watches are installed for all directory components of |target_|.
  // A WatchEntry instance holds:
  // - |watch|: the watch descriptor for a component.
  // - |subdir|: the subdirectory that identifies the next component.
  //   - For the last component, there is no next component, so it is empty.
  // - |linkname|: the target of the symlink.
  //   - Only if the target being watched is a symbolic link.
  struct WatchEntry {
    explicit WatchEntry(const FilePath::StringType& dirname)
        : watch(InotifyReader::kInvalidWatch), subdir(dirname) {}

    InotifyReader::Watch watch;
    FilePath::StringType subdir;
    FilePath::StringType linkname;
  };

  // Reconfigure to watch for the most specific parent directory of |target_|
  // that exists. Also calls UpdateRecursiveWatches() below. Returns true if
  // watch limit is not hit. Otherwise, returns false.
  [[nodiscard]] bool UpdateWatches();

  // Reconfigure to recursively watch |target_| and all its sub-directories.
  // - This is a no-op if the watch is not recursive.
  // - If |target_| does not exist, then clear all the recursive watches.
  // - Assuming |target_| exists, passing kInvalidWatch as |fired_watch| forces
  //   addition of recursive watches for |target_|.
  // - Otherwise, only the directory associated with |fired_watch| and its
  //   sub-directories will be reconfigured.
  // Returns true if watch limit is not hit. Otherwise, returns false.
  [[nodiscard]] bool UpdateRecursiveWatches(InotifyReader::Watch fired_watch,
                                            bool is_dir);

  // Enumerate recursively through |path| and add / update watches.
  // Returns true if watch limit is not hit. Otherwise, returns false.
  [[nodiscard]] bool UpdateRecursiveWatchesForPath(const FilePath& path);

  // Do internal bookkeeping to update mappings between |watch| and its
  // associated full path |path|.
  void TrackWatchForRecursion(InotifyReader::Watch watch, const FilePath& path);

  // Remove all the recursive watches.
  void RemoveRecursiveWatches();

  // |path| is a symlink to a non-existent target. Attempt to add a watch to
  // the link target's parent directory. Update |watch_entry| on success.
  // Returns true if watch limit is not hit. Otherwise, returns false.
  [[nodiscard]] bool AddWatchForBrokenSymlink(const FilePath& path,
                                              WatchEntry* watch_entry);

  bool HasValidWatchVector() const;

  // Callback to notify upon changes.
  FilePathWatcher::Callback callback_;

  // The file or directory we're supposed to watch.
  FilePath target_;

  Type type_ = Type::kNonRecursive;
  bool report_modified_path_ = false;

  // The vector of watches and next component names for all path components,
  // starting at the root directory. The last entry corresponds to the watch for
  // |target_| and always stores an empty next component name in |subdir|.
  std::vector<WatchEntry> watches_;

  std::unordered_map<InotifyReader::Watch, FilePath> recursive_paths_by_watch_;
  std::map<FilePath, InotifyReader::Watch> recursive_watches_by_path_;

  WeakPtrFactory<FilePathWatcherImpl> weak_factory_{this};
};

LazyInstance<InotifyReader>::Leaky g_inotify_reader = LAZY_INSTANCE_INITIALIZER;

void InotifyReaderThreadDelegate::ThreadMain() {
  PlatformThread::SetName("inotify_reader");

  std::array<pollfd, 1> fdarray{{{inotify_fd_, POLLIN, 0}}};

  while (true) {
    // Wait until some inotify events are available.
    int poll_result = HANDLE_EINTR(poll(fdarray.data(), fdarray.size(), -1));
    if (poll_result < 0) {
      DPLOG(WARNING) << "poll failed";
      return;
    }

    // Adjust buffer size to current event queue size.
    int buffer_size;
    int ioctl_result = HANDLE_EINTR(ioctl(inotify_fd_, FIONREAD, &buffer_size));

    if (ioctl_result != 0 || buffer_size < 0) {
      DPLOG(WARNING) << "ioctl failed";
      return;
    }

    std::vector<char> buffer(static_cast<size_t>(buffer_size));

    ssize_t bytes_read = HANDLE_EINTR(
        read(inotify_fd_, buffer.data(), static_cast<size_t>(buffer_size)));

    if (bytes_read < 0) {
      DPLOG(WARNING) << "read from inotify fd failed";
      return;
    }

    for (size_t i = 0; i < static_cast<size_t>(bytes_read);) {
      inotify_event* event = reinterpret_cast<inotify_event*>(&buffer[i]);
      size_t event_size = sizeof(inotify_event) + event->len;
      DCHECK(i + event_size <= static_cast<size_t>(bytes_read));
      g_inotify_reader.Get().OnInotifyEvent(event);
      i += event_size;
    }
  }
}

InotifyReader::InotifyReader()
    : inotify_fd_(inotify_init()), thread_delegate_(inotify_fd_) {
  if (inotify_fd_ < 0) {
    PLOG(ERROR) << "inotify_init() failed";
    return;
  }

  if (!StartThread())
    return;

  valid_ = true;
}

bool InotifyReader::StartThread() {
  // This object is LazyInstance::Leaky, so thread_delegate_ will outlive the
  // thread.
  return PlatformThread::CreateNonJoinable(0, &thread_delegate_);
}

InotifyReader::Watch InotifyReader::AddWatch(const FilePath& path,
                                             FilePathWatcherImpl* watcher) {
  if (!valid_)
    return kInvalidWatch;

  if (watcher->WouldExceedWatchLimit())
    return kWatchLimitExceeded;

  AutoLock auto_lock(lock_);

  ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::WILL_BLOCK);
  const int watch_int =
      inotify_add_watch(inotify_fd_, path.value().c_str(),
                        IN_ATTRIB | IN_CREATE | IN_DELETE | IN_CLOSE_WRITE |
                            IN_MOVE | IN_ONLYDIR);
  if (watch_int == -1)
    return kInvalidWatch;
  const Watch watch = static_cast<Watch>(watch_int);

  watchers_[watch].emplace(std::make_pair(watcher, watcher->GetWatcherEntry()));

  return watch;
}

void InotifyReader::RemoveWatch(Watch watch, FilePathWatcherImpl* watcher) {
  if (!valid_ || (watch == kInvalidWatch))
    return;

  AutoLock auto_lock(lock_);

  auto watchers_it = watchers_.find(watch);
  if (watchers_it == watchers_.end())
    return;

  auto& watcher_map = watchers_it->second;
  watcher_map.erase(watcher);

  if (watcher_map.empty()) {
    watchers_.erase(watchers_it);

    ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                            BlockingType::WILL_BLOCK);
    inotify_rm_watch(inotify_fd_, watch);
  }
}

void InotifyReader::OnInotifyEvent(const inotify_event* event) {
  if (event->mask & IN_IGNORED)
    return;

  FilePath::StringType child(event->len ? event->name : FILE_PATH_LITERAL(""));
  AutoLock auto_lock(lock_);

  // In racing conditions, RemoveWatch() could grab `lock_` first and remove
  // the entry for `event->wd`.
  auto watchers_it = watchers_.find(static_cast<Watch>(event->wd));
  if (watchers_it == watchers_.end())
    return;

  auto& watcher_map = watchers_it->second;
  for (const auto& entry : watcher_map) {
    auto& watcher_entry = entry.second;
    watcher_entry.task_runner->PostTask(
        FROM_HERE,
        BindOnce(&FilePathWatcherImpl::OnFilePathChanged, watcher_entry.watcher,
                 static_cast<Watch>(event->wd), child,
                 event->mask & (IN_CREATE | IN_MOVED_TO),
                 event->mask & (IN_DELETE | IN_MOVED_FROM),
                 event->mask & IN_ISDIR));
  }
}

bool InotifyReader::HasWatches() {
  AutoLock auto_lock(lock_);

  return !watchers_.empty();
}

FilePathWatcherImpl::FilePathWatcherImpl() = default;

FilePathWatcherImpl::~FilePathWatcherImpl() {
  DCHECK(!task_runner() || task_runner()->RunsTasksInCurrentSequence());
}

void FilePathWatcherImpl::OnFilePathChanged(InotifyReader::Watch fired_watch,
                                            const FilePath::StringType& child,
                                            bool created,
                                            bool deleted,
                                            bool is_dir) {
  DCHECK(task_runner()->RunsTasksInCurrentSequence());
  DCHECK(!watches_.empty());
  DCHECK(HasValidWatchVector());

  // Used below to avoid multiple recursive updates.
  bool did_update = false;

  // Whether kWatchLimitExceeded is encountered during update.
  bool exceeded_limit = false;

  // Find the entries in |watches_| that correspond to |fired_watch|.
  for (size_t i = 0; i < watches_.size(); ++i) {
    const WatchEntry& watch_entry = watches_[i];
    if (fired_watch != watch_entry.watch)
      continue;

    // Check whether a path component of |target_| changed.
    bool change_on_target_path = child.empty() ||
                                 (child == watch_entry.linkname) ||
                                 (child == watch_entry.subdir);

    // Check if the change references |target_| or a direct child of |target_|.
    bool target_changed;
    if (watch_entry.subdir.empty()) {
      // The fired watch is for a WatchEntry without a subdir. Thus for a given
      // |target_| = "/path/to/foo", this is for "foo". Here, check either:
      // - the target has no symlink: it is the target and it changed.
      // - the target has a symlink, and it matches |child|.
      target_changed =
          (watch_entry.linkname.empty() || child == watch_entry.linkname);
    } else {
      // The fired watch is for a WatchEntry with a subdir. Thus for a given
      // |target_| = "/path/to/foo", this is for {"/", "/path", "/path/to"}.
      // So we can safely access the next WatchEntry since we have not reached
      // the end yet. Check |watch_entry| is for "/path/to", i.e. the next
      // element is "foo".
      bool next_watch_may_be_for_target = watches_[i + 1].subdir.empty();
      if (next_watch_may_be_for_target) {
        // The current |watch_entry| is for "/path/to", so check if the |child|
        // that changed is "foo".
        target_changed = watch_entry.subdir == child;
      } else {
        // The current |watch_entry| is not for "/path/to", so the next entry
        // cannot be "foo". Thus |target_| has not changed.
        target_changed = false;
      }
    }

    // Update watches if a directory component of the |target_| path
    // (dis)appears. Note that we don't add the additional restriction of
    // checking the event mask to see if it is for a directory here as changes
    // to symlinks on the target path will not have IN_ISDIR set in the event
    // masks. As a result we may sometimes call UpdateWatches() unnecessarily.
    if (change_on_target_path && (created || deleted) && !did_update) {
      if (!UpdateWatches()) {
        exceeded_limit = true;
        break;
      }
      did_update = true;
    }

    // Report the following events:
    //  - The target or a direct child of the target got changed (in case the
    //    watched path refers to a directory).
    //  - One of the parent directories got moved or deleted, since the target
    //    disappears in this case.
    //  - One of the parent directories appears. The event corresponding to
    //    the target appearing might have been missed in this case, so recheck.
    if (target_changed || (change_on_target_path && deleted) ||
        (change_on_target_path && created && PathExists(target_))) {
      if (!did_update) {
        if (!UpdateRecursiveWatches(fired_watch, is_dir)) {
          exceeded_limit = true;
          break;
        }
        did_update = true;
      }
      if (report_modified_path_ && !change_on_target_path) {
        callback_.Run(target_.Append(child),
                      /*error=*/false);  // `this` may be deleted.
      } else {
        callback_.Run(target_, /*error=*/false);  // `this` may be deleted.
      }
      return;
    }
  }

  if (!exceeded_limit && Contains(recursive_paths_by_watch_, fired_watch)) {
    if (!did_update) {
      if (!UpdateRecursiveWatches(fired_watch, is_dir))
        exceeded_limit = true;
    }
    if (!exceeded_limit) {
      if (report_modified_path_) {
        callback_.Run(recursive_paths_by_watch_[fired_watch].Append(child),
                      /*error=*/false);  // `this` may be deleted.
      } else {
        callback_.Run(target_, /*error=*/false);  // `this` may be deleted.
      }
      return;
    }
  }

  if (exceeded_limit) {
    // Cancels all in-flight events from inotify thread.
    weak_factory_.InvalidateWeakPtrs();

    // Reset states and cancels all watches.
    auto callback = callback_;
    Cancel();

    // Fires the "error=true" callback.
    callback.Run(target_, /*error=*/true);  // `this` may be deleted.
  }
}

bool FilePathWatcherImpl::WouldExceedWatchLimit() const {
  DCHECK(task_runner()->RunsTasksInCurrentSequence());

  // `watches_` contains inotify watches of all dir components of `target_`.
  // `recursive_paths_by_watch_` contains inotify watches for sub dirs under
  // `target_` of a Type::kRecursive watcher and keyed by inotify watches.
  // All inotify watches used by this FilePathWatcherImpl are either in
  // `watches_` or as a key in `recursive_paths_by_watch_`. As a result, the
  // two provide a good estimate on the number of inofiy watches used by this
  // FilePathWatcherImpl.
  const size_t number_of_inotify_watches =
      watches_.size() + recursive_paths_by_watch_.size();
  return number_of_inotify_watches >= GetMaxNumberOfInotifyWatches();
}

InotifyReader::WatcherEntry FilePathWatcherImpl::GetWatcherEntry() {
  DCHECK(task_runner()->RunsTasksInCurrentSequence());
  return {task_runner(), weak_factory_.GetWeakPtr()};
}

bool FilePathWatcherImpl::Watch(const FilePath& path,
                                Type type,
                                const FilePathWatcher::Callback& callback) {
  DCHECK(target_.empty());

  set_task_runner(SequencedTaskRunner::GetCurrentDefault());
  callback_ = callback;
  target_ = path;
  type_ = type;

  std::vector<FilePath::StringType> comps = target_.GetComponents();
  DCHECK(!comps.empty());
  for (size_t i = 1; i < comps.size(); ++i)
    watches_.emplace_back(comps[i]);
  watches_.emplace_back(FilePath::StringType());

  if (!UpdateWatches()) {
    Cancel();
    // Note `callback` is not invoked since false is returned.
    return false;
  }

  return true;
}

bool FilePathWatcherImpl::WatchWithOptions(
    const FilePath& path,
    const WatchOptions& options,
    const FilePathWatcher::Callback& callback) {
  report_modified_path_ = options.report_modified_path;
  return Watch(path, options.type, callback);
}

void FilePathWatcherImpl::Cancel() {
  if (!callback_) {
    // Watch() was never called.
    set_cancelled();
    return;
  }

  DCHECK(task_runner()->RunsTasksInCurrentSequence());
  DCHECK(!is_cancelled());

  set_cancelled();
  callback_.Reset();

  for (const auto& watch : watches_)
    g_inotify_reader.Get().RemoveWatch(watch.watch, this);
  watches_.clear();
  target_.clear();
  RemoveRecursiveWatches();
}

bool FilePathWatcherImpl::UpdateWatches() {
  // Ensure this runs on the task_runner() exclusively in order to avoid
  // concurrency issues.
  DCHECK(task_runner()->RunsTasksInCurrentSequence());
  DCHECK(HasValidWatchVector());

  // Walk the list of watches and update them as we go.
  FilePath path(FILE_PATH_LITERAL("/"));
  for (WatchEntry& watch_entry : watches_) {
    InotifyReader::Watch old_watch = watch_entry.watch;
    watch_entry.watch = InotifyReader::kInvalidWatch;
    watch_entry.linkname.clear();
    watch_entry.watch = g_inotify_reader.Get().AddWatch(path, this);
    if (watch_entry.watch == InotifyReader::kWatchLimitExceeded)
      return false;
    if (watch_entry.watch == InotifyReader::kInvalidWatch) {
      // Ignore the error code (beyond symlink handling) to attempt to add
      // watches on accessible children of unreadable directories. Note that
      // this is a best-effort attempt; we may not catch events in this
      // scenario.
      if (IsLink(path)) {
        if (!AddWatchForBrokenSymlink(path, &watch_entry))
          return false;
      }
    }
    if (old_watch != watch_entry.watch)
      g_inotify_reader.Get().RemoveWatch(old_watch, this);
    path = path.Append(watch_entry.subdir);
  }

  return UpdateRecursiveWatches(InotifyReader::kInvalidWatch, /*is_dir=*/false);
}

bool FilePathWatcherImpl::UpdateRecursiveWatches(
    InotifyReader::Watch fired_watch,
    bool is_dir) {
  DCHECK(HasValidWatchVector());

  if (type_ != Type::kRecursive)
    return true;

  if (!DirectoryExists(target_)) {
    RemoveRecursiveWatches();
    return true;
  }

  // Check to see if this is a forced update or if some component of |target_|
  // has changed. For these cases, redo the watches for |target_| and below.
  if (!Contains(recursive_paths_by_watch_, fired_watch) &&
      fired_watch != watches_.back().watch) {
    return UpdateRecursiveWatchesForPath(target_);
  }

  // Underneath |target_|, only directory changes trigger watch updates.
  if (!is_dir)
    return true;

  const FilePath& changed_dir = Contains(recursive_paths_by_watch_, fired_watch)
                                    ? recursive_paths_by_watch_[fired_watch]
                                    : target_;

  auto start_it = recursive_watches_by_path_.upper_bound(changed_dir);
  auto end_it = start_it;
  for (; end_it != recursive_watches_by_path_.end(); ++end_it) {
    const FilePath& cur_path = end_it->first;
    if (!changed_dir.IsParent(cur_path))
      break;

    // There could be a race when another process is changing contents under
    // `changed_dir` while chrome is watching (e.g. an Android app updating
    // a dir with Chrome OS file manager open for the dir). In such case,
    // `cur_dir` under `changed_dir` could exist in this loop but not in
    // the FileEnumerator loop in the upcoming UpdateRecursiveWatchesForPath(),
    // As a result, `g_inotify_reader` would have an entry in its `watchers_`
    // pointing to `this` but `this` is no longer aware of that. Crash in
    // http://crbug/990004 could happen later.
    //
    // Remove the watcher of `cur_path` regardless of whether it exists
    // or not to keep `this` and `g_inotify_reader` consistent even when the
    // race happens. The watcher will be added back if `cur_path` exists in
    // the FileEnumerator loop in UpdateRecursiveWatchesForPath().
    g_inotify_reader.Get().RemoveWatch(end_it->second, this);

    // Keep it in sync with |recursive_watches_by_path_| crbug.com/995196.
    recursive_paths_by_watch_.erase(end_it->second);
  }
  recursive_watches_by_path_.erase(start_it, end_it);
  return UpdateRecursiveWatchesForPath(changed_dir);
}

bool FilePathWatcherImpl::UpdateRecursiveWatchesForPath(const FilePath& path) {
  DCHECK_EQ(type_, Type::kRecursive);
  DCHECK(!path.empty());
  DCHECK(DirectoryExists(path));

  // Note: SHOW_SYM_LINKS exposes symlinks as symlinks, so they are ignored
  // rather than followed. Following symlinks can easily lead to the undesirable
  // situation where the entire file system is being watched.
  FileEnumerator enumerator(
      path, true /* recursive enumeration */,
      FileEnumerator::DIRECTORIES | FileEnumerator::SHOW_SYM_LINKS);
  for (FilePath current = enumerator.Next(); !current.empty();
       current = enumerator.Next()) {
    DCHECK(enumerator.GetInfo().IsDirectory());

    if (!Contains(recursive_watches_by_path_, current)) {
      // Add new watches.
      InotifyReader::Watch watch =
          g_inotify_reader.Get().AddWatch(current, this);
      if (watch == InotifyReader::kWatchLimitExceeded)
        return false;
      TrackWatchForRecursion(watch, current);
    } else {
      // Update existing watches.
      InotifyReader::Watch old_watch = recursive_watches_by_path_[current];
      DCHECK_NE(InotifyReader::kInvalidWatch, old_watch);
      InotifyReader::Watch watch =
          g_inotify_reader.Get().AddWatch(current, this);
      if (watch == InotifyReader::kWatchLimitExceeded)
        return false;
      if (watch != old_watch) {
        g_inotify_reader.Get().RemoveWatch(old_watch, this);
        recursive_paths_by_watch_.erase(old_watch);
        recursive_watches_by_path_.erase(current);
        TrackWatchForRecursion(watch, current);
      }
    }
  }
  return true;
}

void FilePathWatcherImpl::TrackWatchForRecursion(InotifyReader::Watch watch,
                                                 const FilePath& path) {
  DCHECK_EQ(type_, Type::kRecursive);
  DCHECK(!path.empty());
  DCHECK(target_.IsParent(path));

  if (watch == InotifyReader::kInvalidWatch)
    return;

  DCHECK(!Contains(recursive_paths_by_watch_, watch));
  DCHECK(!Contains(recursive_watches_by_path_, path));
  recursive_paths_by_watch_[watch] = path;
  recursive_watches_by_path_[path] = watch;
}

void FilePathWatcherImpl::RemoveRecursiveWatches() {
  if (type_ != Type::kRecursive)
    return;

  for (const auto& it : recursive_paths_by_watch_)
    g_inotify_reader.Get().RemoveWatch(it.first, this);

  recursive_paths_by_watch_.clear();
  recursive_watches_by_path_.clear();
}

bool FilePathWatcherImpl::AddWatchForBrokenSymlink(const FilePath& path,
                                                   WatchEntry* watch_entry) {
#if BUILDFLAG(IS_FUCHSIA)
  // Fuchsia does not support symbolic links.
  return false;
#else   // BUILDFLAG(IS_FUCHSIA)
  DCHECK_EQ(InotifyReader::kInvalidWatch, watch_entry->watch);
  absl::optional<FilePath> link = ReadSymbolicLinkAbsolute(path);
  if (!link) {
    return true;
  }
  DCHECK(link->IsAbsolute());

  // Try watching symlink target directory. If the link target is "/", then we
  // shouldn't get here in normal situations and if we do, we'd watch "/" for
  // changes to a component "/" which is harmless so no special treatment of
  // this case is required.
  InotifyReader::Watch watch =
      g_inotify_reader.Get().AddWatch(link->DirName(), this);
  if (watch == InotifyReader::kWatchLimitExceeded)
    return false;
  if (watch == InotifyReader::kInvalidWatch) {
    // TODO(craig) Symlinks only work if the parent directory for the target
    // exist. Ideally we should make sure we've watched all the components of
    // the symlink path for changes. See crbug.com/91561 for details.
    DPLOG(WARNING) << "Watch failed for " << link->DirName().value();
    return true;
  }
  watch_entry->watch = watch;
  watch_entry->linkname = link->BaseName().value();
  return true;
#endif  // BUILDFLAG(IS_FUCHSIA)
}

bool FilePathWatcherImpl::HasValidWatchVector() const {
  if (watches_.empty())
    return false;
  for (size_t i = 0; i < watches_.size() - 1; ++i) {
    if (watches_[i].subdir.empty())
      return false;
  }
  return watches_.back().subdir.empty();
}

}  // namespace

size_t GetMaxNumberOfInotifyWatches() {
#if BUILDFLAG(IS_FUCHSIA)
  // Fuchsia has no limit on the number of watches.
  return std::numeric_limits<int>::max();
#else
  static const size_t max = []() {
    size_t max_number_of_inotify_watches = 0u;

    std::ifstream in(kInotifyMaxUserWatchesPath);
    if (!in.is_open() || !(in >> max_number_of_inotify_watches)) {
      LOG(ERROR) << "Failed to read " << kInotifyMaxUserWatchesPath;
      return kDefaultInotifyMaxUserWatches / kExpectedFilePathWatchers;
    }

    return max_number_of_inotify_watches / kExpectedFilePathWatchers;
  }();
  return g_override_max_inotify_watches ? g_override_max_inotify_watches : max;
#endif  // if BUILDFLAG(IS_FUCHSIA)
}

ScopedMaxNumberOfInotifyWatchesOverrideForTest::
    ScopedMaxNumberOfInotifyWatchesOverrideForTest(size_t override_max) {
  DCHECK_EQ(g_override_max_inotify_watches, 0u);
  g_override_max_inotify_watches = override_max;
}

ScopedMaxNumberOfInotifyWatchesOverrideForTest::
    ~ScopedMaxNumberOfInotifyWatchesOverrideForTest() {
  g_override_max_inotify_watches = 0u;
}

FilePathWatcher::FilePathWatcher()
    : FilePathWatcher(std::make_unique<FilePathWatcherImpl>()) {}

#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() {
  return g_inotify_reader.Get().HasWatches();
}
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)

}  // namespace base
