From c26d75e9a577e70eb6714363cd4422753eabbcd3 Mon Sep 17 00:00:00 2001 From: Hannah von Reth Date: Wed, 4 Aug 2021 14:03:03 +0200 Subject: [PATCH 1/3] Print the content of the string not the address --- src/common/remotepermissions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/remotepermissions.h b/src/common/remotepermissions.h index 5dfefb2bb75..840aab06cac 100644 --- a/src/common/remotepermissions.h +++ b/src/common/remotepermissions.h @@ -100,7 +100,7 @@ class OCSYNC_EXPORT RemotePermissions friend QDebug operator<<(QDebug &dbg, RemotePermissions p) { - return dbg << p.toString().constData(); + return dbg << p.toString(); } }; From f2e2f683ddddf2d1e64fc6f473c584fa693dc1c2 Mon Sep 17 00:00:00 2001 From: Hannah von Reth Date: Wed, 4 Aug 2021 15:48:03 +0200 Subject: [PATCH 2/3] Make SyncInstructions QFlags --- src/csync/csync.cpp | 12 ++++++++++++ src/csync/csync.h | 8 ++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/csync/csync.cpp b/src/csync/csync.cpp index dfbb2016df4..e11c90d412f 100644 --- a/src/csync/csync.cpp +++ b/src/csync/csync.cpp @@ -20,3 +20,15 @@ #include "csync.h" #include "moc_csync.cpp" + +#include + +QDebug operator<<(QDebug debug, const SyncInstructions &enumValue) +{ + static const QMetaObject *mo = qt_getEnumMetaObject(SyncInstruction()); + static const int enumIdx = mo->indexOfEnumerator(qt_getEnumName(SyncInstruction())); + static const QMetaEnum me = mo->enumerator(enumIdx); + QDebugStateSaver saver(debug); + debug.nospace().noquote() << me.enumName() << "(" << me.valueToKeys(enumValue) << ")"; + return debug; +} diff --git a/src/csync/csync.h b/src/csync/csync.h index ad2316ea72b..d67c0434802 100644 --- a/src/csync/csync.h +++ b/src/csync/csync.h @@ -104,7 +104,7 @@ Q_ENUM_NS(csync_status_codes_e) * the csync state of a file. */ // clang-format off -enum SyncInstructions { +enum SyncInstruction { CSYNC_INSTRUCTION_NONE = 0, /* Nothing to do (UPDATE|RECONCILE) */ CSYNC_INSTRUCTION_REMOVE = 1 << 1, /* The file need to be removed (RECONCILE) */ CSYNC_INSTRUCTION_RENAME = 1 << 2, /* The file need to be renamed (RECONCILE) */ @@ -125,7 +125,9 @@ enum SyncInstructions { CSYNC_INSTRUCTION_EVAL = 1 << 0, // DEPRECATED REMOVED }; // clang-format on -Q_ENUM_NS(SyncInstructions) +Q_ENUM_NS(SyncInstruction) +Q_DECLARE_FLAGS(SyncInstructions, SyncInstruction) +Q_DECLARE_OPERATORS_FOR_FLAGS(SyncInstructions) // This enum is used with BITFIELD(3) and BITFIELD(4) in several places. // Also, this value is stored in the database, so beware of value changes. @@ -212,6 +214,8 @@ struct OCSYNC_EXPORT csync_file_stat_s { { } }; +OCSYNC_EXPORT QDebug operator<<(QDebug debug, const SyncInstructions &job); + /** * }@ */ From 211f48baaf8b22cd43d212aa774ee9b498bbd586 Mon Sep 17 00:00:00 2001 From: Hannah von Reth Date: Wed, 4 Aug 2021 15:07:43 +0200 Subject: [PATCH 3/3] Accept all ignored deletes If the local permissions are not correct we perform a prohibited move The move fails with 403 and creates a blacklist entry, but we might get the correct permissions for that file. In the next sync the we don't retry the move as we have the correct permissions now so we want to restore the original file. The original file however is now on the blacklist we mark the restoration as ignore and end up in findAndCancelDeletedJob Fixes: #8837 --- changelog/unreleased/8837 | 3 +++ src/libsync/discoveryphase.cpp | 30 ++++++++++++++++-------------- 2 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 changelog/unreleased/8837 diff --git a/changelog/unreleased/8837 b/changelog/unreleased/8837 new file mode 100644 index 00000000000..3bb14f575f7 --- /dev/null +++ b/changelog/unreleased/8837 @@ -0,0 +1,3 @@ +Bugfix: Don't crash if a certain move is undone + +https://github.com/owncloud/client/issues/8837 diff --git a/src/libsync/discoveryphase.cpp b/src/libsync/discoveryphase.cpp index 0fc34df6ba5..ebc11a03781 100644 --- a/src/libsync/discoveryphase.cpp +++ b/src/libsync/discoveryphase.cpp @@ -158,34 +158,36 @@ QPair DiscoveryPhase::findAndCancelDeletedJob(const QString &o QByteArray oldEtag; auto it = _deletedItem.find(originalPath); if (it != _deletedItem.end()) { - const SyncInstructions instruction = (*it)->_instruction; - if (instruction == CSYNC_INSTRUCTION_IGNORE && (*it)->_type == ItemTypeVirtualFile) { + const auto &item = *it; + const SyncInstructions instruction = item->_instruction; + if (instruction == CSYNC_INSTRUCTION_IGNORE && item->_type == ItemTypeVirtualFile) { // re-creation of virtual files count as a delete + // restoration after a prohibited move // a file might be in an error state and thus gets marked as CSYNC_INSTRUCTION_IGNORE // after it was initially marked as CSYNC_INSTRUCTION_REMOVE // return true, to not trigger any additional actions on that file that could elad to dataloss result = true; - oldEtag = (*it)->_etag; + oldEtag = item->_etag; } else { if (!(instruction == CSYNC_INSTRUCTION_REMOVE // re-creation of virtual files count as a delete - || ((*it)->_type == ItemTypeVirtualFile && instruction == CSYNC_INSTRUCTION_NEW) - || ((*it)->_isRestoration && instruction == CSYNC_INSTRUCTION_NEW))) - { + || (item->_type == ItemTypeVirtualFile && instruction == CSYNC_INSTRUCTION_NEW) + || (item->_isRestoration && instruction & (CSYNC_INSTRUCTION_NEW | CSYNC_INSTRUCTION_IGNORE)))) { qCWarning(lcDiscovery) << "OC_ENFORCE(FAILING)" << originalPath; qCWarning(lcDiscovery) << "instruction == CSYNC_INSTRUCTION_REMOVE" << (instruction == CSYNC_INSTRUCTION_REMOVE); - qCWarning(lcDiscovery) << "((*it)->_type == ItemTypeVirtualFile && instruction == CSYNC_INSTRUCTION_NEW)" - << ((*it)->_type == ItemTypeVirtualFile && instruction == CSYNC_INSTRUCTION_NEW); - qCWarning(lcDiscovery) << "((*it)->_isRestoration && instruction == CSYNC_INSTRUCTION_NEW))" - << ((*it)->_isRestoration && instruction == CSYNC_INSTRUCTION_NEW); + qCWarning(lcDiscovery) << "(item->_type == ItemTypeVirtualFile && instruction == CSYNC_INSTRUCTION_NEW)" + << (item->_type == ItemTypeVirtualFile && instruction == CSYNC_INSTRUCTION_NEW); + qCWarning(lcDiscovery) << "(item->_isRestoration && instruction & (CSYNC_INSTRUCTION_NEW | CSYNC_INSTRUCTION_IGNORE)" + << (item->_isRestoration && instruction & (CSYNC_INSTRUCTION_NEW | CSYNC_INSTRUCTION_IGNORE); qCWarning(lcDiscovery) << "instruction" << instruction; - qCWarning(lcDiscovery) << "(*it)->_type" << (*it)->_type; - qCWarning(lcDiscovery) << "(*it)->_isRestoration " << (*it)->_isRestoration; + qCWarning(lcDiscovery) << "item->_type" << item->_type; + qCWarning(lcDiscovery) << "item->_isRestoration " << item->_isRestoration; + qCWarning(lcDiscovery) << "item->_remotePerm" << item->_remotePerm; OC_ENFORCE(false); } - (*it)->_instruction = CSYNC_INSTRUCTION_NONE; + item->_instruction = CSYNC_INSTRUCTION_NONE; result = true; - oldEtag = (*it)->_etag; + oldEtag = item->_etag; } _deletedItem.erase(it); }