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)