Skip to main content

basic/
basic.rs

1//! Minimal NFSv3 blocking quickstart.
2//!
3//! For a broader end-to-end example, see `examples/v3_cookbook.rs`.
4
5use std::time::Duration;
6
7use nfs::v3::blocking::ClientBuilder;
8
9const CONTENT: &[u8] = b"hello from nfs-rs over NFSv3\n";
10
11fn main() -> nfs::Result<()> {
12    // Usage:
13    //   cargo run --example basic -- 127.0.0.1:/export /writable-dir
14    //
15    // The first argument is an NFSv3 target in `host:/export` form.
16    // The second argument is a writable directory inside that export.
17    let mut args = std::env::args().skip(1);
18    let target = args
19        .next()
20        .unwrap_or_else(|| "127.0.0.1:/export".to_owned());
21    let dir = args.next().unwrap_or_else(|| "/".to_owned());
22    let file = remote_path(&dir, &format!("nfs-rs-v3-{}.txt", std::process::id()));
23
24    let mut client = ClientBuilder::from_target(&target)?
25        .timeout(Some(Duration::from_secs(10)))
26        .connect()?;
27
28    println!("connected to NFSv3 target {target}");
29    println!("writing {file}");
30    client.write_atomic(&file, CONTENT)?;
31
32    let data = client.read(&file)?;
33    println!("read: {}", String::from_utf8_lossy(&data));
34
35    let range = client.read_range(&file, 0, 5)?;
36    println!("first 5 bytes: {:?}", String::from_utf8_lossy(&range));
37
38    let metadata = client.metadata(&file)?;
39    println!(
40        "metadata: type={:?} size={} mode={:o}",
41        metadata.file_type,
42        metadata.size,
43        metadata.mode & 0o777
44    );
45
46    println!("first entries in {dir}:");
47    for entry in client.read_dir(&dir)?.into_iter().take(8) {
48        println!("  {}", entry.name);
49    }
50
51    client.remove_if_exists(&file)?;
52    println!("removed {file}");
53    Ok(())
54}
55
56fn remote_path(parent: &str, name: &str) -> String {
57    if parent == "/" {
58        format!("/{name}")
59    } else {
60        format!("{}/{name}", parent.trim_end_matches('/'))
61    }
62}