Пример #1
0
bool OperCFThread::CopyFile( FS* srcFs, FSPath& srcPath, FSNode* srcNode, FS* destFs, FSPath& destPath, bool move )
{
	if ( !srcNode->st.IsReg() && !skipNonRegular )
		switch ( RedMessage( _LT( "Can't copy the links or special file:\n" ), srcFs->Uri( srcPath ).GetUtf8(), bSkipSkipallCancel ) )
		{
			case CMD_SKIPALL:
				skipNonRegular = true; // no break

			case CMD_SKIP:
				return true;

			default:
				return false;
		}

	if ( IsSameFile( srcFs, srcPath, &( srcNode->st ), destFs, destPath ) )
	{
		RedMessage( _LT( "Can't copy file to itself:\n" ) , srcFs->Uri( srcPath ).GetUtf8() );
		return false;
	}

	SendCopyNextFileInfo( srcFs->Uri( srcPath ), destFs->Uri( destPath ) );
	SendProgressInfo( srcNode->st.size, 0, 0 );

	bool stopped = false;

	int ret_err;

	int in = -1;

	if (destFs->Type() == FS::TYPES::TMP)
	{
		// copy and move to tmpfs work the same way. Should we yell on move op instead?
		FSTmp* destTmpFS = static_cast<FSTmp*>(destFs);
		if (!destTmpFS->BaseIsEqual(srcFs))
		{
			RedMessage(_LT("Temporary panel can store only files from the same file system:\n"));
			return false;
		}
		if (srcFs->Type() == FS::TMP && srcNode->IsReg())
		{
			FSString srcFullFSString(srcNode->name.GetUnicode());
			FSPath srcFullFSPath(srcFullFSString);
			//srcFullFSPath.dbg_printf("OperCFThread::CopyFile srcFullFSPath=");
			//destPath.dbg_printf("OperCFThread::CopyFile destPath=");
			FSPath destDir(destPath);
			destDir.Pop();
			return destTmpFS->AddNode(srcFullFSPath, destDir);
		}
		else
			return destTmpFS->AddNode(srcPath, srcNode, destPath);
	}

	while ( true )
	{
		in = srcFs->OpenRead( srcPath, FS::SHARE_READ, &ret_err, Info() );

		if ( in == -2 ) { return false; }

		if ( in >= 0 ) { break; }

		switch ( RedMessage( _LT( "Can't open file:\n" ) , srcFs->Uri( srcPath ).GetUtf8(), bRetrySkipCancel, srcFs->StrError( ret_err ).GetUtf8() ) )
		{
			case CMD_CANCEL:
				return false;

			case CMD_SKIP:
				return true;
		}
	}

	int out =  -1;

	out = destFs->OpenCreate( destPath, false | commitAll, srcNode->st.mode, 0, &ret_err, Info() );

	if ( out < 0 && destFs->IsEEXIST( ret_err ) )
		switch ( RedMessage( _LT( "Overwrite file?\n" ) , destFs->Uri( destPath ).GetUtf8(), bOkAllNoCancel ) )
		{
			case CMD_ALL:
				commitAll = true; //no break

			case CMD_OK:
				out = destFs->OpenCreate( destPath, true, srcNode->st.mode, 0, &ret_err, Info() );
				break;

			case CMD_NO:
				srcFs->Close( in, 0, Info() );
				return true;

			default:
				srcFs->Close( in, 0, Info() );
				return false;
		}

	if ( out < 0 )
	{
		srcFs->Close( in, 0, Info() );
		return RedMessage( _LT( "Can't create file:\n" ), destFs->Uri( destPath ).GetUtf8(), bSkipCancel, destFs->StrError( ret_err ).GetUtf8() ) == CMD_SKIP;
	}

	int  bytes;
	//char    buf[BUFSIZE];
	int64_t doneBytes = 0;

	int blockSize = STARTSIZE;

	while ( true )
	{
		if ( Info()->Stopped() )
		{
			stopped = true;
			goto err;
		}

		time_t timeStart = time( 0 );

		if ( ( bytes = srcFs->Read( in, _buffer, blockSize, &ret_err, Info() ) ) < 0 )
		{
			if ( bytes == -2 ||
			     RedMessage( _LT( "Can't read the file:\n" ), srcFs->Uri( srcPath ).GetUtf8(), bSkipCancel, srcFs->StrError( ret_err ).GetUtf8() ) != CMD_SKIP )
			{
				stopped = true;
			}

			goto err;
		}

		if ( !bytes ) { break; }

		int b;

		if ( ( b = destFs->Write( out, _buffer, bytes, &ret_err, Info() ) ) < 0 )
		{
			if ( b == -2 || RedMessage( _LT( "Can't write the file:\n" ), destFs->Uri( destPath ).GetUtf8(), bSkipCancel, destFs->StrError( ret_err ).GetUtf8() ) != CMD_SKIP )
			{
				stopped = true;
			}

			goto err;
		}


		if ( b != bytes )
		{
			if ( RedMessage( "May be disk full \n(writed bytes != readed bytes)\nwhen write:\n", destFs->Uri( destPath ).GetUtf8(), bSkipCancel ) != CMD_SKIP )
			{
				stopped = true;
			}

			goto err;
		}

		time_t timeStop = time( 0 );

		if ( timeStart == timeStop && blockSize < BSIZE )
		{
			blockSize = blockSize * 2;

			if ( blockSize > BSIZE ) { blockSize = BSIZE; }
		}

		doneBytes += bytes;
		SendProgressInfo( srcNode->st.size, doneBytes, bytes );
	}

	srcFs->Close( in, 0, Info() );
	in = -1;

	SendProgressInfo( srcNode->st.size, srcNode->st.size, 0 );

	{
		int r = destFs->Close( out, &ret_err, Info() );

		if ( r )
		{
			if ( r == -2 || RedMessage( "Can't close the file:\n", destFs->Uri( destPath ).GetUtf8(), bSkipCancel, destFs->StrError( ret_err ).GetUtf8() ) != CMD_SKIP )
			{
				stopped = true;
			}

			goto err;
		}
		else
		{
			out = -1;
		}
	}

	destFs->SetFileTime( destPath, srcNode->st.m_CreationTime, srcNode->st.m_LastWriteTime, srcNode->st.m_LastWriteTime, 0, Info() );

	return !move || Unlink( srcFs, srcPath );

err:

	if ( in >= 0 ) { srcFs->Close( in, 0, Info() ); }

	if ( out >= 0 ) { destFs->Close( out, 0, Info() ); }

	Unlink( destFs, destPath );

	return !stopped;
}
Пример #2
0
bool OperCFThread::CopyFile(FS *srcFs, FSPath &srcPath, FSNode *srcNode, FS *destFs, FSPath &destPath, bool move)
{
	if (!srcNode->st.IsReg() && !skipNonRegular)
		switch (RedMessage( _LT("Can't copy the links or special file:\n"), srcFs->Uri(srcPath).GetUtf8(), bSkipSkipallCancel)) {
		case CMD_SKIPALL: skipNonRegular = true; // no break
		case CMD_SKIP: return true;
		default: return false;
		}
	
	if (IsSameFile(srcFs, srcPath, &(srcNode->st), destFs, destPath))
	{
		RedMessage( _LT("Can't copy file to itself:\n") , srcFs->Uri(srcPath).GetUtf8());
		return false;
	}

	SendCopyNextFileInfo(srcFs->Uri(srcPath), destFs->Uri(destPath));
	SendProgressInfo(srcNode->st.size, 0);
	
	bool stopped = false;
	
	int ret_err;
	
	int in = -1;
	
	while (true) 
	{
		in = srcFs->OpenRead(srcPath, FS::SHARE_READ, &ret_err, Info());
		if (in == -2) return false;
		if (in>=0) break;
		
		switch (RedMessage( _LT("Can't open file:\n") , srcFs->Uri(srcPath).GetUtf8(), bRetrySkipCancel, srcFs->StrError(ret_err).GetUtf8())) {
		case CMD_CANCEL: return false;
		case CMD_SKIP: return true;
		}
	}
	
	int out =  -1;
	
	out = destFs->OpenCreate(destPath, false | commitAll, srcNode->st.mode, 0, &ret_err, Info());

	if (out < 0 && destFs->IsEEXIST(ret_err))
		switch (RedMessage( _LT("Owerwrite  file?\n") , destFs->Uri(destPath).GetUtf8(), bOkAllNoCancel)) {
		case CMD_ALL: commitAll = true; //no break
		case CMD_OK: 
			out = destFs->OpenCreate(destPath, true, srcNode->st.mode, 0, &ret_err, Info());
			break;
		case CMD_NO: 
			srcFs->Close(in, 0, Info());
			return true;
		default:
			srcFs->Close(in, 0, Info());
			return false;
		}
	
	if (out < 0)
	{
		srcFs->Close(in, 0, Info());
		return RedMessage( _LT("Can't create file:\n"), destFs->Uri(destPath).GetUtf8(), bSkipCancel, destFs->StrError(ret_err).GetUtf8()) == CMD_SKIP;
	}
	
	int  bytes;
	//char    buf[BUFSIZE];
	int64 doneBytes = 0;
	
	int blockSize = STARTSIZE;
	
	while (true) 
	{
		if (Info()->Stopped()) 
		{
			stopped = true;
			goto err;
		}

		time_t timeStart = time(0);

		if ((bytes = srcFs->Read(in, _buffer, blockSize, &ret_err, Info())) < 0)
		{
			if (bytes == -2 ||  
				RedMessage( _LT("Can't read the file:\n"), srcFs->Uri(srcPath).GetUtf8(), bSkipCancel, srcFs->StrError(ret_err).GetUtf8()) != CMD_SKIP) {
				stopped = true;
			}
			goto err;
		}

		if (!bytes) break;

		int b;

		if ((b = destFs->Write(out, _buffer, bytes, &ret_err, Info())) < 0)
		{
			if (b == -2 || RedMessage( _LT("Can't write the file:\n"), destFs->Uri(destPath).GetUtf8(), bSkipCancel, destFs->StrError(ret_err).GetUtf8()) != CMD_SKIP) 
				stopped = true;
			goto err;
		}

		
		if (b != bytes)
		{
			if (RedMessage("May be disk full \n(writed bytes != readed bytes)\nwhen write:\n", destFs->Uri(destPath).GetUtf8(), bSkipCancel) != CMD_SKIP) 
				stopped = true;
			goto err;
		}

		time_t timeStop = time(0);

		if (timeStart == timeStop && blockSize < BSIZE)
		{
			blockSize = blockSize*2;
			if (blockSize > BSIZE) blockSize = BSIZE;
		}

		doneBytes += bytes;
		SendProgressInfo(srcNode->st.size, doneBytes);
	} 

	srcFs->Close(in, 0, Info());
	in = -1;
	
	SendProgressInfo(srcNode->st.size, srcNode->st.size);

	{
		int r = destFs->Close(out, &ret_err, Info());
		if (r)
		{
			if (r == -2 || RedMessage( "Can't close the file:\n", destFs->Uri(destPath).GetUtf8(), bSkipCancel, destFs->StrError(ret_err).GetUtf8()) != CMD_SKIP) 
				stopped = true;
			goto err;
		} else 
			out = -1;
	}
	
	destFs->SetFileTime(destPath, srcNode->st.mtime, srcNode->st.mtime, 0, Info());

	return !move || Unlink(srcFs, srcPath);

err:
	if (in >= 0) srcFs->Close(in, 0, Info()); 
	if (out >= 0) destFs->Close(out, 0, Info());
	Unlink(destFs, destPath);
	
	return !stopped;
}