diff --git a/src/Renci.SshNet/ISftpClient.cs b/src/Renci.SshNet/ISftpClient.cs
index 82117295c..243cd5dc9 100644
--- a/src/Renci.SshNet/ISftpClient.cs
+++ b/src/Renci.SshNet/ISftpClient.cs
@@ -491,6 +491,18 @@ public interface ISftpClient : IBaseClient, IDisposable
/// The method was called after the client was disposed.
void DeleteFile(string path);
+ ///
+ /// Deletes remote symbolic link specified by path.
+ ///
+ /// File to be deleted path.
+ /// is null or contains only whitespace characters.
+ /// Client is not connected.
+ /// was not found on the remote host.
+ /// Permission to delete the file was denied by the remote host. -or- A SSH command was denied by the server.
+ /// A SSH error where is the message from the remote host.
+ /// The method was called after the client was disposed.
+ void DeleteSymbolicLink(string path);
+
///
/// Asynchronously deletes remote file specified by path.
///
@@ -580,6 +592,20 @@ public interface ISftpClient : IBaseClient, IDisposable
/// The method was called after the client was disposed.
bool Exists(string path);
+ ///
+ /// Checks whether symbolic link exists;
+ ///
+ /// The path.
+ ///
+ /// true if directory or file exists; otherwise false.
+ ///
+ /// is null or contains only whitespace characters.
+ /// Client is not connected.
+ /// Permission to perform the operation was denied by the remote host. -or- A SSH command was denied by the server.
+ /// A SSH error where is the message from the remote host.
+ /// The method was called after the client was disposed.
+ bool SymbolicLinkExists(string path);
+
///
/// Gets reference to remote file or directory.
///
@@ -593,6 +619,19 @@ public interface ISftpClient : IBaseClient, IDisposable
/// The method was called after the client was disposed.
ISftpFile Get(string path);
+ ///
+ /// Gets reference to remote symbolic link.
+ ///
+ /// The path.
+ ///
+ /// A reference to file object.
+ ///
+ /// Client is not connected.
+ /// was not found on the remote host.
+ /// is null.
+ /// The method was called after the client was disposed.
+ ISftpFile GetSymbolicLink(string path);
+
///
/// Gets the of the file on the path.
///
diff --git a/src/Renci.SshNet/Sftp/SftpSession.cs b/src/Renci.SshNet/Sftp/SftpSession.cs
index 54b0c4ad4..318a5b600 100644
--- a/src/Renci.SshNet/Sftp/SftpSession.cs
+++ b/src/Renci.SshNet/Sftp/SftpSession.cs
@@ -159,7 +159,6 @@ public string GetCanonicalPath(string path, bool getRealPath = true)
public async Task GetCanonicalPathAsync(string path, CancellationToken cancellationToken)
{
var fullPath = GetFullRemotePath(path);
-
var canonizedPath = string.Empty;
var realPathFiles = await RequestRealPathAsync(fullPath, nullOnError: true, cancellationToken).ConfigureAwait(false);
if (realPathFiles != null)
diff --git a/src/Renci.SshNet/SftpClient.cs b/src/Renci.SshNet/SftpClient.cs
index a275413a1..ed26a9e49 100644
--- a/src/Renci.SshNet/SftpClient.cs
+++ b/src/Renci.SshNet/SftpClient.cs
@@ -737,6 +737,38 @@ public ISftpFile Get(string path)
return new SftpFile(_sftpSession, fullPath, attributes);
}
+ ///
+ /// Gets reference to remote symbolic link.
+ ///
+ /// The path.
+ ///
+ /// A reference to file object.
+ ///
+ /// Client is not connected.
+ /// was not found on the remote host.
+ /// is null.
+ /// The method was called after the client was disposed.
+ public ISftpFile GetSymbolicLink(string path)
+ {
+ CheckDisposed();
+
+ if (path is null)
+ {
+ throw new ArgumentNullException(nameof(path));
+ }
+
+ if (_sftpSession is null)
+ {
+ throw new SshConnectionException("Client not connected.");
+ }
+
+ var fullPath = _sftpSession.GetCanonicalPath(path, false);
+
+ var attributes = _sftpSession.RequestLStat(fullPath);
+
+ return new SftpFile(_sftpSession, fullPath, attributes);
+ }
+
///
/// Checks whether file or directory exists;
///
@@ -793,6 +825,45 @@ public bool Exists(string path)
}
}
+ ///
+ /// Checks whether symbolic link exists;
+ ///
+ /// The path.
+ ///
+ /// true if directory or file exists; otherwise false.
+ ///
+ /// is null or contains only whitespace characters.
+ /// Client is not connected.
+ /// Permission to perform the operation was denied by the remote host. -or- A SSH command was denied by the server.
+ /// A SSH error where is the message from the remote host.
+ /// The method was called after the client was disposed.
+ public bool SymbolicLinkExists(string path)
+ {
+ CheckDisposed();
+
+ if (path.IsNullOrWhiteSpace())
+ {
+ throw new ArgumentException("path");
+ }
+
+ if (_sftpSession is null)
+ {
+ throw new SshConnectionException("Client not connected.");
+ }
+
+ var fullPath = _sftpSession.GetCanonicalPath(path, false);
+
+ try
+ {
+ _ = _sftpSession.RequestLStat(fullPath);
+ return true;
+ }
+ catch (SftpPathNotFoundException)
+ {
+ return false;
+ }
+ }
+
///
/// Downloads remote file specified by the path into the stream.
///
@@ -1479,6 +1550,20 @@ public void Delete(string path)
file.Delete();
}
+ ///
+ /// Deletes the specified symbolic link.
+ ///
+ /// The name of the file or directory to be deleted. Wildcard characters are not supported.
+ /// is null.
+ /// Client is not connected.
+ /// was not found on the remote host.
+ /// The method was called after the client was disposed.
+ public void DeleteSymbolicLink(string path)
+ {
+ var symLink = GetSymbolicLink(path);
+ symLink.Delete();
+ }
+
///
/// Returns the date and time the specified file or directory was last accessed.
///