Skip to content

Commit 241fe98

Browse files
author
Fernando Bedoya Ortecho
committed
Enable get and delete symlinks
1 parent de4b777 commit 241fe98

File tree

3 files changed

+124
-1
lines changed

3 files changed

+124
-1
lines changed

src/Renci.SshNet/ISftpClient.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,18 @@ public interface ISftpClient : IBaseClient, IDisposable
491491
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
492492
void DeleteFile(string path);
493493

494+
/// <summary>
495+
/// Deletes remote symbolic link specified by path.
496+
/// </summary>
497+
/// <param name="path">File to be deleted path.</param>
498+
/// <exception cref="ArgumentException"><paramref name="path"/> is <b>null</b> or contains only whitespace characters.</exception>
499+
/// <exception cref="SshConnectionException">Client is not connected.</exception>
500+
/// <exception cref="SftpPathNotFoundException"><paramref name="path"/> was not found on the remote host.</exception>
501+
/// <exception cref="SftpPermissionDeniedException">Permission to delete the file was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception>
502+
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message"/> is the message from the remote host.</exception>
503+
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
504+
void DeleteSymbolicLink(string path);
505+
494506
/// <summary>
495507
/// Asynchronously deletes remote file specified by path.
496508
/// </summary>
@@ -580,6 +592,20 @@ public interface ISftpClient : IBaseClient, IDisposable
580592
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
581593
bool Exists(string path);
582594

595+
/// <summary>
596+
/// Checks whether symbolic link exists;
597+
/// </summary>
598+
/// <param name="path">The path.</param>
599+
/// <returns>
600+
/// <c>true</c> if directory or file exists; otherwise <c>false</c>.
601+
/// </returns>
602+
/// <exception cref="ArgumentException"><paramref name="path"/> is <b>null</b> or contains only whitespace characters.</exception>
603+
/// <exception cref="SshConnectionException">Client is not connected.</exception>
604+
/// <exception cref="SftpPermissionDeniedException">Permission to perform the operation was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception>
605+
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message"/> is the message from the remote host.</exception>
606+
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
607+
bool SymbolicLinkExists(string path);
608+
583609
/// <summary>
584610
/// Gets reference to remote file or directory.
585611
/// </summary>
@@ -593,6 +619,19 @@ public interface ISftpClient : IBaseClient, IDisposable
593619
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
594620
ISftpFile Get(string path);
595621

622+
/// <summary>
623+
/// Gets reference to remote symbolic link.
624+
/// </summary>
625+
/// <param name="path">The path.</param>
626+
/// <returns>
627+
/// A reference to <see cref="ISftpFile"/> file object.
628+
/// </returns>
629+
/// <exception cref="SshConnectionException">Client is not connected.</exception>
630+
/// <exception cref="SftpPathNotFoundException"><paramref name="path"/> was not found on the remote host.</exception>
631+
/// <exception cref="ArgumentNullException"><paramref name="path" /> is <b>null</b>.</exception>
632+
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
633+
ISftpFile GetSymbolicLink(string path);
634+
596635
/// <summary>
597636
/// Gets the <see cref="SftpFileAttributes"/> of the file on the path.
598637
/// </summary>

src/Renci.SshNet/Sftp/SftpSession.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ public string GetCanonicalPath(string path, bool getRealPath = true)
159159
public async Task<string> GetCanonicalPathAsync(string path, CancellationToken cancellationToken)
160160
{
161161
var fullPath = GetFullRemotePath(path);
162-
163162
var canonizedPath = string.Empty;
164163
var realPathFiles = await RequestRealPathAsync(fullPath, nullOnError: true, cancellationToken).ConfigureAwait(false);
165164
if (realPathFiles != null)

src/Renci.SshNet/SftpClient.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,38 @@ public ISftpFile Get(string path)
737737
return new SftpFile(_sftpSession, fullPath, attributes);
738738
}
739739

740+
/// <summary>
741+
/// Gets reference to remote symbolic link.
742+
/// </summary>
743+
/// <param name="path">The path.</param>
744+
/// <returns>
745+
/// A reference to <see cref="ISftpFile"/> file object.
746+
/// </returns>
747+
/// <exception cref="SshConnectionException">Client is not connected.</exception>
748+
/// <exception cref="SftpPathNotFoundException"><paramref name="path"/> was not found on the remote host.</exception>
749+
/// <exception cref="ArgumentNullException"><paramref name="path" /> is <b>null</b>.</exception>
750+
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
751+
public ISftpFile GetSymbolicLink(string path)
752+
{
753+
CheckDisposed();
754+
755+
if (path is null)
756+
{
757+
throw new ArgumentNullException(nameof(path));
758+
}
759+
760+
if (_sftpSession is null)
761+
{
762+
throw new SshConnectionException("Client not connected.");
763+
}
764+
765+
var fullPath = _sftpSession.GetCanonicalPath(path, false);
766+
767+
var attributes = _sftpSession.RequestLStat(fullPath);
768+
769+
return new SftpFile(_sftpSession, fullPath, attributes);
770+
}
771+
740772
/// <summary>
741773
/// Checks whether file or directory exists;
742774
/// </summary>
@@ -793,6 +825,45 @@ public bool Exists(string path)
793825
}
794826
}
795827

828+
/// <summary>
829+
/// Checks whether symbolic link exists;
830+
/// </summary>
831+
/// <param name="path">The path.</param>
832+
/// <returns>
833+
/// <c>true</c> if directory or file exists; otherwise <c>false</c>.
834+
/// </returns>
835+
/// <exception cref="ArgumentException"><paramref name="path"/> is <b>null</b> or contains only whitespace characters.</exception>
836+
/// <exception cref="SshConnectionException">Client is not connected.</exception>
837+
/// <exception cref="SftpPermissionDeniedException">Permission to perform the operation was denied by the remote host. <para>-or-</para> A SSH command was denied by the server.</exception>
838+
/// <exception cref="SshException">A SSH error where <see cref="Exception.Message"/> is the message from the remote host.</exception>
839+
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
840+
public bool SymbolicLinkExists(string path)
841+
{
842+
CheckDisposed();
843+
844+
if (path.IsNullOrWhiteSpace())
845+
{
846+
throw new ArgumentException("path");
847+
}
848+
849+
if (_sftpSession is null)
850+
{
851+
throw new SshConnectionException("Client not connected.");
852+
}
853+
854+
var fullPath = _sftpSession.GetCanonicalPath(path, false);
855+
856+
try
857+
{
858+
_ = _sftpSession.RequestLStat(fullPath);
859+
return true;
860+
}
861+
catch (SftpPathNotFoundException)
862+
{
863+
return false;
864+
}
865+
}
866+
796867
/// <summary>
797868
/// Downloads remote file specified by the path into the stream.
798869
/// </summary>
@@ -1479,6 +1550,20 @@ public void Delete(string path)
14791550
file.Delete();
14801551
}
14811552

1553+
/// <summary>
1554+
/// Deletes the specified symbolic link.
1555+
/// </summary>
1556+
/// <param name="path">The name of the file or directory to be deleted. Wildcard characters are not supported.</param>
1557+
/// <exception cref="ArgumentNullException"><paramref name="path"/> is <b>null</b>.</exception>
1558+
/// <exception cref="SshConnectionException">Client is not connected.</exception>
1559+
/// <exception cref="SftpPathNotFoundException"><paramref name="path"/> was not found on the remote host.</exception>
1560+
/// <exception cref="ObjectDisposedException">The method was called after the client was disposed.</exception>
1561+
public void DeleteSymbolicLink(string path)
1562+
{
1563+
var symLink = GetSymbolicLink(path);
1564+
symLink.Delete();
1565+
}
1566+
14821567
/// <summary>
14831568
/// Returns the date and time the specified file or directory was last accessed.
14841569
/// </summary>

0 commit comments

Comments
 (0)