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))