diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp index 89f46136a..91c5c4e21 100644 --- a/src/gui/folderman.cpp +++ b/src/gui/folderman.cpp @@ -21,6 +21,7 @@ #include "account.h" #include "accountmigrator.h" #include "accountstate.h" +#include "filesystem.h" #ifdef Q_OS_MAC #include @@ -852,9 +853,10 @@ bool FolderMan::startFromScratch( const QString& localFolder ) // Make a backup of the folder/file. QString newName = getBackupName( parentDir.absoluteFilePath( folderName ) ); - if( !parentDir.rename( fi.absoluteFilePath(), newName ) ) { + QString renameError; + if( !FileSystem::rename( fi.absoluteFilePath(), newName, &renameError ) ) { qDebug() << "startFromScratch: Could not rename" << fi.absoluteFilePath() - << "to" << newName; + << "to" << newName << "error:" << renameError; return false; } } diff --git a/src/libsync/filesystem.cpp b/src/libsync/filesystem.cpp index 5e014f763..ba94db03c 100644 --- a/src/libsync/filesystem.cpp +++ b/src/libsync/filesystem.cpp @@ -107,6 +107,54 @@ bool FileSystem::setModTime(const QString& filename, time_t modTime) return true; } +#ifdef Q_OS_WIN +static bool isLnkFile(const QString& filename) +{ + return filename.endsWith(".lnk"); +} +#endif + +bool FileSystem::rename(const QString &originFileName, + const QString &destinationFileName, + QString *errorString) +{ + bool success = false; + QString error; +#ifdef Q_OS_WIN + if (isLnkFile(originFileName) || isLnkFile(destinationFileName)) { + success = MoveFileEx((wchar_t*)originFileName.utf16(), + (wchar_t*)destinationFileName.utf16(), + MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH); + if (!success) { + wchar_t *string = 0; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, ::GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPWSTR)&string, 0, NULL); + + error = QString::fromWCharArray(string); + LocalFree((HLOCAL)string); + } + } else +#endif + { + QFile orig(originFileName); + success = orig.rename(destinationFileName); + if (!success) { + error = orig.errorString(); + } + } + + if (!success) { + qDebug() << "FAIL: renaming file" << originFileName + << "to" << destinationFileName + << "failed: " << error; + if (errorString) { + *errorString = error; + } + } + return success; +} + bool FileSystem::renameReplace(const QString& originFileName, const QString& destinationFileName, QString* errorString) { #ifndef Q_OS_WIN @@ -215,16 +263,6 @@ bool FileSystem::openFileSharedRead(QFile* file, QString* error) } #ifdef Q_OS_WIN -static bool isLnkFile(const QString& filename) -{ - return filename.endsWith(".lnk"); -} - -static bool isLnkFile(const QFileInfo& fi) -{ - return fi.suffix() == "lnk"; -} - static qint64 getSizeWithCsync(const QString& filename) { qint64 result = 0; diff --git a/src/libsync/filesystem.h b/src/libsync/filesystem.h index ea97a8658..845ffc493 100644 --- a/src/libsync/filesystem.h +++ b/src/libsync/filesystem.h @@ -59,6 +59,14 @@ qint64 OWNCLOUDSYNC_EXPORT getSize(const QString& filename); */ bool OWNCLOUDSYNC_EXPORT fileExists(const QString& filename); +/** + * Rename the file \a originFileName to \a destinationFileName. + * + * It behaves as QFile::rename() but handles .lnk files correctly on Windows. + */ +bool OWNCLOUDSYNC_EXPORT rename(const QString& originFileName, + const QString& destinationFileName, + QString* errorString = NULL); /** * Rename the file \a originFileName to \a destinationFileName, and overwrite the destination if it * already exists diff --git a/src/libsync/propagatedownload.cpp b/src/libsync/propagatedownload.cpp index 33538e1a3..9084d97d3 100644 --- a/src/libsync/propagatedownload.cpp +++ b/src/libsync/propagatedownload.cpp @@ -492,11 +492,11 @@ void PropagateDownloadFileQNAM::downloadFinished() bool isConflict = _item._instruction == CSYNC_INSTRUCTION_CONFLICT && !FileSystem::fileEquals(fn, _tmpFile.fileName()); if (isConflict) { - QFile f(fn); + QString renameError; QString conflictFileName = makeConflictFileName(fn, Utility::qDateTimeFromTime_t(_item._modtime)); - if (!f.rename(conflictFileName)) { + if (!FileSystem::rename(fn, conflictFileName, &renameError)) { //If the rename fails, don't replace it. - done(SyncFileItem::SoftError, f.errorString()); + done(SyncFileItem::SoftError, renameError); return; } } diff --git a/src/libsync/propagateremotemove.cpp b/src/libsync/propagateremotemove.cpp index 600bbb39d..c6c45f8da 100644 --- a/src/libsync/propagateremotemove.cpp +++ b/src/libsync/propagateremotemove.cpp @@ -16,6 +16,7 @@ #include "owncloudpropagator_p.h" #include "account.h" #include "syncjournalfilerecord.h" +#include "filesystem.h" #include #include @@ -81,7 +82,8 @@ void PropagateRemoteMove::start() QString originalFile(_propagator->getFilePath(QLatin1String("Shared"))); _propagator->addTouchedFile(originalFile); _propagator->addTouchedFile(targetFile); - if( QFile::rename( targetFile, originalFile) ) { + QString renameError; + if( FileSystem::rename(targetFile, originalFile, &renameError) ) { done(SyncFileItem::NormalError, tr("This folder must not be renamed. It is renamed back to its original name.")); } else { done(SyncFileItem::NormalError, tr("This folder must not be renamed. Please name it back to Shared.")); diff --git a/src/libsync/propagator_legacy.cpp b/src/libsync/propagator_legacy.cpp index 0e8561d45..dc714b607 100644 --- a/src/libsync/propagator_legacy.cpp +++ b/src/libsync/propagator_legacy.cpp @@ -695,11 +695,11 @@ void PropagateDownloadFileLegacy::start() && !FileSystem::fileEquals(fn, tmpFile.fileName()); // compare the files to see if there was an actual conflict. //In case of conflict, make a backup of the old file if (isConflict) { - QFile f(fn); QString conflictFileName = makeConflictFileName(fn, Utility::qDateTimeFromTime_t(_item._modtime)); - if (!f.rename(conflictFileName)) { + QString renameError; + if (!FileSystem::rename(fn, conflictFileName, &renameError)) { //If the rename fails, don't replace it. - done(SyncFileItem::NormalError, f.errorString()); + done(SyncFileItem::NormalError, renameError); return; } } diff --git a/src/libsync/propagatorjobs.cpp b/src/libsync/propagatorjobs.cpp index 8c00d2817..9f952576a 100644 --- a/src/libsync/propagatorjobs.cpp +++ b/src/libsync/propagatorjobs.cpp @@ -155,9 +155,9 @@ void PropagateLocalRename::start() _propagator->addTouchedFile(existingFile); _propagator->addTouchedFile(targetFile); - QFile file(existingFile); - if (!file.rename(targetFile)) { - done(SyncFileItem::NormalError, file.errorString()); + QString renameError; + if (!FileSystem::rename(existingFile, targetFile, &renameError)) { + done(SyncFileItem::NormalError, renameError); return; } }