Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kamm <mail@ckamm.de>2018-10-12 12:03:10 +0300
committerckamm <mail@ckamm.de>2018-10-12 13:06:48 +0300
commit55cf407337a5db93511f1cb061165c53fa6dba6e (patch)
tree9cc826d82cf598c7923e2ba16a938d2b10dbade8 /src/gui/folderwatcher_linux.cpp
parentd0815239807540c423c52282e57a5ed8ebfd41e2 (diff)
Folderwatcher: On linux, fix paths after dir renames #6808
If a folder was renamed A -> B, the folder watcher for the inode would be unaware and still report changes for A/foo. Now directory renames in the watched folders are tracked and paths are updated accordingly.
Diffstat (limited to 'src/gui/folderwatcher_linux.cpp')
-rw-r--r--src/gui/folderwatcher_linux.cpp64
1 files changed, 48 insertions, 16 deletions
diff --git a/src/gui/folderwatcher_linux.cpp b/src/gui/folderwatcher_linux.cpp
index 5f6d580b1..d2fdb7d8d 100644
--- a/src/gui/folderwatcher_linux.cpp
+++ b/src/gui/folderwatcher_linux.cpp
@@ -31,6 +31,11 @@ FolderWatcherPrivate::FolderWatcherPrivate(FolderWatcher *p, const QString &path
, _parent(p)
, _folder(path)
{
+ _wipePotentialRenamesSoon = new QTimer(this);
+ _wipePotentialRenamesSoon->setInterval(1000);
+ _wipePotentialRenamesSoon->setSingleShot(true);
+ connect(_wipePotentialRenamesSoon, &QTimer::timeout, this, &FolderWatcherPrivate::wipePotentialRenames);
+
_fd = inotify_init();
if (_fd != -1) {
_socket.reset(new QSocketNotifier(_fd, QSocketNotifier::Read));
@@ -91,6 +96,17 @@ void FolderWatcherPrivate::inotifyRegisterPath(const QString &path)
}
}
+void FolderWatcherPrivate::applyDirectoryRename(const FolderWatcherPrivate::Rename &rename)
+{
+ QString fromSlash = rename.from + "/";
+ qCInfo(lcFolderWatcher) << "Applying rename from" << rename.from << "to" << rename.to;
+ for (auto &watch : _watches) {
+ if (watch == rename.from || watch.startsWith(fromSlash)) {
+ watch = rename.to + watch.mid(rename.from.size());
+ }
+ }
+}
+
void FolderWatcherPrivate::slotAddFolderRecursive(const QString &path)
{
int subdirs = 0;
@@ -126,6 +142,11 @@ void FolderWatcherPrivate::slotAddFolderRecursive(const QString &path)
}
}
+void FolderWatcherPrivate::wipePotentialRenames()
+{
+ _potentialRenames.clear();
+}
+
void FolderWatcherPrivate::slotReceivedNotification(int fd)
{
int len;
@@ -154,33 +175,44 @@ void FolderWatcherPrivate::slotReceivedNotification(int fd)
}
} while (false);
- // reset counter
- i = 0;
- // while there are enough events in the buffer
- while (i + sizeof(struct inotify_event) < static_cast<unsigned int>(len)) {
+ // iterate events in buffer
+ unsigned int ulen = len;
+ for (i = 0; i + sizeof(inotify_event) < ulen; i += sizeof(inotify_event) + (event ? event->len : 0)) {
// cast an inotify_event
event = (struct inotify_event *)&buffer[i];
if (event == NULL) {
qCDebug(lcFolderWatcher) << "NULL event";
- i += sizeof(struct inotify_event);
continue;
}
// Fire event for the path that was changed.
- if (event->len > 0 && event->wd > -1) {
- QByteArray fileName(event->name);
- if (fileName.startsWith("._sync_")
- || fileName.startsWith(".csync_journal.db")
- || fileName.startsWith(".owncloudsync.log")
- || fileName.startsWith(".sync_")) {
+ if (event->len == 0 || event->wd <= -1)
+ continue;
+ QByteArray fileName(event->name);
+ if (fileName.startsWith("._sync_")
+ || fileName.startsWith(".csync_journal.db")
+ || fileName.startsWith(".owncloudsync.log")
+ || fileName.startsWith(".sync_")) {
+ continue;
+ }
+ const QString p = _watches[event->wd] + '/' + fileName;
+ _parent->changeDetected(p);
+
+ // Collect events to form complete renames where possible
+ // and apply directory renames to the cached paths.
+ if ((event->mask & (IN_MOVED_TO | IN_MOVED_FROM)) && (event->mask & IN_ISDIR) && event->cookie > 0) {
+ auto &rename = _potentialRenames[event->cookie];
+ if (event->mask & IN_MOVED_TO)
+ rename.to = p;
+ if (event->mask & IN_MOVED_FROM)
+ rename.from = p;
+ if (!rename.from.isEmpty() && !rename.to.isEmpty()) {
+ applyDirectoryRename(rename);
+ _potentialRenames.remove(event->cookie);
} else {
- const QString p = _watches[event->wd] + '/' + fileName;
- _parent->changeDetected(p);
+ _wipePotentialRenamesSoon->start();
}
}
-
- // increment counter
- i += sizeof(struct inotify_event) + event->len;
}
}