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`
After I used the tokio async method to package, I couldn't build successfully.