| Index: base/files/file_path_watcher_linux.cc
|
| diff --git a/base/files/file_path_watcher_linux.cc b/base/files/file_path_watcher_linux.cc
|
| index 4078920aac985a4ea183b14b3bf2014583297197..36ee66c30a716ce5051487cedb8903922b50e20b 100644
|
| --- a/base/files/file_path_watcher_linux.cc
|
| +++ b/base/files/file_path_watcher_linux.cc
|
| @@ -125,10 +125,13 @@ class FilePathWatcherImpl : public FilePathWatcher::PlatformDelegate,
|
| // cleanup thread, in case it quits before Cancel() is called.
|
| void WillDestroyCurrentMessageLoop() override;
|
|
|
| - // Inotify watches are installed for all directory components of |target_|. A
|
| - // WatchEntry instance holds the watch descriptor for a component and the
|
| - // subdirectory for that identifies the next component. If a symbolic link
|
| - // is being watched, the target of the link is also kept.
|
| + // 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),
|
| @@ -381,11 +384,31 @@ void FilePathWatcherImpl::OnFilePathChanged(InotifyReader::Watch fired_watch,
|
| (child == watch_entry.subdir);
|
|
|
| // Check if the change references |target_| or a direct child of |target_|.
|
| - bool is_watch_for_target = watch_entry.subdir.empty();
|
| - bool target_changed =
|
| - (is_watch_for_target && (child == watch_entry.linkname)) ||
|
| - (is_watch_for_target && watch_entry.linkname.empty()) ||
|
| - (watch_entry.subdir == child && watches_[i + 1].subdir.empty());
|
| + 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
|
|
|