Skip to content

scp: add flag to notify for uploading finished when uploaded an empty file #1658

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 20, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions src/Renci.SshNet/ScpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,12 +240,13 @@ internal ScpClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, IServ
/// </summary>
/// <param name="source">The <see cref="Stream"/> to upload.</param>
/// <param name="path">A relative or absolute path for the remote file.</param>
/// <param name="notifyOnEmptyFile">Should the <see cref="Uploading"/> event be raised when the file is empty?</param>
/// <exception cref="ArgumentNullException"><paramref name="path" /> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length <see cref="string"/>.</exception>
/// <exception cref="ScpException">A directory with the specified path exists on the remote host.</exception>
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
/// <exception cref="SshConnectionException">Client is not connected.</exception>
public void Upload(Stream source, string path)
public void Upload(Stream source, string path, bool notifyOnEmptyFile=false)
{
if (Session is null)
{
Expand All @@ -271,7 +272,7 @@ public void Upload(Stream source, string path)
CheckReturnCode(input);

UploadFileModeAndName(channel, input, source.Length, posixPath.File);
UploadFileContent(channel, input, source, posixPath.File);
UploadFileContent(channel, input, source, posixPath.File, notifyOnEmptyFile);
}
}

Expand All @@ -280,13 +281,14 @@ public void Upload(Stream source, string path)
/// </summary>
/// <param name="fileInfo">The file system info.</param>
/// <param name="path">A relative or absolute path for the remote file.</param>
/// <param name="notifyOnEmptyFile">Should the <see cref="Uploading"/> event be raised when the file is empty?</param>
/// <exception cref="ArgumentNullException"><paramref name="fileInfo" /> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="path" /> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length <see cref="string"/>.</exception>
/// <exception cref="ScpException">A directory with the specified path exists on the remote host.</exception>
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
/// <exception cref="SshConnectionException">Client is not connected.</exception>
public void Upload(FileInfo fileInfo, string path)
public void Upload(FileInfo fileInfo, string path, bool notifyOnEmptyFile=false)
{
ThrowHelper.ThrowIfNull(fileInfo);

Expand Down Expand Up @@ -317,7 +319,7 @@ public void Upload(FileInfo fileInfo, string path)
{
UploadTimes(channel, input, fileInfo);
UploadFileModeAndName(channel, input, source.Length, posixPath.File);
UploadFileContent(channel, input, source, fileInfo.Name);
UploadFileContent(channel, input, source, fileInfo.Name, notifyOnEmptyFile);
}
}
}
Expand All @@ -327,13 +329,14 @@ public void Upload(FileInfo fileInfo, string path)
/// </summary>
/// <param name="directoryInfo">The directory info.</param>
/// <param name="path">A relative or absolute path for the remote directory.</param>
/// <param name="notifyOnEmptyFile">Should the <see cref="Uploading"/> event be raised when the file is empty?</param>
/// <exception cref="ArgumentNullException"><paramref name="directoryInfo"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="path"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="path"/> is a zero-length string.</exception>
/// <exception cref="ScpException"><paramref name="path"/> does not exist on the remote host, is not a directory or the user does not have the required permission.</exception>
/// <exception cref="SshException">The secure copy execution request was rejected by the server.</exception>
/// <exception cref="SshConnectionException">Client is not connected.</exception>
public void Upload(DirectoryInfo directoryInfo, string path)
public void Upload(DirectoryInfo directoryInfo, string path, bool notifyOnEmptyFile=false)
{
ThrowHelper.ThrowIfNull(directoryInfo);
ThrowHelper.ThrowIfNullOrEmpty(path);
Expand Down Expand Up @@ -362,7 +365,7 @@ public void Upload(DirectoryInfo directoryInfo, string path)

CheckReturnCode(input);

UploadDirectoryContent(channel, input, directoryInfo);
UploadDirectoryContent(channel, input, directoryInfo, notifyOnEmptyFile);
}
}

Expand Down Expand Up @@ -556,10 +559,11 @@ private void UploadFileModeAndName(IChannelSession channel, Stream input, long f
/// <param name="input">A <see cref="Stream"/> from which any feedback from the server can be read.</param>
/// <param name="source">The content to upload.</param>
/// <param name="remoteFileName">The name of the remote file, without path, to which the content is uploaded.</param>
/// <param name="notifyOnEmptyFile">Should the <see cref="Uploading"/> event be raised when the file is empty?</param>
/// <remarks>
/// <paramref name="remoteFileName"/> is only used for raising the <see cref="Uploading"/> event.
/// </remarks>
private void UploadFileContent(IChannelSession channel, Stream input, Stream source, string remoteFileName)
private void UploadFileContent(IChannelSession channel, Stream input, Stream source, string remoteFileName, bool notifyOnEmptyFile)
{
var totalLength = source.Length;
var buffer = new byte[BufferSize];
Expand All @@ -579,6 +583,11 @@ private void UploadFileContent(IChannelSession channel, Stream input, Stream sou
read = source.Read(buffer, 0, buffer.Length);
}

if (totalLength == 0 && totalRead == 0 && notifyOnEmptyFile)
{
RaiseUploadingEvent(remoteFileName, totalLength, totalRead);
}

SendSuccessConfirmation(channel);
CheckReturnCode(input);
}
Expand Down Expand Up @@ -687,7 +696,8 @@ private void UploadTimes(IChannelSession channel, Stream input, FileSystemInfo f
/// <param name="channel">The channel to perform the upload in.</param>
/// <param name="input">A <see cref="Stream"/> from which any feedback from the server can be read.</param>
/// <param name="directoryInfo">The directory to upload.</param>
private void UploadDirectoryContent(IChannelSession channel, Stream input, DirectoryInfo directoryInfo)
/// <param name="notifyOnEmptyFile">Should the <see cref="Uploading"/> event be raised when the file is empty?</param>
private void UploadDirectoryContent(IChannelSession channel, Stream input, DirectoryInfo directoryInfo, bool notifyOnEmptyFile=false)
{
// Upload files
var files = directoryInfo.GetFiles();
Expand All @@ -697,7 +707,7 @@ private void UploadDirectoryContent(IChannelSession channel, Stream input, Direc
{
UploadTimes(channel, input, file);
UploadFileModeAndName(channel, input, source.Length, file.Name);
UploadFileContent(channel, input, source, file.Name);
UploadFileContent(channel, input, source, file.Name, notifyOnEmptyFile);
}
}

Expand All @@ -707,7 +717,7 @@ private void UploadDirectoryContent(IChannelSession channel, Stream input, Direc
{
UploadTimes(channel, input, directory);
UploadDirectoryModeAndName(channel, input, directory.Name);
UploadDirectoryContent(channel, input, directory);
UploadDirectoryContent(channel, input, directory, notifyOnEmptyFile);
}

// Mark upload of current directory complete
Expand Down