diff --git a/src/common/filesystembase.cpp b/src/common/filesystembase.cpp index 06152e0fbc..88b1c54e2f 100644 --- a/src/common/filesystembase.cpp +++ b/src/common/filesystembase.cpp @@ -323,6 +323,25 @@ bool FileSystem::openAndSeekFileSharedRead(QFile *file, QString *errorOrNull, qi #endif } +QString FileSystem::joinPath(const QString& path, const QString& file) +{ + if (path.isEmpty()) { + qCWarning(lcFileSystem).nospace() << "joinPath called with an empty path; returning file=" << file; + return QDir::toNativeSeparators(file); + } + + if (file.isEmpty()) { + qCWarning(lcFileSystem).nospace() << "joinPath called with an empty file; returning path=" << path; + return QDir::toNativeSeparators(path); + } + + if (const auto lastChar = path[path.size() - 1]; lastChar == QLatin1Char{'/'} || lastChar == QLatin1Char{'\\'}) { + return QDir::toNativeSeparators(path + file); + } + + return QDir::toNativeSeparators(path + QDir::separator() + file); +} + #ifdef Q_OS_WIN std::filesystem::perms FileSystem::filePermissionsWinSymlinkSafe(const QString &filename) { @@ -804,7 +823,7 @@ bool FileSystem::setAclPermission(const QString &unsafePath, FolderPermissions p const auto currentFolder = safePathFileInfo.dir(); const auto childFiles = currentFolder.entryList(QDir::Filter::Files); for (const auto &oneEntry : childFiles) { - const auto childFile = QDir::toNativeSeparators(path + QDir::separator() + oneEntry); + const auto childFile = joinPath(path, oneEntry); const auto &childFileStdWString = childFile.toStdWString(); const auto attributes = GetFileAttributes(childFileStdWString.c_str()); diff --git a/src/common/filesystembase.h b/src/common/filesystembase.h index d88bfd6107..9e115b6c9d 100644 --- a/src/common/filesystembase.h +++ b/src/common/filesystembase.h @@ -142,6 +142,16 @@ namespace FileSystem { */ bool OCSYNC_EXPORT openAndSeekFileSharedRead(QFile *file, QString *error, qint64 seek); + /** + * Returns `path + "/" + file` with native directory separators. + * + * If `path` ends in a directory separator this method will not insert another one in-between. + * + * In the case one of the parameters is empty, the other parameter will be returned with native + * directory separators and a warning is logged. + */ + QString OCSYNC_EXPORT joinPath(const QString &path, const QString &file); + #ifdef Q_OS_WIN /** * Returns the file system used at the given path. diff --git a/src/libsync/filesystem.cpp b/src/libsync/filesystem.cpp index d2c007ca90..e54ed50033 100644 --- a/src/libsync/filesystem.cpp +++ b/src/libsync/filesystem.cpp @@ -265,7 +265,7 @@ bool FileSystem::removeRecursively(const QString &path, const std::function