From 1fe1f1348afe062ce97a334e03f8d2838d349a86 Mon Sep 17 00:00:00 2001 From: Matthieu Gallien Date: Mon, 19 Aug 2024 15:04:58 +0200 Subject: [PATCH] make folders read-write when needed when deleting local items if a folder is read-only, when deleting content inside this folder, it may be needed to make it temporary read-write do this as required by the automated tests Signed-off-by: Matthieu Gallien --- src/libsync/filesystem.cpp | 19 +++++++++++++++++++ src/libsync/filesystem.h | 13 +++++++++++++ src/libsync/propagatorjobs.cpp | 21 +++++++++++++++++---- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/libsync/filesystem.cpp b/src/libsync/filesystem.cpp index cc65bf1363e00..baafe22255995 100644 --- a/src/libsync/filesystem.cpp +++ b/src/libsync/filesystem.cpp @@ -480,6 +480,25 @@ bool FileSystem::isFolderReadOnly(const std::filesystem::path &path) noexcept return false; } } + +FileSystem::FilePermissionsRestore::FilePermissionsRestore(const QString &path, FolderPermissions temporaryPermissions) + : _path(path) +{ + const auto stdStrPath = _path.toStdWString(); + _initialPermissions = FileSystem::isFolderReadOnly(stdStrPath) ? OCC::FileSystem::FolderPermissions::ReadOnly : OCC::FileSystem::FolderPermissions::ReadWrite; + if (_initialPermissions != temporaryPermissions) { + _rollbackNeeded = true; + FileSystem::setFolderPermissions(_path, temporaryPermissions); + } +} + +FileSystem::FilePermissionsRestore::~FilePermissionsRestore() +{ + if (_rollbackNeeded) { + FileSystem::setFolderPermissions(_path, _initialPermissions); + } +} + #endif } // namespace OCC diff --git a/src/libsync/filesystem.h b/src/libsync/filesystem.h index b8c4735fe3a25..e14cf27681db0 100644 --- a/src/libsync/filesystem.h +++ b/src/libsync/filesystem.h @@ -41,6 +41,19 @@ class SyncJournal; * @brief This file contains file system helper */ namespace FileSystem { + class OWNCLOUDSYNC_EXPORT FilePermissionsRestore { + public: + explicit FilePermissionsRestore(const QString &path, + FileSystem::FolderPermissions temporaryPermissions); + + ~FilePermissionsRestore(); + + private: + QString _path; + FileSystem::FolderPermissions _initialPermissions; + bool _rollbackNeeded = false; + }; + struct OWNCLOUDSYNC_EXPORT FileLockingInfo { enum class Type { Unset = -1, Locked, Unlocked }; QString path; diff --git a/src/libsync/propagatorjobs.cpp b/src/libsync/propagatorjobs.cpp index 313d4b334080f..0732ad17695c3 100644 --- a/src/libsync/propagatorjobs.cpp +++ b/src/libsync/propagatorjobs.cpp @@ -63,6 +63,9 @@ bool PropagateLocalRemove::removeRecursively(const QString &path) QStringList errors; QList> deleted; #if !defined(Q_OS_MACOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15 + const auto fileInfo = QFileInfo{absolute}; + const auto parentFolderPath = fileInfo.dir().absolutePath(); + const auto parentPermissionsHandler = FileSystem::FilePermissionsRestore{parentFolderPath, FileSystem::FolderPermissions::ReadWrite}; FileSystem::setFolderPermissions(absolute, FileSystem::FolderPermissions::ReadWrite); #endif bool success = FileSystem::removeRecursively( @@ -126,10 +129,18 @@ void PropagateLocalRemove::start() return; } } else { - if (FileSystem::fileExists(filename) - && !FileSystem::remove(filename, &removeError)) { - done(SyncFileItem::NormalError, removeError, ErrorCategory::GenericError); - return; + if (FileSystem::fileExists(filename)) { +#if !defined(Q_OS_MACOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_15 + const auto fileInfo = QFileInfo{filename}; + const auto parentFolderPath = fileInfo.dir().absolutePath(); + + const auto parentPermissionsHandler = FileSystem::FilePermissionsRestore{parentFolderPath, FileSystem::FolderPermissions::ReadWrite}; +#endif + + if (!FileSystem::remove(filename, &removeError)) { + done(SyncFileItem::NormalError, removeError, ErrorCategory::GenericError); + return; + } } } } @@ -368,6 +379,8 @@ void PropagateLocalRename::start() }; #endif + auto originalFolder = FileSystem::FilePermissionsRestore{existingFile, FileSystem::FolderPermissions::ReadWrite}; + emit propagator()->touchedFile(existingFile); emit propagator()->touchedFile(targetFile); if (QString renameError; !FileSystem::rename(existingFile, targetFile, &renameError)) {