Skip to content

Commit af8a483

Browse files
committed
Fix canonicalPath for drives (c:)
1 parent 7db48a8 commit af8a483

File tree

4 files changed

+39
-28
lines changed

4 files changed

+39
-28
lines changed

src/gui/folderman.cpp

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ Folder *FolderMan::folderForPath(const QString &path, QString *relativePath)
421421
for (auto *folder : std::as_const(_folders)) {
422422
const QString folderPath = folder->cleanPath() + QLatin1Char('/');
423423

424-
if (absolutePath.startsWith(folderPath, (Utility::isWindows() || Utility::isMac()) ? Qt::CaseInsensitive : Qt::CaseSensitive)) {
424+
if (FileSystem::isChildPathOf2(absolutePath, folderPath).testAnyFlag(FileSystem::ChildResult::IsChild)) {
425425
if (relativePath) {
426426
*relativePath = absolutePath.mid(folderPath.length());
427427
relativePath->chop(1); // we added a '/' above
@@ -541,25 +541,36 @@ QString FolderMan::trayTooltipStatusString(
541541
return folderMessage;
542542
}
543543

544-
// QFileInfo::canonicalPath returns an empty string if the file does not exist.
544+
// canonicalPath returns an empty string if the file does not exist.
545545
// This function also works with files that does not exist and resolve the symlinks in the
546546
// parent directories.
547-
static QString canonicalPath(const QString &path)
548-
{
549-
QFileInfo selFile(path);
550-
if (!selFile.exists()) {
551-
const auto parentPath = selFile.dir().path();
552-
553-
// It's possible for the parentPath to match the path
554-
// (possibly we've arrived at a non-existant drive root on Windows)
555-
// and recursing would be fatal.
556-
if (parentPath == path) {
557-
return path;
547+
static std::filesystem::path canonicalPath(const std::filesystem::path &p)
548+
{
549+
std::error_code ec;
550+
if (!std::filesystem::exists(p, ec) && !ec) {
551+
const auto parentPath = p.lexically_normal().parent_path();
552+
// last invocation will return /
553+
if (parentPath == p) {
554+
return p;
558555
}
559556

560-
return canonicalPath(parentPath) + QLatin1Char('/') + selFile.fileName();
557+
return canonicalPath(parentPath) / p.filename();
558+
}
559+
if (ec) {
560+
qCWarning(lcFolderMan) << "Failed to check existence of path:" << p << ec.message();
561561
}
562-
return selFile.canonicalFilePath();
562+
const auto out = std::filesystem::canonical(p, ec);
563+
if (ec) {
564+
qCWarning(lcFolderMan) << "Failed to canonicalize path:" << p << ec.message();
565+
return p;
566+
}
567+
return out;
568+
}
569+
570+
static QString canonicalPath(const QString &p)
571+
{
572+
// clean path to normalize path back to Qt form
573+
return QDir::cleanPath(FileSystem::fromFilesystemPath(canonicalPath(FileSystem::toFilesystemPath(p))));
563574
}
564575

565576
static QString checkPathForSyncRootMarkingRecursive(const QString &path, FolderMan::NewFolderType folderType, const QUuid &accountUuid)
@@ -645,17 +656,18 @@ QString FolderMan::checkPathValidityRecursive(const QString &path, FolderMan::Ne
645656
QString FolderMan::checkPathValidityForNewFolder(const QString &path, NewFolderType folderType, const QUuid &accountUuid) const
646657
{
647658
// check if the local directory isn't used yet in another sync
648-
const auto cs = Utility::fsCaseSensitivity();
649-
650-
const QString userDir = QDir::cleanPath(canonicalPath(path)) + QLatin1Char('/');
659+
if (path.isEmpty()) {
660+
return u"Passingg an empty path is not supported"_s;
661+
}
662+
const QString userDir = canonicalPath(path) + QLatin1Char('/');
651663
for (auto f : _folders) {
652-
const QString folderDir = QDir::cleanPath(canonicalPath(f->path())) + QLatin1Char('/');
664+
const QString folderDir = canonicalPath(f->path()) + QLatin1Char('/');
653665

654-
if (QString::compare(folderDir, userDir, cs) == 0) {
666+
const auto isChild = FileSystem::isChildPathOf2(folderDir, userDir);
667+
if (isChild.testFlag(FileSystem::ChildResult::IsEqual)) {
655668
return tr("There is already a sync from the server to this local folder. "
656669
"Please pick another local folder!");
657-
}
658-
if (FileSystem::isChildPathOf(folderDir, userDir)) {
670+
} else if (isChild.testFlag(FileSystem::ChildResult::IsChild)) {
659671
return tr("The local folder »%1« already contains a folder used in a folder sync connection. "
660672
"Please pick another local folder!")
661673
.arg(QDir::toNativeSeparators(path));
@@ -681,13 +693,15 @@ QString FolderMan::findGoodPathForNewSyncFolder(
681693
OC_ASSERT(!accountUuid.isNull() || folderType == FolderMan::NewFolderType::SpacesSyncRoot);
682694

683695
// reserve extra characters to allow appending of a number
684-
const QString normalisedPath = FileSystem::createPortableFileName(basePath, FileSystem::pathEscape(newFolder), std::string_view(" (100)").size());
696+
const QString normalisedPath = FileSystem::createPortableFileName(basePath, newFolder, std::string_view(" (100)").size());
685697

686698
// If the parent folder is a sync folder or contained in one, we can't
687699
// possibly find a valid sync folder inside it.
688700
// Example: Someone syncs their home directory. Then ~/foobar is not
689701
// going to be an acceptable sync folder path for any value of foobar.
690-
if (FolderMan::instance()->folderForPath(QFileInfo(normalisedPath).canonicalPath())) {
702+
// If relativePath is empty, the path is equal to newFolder, and we will find a name in the following loop
703+
QString relativePath;
704+
if (FolderMan::instance()->folderForPath(canonicalPath(normalisedPath), &relativePath) && !relativePath.isEmpty()) {
691705
// Any path with that parent is going to be unacceptable,
692706
// so just keep it as-is.
693707
return canonicalPath(normalisedPath);

src/libsync/common/filesystembase.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,6 @@ QString FileSystem::createPortableFileName(const QString &path, const QString &f
556556
tmp.resize(std::min<qsizetype>(tmp.size(), fileNameMaxC - reservedSize));
557557
// remove eventual trailing whitespace after the resize
558558
tmp = tmp.trimmed();
559-
560559
return QDir::cleanPath(path + QLatin1Char('/') + tmp);
561560
}
562561

src/libsync/propagateuploadtus.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,6 @@ void PropagateUploadFileTUS::slotChunkFinished()
235235
propagator()->_anotherSyncNeeded = true;
236236
if (!_finished) {
237237
abortWithError(SyncFileItem::Message, fileChangedMessage());
238-
// FIXME: the legacy code was retrying for a few seconds.
239-
// and also checking that after the last chunk, and removed the file in case of INSTRUCTION_NEW
240238
return;
241239
}
242240
}

test/testfolderman.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ private Q_SLOTS:
105105
QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1/some/sub/path"), type, uuid).isNull());
106106
QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/OpenCloud2/blublu"), type, uuid).isNull());
107107
QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/sub/OpenCloud1/folder/g/h"), type, uuid).isNull());
108-
QVERIFY(!folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link3/folder/neu_folder"), type, uuid).isNull());
108+
QCOMPARE_NE(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link3/folder/neu_folder"), type, uuid), QString());
109109

110110
// Subfolder of links
111111
QVERIFY(folderman->checkPathValidityForNewFolder(dirPath + QStringLiteral("/link1/subfolder"), type, uuid).isNull());

0 commit comments

Comments
 (0)