From 4ca26ef27339267ac233d01a904ed2d9fb99bfa9 Mon Sep 17 00:00:00 2001 From: Matthieu Gallien <matthieu.gallien@nextcloud.com> Date: Fri, 21 Jan 2022 19:03:23 +0100 Subject: [PATCH] use proper API to dehydrate a placeholder file Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com> --- src/libsync/vfs/cfapi/cfapiwrapper.cpp | 32 ++++++++++++++++++++++++++ src/libsync/vfs/cfapi/cfapiwrapper.h | 1 + src/libsync/vfs/cfapi/vfs_cfapi.cpp | 27 ++++++++-------------- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/libsync/vfs/cfapi/cfapiwrapper.cpp b/src/libsync/vfs/cfapi/cfapiwrapper.cpp index 59bf581dc2389..8fa3aeb9a39d7 100644 --- a/src/libsync/vfs/cfapi/cfapiwrapper.cpp +++ b/src/libsync/vfs/cfapi/cfapiwrapper.cpp @@ -740,6 +740,38 @@ OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::up return OCC::Vfs::ConvertToPlaceholderResult::Ok; } +OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::dehydratePlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId) +{ + Q_ASSERT(handle); + + if (modtime <= 0) { + return {QString{"Could not update metadata due to invalid modification time for %1: %2"}.arg(pathForHandle(handle)).arg(modtime)}; + } + + const auto info = findPlaceholderInfo(handle); + if (!info) { + return { "Can't update non existing placeholder info" }; + } + + const auto fileIdentity = QString::fromUtf8(fileId).toStdWString(); + const auto fileIdentitySize = (fileIdentity.length() + 1) * sizeof(wchar_t); + + CF_FILE_RANGE dehydrationRange; + dehydrationRange.StartingOffset.QuadPart = 0; + dehydrationRange.Length.QuadPart = size; + + const qint64 result = CfUpdatePlaceholder(handle.get(), nullptr, + fileIdentity.data(), sizeToDWORD(fileIdentitySize), + &dehydrationRange, 1, CF_UPDATE_FLAG_MARK_IN_SYNC, nullptr, nullptr); + + if (result != S_OK) { + qCWarning(lcCfApiWrapper) << "Couldn't update placeholder info for" << pathForHandle(handle) << ":" << QString::fromWCharArray(_com_error(result).ErrorMessage()); + return { "Couldn't update placeholder info" }; + } + + return OCC::Vfs::ConvertToPlaceholderResult::Ok; +} + OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::convertToPlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath) { Q_UNUSED(modtime); diff --git a/src/libsync/vfs/cfapi/cfapiwrapper.h b/src/libsync/vfs/cfapi/cfapiwrapper.h index e6f4ac8b93b18..5993a7f461b2a 100644 --- a/src/libsync/vfs/cfapi/cfapiwrapper.h +++ b/src/libsync/vfs/cfapi/cfapiwrapper.h @@ -94,6 +94,7 @@ NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> set NEXTCLOUD_CFAPI_EXPORT Result<void, QString> createPlaceholderInfo(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId); NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> updatePlaceholderInfo(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath = QString()); NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> convertToPlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath); +NEXTCLOUD_CFAPI_EXPORT Result<OCC::Vfs::ConvertToPlaceholderResult, QString> dehydratePlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId); } diff --git a/src/libsync/vfs/cfapi/vfs_cfapi.cpp b/src/libsync/vfs/cfapi/vfs_cfapi.cpp index 1adeb5d686b85..aec9289ac8f10 100644 --- a/src/libsync/vfs/cfapi/vfs_cfapi.cpp +++ b/src/libsync/vfs/cfapi/vfs_cfapi.cpp @@ -132,26 +132,19 @@ Result<void, QString> VfsCfApi::createPlaceholder(const SyncFileItem &item) Result<void, QString> VfsCfApi::dehydratePlaceholder(const SyncFileItem &item) { - const auto previousPin = pinState(item._file); - - if (!FileSystem::remove(_setupParams.filesystemPath + item._file)) { - return QStringLiteral("Couldn't remove %1 to fulfill dehydration").arg(item._file); - } - - const auto r = createPlaceholder(item); - if (!r) { - return r; - } - - if (previousPin) { - if (*previousPin == PinState::AlwaysLocal) { - setPinState(item._file, PinState::Unspecified); + const auto localPath = QDir::toNativeSeparators(_setupParams.filesystemPath + item._file); + const auto handle = cfapi::handleForPath(localPath); + if (handle) { + auto result = cfapi::dehydratePlaceholder(handle, item._modtime, item._size, item._fileId); + if (result) { + return {}; } else { - setPinState(item._file, *previousPin); + return result.error(); } + } else { + qCWarning(lcCfApi) << "Couldn't update metadata for non existing file" << localPath; + return {QStringLiteral("Couldn't update metadata")}; } - - return {}; } Result<Vfs::ConvertToPlaceholderResult, QString> VfsCfApi::convertToPlaceholder(const QString &filename, const SyncFileItem &item, const QString &replacesFile)