diff --git a/Renci.SshClient/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj b/Renci.SshClient/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
index 249a0568..611d514d 100644
--- a/Renci.SshClient/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
+++ b/Renci.SshClient/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
@@ -63,6 +63,7 @@
+
diff --git a/Renci.SshClient/Renci.SshNet.Tests/SftpClientTests/ChangeDirectory.cs b/Renci.SshClient/Renci.SshNet.Tests/SftpClientTests/ChangeDirectory.cs
new file mode 100644
index 00000000..939b5256
--- /dev/null
+++ b/Renci.SshClient/Renci.SshNet.Tests/SftpClientTests/ChangeDirectory.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Text;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Renci.SshNet.Tests.Properties;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Tests.SftpClientTests
+{
+ [TestClass]
+ public class ChangeDirectory
+ {
+ [TestInitialize()]
+ public void CleanCurrentFolder()
+ {
+ using (var client = new SshClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
+ {
+ client.Connect();
+ client.RunCommand("rm -rf *");
+ client.Disconnect();
+ }
+ }
+
+ [TestMethod]
+ [TestCategory("Sftp")]
+ [ExpectedException(typeof(SshFileNotFoundException))]
+ public void Test_Sftp_ChangeDirectory_Root_Dont_Exists()
+ {
+ using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
+ {
+ sftp.Connect();
+ sftp.ChangeDirectory("/asdasd");
+ }
+ }
+
+ [TestMethod]
+ [TestCategory("Sftp")]
+ [ExpectedException(typeof(SshFileNotFoundException))]
+ public void Test_Sftp_ChangeDirectory_Root_With_Slash_Dont_Exists()
+ {
+ using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
+ {
+ sftp.Connect();
+ sftp.ChangeDirectory("/asdasd/");
+ }
+ }
+
+ [TestMethod]
+ [TestCategory("Sftp")]
+ [ExpectedException(typeof(SshFileNotFoundException))]
+ public void Test_Sftp_ChangeDirectory_Subfolder_Dont_Exists()
+ {
+ using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
+ {
+ sftp.Connect();
+ sftp.ChangeDirectory("/asdasd/sssddds");
+ }
+ }
+
+ [TestMethod]
+ [TestCategory("Sftp")]
+ [ExpectedException(typeof(SshFileNotFoundException))]
+ public void Test_Sftp_ChangeDirectory_Subfolder_With_Slash_Dont_Exists()
+ {
+ using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
+ {
+ sftp.Connect();
+ sftp.ChangeDirectory("/asdasd/sssddds/");
+ }
+ }
+
+ [TestMethod]
+ [TestCategory("Sftp")]
+ public void Test_Sftp_ChangeDirectory_Which_Exists()
+ {
+ using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
+ {
+ sftp.Connect();
+ sftp.ChangeDirectory("/usr");
+ Assert.AreEqual("/usr", sftp.WorkingDirectory);
+ }
+ }
+
+ [TestMethod]
+ [TestCategory("Sftp")]
+ public void Test_Sftp_ChangeDirectory_Which_Exists_With_Slash()
+ {
+ using (var sftp = new SftpClient(Resources.HOST, Resources.USERNAME, Resources.PASSWORD))
+ {
+ sftp.Connect();
+ sftp.ChangeDirectory("/usr/");
+ Assert.AreEqual("/usr", sftp.WorkingDirectory);
+ }
+ }
+ }
+}
diff --git a/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj b/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj
index 08890cce..b85eecf7 100644
--- a/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj
+++ b/Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj
@@ -130,6 +130,7 @@
+
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/OpenDirectoryCommand.cs b/Renci.SshClient/Renci.SshNet/Sftp/OpenDirectoryCommand.cs
new file mode 100644
index 00000000..9ef1c5ea
--- /dev/null
+++ b/Renci.SshClient/Renci.SshNet/Sftp/OpenDirectoryCommand.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Common;
+using Renci.SshNet.Sftp.Messages;
+using System.Globalization;
+
+namespace Renci.SshNet.Sftp
+{
+ internal class OpenDirectoryCommand : SftpCommand
+ {
+ private string _path;
+
+ public byte[] Handle { get; private set; }
+
+ public OpenDirectoryCommand(SftpSession sftpSession, string path)
+ : base(sftpSession)
+ {
+ this._path = path;
+ }
+
+ protected override void OnExecute()
+ {
+ this.SendOpenDirMessage(this._path);
+ }
+
+ protected override void OnHandle(byte[] handle)
+ {
+ base.OnHandle(handle);
+
+ this.Handle = handle;
+
+ this.CompleteExecution();
+ }
+
+ protected override void OnStatus(StatusCodes statusCode, string errorMessage, string language)
+ {
+ base.OnStatus(statusCode, errorMessage, language);
+
+ if (statusCode == StatusCodes.NoSuchFile)
+ {
+ throw new SshFileNotFoundException(string.Format(CultureInfo.CurrentCulture, "Path '{0}' is not found.", this._path));
+ }
+ }
+ }
+}
diff --git a/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs b/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs
index 62520b1b..360284d8 100644
--- a/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs
+++ b/Renci.SshClient/Renci.SshNet/Sftp/SftpSession.cs
@@ -101,7 +101,25 @@ namespace Renci.SshNet.Sftp
public void ChangeDirectory(string path)
{
- this.WorkingDirectory = this.GetCanonicalPath(path);
+ var fullPath = this.GetCanonicalPath(path);
+
+ // Open directory
+ using (var openCmd = new OpenDirectoryCommand(this, fullPath))
+ {
+ openCmd.CommandTimeout = this._operationTimeout;
+
+ // Try to open directory and throw an exception if can't
+ openCmd.Execute();
+
+ using (SftpCommand closeCmd = new CloseCommand(this, openCmd.Handle))
+ {
+ closeCmd.CommandTimeout = this._operationTimeout;
+
+ closeCmd.Execute();
+ }
+ }
+
+ this.WorkingDirectory = fullPath;
}
///
@@ -141,6 +159,9 @@ namespace Renci.SshNet.Sftp
var partialFullPath = string.Join("/", pathParts, 0, pathParts.Length - 1);
+ if (string.IsNullOrEmpty(partialFullPath))
+ partialFullPath = "/";
+
canonizedPath = this.GetRealPath(partialFullPath);
if (string.IsNullOrEmpty(canonizedPath))