Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/mft.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/mft_dump.rs')
-rw-r--r--src/bin/mft_dump.rs103
1 files changed, 34 insertions, 69 deletions
diff --git a/src/bin/mft_dump.rs b/src/bin/mft_dump.rs
index 75f4a8e..6655524 100644
--- a/src/bin/mft_dump.rs
+++ b/src/bin/mft_dump.rs
@@ -9,12 +9,10 @@ use mft::{MftEntry, ReadSeek};
use dialoguer::Confirmation;
use mft::csv::FlatMftEntryWithName;
-use snafu::ErrorCompat;
-use std::error::Error;
+use anyhow::{anyhow, Context, Error, Result};
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
-use std::process::exit;
use mft::entry::ZERO_HEADER;
use std::fmt::Write as FmtWrite;
@@ -22,13 +20,6 @@ use std::ops::RangeInclusive;
use std::str::FromStr;
use std::{fs, io, path};
-/// Simple error macro for use inside of internal errors in `MftDump`
-macro_rules! err {
- ($($tt:tt)*) => { Err(Box::<dyn std::error::Error>::from(format!($($tt)*))) }
-}
-
-type StdErr = Box<dyn std::error::Error>;
-
#[derive(Debug, PartialOrd, PartialEq)]
enum OutputFormat {
JSON,
@@ -56,19 +47,19 @@ impl Ranges {
}
impl FromStr for Ranges {
- type Err = StdErr;
+ type Err = Error;
- fn from_str(s: &str) -> Result<Self, Self::Err> {
+ fn from_str(s: &str) -> Result<Self> {
let mut ranges = vec![];
for x in s.split(',') {
// range
if x.contains('-') {
let range: Vec<&str> = x.split('-').collect();
if range.len() != 2 {
- return err!(
+ return Err(anyhow!(
"Failed to parse ranges: Range should contain exactly one `-`, found {}",
x
- );
+ ));
}
ranges.push(range[0].parse()?..=range[1].parse()?);
@@ -144,26 +135,27 @@ struct MftDump {
verbosity_level: Option<Level>,
output_format: OutputFormat,
ranges: Option<Ranges>,
- backtraces: bool,
}
impl MftDump {
- pub fn from_cli_matches(matches: &ArgMatches) -> Result<Self, StdErr> {
+ pub fn from_cli_matches(matches: &ArgMatches) -> Result<Self> {
let output_format =
OutputFormat::from_str(matches.value_of("output-format").unwrap_or_default())
.expect("Validated with clap default values");
- let backtraces = matches.is_present("backtraces");
+ if matches.is_present("backtraces") {
+ std::env::set_var("RUST_LIB_BACKTRACE", "1");
+ }
let output: Option<Box<dyn Write>> = if let Some(path) = matches.value_of("output-target") {
match Self::create_output_file(path, !matches.is_present("no-confirm-overwrite")) {
Ok(f) => Some(Box::new(f)),
Err(e) => {
- return err!(
+ return Err(anyhow!(
"An error occurred while creating output file at `{}` - `{}`",
path,
e
- );
+ ));
}
}
} else {
@@ -201,16 +193,18 @@ impl MftDump {
verbosity_level,
output_format,
ranges,
- backtraces,
})
}
- fn create_output_dir(path: impl AsRef<Path>) -> Result<(), StdErr> {
+ fn create_output_dir(path: impl AsRef<Path>) -> Result<()> {
let p = path.as_ref();
if p.exists() {
if !p.is_dir() {
- return err!("There is a file at {}, refusing to overwrite", p.display());
+ return Err(anyhow!(
+ "There is a file at {}, refusing to overwrite",
+ p.display()
+ ));
}
// p exists and is a directory, it's ok to add files.
} else {
@@ -221,17 +215,14 @@ impl MftDump {
}
/// If `prompt` is passed, will display a confirmation prompt before overwriting files.
- fn create_output_file(
- path: impl AsRef<Path>,
- prompt: bool,
- ) -> Result<File, Box<dyn std::error::Error>> {
+ fn create_output_file(path: impl AsRef<Path>, prompt: bool) -> Result<File> {
let p = path.as_ref();
if p.is_dir() {
- return err!(
+ return Err(anyhow!(
"There is a directory at {}, refusing to overwrite",
p.display()
- );
+ ));
}
if p.exists() {
@@ -245,11 +236,11 @@ impl MftDump {
.interact()
{
Ok(true) => Ok(File::create(p)?),
- Ok(false) => err!("Cancelled"),
- Err(e) => err!(
+ Ok(false) => Err(anyhow!("Cancelled")),
+ Err(e) => Err(anyhow!(
"Failed to write confirmation prompt to term caused by\n{}",
e
- ),
+ )),
}
} else {
Ok(File::create(p)?)
@@ -267,25 +258,16 @@ impl MftDump {
Ok(File::create(p)?)
}
}
- None => err!("Output file cannot be root."),
+ None => Err(anyhow!("Output file cannot be root.")),
}
}
}
/// Main entry point for `EvtxDump`
- pub fn run(&mut self) -> Result<(), StdErr> {
+ pub fn run(&mut self) -> Result<()> {
self.try_to_initialize_logging();
- let mut parser = match MftParser::from_path(&self.filepath) {
- Ok(parser) => parser,
- Err(e) => {
- return err!(
- "Failed to open file {}.\n\tcaused by: {}",
- self.filepath.display(),
- &e
- )
- }
- };
+ let mut parser = MftParser::from_path(&self.filepath)?;
// Since the JSON parser can do away with a &mut Write, but the csv parser needs ownership
// of `Write`, we eagerly create the csv writer here, moving the Box<Write> out from
@@ -320,12 +302,6 @@ impl MftDump {
},
Err(error) => {
eprintln!("{}", error);
-
- if self.backtraces {
- if let Some(bt) = error.backtrace() {
- eprintln!("{}", bt);
- }
- }
continue;
}
};
@@ -371,11 +347,11 @@ impl MftDump {
);
if PathBuf::from(&data_stream_path).exists() {
- return err!(
+ return Err(anyhow!(
"Tried to override an existing stream {} already exists!\
This is a bug, please report to github!",
data_stream_path
- );
+ ));
}
let mut f = File::create(&data_stream_path)?;
@@ -407,12 +383,12 @@ impl MftDump {
io::stderr(),
) {
Ok(_) => {}
- Err(e) => eprintln!("Failed to initialize logging: {}", e.description()),
+ Err(e) => eprintln!("Failed to initialize logging: {}", e),
};
}
}
- pub fn print_json_entry(&mut self, entry: &MftEntry) -> Result<(), Box<dyn std::error::Error>> {
+ pub fn print_json_entry(&mut self, entry: &MftEntry) -> Result<()> {
let out = self
.output
.as_mut()
@@ -435,7 +411,7 @@ impl MftDump {
entry: &MftEntry,
parser: &mut MftParser<impl ReadSeek>,
writer: &mut csv::Writer<W>,
- ) -> Result<(), Box<dyn std::error::Error>> {
+ ) -> Result<()> {
let flat_entry = FlatMftEntryWithName::from_entry(&entry, parser);
writer.serialize(flat_entry)?;
@@ -470,7 +446,7 @@ pub fn sanitized(component: &str) -> String {
buf
}
-fn main() {
+fn main() -> Result<()> {
let matches = App::new("MFT Parser")
.version(env!("CARGO_PKG_VERSION"))
.author("Omer B. <omerbenamram@gmail.com>")
@@ -534,19 +510,8 @@ fn main() {
.help("If set, a backtrace will be printed with some errors if available"))
.get_matches();
- let mut app = match MftDump::from_cli_matches(&matches) {
- Ok(app) => app,
- Err(e) => {
- eprintln!("An error occurred while setting up the app: {}", &e);
- exit(1);
- }
- };
+ let mut app = MftDump::from_cli_matches(&matches).context("Failed setting up the app")?;
+ app.run().context("A runtime error has occurred")?;
- match app.run() {
- Ok(()) => {}
- Err(e) => {
- eprintln!("A runtime error has occurred: {}", &e);
- exit(1);
- }
- };
+ Ok(())
}