veeso / remotefs-rs-ssh

RemoteFS SCP/SFTP clients
MIT License
11 stars 2 forks source link

[Feature Request] - After I used the tokio async method to package, I couldn't build successfully. #4

Open wensiwei opened 1 year ago

wensiwei commented 1 year ago

After I used the tokio async method to package, I couldn't build successfully.

pub unsafe fn extend_lifetime<'a, T: ?Sized>(r: &'a T) -> &'static T {
    std::mem::transmute::<&'a T, &'static T>(r)
}

#[async_recursion::async_recursion(? Send)]
pub async fn remote_to_local(client: &mut SftpFs, src: &Path, dst: &Path, dir_mode: u32) -> Result<(), std::io::Error> {
    let mut client = unsafe { extend_lifetime(client) };
    let dst = unsafe { extend_lifetime(dst) };
    let src = unsafe { extend_lifetime(src) };

    let file = client.stat(src).unwrap();
    let meta = file.metadata();
    if meta.is_dir() {
        std::fs::create_dir_all(dst.parent().unwrap());
        let entries = client.list_dir(src).unwrap();
        for entry in entries {
            let mut dst_file = PathBuf::from(dst);
            dst_file.push(entry.name());
            remote_to_local(&mut client, &entry.path(), &dst_file, dir_mode).await.unwrap();
        }
    } else if meta.is_file() {
        let h = tokio::task::spawn_blocking(move || -> Result<(), std::io::Error> {
            std::fs::create_dir_all(dst.parent().unwrap());
            let mut writer = std::fs::OpenOptions::new().create_new(true).write(true).open(dst).unwrap();
            client.open_file(src, Box::new(writer)).ok().unwrap();
            Ok(())
        });
        h.await.unwrap()?;
    }
    Ok(())
}
error[E0277]: `(dyn SshKeyStorage + 'static)` cannot be shared between threads safely
   --> src/bin/sftp.rs:88:45
    |
88  |           let h = tokio::task::spawn_blocking(move || -> Result<(), std::io::Error> {
    |  _________________---------------------------_^
    | |                 |
    | |                 required by a bound introduced by this call
89  | |             std::fs::create_dir_all(dst.parent().unwrap());
90  | |             let mut writer = std::fs::OpenOptions::new().create_new(true).write(true).open(dst).unwrap();
91  | |             client.open_file(src, Box::new(writer)).ok().unwrap();
92  | |             info!("接收文件");
93  | |             Ok(())
94  | |         });
    | |_________^ `(dyn SshKeyStorage + 'static)` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `(dyn SshKeyStorage + 'static)`
    = note: required for `Unique<(dyn SshKeyStorage + 'static)>` to implement `Sync`
    = note: required because it appears within the type `Box<(dyn SshKeyStorage + 'static)>`
    = note: required because it appears within the type `Option<Box<(dyn SshKeyStorage + 'static)>>`
    = note: required because it appears within the type `SshOpts`
    = note: required because it appears within the type `SftpFs`
    = note: required for `&SftpFs` to implement `Send`
note: required because it's used within this closure
   --> src/bin/sftp.rs:88:45
    |
88  |         let h = tokio::task::spawn_blocking(move || -> Result<(), std::io::Error> {
    |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `spawn_blocking`
   --> /root/.cargo/registry/src/rsproxy.cn-8f6827c7555bfaf8/tokio-1.21.1/src/task/blocking.rs:205:28
    |
205 |         F: FnOnce() -> R + Send + 'static,
    |                            ^^^^ required by this bound in `spawn_blocking`