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; }
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; }