From 2c9928aa1e4d0ea047fd08b032d3a705a9d9e62d Mon Sep 17 00:00:00 2001 From: olegkap_cp Date: Fri, 28 Dec 2012 16:35:56 +0000 Subject: [PATCH] Add couple more extended requests for future support --- .../Renci.SshNet.NET35.csproj | 6 ++ .../Renci.SshNet.Silverlight.csproj | 6 ++ .../Renci.SshNet.Silverlight5.csproj | 6 ++ .../Renci.SshNet.WindowsPhone.csproj | 6 ++ .../Renci.SshNet.WindowsPhone8.csproj | 6 ++ .../Renci.SshNet/Renci.SshNet.csproj | 2 + .../ExtendedRequests/FStatVfsRequest.cs | 33 +++++++ .../ExtendedRequests/HardLinkRequest.cs | 36 +++++++ .../Sftp/Requests/SftpUnblockRequest.cs | 1 - .../Renci.SshNet/Sftp/SftpSession.cs | 95 ++++++++++++++++++- 10 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 Renci.SshClient/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs create mode 100644 Renci.SshClient/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs diff --git a/Renci.SshClient/Renci.SshNet.NET35/Renci.SshNet.NET35.csproj b/Renci.SshClient/Renci.SshNet.NET35/Renci.SshNet.NET35.csproj index 32ebb3dc..11af3b40 100644 --- a/Renci.SshClient/Renci.SshNet.NET35/Renci.SshNet.NET35.csproj +++ b/Renci.SshClient/Renci.SshNet.NET35/Renci.SshNet.NET35.csproj @@ -639,6 +639,12 @@ Sftp\Flags.cs + + Sftp\Requests\ExtendedRequests\FStatVfsRequest.cs + + + Sftp\Requests\ExtendedRequests\HardLinkRequest.cs + Sftp\Requests\ExtendedRequests\PosixRenameRequest.cs diff --git a/Renci.SshClient/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj b/Renci.SshClient/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj index aece265c..1dc61057 100644 --- a/Renci.SshClient/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj +++ b/Renci.SshClient/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj @@ -606,6 +606,12 @@ Sftp\Flags.cs + + Sftp\Requests\ExtendedRequests\FStatVfsRequest.cs + + + Sftp\Requests\ExtendedRequests\HardLinkRequest.cs + Sftp\Requests\ExtendedRequests\PosixRenameRequest.cs diff --git a/Renci.SshClient/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj b/Renci.SshClient/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj index 5fdb753c..ab7e9bf4 100644 --- a/Renci.SshClient/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj +++ b/Renci.SshClient/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj @@ -612,6 +612,12 @@ Sftp\Flags.cs + + Sftp\Requests\ExtendedRequests\FStatVfsRequest.cs + + + Sftp\Requests\ExtendedRequests\HardLinkRequest.cs + Sftp\Requests\ExtendedRequests\PosixRenameRequest.cs diff --git a/Renci.SshClient/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj b/Renci.SshClient/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj index a6bb73c6..992eb974 100644 --- a/Renci.SshClient/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj +++ b/Renci.SshClient/Renci.SshNet.WindowsPhone/Renci.SshNet.WindowsPhone.csproj @@ -610,6 +610,12 @@ Sftp\Flags.cs + + Sftp\Requests\ExtendedRequests\FStatVfsRequest.cs + + + Sftp\Requests\ExtendedRequests\HardLinkRequest.cs + Sftp\Requests\ExtendedRequests\PosixRenameRequest.cs diff --git a/Renci.SshClient/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj b/Renci.SshClient/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj index c60b308a..ab551562 100644 --- a/Renci.SshClient/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj +++ b/Renci.SshClient/Renci.SshNet.WindowsPhone8/Renci.SshNet.WindowsPhone8.csproj @@ -653,6 +653,12 @@ Sftp\Flags.cs + + Sftp\Requests\ExtendedRequests\FStatVfsRequest.cs + + + Sftp\Requests\ExtendedRequests\HardLinkRequest.cs + Sftp\Requests\ExtendedRequests\PosixRenameRequest.cs diff --git a/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj b/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj index da8240a2..7a8e43e0 100644 --- a/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj +++ b/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj @@ -358,6 +358,8 @@ + + diff --git a/Renci.SshClient/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs b/Renci.SshClient/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs new file mode 100644 index 00000000..c9ebd0e9 --- /dev/null +++ b/Renci.SshClient/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs @@ -0,0 +1,33 @@ +using System; +using Renci.SshNet.Sftp.Responses; + +namespace Renci.SshNet.Sftp.Requests +{ + internal class FStatVfsRequest : SftpExtendedRequest + { + public override SftpMessageTypes SftpMessageType + { + get { return SftpMessageTypes.Extended; } + } + + public override string Name + { + get { return "fstatvfs@openssh.com"; } + } + + public byte[] Handle { get; private set; } + + public FStatVfsRequest(uint protocolVersion, uint requestId, byte[] handle, Action extendedAction, Action statusAction) + : base(protocolVersion, requestId, statusAction) + { + this.Handle = handle; + this.SetAction(extendedAction); + } + + protected override void SaveData() + { + base.SaveData(); + this.WriteBinaryString(this.Handle); + } + } +} diff --git a/Renci.SshClient/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs b/Renci.SshClient/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs new file mode 100644 index 00000000..188bc1ba --- /dev/null +++ b/Renci.SshClient/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs @@ -0,0 +1,36 @@ +using System; +using Renci.SshNet.Sftp.Responses; + +namespace Renci.SshNet.Sftp.Requests +{ + internal class HardLinkRequest : SftpExtendedRequest + { + public override SftpMessageTypes SftpMessageType + { + get { return SftpMessageTypes.Extended; } + } + + public override string Name + { + get { return "hardlink@openssh.com"; } + } + + public string OldPath { get; private set; } + + public string NewPath { get; private set; } + + public HardLinkRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Action statusAction) + : base(protocolVersion, requestId, statusAction) + { + this.OldPath = oldPath; + this.NewPath = newPath; + } + + protected override void SaveData() + { + base.SaveData(); + this.Write(this.OldPath); + this.Write(this.NewPath); + } + } +} \ No newline at end of file diff --git a/Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpUnblockRequest.cs b/Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpUnblockRequest.cs index 33a6a94a..618c075d 100644 --- a/Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpUnblockRequest.cs +++ b/Renci.SshClient/Renci.SshNet/Sftp/Requests/SftpUnblockRequest.cs @@ -25,7 +25,6 @@ namespace Renci.SshNet.Sftp.Requests this.Handle = handle; this.Offset = offset; this.Length = length; - this.SetAction(dataAction); } protected override void LoadData() diff --git a/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs b/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs index 8d4b794c..dd252c84 100644 --- a/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs +++ b/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs @@ -25,6 +25,8 @@ namespace Renci.SshNet.Sftp private EventWaitHandle _sftpVersionConfirmed = new AutoResetEvent(false); + private IDictionary _supportedExtensions; + /// /// Gets remote working directory. /// @@ -217,6 +219,7 @@ namespace Renci.SshNet.Sftp if (versionResponse != null) { this.ProtocolVersion = versionResponse.Version; + this._supportedExtensions = versionResponse.Extentions; this._sftpVersionConfirmed.Set(); } @@ -862,7 +865,7 @@ namespace Renci.SshNet.Sftp } #endregion - + #region SFTP Extended API functions /// @@ -892,6 +895,9 @@ namespace Renci.SshNet.Sftp } }); + if (!this._supportedExtensions.ContainsKey(request.Name)) + throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", request.Name)); + this.SendRequest(request); this.WaitHandle(wait, this._operationTimeout); @@ -934,6 +940,9 @@ namespace Renci.SshNet.Sftp }); + if (!this._supportedExtensions.ContainsKey(request.Name)) + throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", request.Name)); + this.SendRequest(request); this.WaitHandle(wait, this._operationTimeout); @@ -942,6 +951,90 @@ namespace Renci.SshNet.Sftp return information; } + /// + /// Performs fstatvfs@openssh.com extended request. + /// + /// The file handle. + /// if set to true [null on error]. + /// + /// + internal SftpFileSytemInformation RequestFStatVfs(byte[] handle, bool nullOnError = false) + { + if (this.ProtocolVersion < 3) + { + throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_EXTENDED operation is not supported in {0} version that server operates in.", this.ProtocolVersion)); + } + + SftpFileSytemInformation information = null; + using (var wait = new AutoResetEvent(false)) + { + var request = new FStatVfsRequest(this.ProtocolVersion, this.NextRequestId, handle, + (response) => + { + information = response.GetReply().Information; + + wait.Set(); + }, + (response) => + { + if (nullOnError) + { + wait.Set(); + } + else + { + ThrowSftpException(response); + } + + }); + + if (!this._supportedExtensions.ContainsKey(request.Name)) + throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", request.Name)); + + this.SendRequest(request); + + this.WaitHandle(wait, this._operationTimeout); + } + + return information; + } + + /// + /// Performs hardlink@openssh.com extended request. + /// + /// The old path. + /// The new path. + internal void HardLink(string oldPath, string newPath) + { + if (this.ProtocolVersion < 3) + { + throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "SSH_FXP_EXTENDED operation is not supported in {0} version that server operates in.", this.ProtocolVersion)); + } + + using (var wait = new AutoResetEvent(false)) + { + var request = new HardLinkRequest(this.ProtocolVersion, this.NextRequestId, oldPath, newPath, + (response) => + { + if (response.StatusCode == StatusCodes.Ok) + { + wait.Set(); + } + else + { + ThrowSftpException(response); + } + }); + + if (!this._supportedExtensions.ContainsKey(request.Name)) + throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Extension method {0} currently not supported by the server.", request.Name)); + + this.SendRequest(request); + + this.WaitHandle(wait, this._operationTimeout); + } + } + #endregion private void ThrowSftpException(SftpStatusResponse response)