mirror of
https://github.com/nextcloud/desktop.git
synced 2024-10-27 23:17:13 +03:00
Lnk: Work around QFile::rename() #2792
QFile::rename() fails if the source file is a shortcut to a file or directory that does not exist.
This commit is contained in:
parent
db7919dc2f
commit
efe9f1b442
7 changed files with 72 additions and 22 deletions
|
@ -21,6 +21,7 @@
|
|||
#include "account.h"
|
||||
#include "accountmigrator.h"
|
||||
#include "accountstate.h"
|
||||
#include "filesystem.h"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "owncloudpropagator_p.h"
|
||||
#include "account.h"
|
||||
#include "syncjournalfilerecord.h"
|
||||
#include "filesystem.h"
|
||||
#include <QFile>
|
||||
#include <QStringList>
|
||||
|
||||
|
@ -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."));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue