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:
authorOmer Ben-Amram <omerbenamram@gmail.com>2020-01-06 18:18:01 +0300
committerOmer Ben-Amram <omerbenamram@gmail.com>2020-01-06 18:18:01 +0300
commit84daee189019564510255d4fd861712d5e127ad3 (patch)
tree091d4c9dc486f1023d1d41afec1613a52b157823
parent1450e1050d7f97e0e3c7529680553b6a8299beea (diff)
snafu -> thiserror/anyhow
-rw-r--r--Cargo.toml49
-rw-r--r--src/attribute/header.rs12
-rw-r--r--src/attribute/raw.rs3
-rw-r--r--src/attribute/x10.rs11
-rw-r--r--src/attribute/x20.rs7
-rw-r--r--src/attribute/x30.rs19
-rw-r--r--src/attribute/x40.rs11
-rw-r--r--src/attribute/x80.rs3
-rw-r--r--src/bin/mft_dump.rs70
-rw-r--r--src/entry.rs51
-rw-r--r--src/err.rs62
-rw-r--r--src/mft.rs5
12 files changed, 142 insertions, 161 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 7c0070a..d889597 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,45 +11,46 @@ authors = ["Omer Ben-Amram <omerbenamram@gmail.com>"]
edition = "2018"
[dependencies]
-log = {version = "^0.4", features=["release_max_level_debug"]}
+log = { version = "0.4.8", features = ["release_max_level_debug"] }
clap = "2.33.0"
encoding = "0.2.33"
-byteorder = "1.3.1"
-bitflags = "1.0.4"
-serde = {version = "1.0.91", features = ["derive"]}
-serde_json = "1.0.39"
-csv = "1.0.7"
-snafu = {version="0.5.0", features = ["backtraces", "rust_1_30"]}
-num-traits = "0.2"
-num-derive = "0.3"
-winstructs = "0.2.0"
+byteorder = "1.3.2"
+bitflags = "1.2.1"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+csv = "1.1.1"
+thiserror = "1.0"
+anyhow = "1.0"
+num-traits = "0.2.10"
+num-derive = "0.3.0"
+winstructs = "0.2.3"
lru = "0.4.3"
-itertools = "0.8.0"
-rand = "0.7.0"
+itertools = "0.8.2"
+rand = "0.7.2"
# `mft_dump` dependencies
-simplelog = "0.7.1"
-dialoguer = "0.4.0"
-indoc = "0.3"
+simplelog = "0.7.4"
+dialoguer = "0.5.0"
+indoc = "0.3.4"
[dependencies.chrono]
-version = "0.4.6"
+version = "0.4.10"
features = ["serde"]
[dev-dependencies]
-criterion = "0.3"
-skeptic = "0.13"
-assert_cmd = "0.12"
-predicates = "1"
-env_logger = "0.7.0"
-tempfile = "3"
+criterion = "0.3.0"
+skeptic = "0.13.4"
+assert_cmd = "0.12.0"
+predicates = "1.0.2"
+env_logger = "0.7.1"
+tempfile = "3.1.0"
# rexpect relies on unix process semantics, but it's only used for process interaction tests.
[target.'cfg(not(target_os = "windows"))'.dev-dependencies]
-rexpect = "0.3"
+rexpect = "0.3.0"
[build-dependencies]
-skeptic = "0.13"
+skeptic = "0.13.4"
[[bin]]
name = "mft_dump"
diff --git a/src/attribute/header.rs b/src/attribute/header.rs
index df19697..ac7cf44 100644
--- a/src/attribute/header.rs
+++ b/src/attribute/header.rs
@@ -1,5 +1,5 @@
use crate::attribute::{AttributeDataFlags, MftAttributeType};
-use crate::err::{self, Result};
+use crate::err::{Error, Result};
use crate::utils::read_utf16_string;
use crate::ReadSeek;
@@ -54,10 +54,9 @@ impl MftAttributeHeader {
let type_code = match MftAttributeType::from_u32(type_code_value) {
Some(attribute_type) => attribute_type,
None => {
- return err::UnknownAttributeType {
+ return Err(Error::UnknownAttributeType {
attribute_type: type_code_value,
- }
- .fail()
+ })
}
};
@@ -81,11 +80,10 @@ impl MftAttributeHeader {
0 => ResidentialHeader::Resident(ResidentHeader::from_stream(stream)?),
1 => ResidentialHeader::NonResident(NonResidentHeader::from_stream(stream)?),
_ => {
- return err::UnhandledResidentFlag {
+ return Err(Error::UnhandledResidentFlag {
flag: resident_flag,
offset: stream.tell()?,
- }
- .fail();
+ })
}
};
diff --git a/src/attribute/raw.rs b/src/attribute/raw.rs
index 8285ae5..c00fb1d 100644
--- a/src/attribute/raw.rs
+++ b/src/attribute/raw.rs
@@ -2,7 +2,6 @@ use crate::attribute::MftAttributeType;
use crate::err::{self, Result};
use crate::{utils, ReadSeek};
use serde::{ser, Serialize};
-use snafu::ResultExt;
/// Placeholder attribute for currently unparsed attributes.
#[derive(Serialize, Clone, Debug)]
@@ -20,7 +19,7 @@ impl RawAttribute {
) -> Result<Self> {
let mut data = vec![0_u8; data_size];
- stream.read_exact(&mut data).context(err::IoError)?;
+ stream.read_exact(&mut data)?;
Ok(RawAttribute {
attribute_type,
diff --git a/src/attribute/x10.rs b/src/attribute/x10.rs
index ce7a610..cb7bd2c 100644
--- a/src/attribute/x10.rs
+++ b/src/attribute/x10.rs
@@ -1,12 +1,11 @@
use crate::attribute::FileAttributeFlags;
-use crate::err::{self, Result};
+use crate::err::{Error, Result};
use crate::ReadSeek;
use byteorder::{LittleEndian, ReadBytesExt};
use chrono::{DateTime, Utc};
use log::trace;
use serde::Serialize;
-use snafu::ResultExt;
use winstructs::timestamp::WinTimestamp;
#[derive(Serialize, Debug, Clone)]
@@ -62,16 +61,16 @@ impl StandardInfoAttr {
pub fn from_reader<S: ReadSeek>(reader: &mut S) -> Result<StandardInfoAttr> {
trace!("Offset {}: StandardInfoAttr", reader.tell()?);
let created = WinTimestamp::from_reader(reader)
- .context(err::FailedToReadWindowsTime)?
+ .map_err(Error::failed_to_read_windows_time)?
.to_datetime();
let modified = WinTimestamp::from_reader(reader)
- .context(err::FailedToReadWindowsTime)?
+ .map_err(Error::failed_to_read_windows_time)?
.to_datetime();
let mft_modified = WinTimestamp::from_reader(reader)
- .context(err::FailedToReadWindowsTime)?
+ .map_err(Error::failed_to_read_windows_time)?
.to_datetime();
let accessed = WinTimestamp::from_reader(reader)
- .context(err::FailedToReadWindowsTime)?
+ .map_err(Error::failed_to_read_windows_time)?
.to_datetime();
Ok(StandardInfoAttr {
diff --git a/src/attribute/x20.rs b/src/attribute/x20.rs
index 13425ba..8437823 100644
--- a/src/attribute/x20.rs
+++ b/src/attribute/x20.rs
@@ -1,4 +1,4 @@
-use crate::err::{self, Result};
+use crate::err::{Error, Result};
use crate::ReadSeek;
use log::trace;
@@ -8,7 +8,6 @@ use encoding::{DecoderTrap, Encoding};
use serde::Serialize;
-use snafu::ResultExt;
use std::io::SeekFrom;
use winstructs::ntfs::mft_reference::MftReference;
@@ -34,7 +33,7 @@ impl AttributeListAttr {
let name_offset = stream.read_u8()?;
let first_vcn = stream.read_u64::<LittleEndian>()?;
let base_reference =
- MftReference::from_reader(stream).context(err::FailedToReadMftReference)?;
+ MftReference::from_reader(stream).map_err(Error::failed_to_read_mft_reference)?;
let attribute_id = stream.read_u16::<LittleEndian>()?;
let name = if name_length > 0 {
@@ -45,7 +44,7 @@ impl AttributeListAttr {
match UTF_16LE.decode(&name_buffer, DecoderTrap::Ignore) {
Ok(s) => s,
- Err(_e) => return err::InvalidFilename {}.fail(),
+ Err(_e) => return Err(Error::InvalidFilename {}),
}
} else {
String::new()
diff --git a/src/attribute/x30.rs b/src/attribute/x30.rs
index 8a0d0f4..1228039 100644
--- a/src/attribute/x30.rs
+++ b/src/attribute/x30.rs
@@ -1,8 +1,7 @@
use crate::attribute::FileAttributeFlags;
-use crate::err::{self, Result};
+use crate::err::{self, Error, Result};
use crate::ReadSeek;
use log::trace;
-use snafu::OptionExt;
use byteorder::{LittleEndian, ReadBytesExt};
use encoding::all::UTF_16LE;
@@ -12,7 +11,6 @@ use chrono::{DateTime, Utc};
use num_traits::FromPrimitive;
use serde::Serialize;
-use snafu::ResultExt;
use winstructs::ntfs::mft_reference::MftReference;
use winstructs::timestamp::WinTimestamp;
@@ -77,18 +75,19 @@ impl FileNameAttr {
/// ```
pub fn from_stream<S: ReadSeek>(stream: &mut S) -> Result<FileNameAttr> {
trace!("Offset {}: FilenameAttr", stream.tell()?);
- let parent = MftReference::from_reader(stream).context(err::FailedToReadMftReference)?;
+ let parent =
+ MftReference::from_reader(stream).map_err(Error::failed_to_read_mft_reference)?;
let created = WinTimestamp::from_reader(stream)
- .context(err::FailedToReadWindowsTime)?
+ .map_err(Error::failed_to_read_windows_time)?
.to_datetime();
let modified = WinTimestamp::from_reader(stream)
- .context(err::FailedToReadWindowsTime)?
+ .map_err(Error::failed_to_read_windows_time)?
.to_datetime();
let mft_modified = WinTimestamp::from_reader(stream)
- .context(err::FailedToReadWindowsTime)?
+ .map_err(Error::failed_to_read_windows_time)?
.to_datetime();
let accessed = WinTimestamp::from_reader(stream)
- .context(err::FailedToReadWindowsTime)?
+ .map_err(Error::failed_to_read_windows_time)?
.to_datetime();
let logical_size = stream.read_u64::<LittleEndian>()?;
@@ -98,14 +97,14 @@ impl FileNameAttr {
let name_length = stream.read_u8()?;
let namespace = stream.read_u8()?;
let namespace =
- FileNamespace::from_u8(namespace).context(err::UnknownNamespace { namespace })?;
+ FileNamespace::from_u8(namespace).ok_or(Error::UnknownNamespace { namespace })?;
let mut name_buffer = vec![0; (name_length as usize * 2) as usize];
stream.read_exact(&mut name_buffer)?;
let name = match UTF_16LE.decode(&name_buffer, DecoderTrap::Ignore) {
Ok(s) => s,
- Err(_e) => return err::InvalidFilename {}.fail(),
+ Err(_e) => return Err(Error::InvalidFilename {}),
};
Ok(FileNameAttr {
diff --git a/src/attribute/x40.rs b/src/attribute/x40.rs
index beea829..2526c82 100644
--- a/src/attribute/x40.rs
+++ b/src/attribute/x40.rs
@@ -1,7 +1,6 @@
-use crate::err::{self, Result};
+use crate::err::{Error, Result};
use crate::ReadSeek;
use serde::Serialize;
-use snafu::ResultExt;
use winstructs::guid::Guid;
/// $Data Attribute
@@ -20,11 +19,11 @@ pub struct ObjectIdAttr {
impl ObjectIdAttr {
/// Data size should be either 16 or 64
pub fn from_stream<S: ReadSeek>(stream: &mut S, data_size: usize) -> Result<ObjectIdAttr> {
- let object_id = Guid::from_stream(stream).context(err::FailedToReadGuid)?;
+ let object_id = Guid::from_reader(stream).map_err(Error::failed_to_read_guid)?;
let (birth_volume_id, birth_object_id, domain_id) = if data_size == 64 {
- let g1 = Guid::from_stream(stream).context(err::FailedToReadGuid)?;
- let g2 = Guid::from_stream(stream).context(err::FailedToReadGuid)?;
- let g3 = Guid::from_stream(stream).context(err::FailedToReadGuid)?;
+ let g1 = Guid::from_reader(stream).map_err(Error::failed_to_read_guid)?;
+ let g2 = Guid::from_reader(stream).map_err(Error::failed_to_read_guid)?;
+ let g3 = Guid::from_reader(stream).map_err(Error::failed_to_read_guid)?;
(Some(g1), Some(g2), Some(g3))
} else {
(None, None, None)
diff --git a/src/attribute/x80.rs b/src/attribute/x80.rs
index 3f1efa6..b9d8ec0 100644
--- a/src/attribute/x80.rs
+++ b/src/attribute/x80.rs
@@ -1,7 +1,6 @@
use crate::err::{self, Result};
use crate::{utils, ReadSeek};
use serde::ser;
-use snafu::ResultExt;
/// $Data Attribute
#[derive(Clone, Debug)]
@@ -11,7 +10,7 @@ impl DataAttr {
pub fn from_stream<S: ReadSeek>(stream: &mut S, data_size: usize) -> Result<DataAttr> {
let mut data = vec![0_u8; data_size];
- stream.read_exact(&mut data).context(err::IoError)?;
+ stream.read_exact(&mut data)?;
Ok(DataAttr(data))
}
diff --git a/src/bin/mft_dump.rs b/src/bin/mft_dump.rs
index 75f4a8e..793581a 100644
--- a/src/bin/mft_dump.rs
+++ b/src/bin/mft_dump.rs
@@ -9,8 +9,7 @@ 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};
@@ -22,13 +21,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 +48,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()?);
@@ -148,7 +140,7 @@ struct MftDump {
}
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");
@@ -159,11 +151,11 @@ impl MftDump {
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 {
@@ -205,12 +197,15 @@ impl MftDump {
})
}
- 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 +216,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 +237,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,23 +259,23 @@ 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!(
+ return Err(anyhow!(
"Failed to open file {}.\n\tcaused by: {}",
self.filepath.display(),
&e
- )
+ ))
}
};
@@ -320,12 +312,6 @@ impl MftDump {
},
Err(error) => {
eprintln!("{}", error);
-
- if self.backtraces {
- if let Some(bt) = error.backtrace() {
- eprintln!("{}", bt);
- }
- }
continue;
}
};
@@ -371,11 +357,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 +393,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 +421,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)?;
diff --git a/src/entry.rs b/src/entry.rs
index 9e43855..2f89d04 100644
--- a/src/entry.rs
+++ b/src/entry.rs
@@ -1,8 +1,7 @@
-use crate::err::{self, Result};
+use crate::err::{self, Error, Result};
use crate::impl_serialize_for_bitflags;
use log::trace;
-use snafu::{ensure, ResultExt};
use winstructs::ntfs::mft_reference::MftReference;
@@ -98,12 +97,11 @@ impl EntryHeader {
let header_is_valid = [FILE_HEADER, BAAD_HEADER, ZERO_HEADER].contains(&&signature);
- ensure!(
- header_is_valid,
- err::InvalidEntrySignature {
- bad_sig: signature.to_vec()
- }
- );
+ if !header_is_valid {
+ return Err(Error::InvalidEntrySignature {
+ bad_sig: signature.to_vec(),
+ });
+ }
if signature == *ZERO_HEADER {
return Ok(Self::zero());
@@ -120,7 +118,7 @@ impl EntryHeader {
let entry_size_allocated = reader.read_u32::<LittleEndian>()?;
let base_reference =
- MftReference::from_reader(reader).context(err::FailedToReadMftReference)?;
+ MftReference::from_reader(reader).map_err(Error::failed_to_read_mft_reference)?;
let first_attribute_id = reader.read_u16::<LittleEndian>()?;
@@ -187,8 +185,8 @@ impl MftEntry {
})
}
- /// Initializes an MFT Entry from a buffer but skips checking and fixing the
- /// fixup array. This will throw InvalidEntrySignature error if the entry header
+ /// Initializes an MFT Entry from a buffer but skips checking and fixing the
+ /// fixup array. This will throw InvalidEntrySignature error if the entry header
/// is not valid.
pub fn from_buffer_skip_fixup(buffer: Vec<u8>, entry_number: u64) -> Result<MftEntry> {
let mut cursor = Cursor::new(&buffer);
@@ -196,12 +194,11 @@ impl MftEntry {
let entry_header = EntryHeader::from_reader(&mut cursor, entry_number)?;
trace!("Number of sectors: {:#?}", entry_header);
- ensure!(
- entry_header.is_valid(),
- err::InvalidEntrySignature {
- bad_sig: entry_header.signature.to_vec()
- }
- );
+ if !entry_header.is_valid() {
+ return Err(Error::InvalidEntrySignature {
+ bad_sig: entry_header.signature.to_vec(),
+ });
+ }
Ok(MftEntry {
header: entry_header,
@@ -264,14 +261,13 @@ impl MftEntry {
let end_of_sector_bytes =
&mut buffer[end_of_sector_bytes_start_offset..end_of_sector_bytes_end_offset];
- ensure!(
- end_of_sector_bytes == update_sequence,
- err::FailedToApplyFixup {
+ if end_of_sector_bytes != update_sequence {
+ return Err(Error::FailedToApplyFixup {
stride_number,
end_of_sector_bytes: end_of_sector_bytes.to_vec(),
- fixup_bytes: fixup_bytes.to_vec()
- }
- );
+ fixup_bytes: fixup_bytes.to_vec(),
+ });
+ }
end_of_sector_bytes.copy_from_slice(&fixup_bytes);
}
@@ -308,12 +304,9 @@ impl MftEntry {
return None;
}
- match cursor.seek(SeekFrom::Start(offset)).context(err::IoError) {
- Ok(_) => {}
- Err(e) => {
- exhausted = true;
- return Some(Err(e));
- }
+ if let Err(e) = cursor.seek(SeekFrom::Start(offset)) {
+ exhausted = true;
+ return Some(Err(e.into()));
};
let header = MftAttributeHeader::from_stream(&mut cursor);
diff --git a/src/err.rs b/src/err.rs
index 78076fb..838c55a 100644
--- a/src/err.rs
+++ b/src/err.rs
@@ -1,61 +1,71 @@
-use snafu::{Backtrace, Snafu};
-use std::path::PathBuf;
-use std::{io, result};
+use std::path::{Path, PathBuf};
+use thiserror::Error;
-pub type Result<T> = result::Result<T, Error>;
+pub type Result<T> = ::std::result::Result<T, Error>;
-#[derive(Debug, Snafu)]
-#[snafu(visibility(pub(crate)))]
+#[derive(Debug, Error)]
pub enum Error {
- #[snafu(display("An I/O error has occurred: {}", source))]
+ #[error("An I/O error has occurred: {}", source)]
IoError {
+ #[from]
source: std::io::Error,
- backtrace: Backtrace,
},
- #[snafu(display("Failed to open file {}: {}", path.display(), source))]
+ #[error("Failed to open file {}: {}", path.display(), source)]
FailedToOpenFile {
path: PathBuf,
source: std::io::Error,
},
- #[snafu(display("Error while decoding name in filename attribute"))]
+ #[error("Error while decoding name in filename attribute")]
InvalidFilename,
- #[snafu(display(
+ #[error(
"Bad signature: {:x?}, expected one of [b\"FILE\", b\"BAAD\", b\"0000\"]",
bad_sig
- ))]
+ )]
InvalidEntrySignature { bad_sig: Vec<u8> },
- #[snafu(display("Unknown `AttributeType`: {:04X}", attribute_type))]
+ #[error("Unknown `AttributeType`: {:04X}", attribute_type)]
UnknownAttributeType { attribute_type: u32 },
- #[snafu(display("Unknown filename namespace {}", namespace))]
+ #[error("Unknown filename namespace {}", namespace)]
UnknownNamespace { namespace: u8 },
- #[snafu(display("Unhandled resident flag: {} (offset: {})", flag, offset))]
+ #[error("Unhandled resident flag: {} (offset: {})", flag, offset)]
UnhandledResidentFlag { flag: u8, offset: u64 },
- #[snafu(display(
+ #[error(
"Fixup bytes do not match bytes at end of stride {} {:x?}: {:x?}",
stride_number,
end_of_sector_bytes,
fixup_bytes
- ))]
+ )]
FailedToApplyFixup {
stride_number: usize,
end_of_sector_bytes: Vec<u8>,
fixup_bytes: Vec<u8>,
},
- #[snafu(display("Failed to read MftReference: `{}`", source))]
+ #[error("Failed to read MftReference: `{}`", source)]
FailedToReadMftReference { source: winstructs::err::Error },
- #[snafu(display("Failed to read WindowsTime: `{}`", source))]
+ #[error("Failed to read WindowsTime: `{}`", source)]
FailedToReadWindowsTime { source: winstructs::err::Error },
- #[snafu(display("Failed to read GUID: `{}`", source))]
+ #[error("Failed to read GUID: `{}`", source)]
FailedToReadGuid { source: winstructs::err::Error },
- #[snafu(display("An unexpected error has occurred: {}", detail))]
+ #[error("An unexpected error has occurred: {}", detail)]
Any { detail: String },
}
-impl From<io::Error> for Error {
- fn from(err: io::Error) -> Self {
- Error::IoError {
- source: err,
- backtrace: Backtrace::new(),
+impl Error {
+ pub fn failed_to_read_windows_time(source: winstructs::err::Error) -> Error {
+ Error::FailedToReadWindowsTime { source }
+ }
+
+ pub fn failed_to_read_mft_reference(source: winstructs::err::Error) -> Error {
+ Error::FailedToReadMftReference { source }
+ }
+
+ pub fn failed_to_read_guid(source: winstructs::err::Error) -> Error {
+ Error::FailedToReadGuid { source }
+ }
+
+ pub fn failed_to_open_file(path: impl AsRef<Path>, source: std::io::Error) -> Error {
+ Error::FailedToOpenFile {
+ path: path.as_ref().to_path_buf(),
+ source,
}
}
}
diff --git a/src/mft.rs b/src/mft.rs
index 9d78543..7cf3b0b 100644
--- a/src/mft.rs
+++ b/src/mft.rs
@@ -1,9 +1,8 @@
use crate::entry::MftEntry;
-use crate::err::{self, Result};
+use crate::err::{Error, Result};
use crate::{EntryHeader, ReadSeek};
use log::{debug, trace};
-use snafu::ResultExt;
use lru::LruCache;
use std::fs::{self, File};
@@ -25,7 +24,7 @@ impl MftParser<BufReader<File>> {
pub fn from_path(filename: impl AsRef<Path>) -> Result<Self> {
let f = filename.as_ref();
- let mft_fh = File::open(f).context(err::FailedToOpenFile { path: f.to_owned() })?;
+ let mft_fh = File::open(f).map_err(|e| Error::failed_to_open_file(f, e))?;
let size = fs::metadata(f)?.len();
Self::from_read_seek(BufReader::with_capacity(4096, mft_fh), Some(size))