use std::time::Instant;
use smb2::ErrorKind;
fn env_or(key: &str, default: &str) -> String {
std::env::var(key).unwrap_or_else(|_| default.to_string())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
let addr = env_or("SMB2_HOST", "192.168.1.100:445");
let user = env_or("SMB2_USER", "user");
let pass = std::env::var("SMB2_PASS").unwrap_or_else(|_| {
eprintln!("Set SMB2_PASS to your SMB password. Example:");
eprintln!(" SMB2_PASS=secret cargo run --example server_side_copy");
std::process::exit(1);
});
let share_name = env_or("SMB2_SHARE", "Documents");
let src = env_or("SMB2_SRC", "source.bin");
let dst = env_or("SMB2_DST", "copy.bin");
let mut client = smb2::connect(&addr, &user, &pass).await?;
let mut share = client.connect_share(&share_name).await?;
let start = Instant::now();
match client.server_side_copy_file(&share, &src, &dst).await {
Ok(bytes) => {
let elapsed = start.elapsed();
println!(
"Copied {bytes} bytes {src} -> {dst} server-side in {elapsed:.2?} \
(the data never crossed the wire)"
);
}
Err(e) if e.kind() == ErrorKind::Unsupported => {
eprintln!("Server has no server-side copy; falling back to read+write.");
let data = client.read_file(&mut share, &src).await?;
client.write_file_pipelined(&mut share, &dst, &data).await?;
println!(
"Copied {} bytes {src} -> {dst} client-side in {:.2?}",
data.len(),
start.elapsed()
);
}
Err(e) => return Err(e.into()),
}
client.disconnect_share(&share).await?;
Ok(())
}