format_smoke/format_smoke.rs
1//! Smoke test for `Namespace::format`.
2//!
3//! **Refuses to run unless the controller's model string equals `QEMU NVMe Ctrl`.**
4//! This is a deliberate safety latch — on real hardware the Format NVM admin
5//! command erases all user data on the namespace, and a slipped fingertip
6//! would otherwise wipe whoever's boot drive.
7//!
8//! To exercise on the QEMU fixture:
9//!
10//! ```sh
11//! bash tests/qemu/run.sh
12//! # then inside the guest:
13//! cd /mnt/host && CARGO_TARGET_DIR=/tmp/target sudo -E cargo run \
14//! --example format_smoke -p libnvme
15//! ```
16
17use libnvme::{Root, SecureErase};
18
19const QEMU_MODEL: &str = "QEMU NVMe Ctrl";
20
21fn main() -> Result<(), Box<dyn std::error::Error>> {
22 let root = Root::scan()?;
23 let mut formatted = 0;
24 for host in root.hosts() {
25 for subsys in host.subsystems() {
26 for ctrl in subsys.controllers() {
27 let model = ctrl.model().unwrap_or("?").trim();
28 if model != QEMU_MODEL {
29 println!(
30 "skipping {}: model {model:?} != {QEMU_MODEL:?} (refusing to format real hardware)",
31 ctrl.name()?
32 );
33 continue;
34 }
35 for ns in ctrl.namespaces() {
36 let nsid = ns.nsid();
37 let lba_size_before = ns.lba_size();
38 let lba_count_before = ns.lba_count();
39 println!(
40 "about to format {}: NSID={nsid}, {lba_count_before} blocks × {lba_size_before} B",
41 ns.name()?
42 );
43 ns.format()
44 .lba_format(0)
45 .secure_erase(SecureErase::None)
46 .execute()?;
47 println!(" -> format succeeded");
48 formatted += 1;
49 }
50 }
51 }
52 }
53 if formatted == 0 {
54 println!("(no QEMU virtual NVMe controllers found)");
55 } else {
56 println!("formatted {formatted} namespace(s)");
57 }
58 Ok(())
59}