bool SFtpReader::Copy( Selection& tSelection, // remote const string& sTargetPath, // local Selection* pSelection ) { string sCurName, sTargetPathTmp, sTargetPathTmp2; string sSourceName, sTargetName; vector<File*> vFiles; ullong uFileSize = tSelection.CalcSize(); uint uSize = tSelection.GetSize(); string sSize = toregular(uSize), sRestSize; bool bSkipAll = false, bOverwriteAll = false; ullong uLastSize = 0, uViewCount=1, uPsize=0, uCsize = 0; struct stat src_stat, tar_stat; int nBufSize = g_tCfg.GetValueNum("SSH", "DefBufSize", 8196); char buf[nBufSize]; // reading byte vFiles = tSelection.GetData(); if (sTargetPath.size() == 0) sTargetPathTmp2 = _sCurPath; else sTargetPathTmp2 = sTargetPath; CommonProgress tProgress( _("Copy"), (_("To ") + sTargetPathTmp2).c_str(), true); if (pSelection != NULL) { pSelection->Clear(); pSelection->SetSelectPath(sTargetPathTmp2); } tProgress.Start(); string sSourcePath = tSelection.GetSelectPath(); LOG_WRITE("Copy sTargetPath [%s] [%s] [%s]", sTargetPath.c_str(), _sCurPath.c_str(), sTargetPathTmp2.c_str()); // 파일 복사 for (int n=0; n<(int)vFiles.size(); n++) { File* pFile = vFiles[n]; bool bOverwrite = false; // 파일 이름이 없을경우 continue if (!pFile) continue; // 소스 이름과 타겟 이름 정하기 sSourceName = pFile->sFullName; sTargetName = sTargetPathTmp2 + ChgCurLocale( pFile->sFullName.substr(sSourcePath.size()) ); LIBSSH2_SFTP_ATTRIBUTES tAttr; if (libssh2_sftp_stat((LIBSSH2_SFTP*)_pSessionSFtp, (char*)sSourceName.c_str(), &tAttr) == -1) { // 소스가 없다니.. 참 String sMsg; string sErrMsg = GetLastErrMsg(); sMsg.Append(_("File access error (%s), continue? !!! "), pFile->sName.c_str()); if (!sErrMsg.empty()) sMsg.Append("[%s]", sErrMsg.c_str()); tProgress.End(); if (YNBox(_("Error"), sMsg.c_str(), false) == false) break; tProgress.Start(); continue; } LOG_WRITE("SFtpReader Copy sTargetName 1 [%s] [%s] [%s] [%d]", sSourceName.c_str(), sTargetName.c_str(), _sCurPath.c_str(), tAttr.filesize); String sCount, sCount2; sCount.Printf("%s/%s", toregular(uViewCount).c_str(), sSize.c_str()); tProgress.setLeftStr(pFile->sName.c_str()); tProgress.setRightStr2(sCount.c_str()); if (stat(sTargetName.c_str(), &tar_stat)!=-1) { if (bSkipAll) continue; else if (bOverwriteAll == false) {// 파일이 있을 경우.. askagain_sftp_copy: vector<string> q; q.push_back(_("Overwrite")); q.push_back(_("Skip")); q.push_back(_("Rename")); q.push_back(_("Overwrite All")); q.push_back(_("Skip All")); q.push_back(_("Cancel")); int nSelect = 0; tProgress.End(); nSelect = SelectBox((_("File exists : ") + pFile->sName).c_str(), q, 0); tProgress.Start(); LOG_WRITE("Selection [%d]", nSelect); switch(nSelect) { case 0: // overwrite LOG_WRITE("OverWrite"); bOverwrite = true; break; case 1: // skip uPsize += tAttr.filesize; uViewCount++; continue; case 2: // rename { if ( !pFile->bDir ) { struct stat statbuf; string sRename = pFile->sName; while(1) { tProgress.End(); if (InputBox( _("Rename"), sRename) < 0) goto askagain_sftp_copy; tProgress.Start(); sTargetName = sTargetPathTmp2 + sRename; if (lstat(sTargetName.c_str(), &statbuf) != -1) { tProgress.End(); MsgBox( _("Error"), _("File exists")); tProgress.Start(); continue; } break; } } else { tProgress.End(); MsgBox( _("Error"), _("Directory can't rename.")); tProgress.Start(); } break; } case 3: // overwriteall bOverwriteAll = true; break; case 4: // skipall bSkipAll = true; uPsize += tAttr.filesize; uViewCount++; continue; case -1: case 5: // cancel goto halt_sftp_copy; default: break; } } } // 파일 리스트가 디렉토리 라면 if (pFile->bDir) { if (pSelection != NULL) { File tTargetFile = *pFile; tTargetFile.sFullName = sTargetName; pSelection->Add(&tTargetFile); } if (mkdir(sTargetName.c_str(), tAttr.permissions)==-1) // 디렉토리를 만든다. { // 실패하면 if ( !bOverwriteAll && !bSkipAll && !bOverwrite) { tProgress.End(); MsgBox(_("Error"), _("Directory Making error")); break; } } continue; } uCsize=0; // 실제 복사 오퍼레이션 uViewCount++; LIBSSH2_SFTP_HANDLE* pFtpFileHandle = NULL; pFtpFileHandle = libssh2_sftp_open( (LIBSSH2_SFTP*)_pSessionSFtp, (char*)sSourceName.c_str(), LIBSSH2_FXF_READ, 0644); if (pFtpFileHandle == NULL) { String sMsg; string sErrMsg = GetLastErrMsg(); sMsg.Append(_("File access error (%s), continue? !!! "), pFile->sFullName.c_str()); if (!sErrMsg.empty()) sMsg.Append("[%s]", sErrMsg.c_str()); tProgress.End(); if (YNBox(_("Error"), sMsg.c_str(), false) == false) break; tProgress.Start(); continue; } FILE* out = fopen(sTargetName.c_str(), "wb"); if ( out ) { for(;;) { if (tProgress.isExit()) { tProgress.End(); if (YNBox(_("Warning"), _("Do you want to stop copy operation?"), false)==true) { fclose(out); libssh2_sftp_close_handle(pFtpFileHandle); remove( sTargetName.c_str() ); goto halt_sftp_copy; } tProgress.Start(); } if (tAttr.filesize <= (libssh2_uint64_t)uCsize ) break; if ((uLastSize = libssh2_sftp_read(pFtpFileHandle, buf, sizeof(buf))) == -1) { String sMsg; string sErrMsg = GetLastErrMsg(); sMsg.Append(_("remote file access error (%s), continue? !!! "), pFile->sFullName.c_str()); if (!sErrMsg.empty()) sMsg.Append("[%s]", sErrMsg.c_str()); tProgress.End(); if (YNBox(_("Error"), sMsg.c_str(), false) == false) break; fclose(out); libssh2_sftp_close_handle(pFtpFileHandle); remove( sTargetName.c_str() ); goto halt_sftp_copy; } fwrite(buf, 1, uLastSize, out); uCsize +=uLastSize; uPsize +=uLastSize; // libssh2_sftp_seek(pFtpFileHandle, uCsize); sCount2.Printf("%s/%s", toregular(uCsize).c_str(), toregular(pFile->uSize).c_str()); tProgress.setRightStr(sCount2.c_str()); if ( pFile->uSize && uCsize && uPsize && uFileSize ) tProgress.setCount( uCsize * 100 / pFile->uSize, uPsize * 100 / uFileSize ); } } else { libssh2_sftp_close_handle(pFtpFileHandle); tProgress.End(); if (YNBox(_("Error"), _("local file access error, continue?"), false) == false) break; tProgress.Start(); continue; } fclose(out); chmod(sTargetName.c_str(), tAttr.permissions); libssh2_sftp_close_handle(pFtpFileHandle); if (pSelection != NULL) { File tTargetFile = *pFile; tTargetFile.sFullName = sTargetName; pSelection->Add(&tTargetFile); } } halt_sftp_copy: tProgress.End(); if (pSelection) pSelection->SetSelectPath(sTargetPathTmp2); LOG_WRITE("DirReader Copy End"); return true; }
bool SFtpReader::Paste(Selection& tSelection) { string sCurName, sTargetPathTmp, sTargetPathTmp2; string sSourceName, sTargetName; vector<File*> vFiles; struct stat src_stat; int nBufSize = g_tCfg.GetValueNum("SSH", "DefBufSize", 8196); char buf[nBufSize]; ullong uFileSize = tSelection.CalcSize(); uint uSize = tSelection.GetSize(); string sSize = toregular(uSize), sRestSize; bool bSkipAll = false, bOverwriteAll = false; ullong uLastSize = 0, uViewCount=1, uPsize=0, uCsize = 0; vFiles = tSelection.GetData(); sTargetPathTmp2 = _sCurPath; CommonProgress tProgress( _("Copy"), (_("To ") + sTargetPathTmp2).c_str(), true); string sSourcePath = tSelection.GetSelectPath(); LOG_WRITE("Copy sTargetPath [%s] [%s]", _sCurPath.c_str(), sTargetPathTmp2.c_str()); EncodeChk(vFiles, false); tProgress.Start(); // 파일 디렉토리 먼저 생성 복사 for (int n=0; n<(int)vFiles.size(); n++) { File* pFile = vFiles[n]; // 파일 이름이 없을경우 continue if (!pFile) continue; // 소스 이름과 타겟 이름 정하기 sSourceName = pFile->sFullName; sTargetName = sTargetPathTmp2 + pFile->sFullName.substr(sSourcePath.size()); sTargetName = KorCodeChg(sTargetName, _eEncode); // 파일 리스트가 디렉토리 라면 if (pFile->bDir) { if ( libssh2_sftp_mkdir( (LIBSSH2_SFTP*)_pSessionSFtp, (char*)sTargetName.c_str(), 0755) == -1) { String sMsg; string sErrMsg = GetLastErrMsg(); sMsg.Append(_("SFtp Directory exists, continue !!! [%s]"), sTargetName.c_str()); if (!sErrMsg.empty()) sMsg.Append("[%s]", sErrMsg.c_str()); tProgress.End(); if (YNBox(_("Error"), sMsg.c_str(), false) == false) break; tProgress.Start(); return false; } continue; } } for (int n=0; n<(int)vFiles.size(); n++) { File* pFile = vFiles[n]; // 파일 이름이 없을경우 continue if (!pFile) continue; // 소스 이름과 타겟 이름 정하기 sSourceName = pFile->sFullName; sTargetName = sTargetPathTmp2 + pFile->sFullName.substr(sSourcePath.size()); sTargetName = KorCodeChg(sTargetName, _eEncode); LOG_WRITE("SFtpReader::Paste [%s] [%s]", sSourceName.c_str(), sTargetName.c_str()); if (stat(sSourceName.c_str(), &src_stat)==-1) { // 소스가 없다니.. 참 String sStr; sStr.Append(_("Source is not found : %s"), sSourceName.c_str()); tProgress.End(); MsgBox(_("Error"), sStr); tProgress.Start(); break; } LOG_WRITE("SFtpReader Paste sTargetName 1 [%s] [%s] [%s]", sSourceName.c_str(), sTargetName.c_str(), _sCurPath.c_str()); mode_t permission = src_stat.st_mode; // 파일 리스트가 디렉토리 라면 if (pFile->bDir) continue; String sCount, sCount2; sCount.Printf("%s/%s", toregular(uViewCount).c_str(), sSize.c_str()); tProgress.setLeftStr(pFile->sName.c_str()); tProgress.setRightStr2(sCount.c_str()); LIBSSH2_SFTP_ATTRIBUTES tAttrs; if (libssh2_sftp_stat((LIBSSH2_SFTP*)_pSessionSFtp, (char*)sTargetName.c_str(), &tAttrs) != -1) { if (bSkipAll) continue; else if (bOverwriteAll == false) {// 파일이 있을 경우.. askagain_sftp_paste: vector<string> q; q.push_back(_("Overwrite")); q.push_back(_("Skip")); q.push_back(_("Rename")); q.push_back(_("Overwrite All")); q.push_back(_("Skip All")); q.push_back(_("Cancel")); int nSelect = 0; tProgress.End(); nSelect = SelectBox((_("File exists : ") + pFile->sName).c_str(), q, 0); tProgress.Start(); LOG_WRITE("Selection [%d]", nSelect); switch(nSelect) { case 0: // overwrite LOG_WRITE("OverWrite"); break; case 1: // skip uPsize += src_stat.st_size; uViewCount++; continue; case 2: // rename { if ( !pFile->bDir ) { string sRename = pFile->sName; while(1) { tProgress.End(); if (InputBox( _("Rename"), sRename) < 0) goto askagain_sftp_paste; tProgress.Start(); sTargetName = sTargetPathTmp2 + sRename; if ( libssh2_sftp_rename_ex( (LIBSSH2_SFTP*)_pSessionSFtp, (char*)pFile->sFullName.c_str(), pFile->sFullName.size(), (char*)sTargetName.c_str(), sTargetName.size(), 0644) == -1) { tProgress.End(); MsgBox( _("Error"), _("File exists")); tProgress.Start(); continue; } tProgress.End(); } break; } else { tProgress.End(); MsgBox( _("Error"), _("Directory can't rename.")); tProgress.Start(); } break; } case 3: // overwriteall bOverwriteAll = true; break; case 4: // skipall bSkipAll = true; uPsize += src_stat.st_size; uViewCount++; continue; case -1: case 5: // cancel goto halt_sftp_paste; default: break; } } } uCsize=0; // 실제 복사 오퍼레이션 uViewCount++; LIBSSH2_SFTP_HANDLE* pFtpOutFileHandle = NULL; pFtpOutFileHandle = libssh2_sftp_open( (LIBSSH2_SFTP*)_pSessionSFtp, (char*)sTargetName.c_str(), LIBSSH2_FXF_READ | LIBSSH2_FXF_WRITE | LIBSSH2_FXF_TRUNC | LIBSSH2_FXF_CREAT , 0644); if (pFtpOutFileHandle == NULL) { String sMsg; string sErrMsg = GetLastErrMsg(); sMsg.Append("File write access error (%s), continue? !!! ", sTargetName.c_str()); if (!sErrMsg.empty()) sMsg.Append("[%s]", sErrMsg.c_str()); tProgress.End(); if (YNBox(_("Error"), sMsg.c_str(), false) == false) break; tProgress.Start(); continue; } FILE* fp = fopen(sSourceName.c_str(), "rb"); LOG_WRITE("TEST1"); if ( fp ) { while( !feof(fp) ) { if (tProgress.isExit()) { tProgress.End(); if (YNBox(_("Warning"), _("Do you want to stop copy operation?"), false)==true) { libssh2_sftp_close_handle(pFtpOutFileHandle); fclose(fp); libssh2_sftp_unlink((LIBSSH2_SFTP*)_pSessionSFtp, (char*)sTargetName.c_str()); goto halt_sftp_paste; } tProgress.Start(); } uLastSize = fread(buf, 1, sizeof(buf), fp); int nSize = 0, nSizePlus = 0; do { if (tProgress.isExit()) break; nSize = 0; if ((nSize = libssh2_sftp_write(pFtpOutFileHandle, buf+nSizePlus, uLastSize-nSizePlus)) == -1) { tProgress.End(); String sMsg; string sErrMsg = GetLastErrMsg(); sMsg.Append(_("file writing failure. continue?")); if (!sErrMsg.empty()) sMsg.Append(" [%s]", sErrMsg.c_str()); if (YNBox(_("Error"), sMsg.c_str() , false)==false) { libssh2_sftp_close_handle(pFtpOutFileHandle); fclose(fp); libssh2_sftp_unlink((LIBSSH2_SFTP*)_pSessionSFtp, (char*)sTargetName.c_str()); goto halt_sftp_paste; } tProgress.Start(); break; } uCsize += nSize; uPsize += nSize; nSizePlus += nSize; } while( nSizePlus < uLastSize ); if (tProgress.isExit()) continue; //libssh2_sftp_seek(pFtpOutFileHandle, uCsize); sCount2.Printf("%s/%s", toregular(uPsize).c_str(), toregular(uFileSize).c_str()); tProgress.setRightStr(sCount2.c_str()); if (src_stat.st_size && uCsize && uPsize && uFileSize) tProgress.setCount( uCsize * 100 / src_stat.st_size, uPsize * 100 / uFileSize ); } } else { tProgress.End(); if (YNBox(_("Error"), _("File access error, continue?"), false) == false) break; tProgress.Start(); continue; } LIBSSH2_SFTP_ATTRIBUTES tAttrOut; libssh2_sftp_fstat(pFtpOutFileHandle, &tAttrOut); tAttrOut.permissions = permission; libssh2_sftp_fsetstat(pFtpOutFileHandle, &tAttrOut); libssh2_sftp_close_handle(pFtpOutFileHandle); fclose(fp); } halt_sftp_paste: tProgress.End(); return true; }