1
0
mirror of https://github.com/winscp/winscp.git synced 2026-10-24 02:28:55 +03:00

Remote file duplication in scripting, .NET assembly and XML log + Scripting command mv and .NET assembly function Session.MoveFile report when the server does not support file renaming/moving.

Source commit: 974f6dff9af8f3bb1e39a7b2ef453af0c7b2d0ec
This commit is contained in:
Martin Prikryl
2017-11-09 17:01:23 +00:00
parent 0312eb8ba1
commit 32d26ba76e
9 changed files with 93 additions and 4 deletions

View File

@@ -1054,6 +1054,35 @@ namespace WinSCP
}
}
public void DuplicateFile(string sourcePath, string targetPath)
{
using (Logger.CreateCallstackAndLock())
{
CheckOpened();
string sourceArgument = Tools.ArgumentEscape(EscapeFileMask(sourcePath));
string targetArgument = Tools.ArgumentEscape(targetPath);
string command = string.Format(CultureInfo.InvariantCulture, "cp \"{0}\" \"{1}\"", sourceArgument, targetArgument);
WriteCommand(command);
using (ElementLogReader groupReader = _reader.WaitForGroupAndCreateLogReader())
{
if (!groupReader.TryWaitForNonEmptyElement("cp", LogReadFlags.ThrowFailures))
{
throw Logger.WriteException(new SessionRemoteException(this, string.Format(CultureInfo.CurrentCulture, "{0} not found.", sourcePath)));
}
else
{
using (ElementLogReader cpReader = groupReader.CreateLogReader())
{
ReadElement(cpReader, 0);
groupReader.ReadToEnd(LogReadFlags.ThrowFailures);
}
}
}
}
}
// This is not static method only to make it visible to COM
public string EscapeFileMask(string fileMask)
{

View File

@@ -365,6 +365,7 @@ void __fastcall TScript::Init()
FCommands->Register(L"rmdir", SCRIPT_RMDIR_DESC, SCRIPT_RMDIR_HELP, &RmDirProc, 1, -1, false);
FCommands->Register(L"mv", SCRIPT_MV_DESC, SCRIPT_MV_HELP2, &MvProc, 2, -1, false);
FCommands->Register(L"rename", 0, SCRIPT_MV_HELP2, &MvProc, 2, -1, false);
FCommands->Register(L"cp", SCRIPT_CP_DESC, SCRIPT_CP_HELP, &CpProc, 2, -1, false);
FCommands->Register(L"chmod", SCRIPT_CHMOD_DESC, SCRIPT_CHMOD_HELP2, &ChModProc, 2, -1, false);
FCommands->Register(L"ln", SCRIPT_LN_DESC, SCRIPT_LN_HELP, &LnProc, 2, 2, false);
FCommands->Register(L"symlink", 0, SCRIPT_LN_HELP, &LnProc, 2, 2, false);
@@ -1331,10 +1332,15 @@ void __fastcall TScript::RmDirProc(TScriptProcParams * Parameters)
}
}
//---------------------------------------------------------------------------
void __fastcall TScript::MvProc(TScriptProcParams * Parameters)
void __fastcall TScript::DoMvOrCp(TScriptProcParams * Parameters, TFSCapability Capability, bool Cp)
{
CheckSession();
if (!FTerminal->IsCapable[Capability])
{
NotSupported();
}
TStrings * FileList = CreateFileList(Parameters, 1, Parameters->ParamCount - 1,
fltMask);
try
@@ -1346,7 +1352,14 @@ void __fastcall TScript::MvProc(TScriptProcParams * Parameters)
Target = UnixIncludeTrailingBackslash(TargetDirectory) + FileMask;
CheckMultiFilesToOne(FileList, Target, true);
FTerminal->MoveFiles(FileList, TargetDirectory, FileMask);
if (Cp)
{
FTerminal->CopyFiles(FileList, TargetDirectory, FileMask);
}
else
{
FTerminal->MoveFiles(FileList, TargetDirectory, FileMask);
}
}
__finally
{
@@ -1354,6 +1367,16 @@ void __fastcall TScript::MvProc(TScriptProcParams * Parameters)
}
}
//---------------------------------------------------------------------------
void __fastcall TScript::MvProc(TScriptProcParams * Parameters)
{
DoMvOrCp(Parameters, fcRemoteMove, false);
}
//---------------------------------------------------------------------------
void __fastcall TScript::CpProc(TScriptProcParams * Parameters)
{
DoMvOrCp(Parameters, fcRemoteCopy, true);
}
//---------------------------------------------------------------------------
void __fastcall TScript::ChModProc(TScriptProcParams * Parameters)
{
CheckSession();

View File

@@ -136,6 +136,7 @@ protected:
void __fastcall RmProc(TScriptProcParams * Parameters);
void __fastcall RmDirProc(TScriptProcParams * Parameters);
void __fastcall MvProc(TScriptProcParams * Parameters);
void __fastcall CpProc(TScriptProcParams * Parameters);
void __fastcall ChModProc(TScriptProcParams * Parameters);
void __fastcall LnProc(TScriptProcParams * Parameters);
void __fastcall MkDirProc(TScriptProcParams * Parameters);
@@ -179,6 +180,7 @@ private:
void __fastcall NotSupported();
void __fastcall CheckMultiFilesToOne(TStrings * FileList, const UnicodeString & Target, bool Unix);
void __fastcall LogOption(const UnicodeString & LogStr);
void __fastcall DoMvOrCp(TScriptProcParams * Parameters, TFSCapability Capability, bool Cp);
};
//---------------------------------------------------------------------------
typedef void __fastcall (__closure *TScriptInputEvent)(TScript * Script, const UnicodeString Prompt, UnicodeString & Str);

