diff --git a/CHANGELOG.md b/CHANGELOG.md index d27defc..4a89d66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ This project adheres to [Semantic Versioning](https://semver.org). - In addition to the SD card file naming convention, folders with one file per device are now supported - Each file must have the 16 character hex ID somewhere in the filename - Fix decoding crash when no files are found + - Improve CLI tool output on crashes + - CLI will set `--name` from the input `--path` if not explicitly provided ## [1.10.0] - 2026-06-25 diff --git a/src/lib.rs b/src/lib.rs index cd26dd3..9bb1725 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -161,7 +161,14 @@ pub fn run( let (merged_file, size) = if args.input_files.len() == 1 { let f: PathBuf = args.input_files.get(0).unwrap().clone(); - let s = f.metadata().unwrap().len() as usize; + if !f.exists() { + return io::Result::Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + "Input file does not exist", + )); + } + let m = f.metadata()?; + let s = m.len() as usize; (f, s) } else { let (f, s) = merge_input_files( diff --git a/src/main_cli.rs b/src/main_cli.rs index 0105a75..e23b5c8 100644 --- a/src/main_cli.rs +++ b/src/main_cli.rs @@ -4,6 +4,7 @@ use infuse_decoder::args; use std::collections::HashMap; use std::io; use std::path::PathBuf; +use std::process::ExitCode; #[macro_use] extern crate prettytable; @@ -72,17 +73,32 @@ struct Cli { no_linearize_output: bool, } -fn main() -> io::Result<()> { - let args = Cli::parse(); - - if args.path.is_file() && !args.name.is_some() { - println!("Expected `--name` to be provided when `--path` is a file"); - return Ok(()); +fn print_run_error(err: &io::Error, device_id: u64, files: &[PathBuf], output_folder: &PathBuf) { + eprintln!(); + eprintln!("Decode failed"); + eprintln!("============="); + eprintln!("Device ID : {device_id:016x}"); + eprintln!("Input files : {}", files.len()); + for file in files { + eprintln!(" - {}", file.display()); } + eprintln!("Output folder : {}", output_folder.display()); + eprintln!("Error kind : {:?}", err.kind()); + eprintln!("Cause : {err}"); +} + +fn main() -> ExitCode { + let args = Cli::parse(); // Handle single file supplied let iot_bin_files: HashMap> = if args.path.is_dir() { - infuse_decoder::fs_util::find_infuse_iot_files(&args.path).unwrap() + match infuse_decoder::fs_util::find_infuse_iot_files(&args.path) { + Ok(files) => files, + Err(err) => { + eprintln!("Failed to scan input path '{}': {err}", args.path.display()); + return ExitCode::FAILURE; + } + } } else { let mut f: HashMap> = HashMap::new(); f.insert(0, vec![args.path.clone()]); @@ -106,7 +122,20 @@ fn main() -> io::Result<()> { } } None => { - format!("{device_id:016x}") + if args.path.is_file() { + match args.path.file_stem().and_then(|stem| stem.to_str()) { + Some(stem) => stem.to_string(), + None => { + eprintln!( + "Failed to derive output name from input path '{}'", + args.path.display() + ); + return ExitCode::FAILURE; + } + } + } else { + format!("{device_id:016x}") + } } }; @@ -125,7 +154,13 @@ fn main() -> io::Result<()> { merge_reporter: IndicatifProgress::new(), }; - let (block_stats, tdf_stats, _output_files) = infuse_decoder::run(&mut run_args)?; + let (block_stats, tdf_stats, _output_files) = match infuse_decoder::run(&mut run_args) { + Ok(result) => result, + Err(err) => { + print_run_error(&err, *device_id, files, &args.output); + return ExitCode::FAILURE; + } + }; if args.verbose { for (remote_id, tdfs) in tdf_stats.iter() { @@ -157,5 +192,5 @@ fn main() -> io::Result<()> { table.printstd(); } } - Ok(()) + ExitCode::SUCCESS }