async_ssh2_russh/
sftp.rs

1//! SFTP support for the `async_ssh2_russh` crate.
2
3use russh::client::Handler;
4#[doc(no_inline)]
5pub use russh_sftp::client::error::Error as SftpError;
6use russh_sftp::client::SftpSession;
7
8use crate::{AsyncChannel, AsyncSession, SshError};
9
10impl<H: 'static + Handler> AsyncSession<H> {
11    /// Opens an SFTP channel.
12    ///
13    /// Equivalent to [`AsyncSession::open_channel()`] followed by requesting the SFTP subsystem:
14    /// ```rust,ignore
15    /// channel.request_subsystem(true, "sftp").await?;
16    /// ```
17    #[cfg(feature = "sftp")]
18    pub async fn open_sftp(&self) -> Result<SftpSession, SshOrSftpError> {
19        let channel = self.open_channel().await?;
20        channel.request_subsystem(true, "sftp").await?;
21        let sftp = channel.sftp().await?;
22        Ok(sftp)
23    }
24}
25
26impl AsyncChannel {
27    /// Starst an SFTP session on this channel.
28    ///
29    /// Make sure this channel was opened with [`AsyncSession::open_sftp`], or if not, make sure to
30    /// request the SFTP subsystem before calling this:
31    /// ```rust,ignore
32    /// channel.request_subsystem(true, "sftp").await.unwrap();
33    /// ```
34    #[cfg(feature = "sftp")]
35    pub async fn sftp(&self) -> Result<SftpSession, SftpError> {
36        SftpSession::new(tokio::io::join(self.stdout(), self.stdin())).await
37    }
38}
39
40/// Error enum containing either an [`SshError`] or [`SftpError`].
41///
42/// This is used to unify error handling for SSH and SFTP operations.
43#[derive(Debug, thiserror::Error)]
44pub enum SshOrSftpError {
45    /// SSH error.
46    #[error("SSH Error: {0}")]
47    Ssh(#[from] SshError),
48    /// SFTP error.
49    #[error("SFTP Error: {0}")]
50    Sftp(#[from] SftpError),
51}