Index: src/libchcore/TSubTaskCopyMove.cpp
===================================================================
diff -u -N -r08cb83a990d701a1e962630efeb6640a8c2d3dcd -rdb818324a61602e118506ca8b3973e44d997c8de
--- src/libchcore/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision 08cb83a990d701a1e962630efeb6640a8c2d3dcd)
+++ src/libchcore/TSubTaskCopyMove.cpp	(.../TSubTaskCopyMove.cpp)	(revision db818324a61602e118506ca8b3973e44d997c8de)
@@ -155,9 +155,8 @@
 			m_tSubTaskStats.SetCurrentIndex(fcIndex);
 			m_tSubTaskStats.SetProcessedCount(fcIndex);
 			m_tSubTaskStats.SetCurrentPath(pathCurrent.ToString());
-			m_tSubTaskStats.SetCurrentItemProcessedSize(ullCurrentItemProcessedSize);	// preserve the processed size for the first item
-			ullCurrentItemProcessedSize = 0;
-			m_tSubTaskStats.SetCurrentItemTotalSize(spFileInfo->GetLength64());
+			m_tSubTaskStats.SetCurrentItemSizes(ullCurrentItemProcessedSize, spFileInfo->GetLength64());	// preserve the processed size for the first item
+			ullCurrentItemProcessedSize = 0;	// in next iteration we're not resuming anymore
 			m_tSubTaskStats.SetCurrentItemSilentResume(bCurrentFileSilentResume);
 			bCurrentFileSilentResume = false;
 
@@ -175,8 +174,7 @@
 					return eResult;
 
 				// new stats
-				m_tSubTaskStats.IncreaseProcessedSize(spFileInfo->GetLength64());
-				m_tSubTaskStats.IncreaseCurrentItemProcessedSize(spFileInfo->GetLength64());
+				AdjustProcessedSizeForSkip(spFileInfo);
 
 				spFileInfo->MarkAsProcessed(true);
 			}
