Update: Related questions helped to understand what the problem is but not to solve it.
I now understand that I can not save the Sftp
object with Session
in the same struct, and better generate Sftp
when needed.
New Code is:
use std::io::prelude::*;
use std::io;
use ssh2;
use std::net::TcpStream;
use std::net::ToSocketAddrs;
use std::path::Path;
use ssh2::{Session, Sftp, File};
pub enum SftpClientError {
Ssh(ssh2::Error),
Io(io::Error)
}
pub struct SftpClient {
session: Session,
stream: TcpStream,
}
impl SftpClient {
pub fn new<A: ToSocketAddrs>(addr: A) -> SftpClient {
let mut s = Session::new().unwrap();
let mut t = TcpStream::connect(addr).unwrap();
s.handshake(&t).unwrap();
SftpClient {
session: s,
stream: t,
}
}
pub fn get_file(&self, path: &Path) -> Result<(File, Sftp), SftpClientError> {
let sftp = self.session.sftp().unwrap();
let file = match sftp.create(path) {
Ok(o) => o,
Err(e) => return Err(SftpClientError::Ssh(e)),
};
Ok((file, sftp))
}
}
Which outputs a slightly different error. The new error is that sftp
in the get_file
method, does not live long enough.
So how can I make it live long enough to return a File
and use it on the caller side?
Old Question
The following code tries to create a struct that contains all required data for a SFTP connection in the rust library ssh2. The struct is given as SftpClient
and the new
function should generate it.
use std::io::prelude::*;
use std::io;
use std::net::TcpStream;
use std::net::ToSocketAddrs;
use ssh2::{Session, Sftp, File};
pub struct SftpClient<'s> {
session: Session,
stream: TcpStream,
connection: Sftp<'s>,
}
impl<'s> SftpClient<'s> {
pub fn new<A: ToSocketAddrs>(addr: A) -> SftpClient<'s> {
let mut s = Session::new().unwrap();
let mut t = TcpStream::connect(addr).unwrap();
s.handshake(&t).unwrap();
let sftp = s.sftp().unwrap();
SftpClient {
session: s,
stream: t,
connection: sftp,
}
}
}
When I compile this code rustc complains that s
does not live long enough:
src/sftp.rs:20:20: 20:21 error: `s` does not live long enough
src/sftp.rs:20 let sftp = s.sftp().unwrap();
^
src/sftp.rs:14:61: 26:6 note: reference must be valid for the lifetime 's as defined on the block at 14:60...
src/sftp.rs:14 pub fn new<A: ToSocketAddrs>(addr: A) -> SftpClient<'s> {
src/sftp.rs:15 let mut s = Session::new().unwrap();
src/sftp.rs:16 let mut t = TcpStream::connect(addr).unwrap();
src/sftp.rs:17
src/sftp.rs:18 s.handshake(&t).unwrap();
src/sftp.rs:19
...
src/sftp.rs:15:45: 26:6 note: ...but borrowed value is only valid for the block suffix following statement 0 at 15:44
src/sftp.rs:15 let mut s = Session::new().unwrap();
src/sftp.rs:16 let mut t = TcpStream::connect(addr).unwrap();
src/sftp.rs:17
src/sftp.rs:18 s.handshake(&t).unwrap();
src/sftp.rs:19
src/sftp.rs:20 let sftp = s.sftp().unwrap();
I don't understand why s
does not live long enough as it's given to SftpClient
just like the Sftp
struct. From my understanding they should both live their happy lifes until SftpClient
is dropped.