diff --git a/src/main.rs b/src/main.rs index e093ea6..df82583 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use std::{fs::read_dir, os::linux::fs::MetadataExt, path::Path}; -use anyhow::{anyhow, ensure, Context, Result}; +use anyhow::{anyhow, ensure, Context, Error, Result}; use clap::Parser; use crate::{cli::Args, summary::Summary}; @@ -14,25 +14,15 @@ fn main() -> Result<()> { let mut summary = Summary::default(); for root in args.roots { - fs_entry(&root, &mut summary)?; + fs_entry(&root, &mut summary); } if !args.raw { let (uf, gf) = summary.lookup_names(); - - for (uid, e) in uf { - eprintln!( - "{:#}", - anyhow!(e).context(format!("failed to get name for user {uid}")) - ); - } - - for (gid, e) in gf { - eprintln!( - "{:#}", - anyhow!(e).context(format!("failed to get name for group {gid}")) - ); - } + uf.into_iter() + .for_each(|(uid, e)| print_err(e, format!("failed to get name for user {uid}"))); + gf.into_iter() + .for_each(|(gid, e)| print_err(e, format!("failed to get name for group {gid}"))); } let output = match args.json { false => summary.to_string(), @@ -44,26 +34,48 @@ fn main() -> Result<()> { } /// Perform gid & uid gathering for a file, or a directory and its children. -fn fs_entry(entry: &Path, summary: &mut Summary) -> Result<()> { +fn fs_entry(entry: &Path, summary: &mut Summary) { let display = entry.display(); - ensure!( - entry.is_symlink() || entry.exists(), - format!("{} doesn't exist", display) - ); + if !entry.exists() && !entry.is_symlink() { + print_root_err(format!("{display} doesn't exist")); + } + + let meta = match entry.symlink_metadata() { + Ok(meta) => meta, + Err(e) => { + print_err(e, format!("failed to get metadata for {display}")); + return; + } + }; - let meta = entry - .symlink_metadata() - .context(format!("failed to get metadata for {}", display))?; summary.add_user(meta.st_uid()); summary.add_group(meta.st_gid()); if entry.is_dir() { - let children = read_dir(entry).context(format!("failed to read dir {}", display))?; - for e in children { - let e = e.context(format!("invalid child for {}", display))?; - fs_entry(&e.path(), summary)?; + let children = match read_dir(entry) { + Ok(children) => children, + Err(e) => { + print_err(e, format!("failed to read dir {display}")); + return; + } + }; + + for child in children { + match child { + Ok(child) => fs_entry(&child.path(), summary), + Err(e) => { + print_err(e, format!("invalid child for {display}")); + return; + } + } } } - - Ok(()) +} + +fn print_root_err(message: String) { + eprintln!("{:#}", anyhow!("{message}")); +} + +fn print_err(err: impl Into, message: String) { + eprintln!("{:#}", err.into().context(message)); }