@@ -362,7 +360,7 @@
 					else if(bSkip)
 					{
 						// new stats
-						AdjustProcessedSize(m_tSubTaskStats.GetCurrentItemProcessedSize(), pData->spSrcFile->GetLength64());
+						AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 						pData->bProcessed = false;
 						return TSubTaskBase::eSubResult_Continue;
@@ -388,8 +386,7 @@
 								return eResult;
 							else if(bSkip)
 							{
-								// new stats
-								AdjustProcessedSize(m_tSubTaskStats.GetCurrentItemProcessedSize(), pData->spSrcFile->GetLength64());
+								AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 								pData->bProcessed = false;
 								return TSubTaskBase::eSubResult_Continue;
@@ -399,8 +396,7 @@
 							return eResult;
 						else if(bSkip)
 						{
-							// new stats
-							AdjustProcessedSize(m_tSubTaskStats.GetCurrentItemProcessedSize(), pData->spSrcFile->GetLength64());
+							AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 							pData->bProcessed = false;
 							return TSubTaskBase::eSubResult_Continue;
@@ -415,8 +411,7 @@
 							return eResult;
 						else if(bSkip)
 						{
-							// new stats
-							AdjustProcessedSize(m_tSubTaskStats.GetCurrentItemProcessedSize(), pData->spSrcFile->GetLength64());
+							AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 							pData->bProcessed = false;
 							return TSubTaskBase::eSubResult_Continue;
@@ -442,8 +437,7 @@
 								return eResult;
 							else if(bSkip)
 							{
-								// new stats
-								AdjustProcessedSize(m_tSubTaskStats.GetCurrentItemProcessedSize(), pData->spSrcFile->GetLength64());
+								AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 								pData->bProcessed = false;
 								return TSubTaskBase::eSubResult_Continue;
@@ -453,8 +447,7 @@
 							return eResult;
 						else if(bSkip)
 						{
-							// new stats
-							AdjustProcessedSize(m_tSubTaskStats.GetCurrentItemProcessedSize(), pData->spSrcFile->GetLength64());
+							AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 							pData->bProcessed = false;
 							return TSubTaskBase::eSubResult_Continue;
@@ -467,27 +460,17 @@
 							return eResult;
 						else if (bSkip)
 						{
-							// new stats
-							AdjustProcessedSize(m_tSubTaskStats.GetCurrentItemProcessedSize(), pData->spSrcFile->GetLength64());
+							AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 							pData->bProcessed = false;
 							return TSubTaskBase::eSubResult_Continue;
 						}
 
-						unsigned long long ullCITotalSize = m_tSubTaskStats.GetCurrentItemTotalSize();
-						unsigned long long ullCIProcessedSize = m_tSubTaskStats.GetCurrentItemProcessedSize();
+						file_size_t fsWritten = pBuffer->GetRealDataSize();
 
-						unsigned long long ullWritten = pBuffer->GetBytesTransferred();
-						if(ullCIProcessedSize + ullWritten > ullCITotalSize)
-						{
-							// total size changed
-							pData->spSrcFile->SetLength64(ullCIProcessedSize + ullWritten);
-							AdjustTotalSize(ullCITotalSize, ullCIProcessedSize + ullWritten);
-						}
+						// in case we read past the original eof, try to get new file size from filesystem
+						AdjustProcessedSize(fsWritten, pData->spSrcFile, fileSrc);
 
-						// new stats
-						AdjustProcessedSize(0, ullWritten);
-
 						// stop iterating through file
 						bStopProcessing = pBuffer->IsLastPart();
 						pBuffer->RequeueAsEmpty();
@@ -502,23 +485,55 @@
 		}
 
 		// this is the end of copying of src file - in case it is smaller than expected fix the stats so that difference is accounted for
-		unsigned long long ullCITotalSize = m_tSubTaskStats.GetCurrentItemTotalSize();
-		unsigned long long ullCIProcessedSize = m_tSubTaskStats.GetCurrentItemProcessedSize();
-		if(ullCIProcessedSize < ullCITotalSize)
-		{
-			pData->spSrcFile->SetLength64(ullCIProcessedSize);
+		AdjustFinalSize(pData->spSrcFile, fileSrc);
 
-			AdjustTotalSize(ullCITotalSize, ullCIProcessedSize);
-		}
-
 		pData->bProcessed = true;
-		m_tSubTaskStats.SetCurrentItemProcessedSize(0);
+		m_tSubTaskStats.ResetCurrentItemProcessedSize();
 
 		pData->dbBuffer.WaitForMissingBuffers(rThreadController.GetKillThreadHandle());
 
 		return TSubTaskBase::eSubResult_Continue;
 	}
 
+	void TSubTaskCopyMove::AdjustProcessedSize(file_size_t fsWritten, const TFileInfoPtr& spSrcFileInfo, const IFilesystemFilePtr& spSrcFile)
+	{
+		// in case we read past the original eof, try to get new file size from filesystem
+		if (m_tSubTaskStats.WillAdjustProcessedSizeExceedTotalSize(0, fsWritten))
+		{
+			file_size_t fsNewSize = spSrcFile->GetFileSize();
+			if (fsNewSize == spSrcFileInfo->GetLength64())
+				THROW_CORE_EXCEPTION_MSG(eErr_InternalProblem, L"Read more data from file than it really contained. Possible destination file corruption.");
+
+			m_tSubTaskStats.AdjustTotalSize(spSrcFileInfo->GetLength64(), fsNewSize);
+			spSrcFileInfo->SetLength64(m_tSubTaskStats.GetCurrentItemTotalSize());
+		}
+
+		m_tSubTaskStats.AdjustProcessedSize(0, fsWritten);
+	}
+
+	void TSubTaskCopyMove::AdjustFinalSize(const TFileInfoPtr& spSrcFileInfo, const IFilesystemFilePtr& spSrcFile)
+	{
+		unsigned long long ullCITotalSize = m_tSubTaskStats.GetCurrentItemTotalSize();
+		unsigned long long ullCIProcessedSize = m_tSubTaskStats.GetCurrentItemProcessedSize();
+		if (ullCIProcessedSize < ullCITotalSize)
+		{
+			file_size_t fsNewSize = spSrcFile->GetFileSize();
+			if (fsNewSize == spSrcFileInfo->GetLength64())
+				THROW_CORE_EXCEPTION_MSG(eErr_InternalProblem, L"Read less data from file than it really contained. Possible destination file corruption.");
+
+			if (fsNewSize != ullCIProcessedSize)
+				THROW_CORE_EXCEPTION_MSG(eErr_InternalProblem, L"Updated file size still does not match the count of data read. Possible destination file corruption.");
+
+			m_tSubTaskStats.AdjustTotalSize(ullCITotalSize, fsNewSize);
+			spSrcFileInfo->SetLength64(fsNewSize);
+		}
+	}
+
+	void TSubTaskCopyMove::AdjustProcessedSizeForSkip(const TFileInfoPtr& spSrcFileInfo)
+	{
+		m_tSubTaskStats.AdjustProcessedSize(m_tSubTaskStats.GetCurrentItemProcessedSize(), spSrcFileInfo->GetLength64());
+	}
+
 	TSubTaskCopyMove::ESubOperationResult TSubTaskCopyMove::OpenSrcAndDstFilesFB(const IFeedbackHandlerPtr& spFeedbackHandler, CUSTOM_COPY_PARAMS* pData,
 		const IFilesystemFilePtr& spFileSrc, const IFilesystemFilePtr& spFileDst, bool& bSkip)
 	{
@@ -536,7 +551,7 @@
 		else if(!spFileSrc->IsOpen())
 		{
 			// invalid handle = operation skipped by user
-			AdjustProcessedSize(ullProcessedSize, pData->spSrcFile->GetLength64());
+			AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 			pData->bProcessed = false;
 			bSkip = true;
@@ -552,8 +567,7 @@
 		file_size_t fsOldSize = pData->spSrcFile->GetLength64();
 		if(fsNewSize != fsOldSize)
 		{
-			AdjustTotalSize(fsOldSize, fsNewSize);
-
+			m_tSubTaskStats.AdjustTotalSize(fsOldSize, fsNewSize);
 			pData->spSrcFile->SetLength64(fsNewSize);
 		}
 
@@ -594,7 +608,7 @@
 					return eResult;
 				else if (!spFileDst->IsOpen())
 				{
-					AdjustProcessedSize(ullProcessedSize, pData->spSrcFile->GetLength64());
+					AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 					pData->bProcessed = false;
 					bSkip = true;
@@ -614,7 +628,7 @@
 				return eResult;
 			else if(!spFileDst->IsOpen())
 			{
-				AdjustProcessedSize(ullProcessedSize, pData->spSrcFile->GetLength64());
+				AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 				pData->bProcessed = false;
 				bSkip = true;
@@ -625,7 +639,7 @@
 		if(pData->bOnlyCreate)
 		{
 			// we don't copy contents, but need to increase processed size
-			AdjustProcessedSize(ullProcessedSize, pData->spSrcFile->GetLength64());
+			AdjustProcessedSizeForSkip(pData->spSrcFile);
 
 			return TSubTaskBase::eSubResult_Continue;
 		}
@@ -640,7 +654,7 @@
 			THROW_CORE_EXCEPTION(eErr_InternalProblem);
 
 		// adjust the stats for the difference between what was already processed and what will now be considered processed
-		AdjustProcessedSize(ullProcessedSize, fsMoveTo);
+		m_tSubTaskStats.AdjustProcessedSize(ullProcessedSize, fsMoveTo);
 
 		// if the destination file already exists - truncate it to the current file position
 		if(!bDstFileFreshlyCreated)
@@ -663,36 +677,6 @@
 		return eResult;
 	}
 
-	void TSubTaskCopyMove::AdjustTotalSize(file_size_t fsIncludedSize, file_size_t fsNewSize)
-	{
-		if (fsNewSize > fsIncludedSize)
-		{
-			m_tSubTaskStats.IncreaseTotalSize(fsNewSize - fsIncludedSize);
-			m_tSubTaskStats.IncreaseCurrentItemTotalSize(fsNewSize - fsIncludedSize);
-		}
-		else if(fsNewSize < fsIncludedSize)
-		{
-			m_tSubTaskStats.DecreaseTotalSize(fsIncludedSize - fsNewSize);
-			m_tSubTaskStats.DecreaseCurrentItemTotalSize(fsIncludedSize - fsNewSize);
-		}
-	}
-
-	void TSubTaskCopyMove::AdjustProcessedSize(file_size_t fsIncludedProcessedSize, file_size_t fsNewProcessedSize)
-	{
-		if(fsNewProcessedSize > fsIncludedProcessedSize)
-		{
-			file_size_t fsDiff = fsNewProcessedSize - fsIncludedProcessedSize;
-			m_tSubTaskStats.IncreaseCurrentItemProcessedSize(fsDiff);
-			m_tSubTaskStats.IncreaseProcessedSize(fsDiff);
-		}
-		else if (fsNewProcessedSize < fsIncludedProcessedSize)
-		{
-			file_size_t fsDiff = fsIncludedProcessedSize - fsNewProcessedSize;
-			m_tSubTaskStats.DecreaseCurrentItemProcessedSize(fsDiff);
-			m_tSubTaskStats.DecreaseProcessedSize(fsDiff);
-		}
-	}
-
 	bool TSubTaskCopyMove::AdjustBufferIfNeeded(TOverlappedDataBufferQueue& rBuffer, TBufferSizes& rBufferSizes, bool bForce)
 	{
 		const TConfig& rConfig = GetContext().GetConfig();