summaryrefslogtreecommitdiff
path: root/plugins/CopyEngine/Ultracopier/TransferThread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/CopyEngine/Ultracopier/TransferThread.cpp')
-rw-r--r--plugins/CopyEngine/Ultracopier/TransferThread.cpp2101
1 files changed, 0 insertions, 2101 deletions
diff --git a/plugins/CopyEngine/Ultracopier/TransferThread.cpp b/plugins/CopyEngine/Ultracopier/TransferThread.cpp
deleted file mode 100644
index 210c221..0000000
--- a/plugins/CopyEngine/Ultracopier/TransferThread.cpp
+++ /dev/null
@@ -1,2101 +0,0 @@
-//presume bug linked as multple paralelle inode to resume after "overwrite"
-//then do overwrite node function to not re-set the file name
-
-#include "TransferThread.h"
-#ifdef Q_OS_WIN32
-#include <windows.h>
-#endif
-
-#ifdef Q_OS_WIN32
- #ifndef ULTRACOPIER_PLUGIN_SET_TIME_UNIX_WAY
- #ifndef NOMINMAX
- #define NOMINMAX
- #endif
- #include <windows.h>
- #endif
-#endif
-
-#ifdef Q_OS_WIN32
-#define CURRENTSEPARATOR "\\"
-#else
-#define CURRENTSEPARATOR "/"
-#endif
-
-#include "../../../cpp11addition.h"
-
-TransferThread::TransferThread() :
- haveStartTime (false),
- transfer_stat (TransferStat_Idle),
- doRightTransfer (false),
- #ifdef ULTRACOPIER_PLUGIN_RSYNC
- rsync (false),
- #endif
- stopIt (false),
- fileExistsAction (FileExists_NotSet),
- alwaysDoFileExistsAction (FileExists_NotSet),
- needSkip (false),
- needRemove (false),
- deletePartiallyTransferredFiles (true),
- writeError (false),
- readError (false),
- renameTheOriginalDestination (false),
- havePermission (false)
-{
- start();
- moveToThread(this);
- readThread.setWriteThread(&writeThread);
- source.setCaching(false);
- destination.setCaching(false);
- renameRegex=std::regex("^(.*)(\\.[a-zA-Z0-9]+)$");
- #ifdef Q_OS_WIN32
- #ifndef ULTRACOPIER_PLUGIN_SET_TIME_UNIX_WAY
- regRead=std::regex("^[a-zA-Z]:");
- #endif
- #endif
-
- minTime=QDateTime(QDate(ULTRACOPIER_PLUGIN_MINIMALYEAR,1,1));
-}
-
-TransferThread::~TransferThread()
-{
- stopIt=true;
- readThread.exit();
- readThread.wait();
- writeThread.exit();
- writeThread.wait();
- exit();
- //else cash without this disconnect
- //disconnect(&readThread);
- //disconnect(&writeThread);
- wait();
-}
-
-void TransferThread::run()
-{
- //ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+QStringLiteral("] start: ")+QString::number((qint64)QThread::currentThreadId())));
- transfer_stat = TransferStat_Idle;
- stopIt = false;
- fileExistsAction = FileExists_NotSet;
- alwaysDoFileExistsAction= FileExists_NotSet;
- //the error push
- connect(&readThread,&ReadThread::error, this, &TransferThread::getReadError, Qt::QueuedConnection);
- connect(&writeThread,&WriteThread::error, this, &TransferThread::getWriteError, Qt::QueuedConnection);
- //the thread change operation
- connect(this,&TransferThread::internalStartPreOperation, this, &TransferThread::preOperation, Qt::QueuedConnection);
- connect(this,&TransferThread::internalStartPostOperation, this, &TransferThread::postOperation, Qt::QueuedConnection);
- //the state change operation
- connect(&readThread,&ReadThread::opened, this, &TransferThread::readIsReady, Qt::QueuedConnection);
- connect(&writeThread,&WriteThread::opened, this, &TransferThread::writeIsReady, Qt::QueuedConnection);
- connect(&readThread,&ReadThread::readIsStopped, this, &TransferThread::readIsStopped, Qt::QueuedConnection);
- connect(&writeThread,&WriteThread::writeIsStopped, this, &TransferThread::writeIsStopped, Qt::QueuedConnection);
- connect(&readThread,&ReadThread::readIsStopped, &writeThread, &WriteThread::endIsDetected, Qt::QueuedConnection);
- connect(&readThread,&ReadThread::closed, this, &TransferThread::readIsClosed, Qt::QueuedConnection);
- connect(&writeThread,&WriteThread::closed, this, &TransferThread::writeIsClosed, Qt::QueuedConnection);
- connect(&writeThread,&WriteThread::reopened, this, &TransferThread::writeThreadIsReopened, Qt::QueuedConnection);
- connect(&readThread,&ReadThread::checksumFinish, this, &TransferThread::readChecksumFinish, Qt::QueuedConnection);
- connect(&writeThread,&WriteThread::checksumFinish, this, &TransferThread::writeChecksumFinish, Qt::QueuedConnection);
- //error management
- connect(&readThread,&ReadThread::isSeekToZeroAndWait, this, &TransferThread::readThreadIsSeekToZeroAndWait, Qt::QueuedConnection);
- connect(&readThread,&ReadThread::resumeAfterErrorByRestartAtTheLastPosition,this, &TransferThread::readThreadResumeAfterError, Qt::QueuedConnection);
- connect(&readThread,&ReadThread::resumeAfterErrorByRestartAll,&writeThread, &WriteThread::flushAndSeekToZero, Qt::QueuedConnection);
- connect(&writeThread,&WriteThread::flushedAndSeekedToZero, this, &TransferThread::readThreadResumeAfterError, Qt::QueuedConnection);
- connect(this,&TransferThread::internalTryStartTheTransfer, this, &TransferThread::internalStartTheTransfer, Qt::QueuedConnection);
-
- #ifdef ULTRACOPIER_PLUGIN_DEBUG
- connect(&readThread,&ReadThread::debugInformation, this, &TransferThread::debugInformation, Qt::QueuedConnection);
- connect(&writeThread,&WriteThread::debugInformation, this, &TransferThread::debugInformation, Qt::QueuedConnection);
- connect(&driveManagement,&DriveManagement::debugInformation,this, &TransferThread::debugInformation, Qt::QueuedConnection);
- #endif
-
- exec();
-}
-
-TransferStat TransferThread::getStat() const
-{
- return transfer_stat;
-}
-
-void TransferThread::startTheTransfer()
-{
- emit internalTryStartTheTransfer();
-}
-
-void TransferThread::internalStartTheTransfer()
-{
- if(transfer_stat==TransferStat_Idle)
- {
- if(mode!=Ultracopier::Move)
- {
- /// \bug can pass here because in case of direct move on same media, it return to idle stat directly
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] can't start transfert at idle"));
- }
- return;
- }
- if(transfer_stat==TransferStat_PostOperation)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] can't start transfert at PostOperation"));
- return;
- }
- if(transfer_stat==TransferStat_Transfer)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] can't start transfert at Transfer"));
- return;
- }
- if(canStartTransfer)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] canStartTransfer is already set to true"));
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+("] check how start the transfer"));
- canStartTransfer=true;
- if(readIsReadyVariable && writeIsReadyVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+("] start directly the transfer"));
- ifCanStartTransfer();
- }
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+("] start the transfer as delayed"));
-}
-
-bool TransferThread::setFiles(const QFileInfo& source, const int64_t &size, const QFileInfo& destination, const Ultracopier::CopyMode &mode)
-{
- if(transfer_stat!=TransferStat_Idle)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] already used, source: ")+source.absoluteFilePath().toStdString()+", destination: "+destination.absoluteFilePath().toStdString());
- return false;
- }
- //to prevent multiple file alocation into ListThread::doNewActions_inode_manipulation()
- transfer_stat = TransferStat_PreOperation;
- //emit pushStat(stat,transferId);
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start, source: "+source.absoluteFilePath().toStdString()+", destination: "+destination.absoluteFilePath().toStdString());
- this->source = source;
- this->destination = destination;
- this->mode = mode;
- this->size = size;
- stopIt = false;
- fileExistsAction = FileExists_NotSet;
- canStartTransfer = false;
- sended_state_preOperationStopped= false;
- canBeMovedDirectlyVariable = false;
- canBeCopiedDirectlyVariable = false;
- fileContentError = false;
- real_doChecksum = false;
- writeError = false;
- writeError_source_seeked = false;
- writeError_destination_reopened = false;
- readError = false;
- fileContentError = false;
- resetExtraVariable();
- emit internalStartPreOperation();
- return true;
-}
-
-void TransferThread::setFileExistsAction(const FileExistsAction &action)
-{
- if(transfer_stat!=TransferStat_PreOperation)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] already used, source: ")+source.absoluteFilePath().toStdString()+(", destination: ")+destination.absoluteFilePath().toStdString());
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+("] action: ")+std::to_string(action));
- if(action!=FileExists_Rename)
- fileExistsAction = action;
- else
- {
- //always rename pass here
- fileExistsAction = action;
- alwaysDoFileExistsAction=action;
- }
- if(action==FileExists_Skip)
- {
- skip();
- return;
- }
- resetExtraVariable();
- emit internalStartPreOperation();
-}
-
-void TransferThread::setFileRename(const std::string &nameForRename)
-{
- if(transfer_stat!=TransferStat_PreOperation)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] already used, source: ")+source.absoluteFilePath().toStdString()+(", destination: ")+destination.absoluteFilePath().toStdString());
- return;
- }
- if(QString::fromStdString(nameForRename).contains(QRegularExpression(QStringLiteral("[/\\\\\\*]"))))
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] can't use this kind of name, internal error"));
- emit errorOnFile(destination,tr("Try rename with using special characters").toStdString());
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] nameForRename: "+nameForRename);
- if(!renameTheOriginalDestination)
- destination.setFile(destination.absolutePath()+CURRENTSEPARATOR+QString::fromStdString(nameForRename));
- else
- {
- QString tempDestination=destination.absoluteFilePath();
- QFile destinationFile(tempDestination);
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Information,"["+std::to_string(id)+"] "+QStringLiteral("rename %1: to: %2").arg(destination.absoluteFilePath()).arg(destination.absolutePath()+CURRENTSEPARATOR+QString::fromStdString(nameForRename)).toStdString());
- if(!destinationFile.rename(destination.absolutePath()+CURRENTSEPARATOR+QString::fromStdString(nameForRename)))
- {
- if(!destinationFile.exists())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("source not exists %1: destination: %2, error: %3").arg(destinationFile.fileName()).arg(destinationFile.fileName()).arg(destinationFile.errorString()).toStdString());
- emit errorOnFile(destinationFile,tr("File not found").toStdString());
- return;
- }
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("unable to do real move %1: %2, error: %3").arg(destinationFile.fileName()).arg(destinationFile.fileName()).arg(destinationFile.errorString()).toStdString());
- emit errorOnFile(destinationFile,destinationFile.errorString().toStdString());
- return;
- }
- if(source.absoluteFilePath()==destination.absoluteFilePath())
- source.setFile(destination.absolutePath()+CURRENTSEPARATOR+QString::fromStdString(nameForRename));
- destination.setFile(tempDestination);
- destination.refresh();
- }
- fileExistsAction = FileExists_NotSet;
- resetExtraVariable();
- emit internalStartPreOperation();
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] destination is: "+destination.absoluteFilePath().toStdString());
-}
-
-void TransferThread::setAlwaysFileExistsAction(const FileExistsAction &action)
-{
- //ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+QStringLiteral("] action to do always: ")+QString::number(action)));
- alwaysDoFileExistsAction=action;
-}
-
-void TransferThread::resetExtraVariable()
-{
- sended_state_preOperationStopped=false;
- sended_state_readStopped = false;
- sended_state_writeStopped = false;
- writeError = false;
- readError = false;
- readIsReadyVariable = false;
- writeIsReadyVariable = false;
- readIsFinishVariable = false;
- writeIsFinishVariable = false;
- readIsClosedVariable = false;
- writeIsClosedVariable = false;
- needRemove = false;
- needSkip = false;
- retry = false;
- readIsOpenVariable = false;
- writeIsOpenVariable = false;
- readIsOpeningVariable = false;
- writeIsOpeningVariable = false;
- havePermission = false;
-}
-
-void TransferThread::preOperation()
-{
- if(transfer_stat!=TransferStat_PreOperation)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] already used, source: ")+source.absoluteFilePath().toStdString()+", destination: "+destination.absoluteFilePath().toStdString());
- return;
- }
- haveStartTime=true;
- startTransferTime.restart();
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start: source: "+source.absoluteFilePath().toStdString()+", destination: "+destination.absoluteFilePath().toStdString());
- needRemove=false;
- if(isSame())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] is same "+source.absoluteFilePath().toStdString()+" than "+destination.absoluteFilePath().toStdString());
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] after is same");
- /*Why this code?
- if(readError)
- {
- readError=false;
- return;
- }*/
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] before destination exists");
- if(destinationExists())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] destination exists: "+destination.absoluteFilePath().toStdString());
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] after destination exists");
- /*Why this code?
- if(readError)
- {
- readError=false;
- return;
- }*/
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] before keep date");
- #ifdef Q_OS_WIN32
- doTheDateTransfer=!source.isSymLink();
- #else
- doTheDateTransfer=true;
- #endif
- if(doTheDateTransfer)
- {
- if(source.lastModified()<minTime)
- {
- if(/*true when the destination have been remove but not the symlink:*/source.isSymLink())
- doTheDateTransfer=false;
- else
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"the sources is older to copy the time: "+source.absoluteFilePath().toStdString()+": "+minTime.toString(QStringLiteral("dd.MM.yyyy hh:mm:ss.zzz")).toStdString()+">="+source.lastModified().toString(QStringLiteral("dd.MM.yyyy hh:mm:ss.zzz")).toStdString());
- doTheDateTransfer=false;
- if(keepDate)
- {
- emit errorOnFile(source,tr("Wrong modification date or unable to get it, you can disable time transfer to do it").toStdString());
- return;
- }
- }
- }
- else
- {
- doTheDateTransfer=readFileDateTime(source);
- #ifdef Q_OS_MAC
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] read the source time: "+std::to_string(butime.modtime));
- #endif
- if(!doTheDateTransfer)
- {
- //will have the real error at source open
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] unable to read the source time: "+source.absoluteFilePath().toStdString());
- if(keepDate)
- {
- emit errorOnFile(source,tr("Wrong modification date or unable to get it, you can disable time transfer to do it").toStdString());
- return;
- }
- }
- }
- }
- if(canBeMovedDirectly())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] "+QStringLiteral("need moved directly: %1 to %2").arg(source.absoluteFilePath()).arg(destination.absoluteFilePath()).toStdString());
- canBeMovedDirectlyVariable=true;
- readThread.fakeOpen();
- writeThread.fakeOpen();
- return;
- }
- if(canBeCopiedDirectly())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] "+QStringLiteral("need copied directly: %1 to %2").arg(source.absoluteFilePath()).arg(destination.absoluteFilePath()).toStdString());
- canBeCopiedDirectlyVariable=true;
- readThread.fakeOpen();
- writeThread.fakeOpen();
- return;
- }
- tryOpen();
-}
-
-void TransferThread::tryOpen()
-{
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start source and destination: "+source.absoluteFilePath().toStdString()+" and "+destination.absoluteFilePath().toStdString());
- TransferAlgorithm transferAlgorithm=this->transferAlgorithm;
- if(transferAlgorithm==TransferAlgorithm_Automatic)
- {
- #ifdef Q_OS_LINUX
- if(driveManagement.isSameDrive(destination.absoluteFilePath().toStdString(),source.absoluteFilePath().toStdString()))
- {
- const QByteArray &type=driveManagement.getDriveType(driveManagement.getDrive(source.absoluteFilePath().toStdString()));
- if(type=="nfs" || type=="smb")
- transferAlgorithm=TransferAlgorithm_Parallel;
- else
- transferAlgorithm=TransferAlgorithm_Sequential;
- }
- else
- #endif
- transferAlgorithm=TransferAlgorithm_Parallel;
- }
- if(!readIsOpenVariable)
- {
- if(!readIsOpeningVariable)
- {
- readError=false;
- readThread.open(source.absoluteFilePath(),mode);
- readIsOpeningVariable=true;
-
- if(doRightTransfer)
- havePermission=readFilePermissions(QFile(source.absoluteFilePath()));
- }
- else
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] readIsOpeningVariable is true when try open");
- emit errorOnFile(source,tr("Internal error: Already opening").toStdString());
- readError=true;
- return;
- }
- }
- if(!writeIsOpenVariable)
- {
- if(!writeIsOpeningVariable)
- {
- if(transferAlgorithm==TransferAlgorithm_Sequential)
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] transferAlgorithm==TransferAlgorithm_Sequential");
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] transferAlgorithm==TransferAlgorithm_Parallel");
- writeError=false;
- if(transferAlgorithm==TransferAlgorithm_Sequential)
- writeThread.open(destination.absoluteFilePath(),size,osBuffer && (!osBufferLimited || (osBufferLimited && size<osBufferLimit)),sequentialBuffer,true);
- else
- writeThread.open(destination.absoluteFilePath(),size,osBuffer && (!osBufferLimited || (osBufferLimited && size<osBufferLimit)),parallelBuffer,false);
- writeIsOpeningVariable=true;
- }
- else
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+"writeIsOpeningVariable is true when try open");
- emit errorOnFile(destination,tr("Internal error: Already opening").toStdString());
- writeError=true;
- return;
- }
- }
-}
-
-bool TransferThread::isSame()
-{
- //check if source and destination is not the same
- //source.absoluteFilePath()==destination.absoluteFilePath() not work is source don't exists
- if(source.absoluteFilePath()==destination.absoluteFilePath())
- {
- #ifdef ULTRACOPIER_PLUGIN_DEBUG
- if(!source.exists())
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start source: "+source.absoluteFilePath().toStdString()+" not exists");
- if(!source.isSymLink())
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start source: "+source.absoluteFilePath().toStdString()+" isSymLink");
- if(!destination.isSymLink())
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start source: "+destination.absoluteFilePath().toStdString()+" isSymLink");
- #endif
- if(fileExistsAction==FileExists_NotSet && alwaysDoFileExistsAction==FileExists_Skip)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] is same but skip");
- transfer_stat=TransferStat_Idle;
- emit postOperationStopped();
- //quit
- return true;
- }
- if(checkAlwaysRename())
- return false;
- emit fileAlreadyExists(source,destination,true);
- return true;
- }
- return false;
-}
-
-bool TransferThread::destinationExists()
-{
- //check if destination exists
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] "+QStringLiteral("overwrite: %1, alwaysDoFileExistsAction: %2, readError: %3, writeError: %4")
- .arg(fileExistsAction)
- .arg(alwaysDoFileExistsAction)
- .arg(readError)
- .arg(writeError)
- .toStdString()
- );
- if(alwaysDoFileExistsAction==FileExists_Overwrite || readError || writeError
- #ifdef ULTRACOPIER_PLUGIN_RSYNC
- || rsync
- #endif
- )
- return false;
- bool destinationExists;
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] time to first FS access");
- destination.refresh();
- destinationExists=destination.exists();
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] finish first FS access");
- if(destinationExists)
- {
- if(fileExistsAction==FileExists_NotSet && alwaysDoFileExistsAction==FileExists_Skip)
- {
- transfer_stat=TransferStat_Idle;
- emit postOperationStopped();
- //quit
- return true;
- }
- if(checkAlwaysRename())
- return false;
- if(source.exists())
- {
- if(fileExistsAction==FileExists_OverwriteIfNewer || (fileExistsAction==FileExists_NotSet && alwaysDoFileExistsAction==FileExists_OverwriteIfNewer))
- {
- if(destination.lastModified()<source.lastModified())
- return false;
- else
- {
- transfer_stat=TransferStat_Idle;
- emit postOperationStopped();
- return true;
- }
- }
- if(fileExistsAction==FileExists_OverwriteIfOlder || (fileExistsAction==FileExists_NotSet && alwaysDoFileExistsAction==FileExists_OverwriteIfOlder))
- {
- if(destination.lastModified()>source.lastModified())
- return false;
- else
- {
- transfer_stat=TransferStat_Idle;
- emit postOperationStopped();
- return true;
- }
- }
- if(fileExistsAction==FileExists_OverwriteIfNotSame || (fileExistsAction==FileExists_NotSet && alwaysDoFileExistsAction==FileExists_OverwriteIfNotSame))
- {
- if(destination.lastModified()!=source.lastModified() || destination.size()!=source.size())
- return false;
- else
- {
- transfer_stat=TransferStat_Idle;
- emit postOperationStopped();
- return true;
- }
- }
- }
- else
- {
- if(fileExistsAction!=FileExists_NotSet)
- {
- transfer_stat=TransferStat_Idle;
- emit postOperationStopped();
- return true;
- }
- }
- if(fileExistsAction==FileExists_NotSet)
- {
- emit fileAlreadyExists(source,destination,false);
- return true;
- }
- }
- return false;
-}
-
-std::string TransferThread::resolvedName(const QFileInfo &inode)
-{
- QString fileName=inode.fileName();
- if(fileName.isEmpty())
- {
- QDir absoluteDir=inode.absoluteDir();
- fileName=absoluteDir.dirName();
- if(fileName.isEmpty())
- {
- fileName=absoluteDir.cdUp();
- fileName=absoluteDir.dirName();
- }
- }
- #ifdef Q_OS_WIN32
- if(fileName.isEmpty())
- {
- fileName=inode.absolutePath();
- fileName.replace(QRegularExpression(QStringLiteral("^([a-zA-Z]+):.*$")),QStringLiteral("\\1"));
- if(inode.absolutePath().contains(QRegularExpression(QStringLiteral("^[a-zA-Z]+:[/\\\\]?$"))))
- fileName=tr("Drive %1").arg(fileName);
- else
- fileName=tr("Unknown folder");
- }
- #else
- if(fileName.isEmpty())
- fileName=tr("root");
- #endif
- return fileName.toStdString();
-}
-
-std::string TransferThread::getSourcePath() const
-{
- return source.absoluteFilePath().toStdString();
-}
-
-std::string TransferThread::getDestinationPath() const
-{
- return destination.absoluteFilePath().toStdString();
-}
-
-QFileInfo TransferThread::getSourceInode() const
-{
- return source;
-}
-
-QFileInfo TransferThread::getDestinationInode() const
-{
- return destination;
-}
-
-Ultracopier::CopyMode TransferThread::getMode() const
-{
- return mode;
-}
-
-//return true if has been renamed
-bool TransferThread::checkAlwaysRename()
-{
- if(alwaysDoFileExistsAction==FileExists_Rename)
- {
- QFileInfo newDestination=destination;
- std::string fileName=resolvedName(newDestination);
- std::string suffix;
- std::string newFileName;
- //resolv the suffix
- if(std::regex_match(fileName,renameRegex))
- {
- suffix=fileName;
- suffix=std::regex_replace(suffix,renameRegex,"$2");
- fileName=std::regex_replace(fileName,renameRegex,"$1");
- }
- //resolv the new name
- int num=1;
- do
- {
- if(num==1)
- {
- if(firstRenamingRule.empty())
- newFileName=tr("%name% - copy").toStdString();
- else
- newFileName=firstRenamingRule;
- }
- else
- {
- if(otherRenamingRule.empty())
- newFileName=tr("%name% - copy (%number%)").toStdString();
- else
- newFileName=otherRenamingRule;
- stringreplaceAll(newFileName,"%number%",std::to_string(num));
- }
- stringreplaceAll(newFileName,"%name%",fileName);
- stringreplaceAll(newFileName,"%suffix%",suffix);
- newDestination.setFile(newDestination.absolutePath()+CURRENTSEPARATOR+QString::fromStdString(newFileName));
- num++;
- }
- while(newDestination.exists());
- if(!renameTheOriginalDestination)
- destination=newDestination;
- else
- {
- QFile destinationFile(destination.absoluteFilePath());
- if(!destinationFile.rename(newDestination.absoluteFilePath()))
- {
- if(!destinationFile.exists())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("source not exists %1: destination: %2, error: %3").arg(destinationFile.fileName()).arg(destinationFile.fileName()).arg(destinationFile.errorString()).toStdString());
- emit errorOnFile(destinationFile,tr("File not found").toStdString());
- readError=true;
- return true;
- }
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("unable to do real move %1: %2, error: %3").arg(destinationFile.fileName()).arg(destinationFile.fileName()).arg(destinationFile.errorString()).toStdString());
- readError=true;
- emit errorOnFile(destinationFile,destinationFile.errorString().toStdString());
- return true;
- }
- }
- return true;
- }
- return false;
-}
-
-void TransferThread::tryMoveDirectly()
-{
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] "+QStringLiteral("need moved directly: %1 to %2").arg(source.absoluteFilePath()).arg(destination.absoluteFilePath()).toStdString());
-
- sended_state_readStopped = false;
- sended_state_writeStopped = false;
- writeError = false;
- readError = false;
- readIsFinishVariable = false;
- writeIsFinishVariable = false;
- readIsClosedVariable = false;
- writeIsClosedVariable = false;
- //move if on same mount point
- QFile sourceFile(source.absoluteFilePath());
- QFile destinationFile(destination.absoluteFilePath());
- #ifndef Q_OS_WIN32
- if(destinationFile.exists() || destination.isSymLink())
- {
- if(!sourceFile.exists() && !source.isSymLink())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+destinationFile.fileName().toStdString()+", source not exists");
- readError=true;
- emit errorOnFile(destination,tr("The source file doesn't exist").toStdString());
- return;
- }
- else if(!destinationFile.remove())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+destinationFile.fileName().toStdString()+", error: "+destinationFile.errorString().toStdString());
- readError=true;
- emit errorOnFile(destination,destinationFile.errorString().toStdString());
- return;
- }
- }
- #endif
- QDir dir(destination.absolutePath());
- {
- mkpathTransfer->acquire();
- if(!dir.exists())
- dir.mkpath(destination.absolutePath());
- mkpathTransfer->release();
- }
- #ifdef Q_OS_WIN32
- //if(!sourceFile.copy(destinationFile.fileName()))
- if(MoveFileEx(
- reinterpret_cast<const wchar_t*>(sourceFile.fileName().utf16()),
- reinterpret_cast<const wchar_t*>(destinationFile.fileName().utf16()),
- MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING
- )==0)
- #else
- if(!sourceFile.rename(destinationFile.fileName()))
- #endif
- {
- readError=true;
- if(!sourceFile.exists() && !source.isSymLink())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("source not exists %1: destination: %2, error: %3").arg(sourceFile.fileName()).arg(destinationFile.fileName()).arg(sourceFile.errorString()).toStdString());
- emit errorOnFile(sourceFile,tr("File not found").toStdString());
- return;
- }
- else if(!dir.exists())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("destination folder not exists %1: %2, error: %3").arg(sourceFile.fileName()).arg(destinationFile.fileName()).arg(sourceFile.errorString()).toStdString());
- emit errorOnFile(destination.absolutePath(),tr("Unable to do the folder").toStdString());
- return;
- }
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("unable to do real move %1: %2, error: %3").arg(sourceFile.fileName()).arg(destinationFile.fileName()).arg(sourceFile.errorString()).toStdString());
- emit errorOnFile(sourceFile,sourceFile.errorString().toStdString());
- return;
- }
- readThread.fakeReadIsStarted();
- writeThread.fakeWriteIsStarted();
- readThread.fakeReadIsStopped();
- writeThread.fakeWriteIsStopped();
-}
-
-void TransferThread::tryCopyDirectly()
-{
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] "+QStringLiteral("need copied directly: %1 to %2").arg(source.absoluteFilePath()).arg(destination.absoluteFilePath()).toStdString());
-
- sended_state_readStopped = false;
- sended_state_writeStopped = false;
- writeError = false;
- readError = false;
- readIsFinishVariable = false;
- writeIsFinishVariable = false;
- readIsClosedVariable = false;
- writeIsClosedVariable = false;
- //move if on same mount point
- QFile sourceFile(source.absoluteFilePath());
- QFile destinationFile(destination.absoluteFilePath());
- #ifndef Q_OS_WIN32
- if(destinationFile.exists() || destination.isSymLink())
- {
- if(!sourceFile.exists() && !source.isSymLink())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+destinationFile.fileName().toStdString()+", source not exists");
- readError=true;
- emit errorOnFile(destination,tr("The source doesn't exist").toStdString());
- return;
- }
- else if(!destinationFile.remove())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+destinationFile.fileName().toStdString()+", error: "+destinationFile.errorString().toStdString());
- readError=true;
- emit errorOnFile(destination,destinationFile.errorString().toStdString());
- return;
- }
- }
- #endif
- QDir dir(destination.absolutePath());
- {
- mkpathTransfer->acquire();
- if(!dir.exists())
- dir.mkpath(destination.absolutePath());
- mkpathTransfer->release();
- }
- /** on windows, symLink is normal file, can be copied
- * on unix not, should be created **/
- #ifdef Q_OS_WIN32
- //if(!sourceFile.copy(destinationFile.fileName()))
- if(CopyFileEx(
- reinterpret_cast<const wchar_t*>(sourceFile.fileName().utf16()),
- reinterpret_cast<const wchar_t*>(destinationFile.fileName().utf16()),
- NULL,
- NULL,
- FALSE,
- 0
- )==0)
- #else
- if(!QFile::link(sourceFile.symLinkTarget(),destinationFile.fileName()))
- #endif
- {
- readError=true;
- if(!sourceFile.exists() && !source.isSymLink())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("source not exists %1 -> %4: %2, error: %3").arg(sourceFile.fileName()).arg(destinationFile.fileName()).arg(sourceFile.errorString()).arg(sourceFile.symLinkTarget()).toStdString());
- emit errorOnFile(sourceFile,tr("The source file doesn't exist").toStdString());
- return;
- }
- else if(destinationFile.exists() || destination.isSymLink())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("destination already exists %1 -> %4: %2, error: %3").arg(sourceFile.fileName()).arg(destinationFile.fileName()).arg(sourceFile.errorString()).arg(sourceFile.symLinkTarget()).toStdString());
- emit errorOnFile(sourceFile,tr("Another file exists at same place").toStdString());
- return;
- }
- else if(!dir.exists())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("destination folder not exists %1 -> %4: %2, error: %3").arg(sourceFile.fileName()).arg(destinationFile.fileName()).arg(sourceFile.errorString()).arg(sourceFile.symLinkTarget()).toStdString());
- emit errorOnFile(sourceFile,tr("Unable to do the folder").toStdString());
- return;
- }
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] "+QStringLiteral("unable to do sym link copy %1 -> %4: %2, error: %3").arg(sourceFile.fileName()).arg(destinationFile.fileName()).arg(sourceFile.errorString()).arg(sourceFile.symLinkTarget()).toStdString());
- emit errorOnFile(sourceFile,sourceFile.errorString().toStdString());
- return;
- }
- readThread.fakeReadIsStarted();
- writeThread.fakeWriteIsStarted();
- readThread.fakeReadIsStopped();
- writeThread.fakeWriteIsStopped();
-}
-
-bool TransferThread::canBeMovedDirectly() const
-{
- if(mode!=Ultracopier::Move)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] mode!=Ultracopier::Move");
- return false;
- }
- return source.isSymLink() || driveManagement.isSameDrive(destination.absoluteFilePath().toStdString(),source.absoluteFilePath().toStdString());
-}
-
-bool TransferThread::canBeCopiedDirectly() const
-{
- return source.isSymLink();
-}
-
-void TransferThread::readIsReady()
-{
- if(readIsReadyVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] double event dropped");
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- readIsReadyVariable=true;
- readIsOpenVariable=true;
- readIsClosedVariable=false;
- readIsOpeningVariable=false;
- ifCanStartTransfer();
-}
-
-void TransferThread::ifCanStartTransfer()
-{
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] readIsReadyVariable: "+std::to_string(readIsReadyVariable)+", writeIsReadyVariable: "+std::to_string(writeIsReadyVariable));
- if(readIsReadyVariable && writeIsReadyVariable)
- {
- transfer_stat=TransferStat_WaitForTheTransfer;
- sended_state_readStopped = false;
- sended_state_writeStopped = false;
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] stat=WaitForTheTransfer");
- if(!sended_state_preOperationStopped)
- {
- sended_state_preOperationStopped=true;
- emit preOperationStopped();
- }
- if(canStartTransfer)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] stat=Transfer, "+QStringLiteral("canBeMovedDirectlyVariable: %1, canBeCopiedDirectlyVariable: %2").arg(canBeMovedDirectlyVariable).arg(canBeCopiedDirectlyVariable).toStdString());
- transfer_stat=TransferStat_Transfer;
- if(canBeMovedDirectlyVariable)
- tryMoveDirectly();
- else if(canBeCopiedDirectlyVariable)
- tryCopyDirectly();
- else
- {
- needRemove=deletePartiallyTransferredFiles;
- readThread.startRead();
- }
- emit pushStat(transfer_stat,transferId);
- }
- //else
- //emit pushStat(stat,transferId);
- }
-}
-
-void TransferThread::writeIsReady()
-{
- if(writeIsReadyVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] double event dropped");
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- writeIsReadyVariable=true;
- writeIsOpenVariable=true;
- writeIsClosedVariable=false;
- writeIsOpeningVariable=false;
- ifCanStartTransfer();
-}
-
-
-//set the copy info and options before runing
-void TransferThread::setRightTransfer(const bool doRightTransfer)
-{
- this->doRightTransfer=doRightTransfer;
-}
-
-//set keep date
-void TransferThread::setKeepDate(const bool keepDate)
-{
- this->keepDate=keepDate;
-}
-
-#ifdef ULTRACOPIER_PLUGIN_SPEED_SUPPORT
-//set the current max speed in KB/s
-void TransferThread::setMultiForBigSpeed(const int &multiForBigSpeed)
-{
- readThread.setMultiForBigSpeed(multiForBigSpeed);
- writeThread.setMultiForBigSpeed(multiForBigSpeed);
-}
-#endif
-
-//set block size in Bytes
-bool TransferThread::setBlockSize(const unsigned int blockSize)
-{
- bool read=readThread.setBlockSize(blockSize);
- bool write=writeThread.setBlockSize(blockSize);
- return (read && write);
-}
-
-//pause the copy
-void TransferThread::pause()
-{
- //only pause/resume during the transfer of file data
- //from transfer_stat!=TransferStat_Idle because it resume at wrong order
- if(transfer_stat!=TransferStat_Transfer && transfer_stat!=TransferStat_PostTransfer && transfer_stat!=TransferStat_Checksum)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] wrong stat to put in pause");
- return;
- }
- haveStartTime=false;
- readThread.pause();
- writeThread.pause();
-}
-
-//resume the copy
-void TransferThread::resume()
-{
- //only pause/resume during the transfer of file data
- //from transfer_stat!=TransferStat_Idle because it resume at wrong order
- if(transfer_stat!=TransferStat_Transfer && transfer_stat!=TransferStat_PostTransfer && transfer_stat!=TransferStat_Checksum)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] wrong stat to put in pause");
- return;
- }
- readThread.resume();
- writeThread.resume();
-}
-
-//stop the current copy
-void TransferThread::stop()
-{
- stopIt=true;
- haveStartTime=false;
- if(transfer_stat==TransferStat_Idle)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"transfer_stat==TransferStat_Idle");
- return;
- }
- if(remainSourceOpen())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"remainSourceOpen()");
- readThread.stop();
- }
- if(remainDestinationOpen())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"remainDestinationOpen()");
- writeThread.stop();
- }
- if(!remainFileOpen())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"transfer_stat==TransferStat_Idle");
- if(needRemove && source.absoluteFilePath()!=destination.absoluteFilePath())
- {
- if(source.exists())
- QFile(destination.absoluteFilePath()).remove();
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] try destroy the destination when the source don't exists"));
- }
- transfer_stat=TransferStat_PostOperation;
- emit internalStartPostOperation();
- }
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,QStringLiteral("transfer_stat==%1 && remainFileOpen()").arg(transfer_stat).toStdString());
-}
-
-bool TransferThread::remainFileOpen() const
-{
- return remainSourceOpen() || remainDestinationOpen();
-}
-
-bool TransferThread::remainSourceOpen() const
-{
- return (readIsOpenVariable || readIsOpeningVariable) && !readIsClosedVariable;
-}
-
-bool TransferThread::remainDestinationOpen() const
-{
- return (writeIsOpenVariable || writeIsOpeningVariable) && !writeIsClosedVariable;
-}
-
-void TransferThread::readIsFinish()
-{
- if(readIsFinishVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] double event dropped"));
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- readIsFinishVariable=true;
- canStartTransfer=false;
- //check here if need start checksuming or not
- real_doChecksum=doChecksum && (!checksumOnlyOnError || fileContentError) && (!canBeMovedDirectlyVariable && !canBeCopiedDirectlyVariable);
- if(real_doChecksum)
- {
- readIsFinishVariable=false;
- transfer_stat=TransferStat_Checksum;
- sourceChecksum=QByteArray();
- destinationChecksum=QByteArray();
- readThread.startCheckSum();
- }
- else
- {
- transfer_stat=TransferStat_PostTransfer;
- if(!needSkip || (canBeCopiedDirectlyVariable || canBeMovedDirectlyVariable))//if skip, stop call, then readIsClosed() already call
- readThread.postOperation();
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] in skip, don't start postOperation");
- }
- emit pushStat(transfer_stat,transferId);
-}
-
-void TransferThread::writeIsFinish()
-{
- if(writeIsFinishVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+"] double event dropped");
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- writeIsFinishVariable=true;
- //check here if need start checksuming or not
- if(real_doChecksum)
- {
- writeIsFinishVariable=false;
- transfer_stat=TransferStat_Checksum;
- writeThread.startCheckSum();
- }
- else
- {
- if(!needSkip || (canBeCopiedDirectlyVariable || canBeMovedDirectlyVariable))//if skip, stop call, then writeIsClosed() already call
- writeThread.postOperation();
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] in skip, don't start postOperation");
- }
-}
-
-void TransferThread::readChecksumFinish(const QByteArray& checksum)
-{
- sourceChecksum=checksum;
- compareChecksum();
-}
-
-void TransferThread::writeChecksumFinish(const QByteArray& checksum)
-{
- destinationChecksum=checksum;
- compareChecksum();
-}
-
-void TransferThread::compareChecksum()
-{
- if(sourceChecksum.size()==0)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] the checksum of source is missing");
- return;
- }
- if(destinationChecksum.size()==0)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] the checksum of destination is missing");
- return;
- }
- if(sourceChecksum==destinationChecksum)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] the checksum match");
- readThread.postOperation();
- writeThread.postOperation();
- transfer_stat=TransferStat_PostTransfer;
- emit pushStat(transfer_stat,transferId);
- }
- else
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] the checksum not match"));
- //emit error here, and wait to resume
- emit errorOnFile(destination,tr("The checksums do not match").toStdString());
- }
-}
-
-void TransferThread::readIsClosed()
-{
- if(readIsClosedVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] double event dropped"));
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- readIsClosedVariable=true;
- readIsOpeningVariable=false;
- checkIfAllIsClosedAndDoOperations();
-}
-
-void TransferThread::writeIsClosed()
-{
- if(writeIsClosedVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+"] double event dropped");
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- writeIsClosedVariable=true;
- writeIsOpeningVariable=false;
- if(stopIt && needRemove && source.absoluteFilePath()!=destination.absoluteFilePath())
- {
- if(source.exists())
- QFile(destination.absoluteFilePath()).remove();
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] try destroy the destination when the source don't exists"));
- }
- checkIfAllIsClosedAndDoOperations();
-}
-
-// return true if all is closed, and do some operations, don't use into condition to check if is closed!
-bool TransferThread::checkIfAllIsClosedAndDoOperations()
-{
- if((readError || writeError) && !needSkip && !stopIt)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] resolve error before progress");
- return false;
- }
- if(!remainFileOpen())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] emit internalStartPostOperation() to do the real post operation");
- transfer_stat=TransferStat_PostOperation;
- //emit pushStat(stat,transferId);
- emit internalStartPostOperation();
- return true;
- }
- else
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] "+QStringLiteral("wait self close: readIsReadyVariable: %1, readIsClosedVariable: %2, writeIsReadyVariable: %3, writeIsClosedVariable: %4")
- .arg(readIsReadyVariable)
- .arg(readIsClosedVariable)
- .arg(writeIsReadyVariable)
- .arg(writeIsClosedVariable)
- .toStdString()
- );
- return false;
- }
-}
-
-/// \todo found way to retry that's
-/// \todo the rights copy
-void TransferThread::postOperation()
-{
- if(transfer_stat!=TransferStat_PostOperation)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+"] need be in transfer, source: "+source.absoluteFilePath().toStdString()+", destination: "+destination.absoluteFilePath().toStdString()+", stat:"+std::to_string(transfer_stat));
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- //all except closing
- if((readError || writeError) && !needSkip && !stopIt)//normally useless by checkIfAllIsFinish()
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] resume after error");
- return;
- }
-
- if(!needSkip && !stopIt)
- {
- if(!canBeCopiedDirectlyVariable && !canBeMovedDirectlyVariable)
- {
- if(writeIsOpenVariable && !writeIsClosedVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] can't pass in post operation if write is not closed"));
- emit errorOnFile(destination,tr("Internal error: The destination is not closed").toStdString());
- needSkip=false;
- if(deletePartiallyTransferredFiles)
- needRemove=true;
- writeError=true;
- return;
- }
- if(readThread.getLastGoodPosition()!=writeThread.getLastGoodPosition())
- {
- writeThread.flushBuffer();
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+QString("] readThread.getLastGoodPosition(%1)!=writeThread.getLastGoodPosition(%2)")
- .arg(readThread.getLastGoodPosition())
- .arg(writeThread.getLastGoodPosition())
- .toStdString()
- );
- emit errorOnFile(destination,tr("Internal error: The size transfered doesn't match").toStdString());
- needSkip=false;
- if(deletePartiallyTransferredFiles)
- needRemove=true;
- writeError=true;
- return;
- }
- if(!writeThread.bufferIsEmpty())
- {
- writeThread.flushBuffer();
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] buffer is not empty"));
- emit errorOnFile(destination,tr("Internal error: The buffer is not empty").toStdString());
- needSkip=false;
- if(deletePartiallyTransferredFiles)
- needRemove=true;
- writeError=true;
- return;
- }
- //in normal mode, without copy/move syscall
- if(!doFilePostOperation())
- return;
- }
-
- //remove source in moving mode
- if(mode==Ultracopier::Move && !canBeMovedDirectlyVariable)
- {
- if(destination.exists() && destination.isFile())
- {
- QFile sourceFile(source.absoluteFilePath());
- if(!sourceFile.remove())
- {
- needSkip=false;
- emit errorOnFile(source,sourceFile.errorString().toStdString());
- return;
- }
- }
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] try remove source but destination not exists!"));
- }
- }
- else//do difference skip a file and skip this error case
- {
- if(needRemove && destination.exists() && source.exists() && source.absoluteFilePath()!=destination.absoluteFilePath() && destination.isFile())
- {
- QFile destinationFile(destination.absoluteFilePath());
- if(!destinationFile.remove())
- {
- //emit errorOnFile(source,destinationFile.errorString());
- //return;
- }
- }
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] try remove destination but not exists!");
- }
- source.setFile(QStringLiteral(""));
- destination.setFile(QStringLiteral(""));
- //don't need remove because have correctly finish (it's not in: have started)
- needRemove=false;
- needSkip=false;
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] emit postOperationStopped()");
- transfer_stat=TransferStat_Idle;
- emit postOperationStopped();
-}
-
-bool TransferThread::doFilePostOperation()
-{
- //do operation needed by copy
- //set the time if no write thread used
-
- destination.refresh();
- if(!destination.exists() && !destination.isSymLink())
- {
- if(!stopIt)
- if(/*true when the destination have been remove but not the symlink:*/!source.isSymLink())
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] Unable to change the date: File not found");
- emit errorOnFile(destination,tr("Unable to change the date").toStdString()+": "+tr("File not found").toStdString());
- return false;
- }
- }
- else
- {
- if(doTheDateTransfer)
- {
- if(!writeFileDateTime(destination))
- {
- if(!destination.isFile())
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] Unable to change the date (is not a file)");
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] Unable to change the date");
- /* error with virtual folder under windows */
- #ifndef Q_OS_WIN32
- if(keepDate)
- {
- emit errorOnFile(destination,tr("Unable to change the date").toStdString());
- return false;
- }
- #endif
- }
- else
- {
- #ifndef Q_OS_WIN32
- destination.refresh();
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] read the destination time: "+destination.lastModified().toString().toStdString());
- if(destination.lastModified()<minTime)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] read the destination time lower than min time: "+destination.lastModified().toString().toStdString());
- if(keepDate)
- {
- emit errorOnFile(destination,tr("Unable to change the date").toStdString());
- return false;
- }
- }
- #endif
- }
- }
- if(doRightTransfer)
- {
- //should be never used but...
- /*source.refresh();
- if(source.exists())*/
- if(havePermission)
- {
- QFile destinationFile(destination.absoluteFilePath());
- if(!writeFilePermissions(destinationFile))
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] Unable to set the destination file permission");
- //emit errorOnFile(destination,tr("Unable to set the destination file permission"));
- //return false;
- }
- }
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] Try doRightTransfer when source not exists");
- }
- }
- if(stopIt)
- return false;
-
- return true;
-}
-
-//////////////////////////////////////////////////////////////////
-/////////////////////// Error management /////////////////////////
-//////////////////////////////////////////////////////////////////
-
-void TransferThread::getWriteError()
-{
- if(writeError)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] already in write error!");
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- fileContentError = true;
- writeError = true;
- writeIsReadyVariable = false;
- writeError_source_seeked = false;
- writeError_destination_reopened = false;
- writeIsOpeningVariable=false;
- if(!readError)//already display error for the read
- emit errorOnFile(destination,writeThread.errorString());
-}
-
-void TransferThread::getReadError()
-{
- if(readError)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] already in read error!");
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- fileContentError = true;
- readError = true;
- //writeIsReadyVariable = false;//wrong because write can be ready here
- readIsReadyVariable = false;
- readIsOpeningVariable=false;
- if(!writeError)//already display error for the write
- emit errorOnFile(source,readThread.errorString());
-}
-
-//retry after error
-void TransferThread::retryAfterError()
-{
- /// \warning skip the resetExtraVariable(); to be more exact and resolv some bug
- if(transfer_stat==TransferStat_Idle)
- {
- if(transferId==0)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] seam have bug, source: ")+source.absoluteFilePath().toStdString()+", destination: "+destination.absoluteFilePath().toStdString());
- return;
- }
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] restart all, source: "+source.absoluteFilePath().toStdString()+", destination: "+destination.absoluteFilePath().toStdString());
- readError=false;
- //writeError=false;
- emit internalStartPreOperation();
- return;
- }
- //opening error
- if(transfer_stat==TransferStat_PreOperation)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] is not idle, source: "+source.absoluteFilePath().toStdString()+", destination: "+destination.absoluteFilePath().toStdString()+", stat: "+std::to_string(transfer_stat));
- readError=false;
- //writeError=false;
- emit internalStartPreOperation();
- //tryOpen();-> recheck all, because can be an error into isSame(), rename(), ...
- return;
- }
- //data streaming error
- if(transfer_stat!=TransferStat_PostOperation && transfer_stat!=TransferStat_Transfer && transfer_stat!=TransferStat_PostTransfer && transfer_stat!=TransferStat_Checksum)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Critical,"["+std::to_string(id)+("] is not in right stat, source: ")+source.absoluteFilePath().toStdString()+", destination: "+destination.absoluteFilePath().toStdString()+", stat: "+std::to_string(transfer_stat));
- return;
- }
- if(transfer_stat==TransferStat_PostOperation)
- {
- if(readError || writeError)
- {
- readError=false;
- //writeError=false;
- resumeTransferAfterWriteError();
- writeThread.flushBuffer();
- transfer_stat=TransferStat_PreOperation;
- emit internalStartPreOperation();
- return;
- }
- emit internalStartPostOperation();
- return;
- }
- if(canBeMovedDirectlyVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] retry the system move");
- tryMoveDirectly();
- return;
- }
- if(canBeCopiedDirectlyVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] retry the copy directly");
- tryCopyDirectly();
- return;
- }
- if(transfer_stat==TransferStat_Checksum)
- {
- if(writeError)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start and resume the write error");
- writeThread.reopen();
- }
- else if(readError)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start and resume the read error");
- readThread.reopen();
- }
- else //only checksum difference
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] retry all the transfer");
- canStartTransfer=true;
- ifCanStartTransfer();
- }
- return;
- }
- //can have error on source and destination at the same time
- if(writeError)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start and resume the write error: "+std::to_string(readError));
- if(readError)
- readThread.reopen();
- else
- {
- readIsClosedVariable=false;
- readThread.seekToZeroAndWait();
- }
- writeThread.reopen();
- }
- if(readError)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start and resume the read error");
- readThread.reopen();
- }
- if(!writeError && !readError)
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] unknow error resume");
-}
-
-void TransferThread::writeThreadIsReopened()
-{
- if(writeError_destination_reopened)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] double event dropped");
- return;
- }
- writeError_destination_reopened=true;
- if(transfer_stat==TransferStat_Checksum)
- {
- writeThread.startCheckSum();
- return;
- }
- if(writeError_source_seeked && writeError_destination_reopened)
- resumeTransferAfterWriteError();
-}
-
-void TransferThread::readThreadIsSeekToZeroAndWait()
-{
- if(writeError_source_seeked)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] double event dropped");
- return;
- }
- writeError_source_seeked=true;
- if(writeError_source_seeked && writeError_destination_reopened)
- resumeTransferAfterWriteError();
-}
-
-void TransferThread::resumeTransferAfterWriteError()
-{
- writeError=false;
-/********************************
- if(canStartTransfer)
- readThread.startRead();
-useless, because the open destination event
-will restart the transfer as normal
-*********************************/
-/*********************************
-if(!canStartTransfer)
- stat=WaitForTheTransfer;
-useless because already do at open event
-**********************************/
- //if is in wait
- if(!canStartTransfer)
- emit checkIfItCanBeResumed();
-}
-
-void TransferThread::readThreadResumeAfterError()
-{
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- readError=false;
- writeIsReady();
- readIsReady();
-}
-
-//////////////////////////////////////////////////////////////////
-///////////////////////// Normal event ///////////////////////////
-//////////////////////////////////////////////////////////////////
-
-void TransferThread::readIsStopped()
-{
- if(!sended_state_readStopped)
- {
- sended_state_readStopped=true;
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] emit readIsStopped()");
- emit readStopped();
- }
- else
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] drop dual read stopped");
- return;
- }
- readIsFinish();
-}
-
-void TransferThread::writeIsStopped()
-{
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start");
- if(!sended_state_writeStopped)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] emit writeStopped()");
- sended_state_writeStopped=true;
- emit writeStopped();
- }
- else
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] double event dropped");
- return;
- }
- writeIsFinish();
-}
-
-#ifdef ULTRACOPIER_PLUGIN_SPEED_SUPPORT
-void TransferThread::timeOfTheBlockCopyFinished()
-{
- readThread.timeOfTheBlockCopyFinished();
- writeThread.timeOfTheBlockCopyFinished();
-}
-#endif
-
-bool TransferThread::setParallelBuffer(const int &parallelBuffer)
-{
- if(parallelBuffer<1 || parallelBuffer>ULTRACOPIER_PLUGIN_MAX_PARALLEL_NUMBER_OF_BLOCK)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] wrong parallelBuffer: "+std::to_string(parallelBuffer));
- return false;
- }
- else
- {
- this->parallelBuffer=parallelBuffer;
- return true;
- }
-}
-
-bool TransferThread::setSequentialBuffer(const int &sequentialBuffer)
-{
- if(sequentialBuffer<1 || sequentialBuffer>ULTRACOPIER_PLUGIN_MAX_SEQUENTIAL_NUMBER_OF_BLOCK)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] wrong sequentialBuffer: "+std::to_string(sequentialBuffer));
- return false;
- }
- else
- {
- this->sequentialBuffer=sequentialBuffer;
- return true;
- }
-}
-
-void TransferThread::setTransferAlgorithm(const TransferAlgorithm &transferAlgorithm)
-{
- this->transferAlgorithm=transferAlgorithm;
- if(transferAlgorithm==TransferAlgorithm_Sequential)
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] transferAlgorithm==TransferAlgorithm_Sequential");
- else if(transferAlgorithm==TransferAlgorithm_Automatic)
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] transferAlgorithm==TransferAlgorithm_Automatic");
- else
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] transferAlgorithm==TransferAlgorithm_Parallel");
-}
-
-//fonction to read the file date time
-bool TransferThread::readFileDateTime(const QFileInfo &source)
-{
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] readFileDateTime("+source.absoluteFilePath().toStdString()+")");
- if(source.lastModified()<minTime)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] the sources is older to copy the time: "+source.absoluteFilePath().toStdString()+": "+source.lastModified().toString().toStdString());
- return false;
- }
- /** Why not do it with Qt? Because it not support setModificationTime(), and get the time with Qt, that's mean use local time where in C is UTC time */
- #ifdef Q_OS_UNIX
- #ifdef Q_OS_LINUX
- struct stat info;
- if(stat(source.absoluteFilePath().toLatin1().data(),&info)!=0)
- return false;
- time_t ctime=info.st_ctim.tv_sec;
- time_t actime=info.st_atim.tv_sec;
- time_t modtime=info.st_mtim.tv_sec;
- //this function avalaible on unix and mingw
- butime.actime=actime;
- butime.modtime=modtime;
- Q_UNUSED(ctime);
- return true;
- #else //mainly for mac
- time_t ctime=source.created().toTime_t();
- time_t actime=source.lastRead().toTime_t();
- time_t modtime=source.lastModified().toTime_t();
- //this function avalaible on unix and mingw
- butime.actime=actime;
- butime.modtime=modtime;
- Q_UNUSED(ctime);
- return true;
- #endif
- #else
- #ifdef Q_OS_WIN32
- #ifdef ULTRACOPIER_PLUGIN_SET_TIME_UNIX_WAY
- struct stat info;
- if(stat(source.toLatin1().data(),&info)!=0)
- return false;
- time_t ctime=info.st_ctim.tv_sec;
- time_t actime=info.st_atim.tv_sec;
- time_t modtime=info.st_mtim.tv_sec;
- //this function avalaible on unix and mingw
- butime.actime=actime;
- butime.modtime=modtime;
- Q_UNUSED(ctime);
- return true;
- #else
- wchar_t filePath[65535];
- if(std::regex_match(source.absoluteFilePath().toStdString(),regRead))
- filePath[QDir::toNativeSeparators(QStringLiteral("\\\\?\\")+source.absoluteFilePath()).toWCharArray(filePath)]=L'\0';
- else
- filePath[QDir::toNativeSeparators(source.absoluteFilePath()).toWCharArray(filePath)]=L'\0';
- HANDLE hFileSouce = CreateFileW(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
- if(hFileSouce == INVALID_HANDLE_VALUE)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] open failed to read: "+QString::fromWCharArray(filePath).toStdString()+", error: "+std::to_string(GetLastError()));
- return false;
- }
- FILETIME ftCreate, ftAccess, ftWrite;
- if(!GetFileTime(hFileSouce, &ftCreate, &ftAccess, &ftWrite))
- {
- CloseHandle(hFileSouce);
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] unable to get the file time");
- return false;
- }
- this->ftCreateL=ftCreate.dwLowDateTime;
- this->ftCreateH=ftCreate.dwHighDateTime;
- this->ftAccessL=ftAccess.dwLowDateTime;
- this->ftAccessH=ftAccess.dwHighDateTime;
- this->ftWriteL=ftWrite.dwLowDateTime;
- this->ftWriteH=ftWrite.dwHighDateTime;
- CloseHandle(hFileSouce);
- return true;
- #endif
- #else
- return false;
- #endif
- #endif
- return false;
-}
-
-bool TransferThread::writeFileDateTime(const QFileInfo &destination)
-{
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] writeFileDateTime("+destination.absoluteFilePath().toStdString()+")");
- /** Why not do it with Qt? Because it not support setModificationTime(), and get the time with Qt, that's mean use local time where in C is UTC time */
- #ifdef Q_OS_UNIX
- #ifdef Q_OS_LINUX
- return utime(destination.absoluteFilePath().toLatin1().data(),&butime)==0;
- #else //mainly for mac
- return utime(destination.absoluteFilePath().toLatin1().data(),&butime)==0;
- #endif
- #else
- #ifdef Q_OS_WIN32
- #ifdef ULTRACOPIER_PLUGIN_SET_TIME_UNIX_WAY
- return utime(destination.toLatin1().data(),&butime)==0;
- #else
- wchar_t filePath[65535];
- if(std::regex_match(destination.absoluteFilePath().toStdString(),regRead))
- filePath[QDir::toNativeSeparators(QStringLiteral("\\\\?\\")+destination.absoluteFilePath()).toWCharArray(filePath)]=L'\0';
- else
- filePath[QDir::toNativeSeparators(destination.absoluteFilePath()).toWCharArray(filePath)]=L'\0';
- HANDLE hFileDestination = CreateFileW(filePath, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
- if(hFileDestination == INVALID_HANDLE_VALUE)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] open failed to write: "+QString::fromWCharArray(filePath).toStdString()+", error: "+std::to_string(GetLastError()));
- return false;
- }
- FILETIME ftCreate, ftAccess, ftWrite;
- ftCreate.dwLowDateTime=this->ftCreateL;
- ftCreate.dwHighDateTime=this->ftCreateH;
- ftAccess.dwLowDateTime=this->ftAccessL;
- ftAccess.dwHighDateTime=this->ftAccessH;
- ftWrite.dwLowDateTime=this->ftWriteL;
- ftWrite.dwHighDateTime=this->ftWriteH;
- if(!SetFileTime(hFileDestination, &ftCreate, &ftAccess, &ftWrite))
- {
- CloseHandle(hFileDestination);
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] unable to set the file time");
- return false;
- }
- CloseHandle(hFileDestination);
- return true;
- #endif
- #else
- return false;
- #endif
- #endif
- return false;
-}
-
-bool TransferThread::readFilePermissions(const QFile &source)
-{
- this->permissions=source.permissions();
- return true;
-}
-
-bool TransferThread::writeFilePermissions(QFile &destination)
-{
- return destination.setPermissions(this->permissions);
-}
-
-//skip the copy
-void TransferThread::skip()
-{
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] start with stat: "+std::to_string(transfer_stat));
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] readIsOpeningVariable: "+std::to_string(readIsOpeningVariable)+", readIsOpenVariable: "+std::to_string(readIsOpenVariable)+", readIsReadyVariable: "+std::to_string(readIsReadyVariable)+", readIsFinishVariable: "+std::to_string(readIsFinishVariable)+", readIsClosedVariable: "+std::to_string(readIsClosedVariable));
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] writeIsOpeningVariable: "+std::to_string(writeIsOpeningVariable)+", writeIsOpenVariable: "+std::to_string(writeIsOpenVariable)+", writeIsReadyVariable: "+std::to_string(writeIsReadyVariable)+", writeIsFinishVariable: "+std::to_string(writeIsFinishVariable)+", writeIsClosedVariable: "+std::to_string(writeIsClosedVariable));
- switch(transfer_stat)
- {
- case TransferStat_WaitForTheTransfer:
- //needRemove=true;never put that's here, can product destruction of the file
- case TransferStat_PreOperation:
- if(needSkip)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] skip already in progress");
- return;
- }
- needSkip=true;
- //check if all is source and destination is closed
- if(remainFileOpen())
- {
- if(remainSourceOpen())
- readThread.stop();
- if(remainDestinationOpen())
- writeThread.stop();
- }
- else // wait nothing, just quit
- {
- transfer_stat=TransferStat_PostOperation;
- emit internalStartPostOperation();
- }
- break;
- case TransferStat_Transfer:
- case TransferStat_PostTransfer:
- if(needSkip)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] skip already in progress");
- return;
- }
- //needRemove=true;never put that's here, can product destruction of the file
- needSkip=true;
- if(canBeMovedDirectlyVariable || canBeCopiedDirectlyVariable)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] Do the direct FS fake close, canBeMovedDirectlyVariable: "+std::to_string(canBeMovedDirectlyVariable)+", canBeCopiedDirectlyVariable: "+std::to_string(canBeCopiedDirectlyVariable));
- readThread.fakeReadIsStarted();
- writeThread.fakeWriteIsStarted();
- readThread.fakeReadIsStopped();
- writeThread.fakeWriteIsStopped();
- return;
- }
- writeThread.flushBuffer();
- if(remainFileOpen())
- {
- if(remainSourceOpen())
- readThread.stop();
- if(remainDestinationOpen())
- writeThread.stop();
- }
- else // wait nothing, just quit
- {
- transfer_stat=TransferStat_PostOperation;
- emit internalStartPostOperation();
- }
- break;
- case TransferStat_Checksum:
- if(needSkip)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] skip already in progress");
- return;
- }
- //needRemove=true;never put that's here, can product destruction of the file
- needSkip=true;
- if(remainFileOpen())
- {
- if(remainSourceOpen())
- readThread.stop();
- if(remainDestinationOpen())
- writeThread.stop();
- }
- else // wait nothing, just quit
- {
- transfer_stat=TransferStat_PostOperation;
- emit internalStartPostOperation();
- }
- break;
- case TransferStat_PostOperation:
- if(needSkip)
- {
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Notice,"["+std::to_string(id)+"] skip already in progress");
- return;
- }
- //needRemove=true;never put that's here, can product destruction of the file
- needSkip=true;
- writeThread.flushBuffer();
- emit internalStartPostOperation();
- break;
- default:
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+"] can skip in this state: "+std::to_string(transfer_stat));
- return;
- }
-}
-
-//return info about the copied size
-int64_t TransferThread::copiedSize()
-{
- switch(transfer_stat)
- {
- case TransferStat_Transfer:
- case TransferStat_PostOperation:
- case TransferStat_PostTransfer:
- return (readThread.getLastGoodPosition()+writeThread.getLastGoodPosition())/2;
- case TransferStat_Checksum:
- return transferSize;
- default:
- return 0;
- }
-}
-
-//retry after error
-void TransferThread::putAtBottom()
-{
- emit tryPutAtBottom();
-}
-
-#ifdef ULTRACOPIER_PLUGIN_RSYNC
-/// \brief set rsync
-void TransferThread::setRsync(const bool rsync)
-{
- this->rsync=rsync;
-}
-#endif
-
-void TransferThread::set_osBufferLimit(const unsigned int &osBufferLimit)
-{
- this->osBufferLimit=osBufferLimit;
-}
-
-#ifdef ULTRACOPIER_PLUGIN_DEBUG
-//to set the id
-void TransferThread::setId(int id)
-{
- this->id=id;
- readThread.setId(id);
- writeThread.setId(id);
-}
-
-char TransferThread::readingLetter() const
-{
- switch(readThread.stat)
- {
- case ReadThread::Idle:
- return '_';
- break;
- case ReadThread::InodeOperation:
- return 'I';
- break;
- case ReadThread::Read:
- return 'R';
- break;
- case ReadThread::WaitWritePipe:
- return 'W';
- break;
- case ReadThread::Checksum:
- return 'S';
- break;
- default:
- return '?';
- }
-}
-
-char TransferThread::writingLetter() const
-{
- switch(writeThread.stat)
- {
- case WriteThread::Idle:
- return '_';
- break;
- case WriteThread::InodeOperation:
- return 'I';
- break;
- case WriteThread::Write:
- return 'W';
- break;
- case WriteThread::Close:
- return 'C';
- break;
- case WriteThread::Read:
- return 'R';
- break;
- case WriteThread::Checksum:
- return 'S';
- break;
- default:
- return '?';
- }
-}
-
-#endif
-
-void TransferThread::setMkpathTransfer(QSemaphore *mkpathTransfer)
-{
- this->mkpathTransfer=mkpathTransfer;
- writeThread.setMkpathTransfer(mkpathTransfer);
-}
-
-void TransferThread::set_doChecksum(bool doChecksum)
-{
- this->doChecksum=doChecksum;
-}
-
-void TransferThread::set_checksumIgnoreIfImpossible(bool checksumIgnoreIfImpossible)
-{
- this->checksumIgnoreIfImpossible=checksumIgnoreIfImpossible;
-}
-
-void TransferThread::set_checksumOnlyOnError(bool checksumOnlyOnError)
-{
- this->checksumOnlyOnError=checksumOnlyOnError;
-}
-
-void TransferThread::set_osBuffer(bool osBuffer)
-{
- this->osBuffer=osBuffer;
-}
-
-void TransferThread::set_osBufferLimited(bool osBufferLimited)
-{
- this->osBufferLimited=osBufferLimited;
-}
-
-//not copied size, because that's count to the checksum, ...
-uint64_t TransferThread::realByteTransfered() const
-{
- switch(transfer_stat)
- {
- case TransferStat_Transfer:
- case TransferStat_Checksum:
- return (readThread.getLastGoodPosition()+writeThread.getLastGoodPosition())/2;
- case TransferStat_PostTransfer:
- return (readThread.getLastGoodPosition()+writeThread.getLastGoodPosition())/2;
- case TransferStat_PostOperation:
- return transferSize;
- default:
- return 0;
- }
-}
-
-//first is read, second is write
-std::pair<uint64_t, uint64_t> TransferThread::progression() const
-{
- std::pair<uint64_t,uint64_t> returnVar;
- switch(transfer_stat)
- {
- case TransferStat_Transfer:
- returnVar.first=readThread.getLastGoodPosition();
- returnVar.second=writeThread.getLastGoodPosition();
- /*if(returnVar.first<returnVar.second)
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+QStringLiteral("] read is smaller than write"));*/
- break;
- case TransferStat_Checksum:
- returnVar.first=readThread.getLastGoodPosition();
- returnVar.second=writeThread.getLastGoodPosition();
- break;
- case TransferStat_PostTransfer:
- returnVar.first=transferSize;
- returnVar.second=writeThread.getLastGoodPosition();
- /*if(returnVar.first<returnVar.second)
- ULTRACOPIER_DEBUGCONSOLE(Ultracopier::DebugLevel_Warning,"["+std::to_string(id)+QStringLiteral("] read is smaller than write"));*/
- break;
- case TransferStat_PostOperation:
- returnVar.first=transferSize;
- returnVar.second=transferSize;
- break;
- default:
- returnVar.first=0;
- returnVar.second=0;
- }
- return returnVar;
-}
-
-void TransferThread::setRenamingRules(const std::string &firstRenamingRule, const std::string &otherRenamingRule)
-{
- this->firstRenamingRule=firstRenamingRule;
- this->otherRenamingRule=otherRenamingRule;
-}
-
-void TransferThread::setDeletePartiallyTransferredFiles(const bool &deletePartiallyTransferredFiles)
-{
- this->deletePartiallyTransferredFiles=deletePartiallyTransferredFiles;
-}
-
-void TransferThread::setRenameTheOriginalDestination(const bool &renameTheOriginalDestination)
-{
- this->renameTheOriginalDestination=renameTheOriginalDestination;
-}
-
-void TransferThread::set_updateMount()
-{
- driveManagement.tryUpdate();
-}