Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: base/files/file_path_watcher_linux.cc

Issue 822713002: Update from https://crrev.com/309415 (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/files/file_path_watcher.h" 5 #include "base/files/file_path_watcher.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <string.h> 8 #include <string.h>
9 #include <sys/inotify.h> 9 #include <sys/inotify.h>
10 #include <sys/ioctl.h> 10 #include <sys/ioctl.h>
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 void Cancel() override; 118 void Cancel() override;
119 119
120 // Cleans up and stops observing the message_loop() thread. 120 // Cleans up and stops observing the message_loop() thread.
121 void CancelOnMessageLoopThread() override; 121 void CancelOnMessageLoopThread() override;
122 122
123 // Deletion of the FilePathWatcher will call Cancel() to dispose of this 123 // Deletion of the FilePathWatcher will call Cancel() to dispose of this
124 // object in the right thread. This also observes destruction of the required 124 // object in the right thread. This also observes destruction of the required
125 // cleanup thread, in case it quits before Cancel() is called. 125 // cleanup thread, in case it quits before Cancel() is called.
126 void WillDestroyCurrentMessageLoop() override; 126 void WillDestroyCurrentMessageLoop() override;
127 127
128 // Inotify watches are installed for all directory components of |target_|. A 128 // Inotify watches are installed for all directory components of |target_|.
129 // WatchEntry instance holds the watch descriptor for a component and the 129 // A WatchEntry instance holds:
130 // subdirectory for that identifies the next component. If a symbolic link 130 // - |watch|: the watch descriptor for a component.
131 // is being watched, the target of the link is also kept. 131 // - |subdir|: the subdirectory that identifies the next component.
132 // - For the last component, there is no next component, so it is empty.
133 // - |linkname|: the target of the symlink.
134 // - Only if the target being watched is a symbolic link.
132 struct WatchEntry { 135 struct WatchEntry {
133 explicit WatchEntry(const FilePath::StringType& dirname) 136 explicit WatchEntry(const FilePath::StringType& dirname)
134 : watch(InotifyReader::kInvalidWatch), 137 : watch(InotifyReader::kInvalidWatch),
135 subdir(dirname) {} 138 subdir(dirname) {}
136 139
137 InotifyReader::Watch watch; 140 InotifyReader::Watch watch;
138 FilePath::StringType subdir; 141 FilePath::StringType subdir;
139 FilePath::StringType linkname; 142 FilePath::StringType linkname;
140 }; 143 };
141 typedef std::vector<WatchEntry> WatchVector; 144 typedef std::vector<WatchEntry> WatchVector;
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 if (fired_watch != watch_entry.watch) 377 if (fired_watch != watch_entry.watch)
375 continue; 378 continue;
376 379
377 // Check whether a path component of |target_| changed. 380 // Check whether a path component of |target_| changed.
378 bool change_on_target_path = 381 bool change_on_target_path =
379 child.empty() || 382 child.empty() ||
380 (child == watch_entry.linkname) || 383 (child == watch_entry.linkname) ||
381 (child == watch_entry.subdir); 384 (child == watch_entry.subdir);
382 385
383 // Check if the change references |target_| or a direct child of |target_|. 386 // Check if the change references |target_| or a direct child of |target_|.
384 bool is_watch_for_target = watch_entry.subdir.empty(); 387 bool target_changed;
385 bool target_changed = 388 if (watch_entry.subdir.empty()) {
386 (is_watch_for_target && (child == watch_entry.linkname)) || 389 // The fired watch is for a WatchEntry without a subdir. Thus for a given
387 (is_watch_for_target && watch_entry.linkname.empty()) || 390 // |target_| = "/path/to/foo", this is for "foo". Here, check either:
388 (watch_entry.subdir == child && watches_[i + 1].subdir.empty()); 391 // - the target has no symlink: it is the target and it changed.
392 // - the target has a symlink, and it matches |child|.
393 target_changed = (watch_entry.linkname.empty() ||
394 child == watch_entry.linkname);
395 } else {
396 // The fired watch is for a WatchEntry with a subdir. Thus for a given
397 // |target_| = "/path/to/foo", this is for {"/", "/path", "/path/to"}.
398 // So we can safely access the next WatchEntry since we have not reached
399 // the end yet. Check |watch_entry| is for "/path/to", i.e. the next
400 // element is "foo".
401 bool next_watch_may_be_for_target = watches_[i + 1].subdir.empty();
402 if (next_watch_may_be_for_target) {
403 // The current |watch_entry| is for "/path/to", so check if the |child|
404 // that changed is "foo".
405 target_changed = watch_entry.subdir == child;
406 } else {
407 // The current |watch_entry| is not for "/path/to", so the next entry
408 // cannot be "foo". Thus |target_| has not changed.
409 target_changed = false;
410 }
411 }
389 412
390 // Update watches if a directory component of the |target_| path 413 // Update watches if a directory component of the |target_| path
391 // (dis)appears. Note that we don't add the additional restriction of 414 // (dis)appears. Note that we don't add the additional restriction of
392 // checking the event mask to see if it is for a directory here as changes 415 // checking the event mask to see if it is for a directory here as changes
393 // to symlinks on the target path will not have IN_ISDIR set in the event 416 // to symlinks on the target path will not have IN_ISDIR set in the event
394 // masks. As a result we may sometimes call UpdateWatches() unnecessarily. 417 // masks. As a result we may sometimes call UpdateWatches() unnecessarily.
395 if (change_on_target_path && (created || deleted) && !did_update) { 418 if (change_on_target_path && (created || deleted) && !did_update) {
396 UpdateWatches(); 419 UpdateWatches();
397 did_update = true; 420 did_update = true;
398 } 421 }
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 return watches_[watches_.size() - 1].subdir.empty(); 683 return watches_[watches_.size() - 1].subdir.empty();
661 } 684 }
662 685
663 } // namespace 686 } // namespace
664 687
665 FilePathWatcher::FilePathWatcher() { 688 FilePathWatcher::FilePathWatcher() {
666 impl_ = new FilePathWatcherImpl(); 689 impl_ = new FilePathWatcherImpl();
667 } 690 }
668 691
669 } // namespace base 692 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698