diff --git a/async-ssh2-lite/Cargo.toml b/async-ssh2-lite/Cargo.toml index c362a83..26b3ad5 100644 --- a/async-ssh2-lite/Cargo.toml +++ b/async-ssh2-lite/Cargo.toml @@ -22,6 +22,7 @@ _integration_tests_tokio_ext = [] [dependencies] ssh2 = { version = "0.9", default-features = false } +libssh2-sys = { version = "0.2", default-features = false } futures-util = { version = "0.3", default-features = false, features = ["io", "std", "async-await-macro"] } async-trait = { version = "0.1", default-features = false } diff --git a/async-ssh2-lite/src/sftp.rs b/async-ssh2-lite/src/sftp.rs index dda3497..4fd1d6e 100644 --- a/async-ssh2-lite/src/sftp.rs +++ b/async-ssh2-lite/src/sftp.rs @@ -90,9 +90,27 @@ where } pub async fn readdir(&self, dirname: &Path) -> Result, Error> { - self.stream - .rw_with(|| self.inner.readdir(dirname), &self.sess) - .await + // Copy from ssh2 + let mut dir = self.opendir(dirname).await?; + let mut ret = Vec::new(); + loop { + match dir.readdir().await { + Ok((filename, stat)) => { + if &*filename == Path::new(".") || &*filename == Path::new("..") { + continue; + } + + ret.push((dirname.join(&filename), stat)) + } + Err(Error::Ssh2(ref e)) + if e.code() == ssh2::ErrorCode::Session(libssh2_sys::LIBSSH2_ERROR_FILE) => + { + break + } + Err(e) => return Err(e), + } + } + Ok(ret) } pub async fn mkdir(&self, filename: &Path, mode: i32) -> Result<(), Error> { @@ -184,6 +202,17 @@ impl AsyncFile { } } +impl AsyncFile +where + S: AsyncSessionStream + Send + Sync + 'static, +{ + pub async fn readdir(&mut self) -> Result<(PathBuf, FileStat), Error> { + self.stream + .rw_with(|| self.inner.readdir(), &self.sess) + .await + } +} + mod impl_futures_util { use core::{ pin::Pin, diff --git a/async-ssh2-lite/tests/integration_tests/agent__list_identities.rs b/async-ssh2-lite/tests/integration_tests/agent__list_identities.rs index fc4a4c7..d07af20 100644 --- a/async-ssh2-lite/tests/integration_tests/agent__list_identities.rs +++ b/async-ssh2-lite/tests/integration_tests/agent__list_identities.rs @@ -24,7 +24,7 @@ fn simple_with_async_io() -> Result<(), Box> { let dir = tempdir()?; let path = dir.path().join("ssh_agent"); - Async::::bind(&path)? + Async::::bind(path)? } else { use std::net::TcpListener; diff --git a/async-ssh2-lite/tests/integration_tests/sftp.rs b/async-ssh2-lite/tests/integration_tests/sftp.rs index 4a85972..c27ce75 100644 --- a/async-ssh2-lite/tests/integration_tests/sftp.rs +++ b/async-ssh2-lite/tests/integration_tests/sftp.rs @@ -47,5 +47,10 @@ async fn __run__session__sftp( println!("sftp file_stat:{:?}", file_stat); sftp.unlink(&remote_path).await?; + let list = sftp.readdir(&PathBuf::from("/")).await?; + for (file_path, file_stat) in list.iter().take(10) { + println!("sftp file_path:{:?} file_stat:{:?}", file_path, file_stat); + } + Ok(()) }