From 6556185b73ca1c32a76a7a012b3843f0bb11a292 Mon Sep 17 00:00:00 2001 From: Jyrki Gadinger Date: Mon, 16 Mar 2026 13:37:15 +0100 Subject: [PATCH] fix(filesystem): deal with win32 long paths when recursively removing folders `std::filesystem::remove` etc. seem to behave the same way as the pure win32-APIs: sometimes long paths work, sometimes they won't. In this case it seems to be able to deal with long UNC-style paths just fine ... Resolves #9293 Signed-off-by: Jyrki Gadinger --- src/libsync/filesystem.cpp | 8 +++++++- test/testfilesystem.cpp | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/libsync/filesystem.cpp b/src/libsync/filesystem.cpp index 3e65aed6b41fa..e27301c035f1b 100644 --- a/src/libsync/filesystem.cpp +++ b/src/libsync/filesystem.cpp @@ -312,7 +312,13 @@ bool FileSystem::removeRecursively(const QString &path, auto folderDeleteError = QString{}; try { - if (!std::filesystem::remove(std::filesystem::path{fileInfo.filePath().toStdWString()})) { +#ifdef Q_OS_WIN + // std::filesystem::remove does not handle paths greater than MAX_PATH, but it seems to be fine with the prefixed UNC paths ... + const auto fspath = std::filesystem::path{FileSystem::longWinPath(fileInfo.filePath()).toStdWString()}; +#else + const auto fspath = std::filesystem::path{fileInfo.filePath().toStdWString()}; +#endif + if (!std::filesystem::remove(fspath)) { qCWarning(lcFileSystem()) << "File is already deleted" << fileInfo.filePath(); } } diff --git a/test/testfilesystem.cpp b/test/testfilesystem.cpp index d3e5dc20b8a08..37abf3784f537 100644 --- a/test/testfilesystem.cpp +++ b/test/testfilesystem.cpp @@ -320,6 +320,28 @@ private Q_SLOTS: QCOMPARE_EQ(aclSizeAfterReadWrite.AclBytesInUse, aclSizeInitial.AclBytesInUse); } #endif + + void testRecursiveDeletionLongPaths() + { + QTemporaryDir tempDir; + QDir tempQDir{tempDir.path()}; + + const auto makeLongPathSegment = [](const QString &base) -> QString { + QString baseSegment = base + " "; + return baseSegment + QString("0").repeated(200 - baseSegment.size()); + }; + + tempQDir.mkpath("Folder 1 - short name but long single subfolder/" + makeLongPathSegment("Subfolder without accentued characters - padding")); + tempQDir.mkpath(makeLongPathSegment("Folder 2 - directly a very long name")); + auto folder3Path = u"Folder 3 - short name but long multiples subfolder"_s; + for (auto i = 0; i < 5; i++) { + folder3Path.append("/subfolder %1 - total length 40 characters"_L1.arg(QString::number(i + 1))); + } + tempQDir.mkpath(folder3Path); + tempQDir.mkpath("Folder 4 - short name"); + + QVERIFY(FileSystem::removeRecursively(tempDir.path())); + } }; QTEST_GUILESS_MAIN(TestFileSystem)