From: Christian Kamm Date: Fri, 1 Feb 2019 10:23:00 +0000 (+0100) Subject: Vfs: dehydration is separate action X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~12^2~21^2~468^2~301 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=6c5fa1daddc58a8dbde4fa0dcc73a9ab9939fa19;p=nextcloud-desktop.git Vfs: dehydration is separate action Allows for better attribute preservation. Also add verifyFileUnchanged() call before dehydration to avoid data loss when discovery takes a while. --- diff --git a/src/common/vfs.h b/src/common/vfs.h index 5d3e993ff..7239a911c 100644 --- a/src/common/vfs.h +++ b/src/common/vfs.h @@ -143,7 +143,14 @@ public: virtual bool updateMetadata(const QString &filePath, time_t modtime, quint64 size, const QByteArray &fileId, QString *error) = 0; /// Create a new dehydrated placeholder. Called from PropagateDownload. - virtual void createPlaceholder(const QString &syncFolder, const SyncFileItem &item) = 0; + virtual void createPlaceholder(const SyncFileItem &item) = 0; + + /** Convert a hydrated placeholder to a dehydrated one. Called from PropagateDownlaod. + * + * This is different from delete+create because preserving some file metadata + * (like pin states) may be essential for some vfs plugins. + */ + virtual void dehydratePlaceholder(const SyncFileItem &item) = 0; /** Convert a new file to a hydrated placeholder. * @@ -247,7 +254,8 @@ public: bool isHydrating() const override { return false; } bool updateMetadata(const QString &, time_t, quint64, const QByteArray &, QString *) override { return true; } - void createPlaceholder(const QString &, const SyncFileItem &) override {} + void createPlaceholder(const SyncFileItem &) override {} + void dehydratePlaceholder(const SyncFileItem &) override {} void convertToPlaceholder(const QString &, const SyncFileItem &, const QString &) override {} bool isDehydratedPlaceholder(const QString &) override { return false; } diff --git a/src/libsync/propagatedownload.cpp b/src/libsync/propagatedownload.cpp index 7ae067797..d926542b4 100644 --- a/src/libsync/propagatedownload.cpp +++ b/src/libsync/propagatedownload.cpp @@ -417,31 +417,29 @@ void PropagateDownloadFile::startAfterIsEncryptedIsChecked() auto &syncOptions = propagator()->syncOptions(); auto &vfs = syncOptions._vfs; - // For virtual files just create the file and be done + // For virtual files just dehydrate or create the file and be done if (_item->_type == ItemTypeVirtualFileDehydration) { - _item->_type = ItemTypeVirtualFile; - // TODO: Could dehydrate without wiping the file entirely - // TODO: That would be useful as it could preserve file attributes (pins) - auto fn = propagator()->getFilePath(_item->_file); - qCDebug(lcPropagateDownload) << "dehydration: wiping base file" << fn; - propagator()->_journal->deleteFileRecord(_item->_file); - QFile::remove(fn); - - if (vfs->mode() == Vfs::WithSuffix) { - // Normally new suffix-virtual files already have the suffix included in the path - // but for dehydrations that isn't the case. Adjust it here. - _item->_file.append(vfs->fileSuffix()); + QString fsPath = propagator()->getFilePath(_item->_file); + if (!FileSystem::verifyFileUnchanged(fsPath, _item->_previousSize, _item->_previousModtime)) { + propagator()->_anotherSyncNeeded = true; + done(SyncFileItem::SoftError, tr("File has changed since discovery")); + return; } + + qCDebug(lcPropagateDownload) << "dehydrating file" << _item->_file; + _item->_type = ItemTypeVirtualFile; // Needed? + vfs->dehydratePlaceholder(*_item); + propagator()->_journal->deleteFileRecord(_item->_file); + updateMetadata(false); + return; } if (vfs->mode() == Vfs::Off && _item->_type == ItemTypeVirtualFile) { qCWarning(lcPropagateDownload) << "ignored virtual file type of" << _item->_file; _item->_type = ItemTypeFile; } if (_item->_type == ItemTypeVirtualFile) { - auto fn = propagator()->getFilePath(_item->_file); - qCDebug(lcPropagateDownload) << "creating virtual file" << fn; - - vfs->createPlaceholder(propagator()->_localDir, *_item); + qCDebug(lcPropagateDownload) << "creating virtual file" << _item->_file; + vfs->createPlaceholder(*_item); updateMetadata(false); return; } diff --git a/src/libsync/vfs/suffix/vfs_suffix.cpp b/src/libsync/vfs/suffix/vfs_suffix.cpp index 711ee14ea..f489aa407 100644 --- a/src/libsync/vfs/suffix/vfs_suffix.cpp +++ b/src/libsync/vfs/suffix/vfs_suffix.cpp @@ -59,10 +59,10 @@ bool VfsSuffix::updateMetadata(const QString &filePath, time_t modtime, quint64, return true; } -void VfsSuffix::createPlaceholder(const QString &syncFolder, const SyncFileItem &item) +void VfsSuffix::createPlaceholder(const SyncFileItem &item) { // The concrete shape of the placeholder is also used in isDehydratedPlaceholder() below - QString fn = syncFolder + item._file; + QString fn = _setupParams.filesystemPath + item._file; QFile file(fn); file.open(QFile::ReadWrite | QFile::Truncate); file.write(" "); @@ -70,6 +70,14 @@ void VfsSuffix::createPlaceholder(const QString &syncFolder, const SyncFileItem FileSystem::setModTime(fn, item._modtime); } +void VfsSuffix::dehydratePlaceholder(const SyncFileItem &item) +{ + QFile::remove(_setupParams.filesystemPath + item._file); + SyncFileItem virtualItem(item); + virtualItem._file.append(fileSuffix()); + createPlaceholder(virtualItem); +} + void VfsSuffix::convertToPlaceholder(const QString &, const SyncFileItem &, const QString &) { // Nothing necessary diff --git a/src/libsync/vfs/suffix/vfs_suffix.h b/src/libsync/vfs/suffix/vfs_suffix.h index 97d444ffc..8f2c1e106 100644 --- a/src/libsync/vfs/suffix/vfs_suffix.h +++ b/src/libsync/vfs/suffix/vfs_suffix.h @@ -39,7 +39,8 @@ public: bool updateMetadata(const QString &filePath, time_t modtime, quint64 size, const QByteArray &fileId, QString *error) override; - void createPlaceholder(const QString &syncFolder, const SyncFileItem &item) override; + void createPlaceholder(const SyncFileItem &item) override; + void dehydratePlaceholder(const SyncFileItem &item) override; void convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &) override; bool isDehydratedPlaceholder(const QString &filePath) override;