use std::process::ExitCode;
fn main() -> ExitCode {
let mut json = false;
let mut path: Option<String> = None;
for arg in std::env::args().skip(1) {
match arg.as_str() {
"--json" => json = true,
"-h" | "--help" => {
eprintln!("usage: disk4n6 [--json] <image>");
return ExitCode::from(2);
}
_ => path = Some(arg),
}
}
let Some(path) = path else {
eprintln!("usage: disk4n6 [--json] <image>");
return ExitCode::from(2);
};
let mut opened = match disk_forensic::container::open(std::path::Path::new(&path)) {
Ok(o) => o,
Err(disk_forensic::container::OpenError::Unsupported(fmt)) => {
eprintln!(
"disk4n6: {path}: {fmt:?} container decoding is not yet supported — decode it to \
a raw image first"
);
return ExitCode::from(2);
}
Err(e) => {
eprintln!("disk4n6: cannot open {path}: {e}");
return ExitCode::from(2);
}
};
let report = match disk_forensic::analyse_disk(&mut opened.reader, opened.size) {
Ok(r) => r,
Err(e) => {
eprintln!("disk4n6: {path}: {e}");
return ExitCode::FAILURE;
}
};
if json {
#[cfg(feature = "serde")]
{
match serde_json::to_string_pretty(&report) {
Ok(s) => println!("{s}"),
Err(e) => {
eprintln!("disk4n6: JSON error: {e}");
return ExitCode::FAILURE;
}
}
}
#[cfg(not(feature = "serde"))]
{
eprintln!("disk4n6: --json requires the `serde` feature");
return ExitCode::from(2);
}
} else {
println!("Scheme: {:?}\n", report.scheme());
print!("{}", disk_forensic::report::text_report(&report));
println!();
print!(
"{}",
disk_forensic::report::render(&disk_forensic::normalize::report(&report))
);
}
if report.has_anomalies() {
ExitCode::FAILURE
} else {
ExitCode::SUCCESS
}
}