From 858a447c25e2ae02d5a3a5d40f23a2a3b521ff1c Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Tue, 30 Jun 2026 13:05:02 +1000 Subject: [PATCH 1/3] lib: return error on file not found Return an error when an explicitly provided input file is not found, instead of panicing. Signed-off-by: Jordan Yates --- src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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( From 8ca1fe857b6e11412d8ca0b0bab65f3d9733a31e Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Tue, 30 Jun 2026 13:11:37 +1000 Subject: [PATCH 2/3] main_cli: nicer error output If the decoding fails, use a custom error printer to give nicely formatted output instead of letting the rust error handler print info. Assisted-by: GPT-5.5 Signed-off-by: Jordan Yates --- CHANGELOG.md | 1 + src/main_cli.rs | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d27defc..64791b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ 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 ## [1.10.0] - 2026-06-25 diff --git a/src/main_cli.rs b/src/main_cli.rs index 0105a75..4d48580 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,37 @@ struct Cli { no_linearize_output: bool, } -fn main() -> io::Result<()> { +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(); if args.path.is_file() && !args.name.is_some() { println!("Expected `--name` to be provided when `--path` is a file"); - return Ok(()); + return ExitCode::FAILURE; } // 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()]); @@ -125,7 +146,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 +184,5 @@ fn main() -> io::Result<()> { table.printstd(); } } - Ok(()) + ExitCode::SUCCESS } From 9dbbcf4b15adf32b0b252e4cb8497b168b1a5f35 Mon Sep 17 00:00:00 2001 From: Jordan Yates Date: Tue, 30 Jun 2026 13:25:32 +1000 Subject: [PATCH 3/3] main_cli: auto-populate `--name` If `--path` is a file and `--name` is not provided, automatically populate the value from the filename instead of failing. Signed-off-by: Jordan Yates --- CHANGELOG.md | 1 + src/main_cli.rs | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64791b5..4a89d66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org). - 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/main_cli.rs b/src/main_cli.rs index 4d48580..e23b5c8 100644 --- a/src/main_cli.rs +++ b/src/main_cli.rs @@ -90,11 +90,6 @@ fn print_run_error(err: &io::Error, device_id: u64, files: &[PathBuf], output_fo fn main() -> ExitCode { 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 ExitCode::FAILURE; - } - // Handle single file supplied let iot_bin_files: HashMap> = if args.path.is_dir() { match infuse_decoder::fs_util::find_infuse_iot_files(&args.path) { @@ -127,7 +122,20 @@ fn main() -> ExitCode { } } 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}") + } } };