use serial_test::serial;
use smb::{
connection::EncryptionMode,
packets::{fscc::*, smb2::CreateDisposition},
resource::Directory,
tree::Tree,
ConnectionConfig,
};
use std::sync::Arc;
#[cfg(feature = "async")]
use futures_util::StreamExt;
mod common;
use common::make_server_connection;
const LONG_DIR: &str = "longdir";
const NUM_ITEMS: usize = 1000;
#[maybe_async::test(
feature = "sync",
async(
feature = "async",
test_log::test(tokio::test(flavor = "multi_thread"))
)
)]
#[serial]
#[cfg(all(feature = "sign", feature = "encrypt"))] async fn test_smb_iterating_long_directory() -> Result<(), Box<dyn std::error::Error>> {
let (_smb, _session, tree) = make_server_connection(
"MyShare",
ConnectionConfig {
encryption_mode: EncryptionMode::Disabled,
..Default::default()
}
.into(),
)
.await?;
let tree = Arc::new(tree);
tree.create_directory(
LONG_DIR,
CreateDisposition::Create,
FileAccessMask::new().with_generic_read(true),
)
.await?
.unwrap_dir();
for i in 0..NUM_ITEMS {
let file_name = format!("{}\\file_{}", LONG_DIR, i);
let file = tree
.create_file(
&file_name,
CreateDisposition::Create,
FileAccessMask::new()
.with_generic_read(true)
.with_generic_write(true),
)
.await?
.unwrap_file();
file.write_block(b"Hello, World!", 0).await?;
}
{
let directory = tree
.open_existing(
LONG_DIR,
FileAccessMask::new()
.with_generic_read(true)
.with_delete(true),
)
.await?
.unwrap_dir();
let directory = Arc::new(directory);
let found =
Directory::query_directory::<FileFullDirectoryInformation>(&directory, "file_*")
.await?
.fold(0, |sum, entry| {
let tree = tree.clone();
async move {
let entry = entry.unwrap();
let file_name = entry.file_name.to_string();
assert!(file_name.starts_with("file_"));
let file_number: usize = file_name[5..].parse().unwrap();
assert!(file_number < NUM_ITEMS);
let full_file_name = format!("{}\\{}", LONG_DIR, file_name);
let file = tree
.open_existing(
&full_file_name,
FileAccessMask::new()
.with_generic_read(true)
.with_delete(true),
)
.await
.unwrap()
.unwrap_file();
file.set_file_info(FileDispositionInformation {
delete_pending: true.into(),
})
.await
.unwrap();
sum + 1
}
})
.await;
assert_eq!(found, NUM_ITEMS);
}
{
let directory = Arc::new(
tree.open_existing(LONG_DIR, FileAccessMask::new().with_delete(true))
.await?
.unwrap_dir(),
);
directory
.set_file_info(FileDispositionInformation {
delete_pending: true.into(),
})
.await?;
}
Ok(())
}
#[maybe_async::maybe_async]
pub async fn remove_file_by_name(tree: &Tree, file_name: &str) -> smb::Result<()> {
let file = tree
.open_existing(
file_name,
FileAccessMask::new()
.with_generic_read(true)
.with_delete(true),
)
.await?
.unwrap_file();
file.set_file_info(FileDispositionInformation {
delete_pending: true.into(),
})
.await?;
Ok(())
}