View File

@@ -296,6 +296,7 @@ protected:
case laMkdir: return L"mkdir";
case laRm: return L"rm";
case laMv: return L"mv";
case laCp: return L"cp";
case laCall: return L"call";
case laLs: return L"ls";
case laStat: return L"stat";
@@ -532,6 +533,13 @@ __fastcall TMvSessionAction::TMvSessionAction(TActionLog * Log,
Destination(ADestination);
}
//---------------------------------------------------------------------------
__fastcall TCpSessionAction::TCpSessionAction(TActionLog * Log,
const UnicodeString & FileName, const UnicodeString & ADestination) :
TFileLocationSessionAction(Log, laCp, FileName)
{
Destination(ADestination);
}
//---------------------------------------------------------------------------
__fastcall TCallSessionAction::TCallSessionAction(TActionLog * Log,
const UnicodeString & Command, const UnicodeString & Destination) :
TSessionAction(Log, laCall)

View File

@@ -80,7 +80,7 @@ public:
enum TLogLineType { llOutput, llInput, llStdError, llMessage, llException };
enum TLogAction
{
laUpload, laDownload, laTouch, laChmod, laMkdir, laRm, laMv, laCall, laLs,
laUpload, laDownload, laTouch, laChmod, laMkdir, laRm, laMv, laCp, laCall, laLs,
laStat, laChecksum, laCwd
};
//---------------------------------------------------------------------------
@@ -180,6 +180,13 @@ public:
const UnicodeString & Destination);
};
//---------------------------------------------------------------------------
class TCpSessionAction : public TFileLocationSessionAction
{
public:
__fastcall TCpSessionAction(TActionLog * Log, const UnicodeString & FileName,
const UnicodeString & Destination);
};
//---------------------------------------------------------------------------
class TCallSessionAction : public TSessionAction
{
public:

View File

@@ -4485,6 +4485,7 @@ void __fastcall TTerminal::DoCopyFile(const UnicodeString FileName,
TRetryOperationLoop RetryLoop(this);
do
{
TCpSessionAction Action(ActionLog, AbsolutePath(FileName, true), AbsolutePath(NewName, true));
try
{
DebugAssert(FFileSystem);
@@ -4503,7 +4504,7 @@ void __fastcall TTerminal::DoCopyFile(const UnicodeString FileName,
}
catch(Exception & E)
{
RetryLoop.Error(E, FMTLOAD(COPY_FILE_ERROR, (FileName, NewName)));
RetryLoop.Error(E, Action, FMTLOAD(COPY_FILE_ERROR, (FileName, NewName)));
}
}
while (RetryLoop.Retry());

View File

@@ -31,6 +31,7 @@
#define SCRIPT_ECHO_HELP 27
#define SCRIPT_STAT_HELP 28
#define SCRIPT_CHECKSUM_HELP 29
#define SCRIPT_CP_HELP 30
#define CORE_ERROR_STRINGS 100
#define KEY_NOT_VERIFIED 101
@@ -320,6 +321,7 @@
#define S3_ACCESS_KEY_ID_PROMPT 357
#define S3_SECRET_ACCESS_KEY_TITLE 358
#define S3_SECRET_ACCESS_KEY_PROMPT 359
#define DUPLICATE_FOLDER_NOT_SUPPORTED 360
#define CORE_INFORMATION_STRINGS 400
#define YES_STR 401
@@ -468,6 +470,7 @@
#define AND_STR 556
#define AUTH_CHANGING_PASSWORD 557
#define PASTE_KEY_BUTTON 558
#define SCRIPT_CP_DESC 559
#define CORE_VARIABLE_STRINGS 600
#define PUTTY_BASED_ON 601

View File

@@ -237,6 +237,7 @@ BEGIN
S3_ERROR_FURTHER_DETAILS, "Further details: %s"
S3_ERROR_EXTRA_DETAILS, "Extra Details: "
S3_STATUS_ACCESS_DENIED, "Access denied."
DUPLICATE_FOLDER_NOT_SUPPORTED, "Direct duplication of folders is not supported. Use a duplication via a local temporary copy."
CORE_CONFIRMATION_STRINGS, "CORE_CONFIRMATION"
CONFIRM_PROLONG_TIMEOUT3, "Host is not communicating for %d seconds.\n\nWait for another %0:d seconds?"
@@ -438,6 +439,7 @@ BEGIN
AND_STR, "%s and %s"
AUTH_CHANGING_PASSWORD, "Changing password."
PASTE_KEY_BUTTON, "&Paste key"
SCRIPT_CP_DESC, "Duplicates remote file"
CORE_VARIABLE_STRINGS, "CORE_VARIABLE"
PUTTY_BASED_ON, "SSH and SCP code based on PuTTY %s"

View File

@@ -376,4 +376,18 @@ BEGIN
" Calculates checksum of remote file.\n"
"example:\n"
" checksum sha-1 index.html\n"
SCRIPT_CP_HELP,
"cp <file> [ <file2> ... ] [ <directory>/ ][ <newname> ]\n"
" Duplicates one or more remote files. Destination directory or new\n"
" name or both must be specified. Destination directory must end with\n"
" slash. Operation mask can be used instead of new name.\n"
" Filename can be replaced with wildcard to select multiple files.\n"
"effective option:\n"
" failonnomatch\n"
"examples:\n"
" cp index.html public_html/\n"
" cp index.html about.*\n"
" cp index.html public_html/about.*\n"
" cp public_html/index.html public_html/about.html /home/martin/*.bak\n"
" cp *.html /home/backup/*.bak\n"
END