141 lines
3.9 KiB
Rust
141 lines
3.9 KiB
Rust
#![allow(unused_imports, dead_code, unused_variables)]
|
|
use assert_cmd::Command;
|
|
use predicates::prelude::*;
|
|
use std::fs;
|
|
use std::io::{Read, Write};
|
|
use std::os::unix::fs::FileTypeExt;
|
|
use std::path::Path;
|
|
use std::process::Command as StdCommand;
|
|
use tempfile::TempDir;
|
|
|
|
/// Helper to check if we can run loop tests (need root and losetup)
|
|
fn can_run_loop_test() -> bool {
|
|
// Check if we are root and losetup exists
|
|
if unsafe { libc::geteuid() } != 0 {
|
|
return false;
|
|
}
|
|
StdCommand::new("which")
|
|
.arg("losetup")
|
|
.output()
|
|
.map(|o| o.status.success())
|
|
.unwrap_or(false)
|
|
}
|
|
|
|
#[test]
|
|
#[ignore]
|
|
fn test_loop_device_zero_wipe() {
|
|
if !can_run_loop_test() {
|
|
eprintln!("Skipping loop test: need root and losetup");
|
|
return;
|
|
}
|
|
|
|
let dir = TempDir::new().unwrap();
|
|
let img_path = dir.path().join("test.img");
|
|
let size = 16 * 1024 * 1024; // 16 MiB
|
|
|
|
// Create image file
|
|
let file = fs::File::create(&img_path).unwrap();
|
|
file.set_len(size as u64).unwrap();
|
|
|
|
// Attach loop device
|
|
let output = StdCommand::new("losetup")
|
|
.args(["--find", "--show", img_path.to_str().unwrap()])
|
|
.output()
|
|
.unwrap();
|
|
if !output.status.success() {
|
|
eprintln!(
|
|
"losetup failed: {}",
|
|
String::from_utf8_lossy(&output.stderr)
|
|
);
|
|
return;
|
|
}
|
|
let loop_dev = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
|
assert!(Path::new(&loop_dev).exists());
|
|
|
|
// Ensure cleanup
|
|
let cleanup = || {
|
|
let _ = StdCommand::new("losetup").args(["-d", &loop_dev]).output();
|
|
let _ = fs::remove_file(&img_path);
|
|
};
|
|
|
|
// Write known pattern
|
|
{
|
|
let mut f = fs::OpenOptions::new().write(true).open(&loop_dev).unwrap();
|
|
f.write_all(&vec![0xAB; 1024 * 1024]).unwrap();
|
|
f.flush().unwrap();
|
|
let _ = StdCommand::new("sync").output();
|
|
}
|
|
|
|
// Run wipe with zero method
|
|
let wipe_bin = assert_cmd::Command::cargo_bin("wipe")
|
|
.unwrap()
|
|
.get_program()
|
|
.to_string_lossy()
|
|
.to_string();
|
|
let output = StdCommand::new(&wipe_bin)
|
|
.args([
|
|
&loop_dev,
|
|
"--whole-disk",
|
|
"--method",
|
|
"zero",
|
|
"--yes",
|
|
"--buffer-size",
|
|
"1M",
|
|
])
|
|
.output()
|
|
.unwrap();
|
|
|
|
if !output.status.success() {
|
|
eprintln!(
|
|
"wipe failed: stdout={} stderr={}",
|
|
String::from_utf8_lossy(&output.stdout),
|
|
String::from_utf8_lossy(&output.stderr)
|
|
);
|
|
cleanup();
|
|
panic!("wipe zero failed");
|
|
}
|
|
|
|
// Verify zero
|
|
{
|
|
let mut f = fs::File::open(&loop_dev).unwrap();
|
|
let mut buf = vec![0u8; 1024 * 1024];
|
|
f.read_exact(&mut buf).unwrap();
|
|
assert!(buf.iter().all(|&b| b == 0x00), "device not zeroed");
|
|
}
|
|
|
|
cleanup();
|
|
}
|
|
|
|
#[test]
|
|
fn test_dry_run_loop_sim_with_file_block() {
|
|
// This is a lightweight integration test that doesn't need loop device
|
|
// It tests that dry-run with a real block device (if available) doesn't modify
|
|
let candidates = ["/dev/loop0", "/dev/loop1", "/dev/sda"];
|
|
for cand in candidates {
|
|
if !Path::new(cand).exists() {
|
|
continue;
|
|
}
|
|
if let Ok(meta) = fs::metadata(cand) {
|
|
if !meta.file_type().is_block_device() {
|
|
continue;
|
|
}
|
|
let output = Command::cargo_bin("wipe")
|
|
.unwrap()
|
|
.args([
|
|
cand,
|
|
"--whole-disk",
|
|
"--dry-run",
|
|
"--yes",
|
|
"--method",
|
|
"zero",
|
|
])
|
|
.output()
|
|
.unwrap();
|
|
// Should be success or known safety code, but not crash
|
|
let code = output.status.code().unwrap_or(1);
|
|
assert!(code == 0 || (2..=15).contains(&code));
|
|
break;
|
|
}
|
|
}
|
|
}
|