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 "account.h"
|
||||||
#include "accountmigrator.h"
|
#include "accountmigrator.h"
|
||||||
#include "accountstate.h"
|
#include "accountstate.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
#include <CoreServices/CoreServices.h>
|
#include <CoreServices/CoreServices.h>
|
||||||
|
@ -852,9 +853,10 @@ bool FolderMan::startFromScratch( const QString& localFolder )
|
||||||
|
|
||||||
// Make a backup of the folder/file.
|
// Make a backup of the folder/file.
|
||||||
QString newName = getBackupName( parentDir.absoluteFilePath( folderName ) );
|
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()
|
qDebug() << "startFromScratch: Could not rename" << fi.absoluteFilePath()
|
||||||
<< "to" << newName;
|
<< "to" << newName << "error:" << renameError;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,54 @@ bool FileSystem::setModTime(const QString& filename, time_t modTime)
|
||||||
return true;
|
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)
|
bool FileSystem::renameReplace(const QString& originFileName, const QString& destinationFileName, QString* errorString)
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
|
@ -215,16 +263,6 @@ bool FileSystem::openFileSharedRead(QFile* file, QString* error)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#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)
|
static qint64 getSizeWithCsync(const QString& filename)
|
||||||
{
|
{
|
||||||
qint64 result = 0;
|
qint64 result = 0;
|
||||||
|
|
|
@ -59,6 +59,14 @@ qint64 OWNCLOUDSYNC_EXPORT getSize(const QString& filename);
|
||||||
*/
|
*/
|
||||||
bool OWNCLOUDSYNC_EXPORT fileExists(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
|
* Rename the file \a originFileName to \a destinationFileName, and overwrite the destination if it
|
||||||
* already exists
|
* already exists
|
||||||
|
|
|
@ -492,11 +492,11 @@ void PropagateDownloadFileQNAM::downloadFinished()
|
||||||
bool isConflict = _item._instruction == CSYNC_INSTRUCTION_CONFLICT
|
bool isConflict = _item._instruction == CSYNC_INSTRUCTION_CONFLICT
|
||||||
&& !FileSystem::fileEquals(fn, _tmpFile.fileName());
|
&& !FileSystem::fileEquals(fn, _tmpFile.fileName());
|
||||||
if (isConflict) {
|
if (isConflict) {
|
||||||
QFile f(fn);
|
QString renameError;
|
||||||
QString conflictFileName = makeConflictFileName(fn, Utility::qDateTimeFromTime_t(_item._modtime));
|
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.
|
//If the rename fails, don't replace it.
|
||||||
done(SyncFileItem::SoftError, f.errorString());
|
done(SyncFileItem::SoftError, renameError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "owncloudpropagator_p.h"
|
#include "owncloudpropagator_p.h"
|
||||||
#include "account.h"
|
#include "account.h"
|
||||||
#include "syncjournalfilerecord.h"
|
#include "syncjournalfilerecord.h"
|
||||||
|
#include "filesystem.h"
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
|
@ -81,7 +82,8 @@ void PropagateRemoteMove::start()
|
||||||
QString originalFile(_propagator->getFilePath(QLatin1String("Shared")));
|
QString originalFile(_propagator->getFilePath(QLatin1String("Shared")));
|
||||||
_propagator->addTouchedFile(originalFile);
|
_propagator->addTouchedFile(originalFile);
|
||||||
_propagator->addTouchedFile(targetFile);
|
_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."));
|
done(SyncFileItem::NormalError, tr("This folder must not be renamed. It is renamed back to its original name."));
|
||||||
} else {
|
} else {
|
||||||
done(SyncFileItem::NormalError, tr("This folder must not be renamed. Please name it back to Shared."));
|
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.
|
&& !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
|
//In case of conflict, make a backup of the old file
|
||||||
if (isConflict) {
|
if (isConflict) {
|
||||||
QFile f(fn);
|
|
||||||
QString conflictFileName = makeConflictFileName(fn, Utility::qDateTimeFromTime_t(_item._modtime));
|
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.
|
//If the rename fails, don't replace it.
|
||||||
done(SyncFileItem::NormalError, f.errorString());
|
done(SyncFileItem::NormalError, renameError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,9 +155,9 @@ void PropagateLocalRename::start()
|
||||||
|
|
||||||
_propagator->addTouchedFile(existingFile);
|
_propagator->addTouchedFile(existingFile);
|
||||||
_propagator->addTouchedFile(targetFile);
|
_propagator->addTouchedFile(targetFile);
|
||||||
QFile file(existingFile);
|
QString renameError;
|
||||||
if (!file.rename(targetFile)) {
|
if (!FileSystem::rename(existingFile, targetFile, &renameError)) {
|
||||||
done(SyncFileItem::NormalError, file.errorString());
|
done(SyncFileItem::NormalError, renameError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue