Skip to content
Merged
4 changes: 2 additions & 2 deletions src/Renci.SshNet/ISftpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,7 @@ public interface ISftpClient
/// </summary>
/// <param name="input">Data input stream.</param>
/// <param name="path">Remote file path.</param>
/// <param name="canOverride">if set to <c>true</c> then existing file will be overwritten.</param>
/// <param name="createMode">Specifies how the file should be created.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous upload operation.</returns>
/// <exception cref="ArgumentNullException"><paramref name="input" /> is <b>null</b>.</exception>
Expand All @@ -1042,7 +1042,7 @@ public interface ISftpClient
/// <remarks>
/// Method calls made by this method to <paramref name="input" />, may under certain conditions result in exceptions thrown by the stream.
/// </remarks>
Task UploadFileAsync(Stream input, string path, bool canOverride, CancellationToken cancellationToken);
Task UploadFileAsync(Stream input, string path, UploadMode createMode, CancellationToken cancellationToken);
#endif

/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Renci.SshNet/Sftp/ISftpSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ internal interface ISftpSession : ISubsystemSession
/// </returns>
SftpFileAttributes RequestFStat(byte[] handle, bool nullOnError);

#if FEATURE_TAP
Task<SftpFileAttributes> RequestFStatAsync(byte[] handle, CancellationToken cancellationToken);
#endif

/// <summary>
/// Performs SSH_FXP_STAT request.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Renci.SshNet/Sftp/SftpFileStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -382,12 +382,12 @@ internal static async Task<SftpFileStream> OpenAsync(ISftpSession session, strin
{
try
{
var attributes = session.RequestFStat(handle, false); // ToDo: Async
var attributes = await session.RequestFStatAsync(handle, cancellationToken).ConfigureAwait(false);
position = attributes.Size;
}
catch
{
session.RequestClose(handle); // ToDo: Async
session.RequestClose(handle);
throw;
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/Renci.SshNet/Sftp/SftpSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,24 @@ public SftpFileAttributes RequestFStat(byte[] handle, bool nullOnError)
return attributes;
}

#if FEATURE_TAP
public async Task<SftpFileAttributes> RequestFStatAsync(byte[] handle, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();

TaskCompletionSource<SftpFileAttributes> tcs = new TaskCompletionSource<SftpFileAttributes>(TaskCreationOptions.RunContinuationsAsynchronously);

using (cancellationToken.Register((s) => ((TaskCompletionSource<SftpFileAttributes>)s).TrySetCanceled(), tcs, false))
{
SendRequest(new SftpFStatRequest(ProtocolVersion, NextRequestId, handle,
response => tcs.TrySetResult(response.Attributes),
response => tcs.TrySetException(GetSftpException(response))));

return await tcs.Task.ConfigureAwait(false);
}
}
#endif

/// <summary>
/// Performs SSH_FXP_SETSTAT request.
/// </summary>
Expand Down
23 changes: 23 additions & 0 deletions src/Renci.SshNet/Sftp/UploadMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace Renci.SshNet.Sftp
{
/// <summary>
/// Specifies how the uploaded file should be created.
/// </summary>
public enum UploadMode
{
/// <summary>
/// A new file should be created. If the file already exists, an exception is thrown.
/// </summary>
CreateNew = 1,

/// <summary>
/// A new file should be created. If the file already exists, it will be overwritten.
/// </summary>
Overwrite = 2,

/// <summary>
/// Opens the file if it exists and seeks to the end of the file, or creates a new file.
/// </summary>
Append = 6
}
}
6 changes: 3 additions & 3 deletions src/Renci.SshNet/SftpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ public void UploadFile(Stream input, string path, bool canOverride, Action<ulong
/// </summary>
/// <param name="input">Data input stream.</param>
/// <param name="path">Remote file path.</param>
/// <param name="canOverride">if set to <c>true</c> then existing file will be overwritten.</param>
/// <param name="createMode">Specifies how the file should be created.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to observe.</param>
/// <returns>A <see cref="Task"/> that represents the asynchronous upload operation.</returns>
/// <exception cref="ArgumentNullException"><paramref name="input" /> is <b>null</b> -or- <paramref name="path" /> is <b>null</b>.</exception>
Expand All @@ -975,7 +975,7 @@ public void UploadFile(Stream input, string path, bool canOverride, Action<ulong
/// <remarks>
/// Method calls made by this method to <paramref name="input" />, may under certain conditions result in exceptions thrown by the stream.
/// </remarks>
public async Task UploadFileAsync(Stream input, string path, bool canOverride, CancellationToken cancellationToken)
public async Task UploadFileAsync(Stream input, string path, UploadMode createMode, CancellationToken cancellationToken)
{
if (input == null)
throw new ArgumentNullException("input");
Expand All @@ -985,7 +985,7 @@ public async Task UploadFileAsync(Stream input, string path, bool canOverride, C
CheckDisposedOrNotConnected();
cancellationToken.ThrowIfCancellationRequested();

using (SftpFileStream output = await SftpFileStream.OpenAsync(_sftpSession, path, canOverride ? FileMode.Create : FileMode.CreateNew, FileAccess.Write, (int)_bufferSize, cancellationToken).ConfigureAwait(false))
using (SftpFileStream output = await SftpFileStream.OpenAsync(_sftpSession, path, (FileMode)createMode, FileAccess.Write, (int)_bufferSize, cancellationToken).ConfigureAwait(false))
{
await input.CopyToAsync(output, (int)_sftpSession.CalculateOptimalWriteLength(_bufferSize, output.Handle), cancellationToken).ConfigureAwait(false);
}
Expand Down