diff options
author | Omer Ben-Amram <omerbenamram@gmail.com> | 2019-05-08 21:39:26 +0300 |
---|---|---|
committer | Omer Ben-Amram <omerbenamram@gmail.com> | 2019-05-08 21:39:39 +0300 |
commit | e8f6804dca46eecd819aeeb61213da5a024a2e9b (patch) | |
tree | 2a3fe7c8471ccc21ec86e61b871707640727f326 | |
parent | 5e48d3c0b2886aa1b82e2007bc36ac631c5dcb94 (diff) |
fix doc-tests
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/attr_x10.rs | 35 | ||||
-rw-r--r-- | src/attr_x30.rs | 40 | ||||
-rw-r--r-- | src/attribute.rs | 2 | ||||
-rw-r--r-- | src/bin/mft_dump.rs | 2 | ||||
-rw-r--r-- | src/entry.rs | 18 | ||||
-rw-r--r-- | src/enumerator.rs | 2 | ||||
-rw-r--r-- | src/err.rs | 4 | ||||
-rw-r--r-- | src/mft.rs | 40 |
9 files changed, 81 insertions, 64 deletions
@@ -20,7 +20,7 @@ serde = {version = "1.0.91", features = ["derive"]} serde_json = "1.0.39" env_logger = "0.6.1" snafu = "0.2.3" -winstructs = "0.1.0" +winstructs = {git = "https://github.com/omerbenamram/winstructs.git", branch = "master"} [dependencies.jmespath] version = "^0.1.1" diff --git a/src/attr_x10.rs b/src/attr_x10.rs index 4e08223..3366714 100644 --- a/src/attr_x10.rs +++ b/src/attr_x10.rs @@ -1,11 +1,12 @@ -use crate::err::{Result}; +use crate::err::{self, Result}; -use log::trace; use byteorder::{LittleEndian, ReadBytesExt}; use chrono::{DateTime, Utc}; +use log::trace; use serde::Serialize; use std::io::Read; use winstructs::timestamp::WinTimestamp; +use snafu::ResultExt; #[derive(Serialize, Debug, Clone)] pub struct StandardInfoAttr { @@ -31,7 +32,8 @@ impl StandardInfoAttr { /// Parse a raw buffer. /// /// ``` - /// use rustymft::attr_x10::StandardInfoAttr; + /// use mft::attr_x10::StandardInfoAttr; + /// # use std::io::Cursor; /// # fn test_standard_information() { /// let attribute_buffer: &[u8] = &[ /// 0x2F,0x6D,0xB6,0x6F,0x0C,0x97,0xCE,0x01,0x56,0xCD,0x1A,0x75,0x73,0xB5,0xCE,0x01, @@ -41,12 +43,12 @@ impl StandardInfoAttr { /// 0x68,0x58,0xA0,0x0A,0x02,0x00,0x00,0x00 /// ]; /// - /// let attribute = StandardInfoAttr::new(attribute_buffer).unwrap(); + /// let attribute = StandardInfoAttr::from_reader(&mut Cursor::new(attribute_buffer)).unwrap(); /// - /// assert_eq!(attribute.created.0, 130207518909951279); - /// assert_eq!(attribute.modified.0, 130240946730880342); - /// assert_eq!(attribute.mft_modified.0, 130240946730880342); - /// assert_eq!(attribute.accessed.0, 130240946730880342); + /// assert_eq!(attribute.created.timestamp(), 130207518909951279); + /// assert_eq!(attribute.modified.timestamp(), 130240946730880342); + /// assert_eq!(attribute.mft_modified.timestamp(), 130240946730880342); + /// assert_eq!(attribute.accessed.timestamp(), 130240946730880342); /// assert_eq!(attribute.file_flags, 32); /// assert_eq!(attribute.max_version, 0); /// assert_eq!(attribute.version, 0); @@ -58,10 +60,19 @@ impl StandardInfoAttr { /// ``` pub fn from_reader<R: Read>(reader: &mut R) -> Result<StandardInfoAttr> { trace!("StandardInfoAttr"); - let created = WinTimestamp::from_reader(reader)?.to_datetime(); - let modified = WinTimestamp::from_reader(reader)?.to_datetime(); - let mft_modified = WinTimestamp::from_reader(reader)?.to_datetime(); - let accessed = WinTimestamp::from_reader(reader)?.to_datetime(); + let created = WinTimestamp::from_reader(reader) + .context(err::FailedToReadWindowsTime)? + .to_datetime(); + let modified = WinTimestamp::from_reader(reader) + .context(err::FailedToReadWindowsTime)? + .to_datetime(); + let mft_modified = WinTimestamp::from_reader(reader) + .context(err::FailedToReadWindowsTime)? + .to_datetime(); + let accessed = WinTimestamp::from_reader(reader) + .context(err::FailedToReadWindowsTime)? + .to_datetime(); + let file_flags = reader.read_u32::<LittleEndian>()?; let max_version = reader.read_u32::<LittleEndian>()?; let version = reader.read_u32::<LittleEndian>()?; diff --git a/src/attr_x30.rs b/src/attr_x30.rs index 105aec8..63564e7 100644 --- a/src/attr_x30.rs +++ b/src/attr_x30.rs @@ -10,7 +10,8 @@ use std::io::Read; use chrono::{DateTime, Utc}; use serde::Serialize; -use winstructs::reference::MftReference; +use snafu::ResultExt; +use winstructs::ntfs::mft_reference::MftReference; use winstructs::timestamp::WinTimestamp; #[derive(Serialize, Clone, Debug)] @@ -30,7 +31,6 @@ pub struct FileNameAttr { pub fullname: Option<String>, } -// TODO: fix docs (use correct idioms) impl FileNameAttr { /// Parse a Filename attrbiute buffer. /// @@ -39,7 +39,8 @@ impl FileNameAttr { /// Parse a raw buffer. /// /// ``` - /// use rustymft::attr_x30::FileNameAttr; + /// use mft::attr_x30::FileNameAttr; + /// # use std::io::Cursor; /// # fn test_filename_attribute() { /// let attribute_buffer: &[u8] = &[ /// 0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0xD5,0x2D,0x48,0x58,0x43,0x5F,0xCE,0x01, @@ -50,16 +51,13 @@ impl FileNameAttr { /// 0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /// ]; /// - /// let attribute = match FileNameAttr::new(attribute_buffer) { - /// Ok(attribute) => attribute, - /// Err(error) => panic!(error) - /// }; + /// let attribute = FileNameAttr::from_reader(&mut Cursor::new(attribute_buffer)).unwrap(); /// - /// assert_eq!(attribute.parent.0, 1407374883553285); - /// assert_eq!(attribute.created.0, 130146182088895957); - /// assert_eq!(attribute.modified.0, 130146182088895957); - /// assert_eq!(attribute.mft_modified.0, 130146182088895957); - /// assert_eq!(attribute.accessed.0, 130146182088895957); + /// assert_eq!(attribute.parent.entry, 1407374883553285); + /// assert_eq!(attribute.created.timestamp(), 130146182088895957); + /// assert_eq!(attribute.modified.timestamp(), 130146182088895957); + /// assert_eq!(attribute.mft_modified.timestamp(), 130146182088895957); + /// assert_eq!(attribute.accessed.timestamp(), 130146182088895957); /// assert_eq!(attribute.logical_size, 67108864); /// assert_eq!(attribute.physical_size, 67108864); /// assert_eq!(attribute.flags, 6); @@ -71,11 +69,19 @@ impl FileNameAttr { /// ``` pub fn from_reader<R: Read>(reader: &mut R) -> Result<FileNameAttr> { trace!("FileNameAttr"); - let parent = MftReference(reader.read_u64::<LittleEndian>()?); - let created = WinTimestamp::from_reader(reader)?.to_datetime(); - let modified = WinTimestamp::from_reader(reader)?.to_datetime(); - let mft_modified = WinTimestamp::from_reader(reader)?.to_datetime(); - let accessed = WinTimestamp::from_reader(reader)?.to_datetime(); + let parent = MftReference::from_reader(reader).context(err::FailedToReadMftReference)?; + let created = WinTimestamp::from_reader(reader) + .context(err::FailedToReadWindowsTime)? + .to_datetime(); + let modified = WinTimestamp::from_reader(reader) + .context(err::FailedToReadWindowsTime)? + .to_datetime(); + let mft_modified = WinTimestamp::from_reader(reader) + .context(err::FailedToReadWindowsTime)? + .to_datetime(); + let accessed = WinTimestamp::from_reader(reader) + .context(err::FailedToReadWindowsTime)? + .to_datetime(); let logical_size = reader.read_u64::<LittleEndian>()?; let physical_size = reader.read_u64::<LittleEndian>()?; let flags = reader.read_u32::<LittleEndian>()?; diff --git a/src/attribute.rs b/src/attribute.rs index 6c6db92..17faad2 100644 --- a/src/attribute.rs +++ b/src/attribute.rs @@ -3,7 +3,7 @@ use crate::attr_x30::FileNameAttr; use crate::err::{self, Result}; use crate::utils::read_utf16_string; use crate::{utils, ReadSeek}; -use log::debug; + use bitflags::bitflags; use byteorder::{LittleEndian, ReadBytesExt}; diff --git a/src/bin/mft_dump.rs b/src/bin/mft_dump.rs index 2648916..3f7037d 100644 --- a/src/bin/mft_dump.rs +++ b/src/bin/mft_dump.rs @@ -1,6 +1,6 @@ use clap::{App, Arg}; use env_logger; -use log::{debug, error, info, warn}; +use log::{info, warn}; use mft::mft::MftHandler; fn process_file(filename: &str, indent: bool) -> bool { diff --git a/src/entry.rs b/src/entry.rs index 8aa3c38..6f45b5c 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -3,14 +3,12 @@ use crate::err::{self, Result}; use crate::attr_x10::StandardInfoAttr; use crate::attr_x30::FileNameAttr; use crate::enumerator::PathMapping; -use crate::mft::MftHandler; + use crate::{attribute, ReadSeek}; use log::debug; -use snafu::ensure; - -use std::collections::BTreeMap; +use snafu::{ensure, ResultExt}; -use winstructs::reference::MftReference; +use winstructs::ntfs::mft_reference::MftReference; use byteorder::{LittleEndian, ReadBytesExt}; @@ -20,7 +18,6 @@ use serde::{ser, Serialize}; use crate::attribute::MftAttribute; use std::io::Cursor; use std::io::Read; -use std::io::Seek; use std::io::SeekFrom; //https://github.com/libyal/libfsntfs/blob/master/documentation/New%20Technologies%20File%20System%20(NTFS).asciidoc#5-the-master-file-table-mft @@ -89,7 +86,8 @@ impl EntryHeader { let flags = EntryFlags::from_bits_truncate(reader.read_u16::<LittleEndian>()?); let entry_size_real = reader.read_u32::<LittleEndian>()?; let entry_size_allocated = reader.read_u32::<LittleEndian>()?; - let base_reference = MftReference(reader.read_u64::<LittleEndian>()?); + let base_reference = + MftReference::from_reader(reader).context(err::FailedToReadMftReference)?; let next_attribute_id = reader.read_u16::<LittleEndian>()?; ensure!( @@ -100,7 +98,7 @@ impl EntryHeader { let _padding = reader.read_u16::<LittleEndian>()?; let record_number = u64::from(reader.read_u32::<LittleEndian>()?); - let entry_reference = MftReference::get_from_entry_and_seq(record_number as u64, sequence); + let entry_reference = MftReference::new(record_number as u64, sequence); Ok(EntryHeader { signature, @@ -157,7 +155,7 @@ impl MftEntry { if attrib.namespace != 2 { return Some(PathMapping { name: attrib.name.clone(), - parent: MftReference(attrib.parent.0), + parent: attrib.parent.clone(), }); } } @@ -287,7 +285,7 @@ mod tests { assert_eq!(entry_header.flags.bits(), 5); assert_eq!(entry_header.entry_size_real, 840); assert_eq!(entry_header.entry_size_allocated, 1024); - assert_eq!(entry_header.base_reference.0, 0); + assert_eq!(entry_header.base_reference.entry, 0); assert_eq!(entry_header.next_attribute_id, 6); assert_eq!(entry_header.record_number, 38357); } diff --git a/src/enumerator.rs b/src/enumerator.rs index ad6a322..eb5e6e5 100644 --- a/src/enumerator.rs +++ b/src/enumerator.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use winstructs::reference::MftReference; +use winstructs::ntfs::mft_reference::MftReference; #[derive(Hash, Eq, PartialEq, Debug, Clone)] pub struct PathMapping { @@ -22,6 +22,10 @@ pub enum Error { UnhandledResidentFlag { flag: u8, offset: u64 }, #[snafu(display("Expected usa_offset `{}` to equal 48", offset))] InvalidUsaOffset { offset: u16 }, + #[snafu(display("Failed to read MftReference: `{}`", "source"))] + FailedToReadMftReference { source: winstructs::err::Error }, + #[snafu(display("Failed to read WindowsTime: `{}`", "source"))] + FailedToReadWindowsTime { source: winstructs::err::Error }, #[snafu(display("An unexpected error has occurred: {}", detail))] Any { detail: String }, } @@ -1,20 +1,20 @@ -use crate::ReadSeek; use crate::entry::MftEntry; use crate::enumerator::{PathEnumerator, PathMapping}; use crate::err::{self, Result}; + use log::debug; use snafu::ResultExt; use std::fs::File; use std::io::{BufReader, Read, Seek, SeekFrom}; use std::path::Path; -use winstructs::reference::MftReference; +use winstructs::ntfs::mft_reference::MftReference; pub struct MftHandler { file: BufReader<File>, path_enumerator: PathEnumerator, - _entry_size: u32, - _offset: u64, - _size: u64, + entry_size: u32, + offset: u64, + size: u64, } impl MftHandler { @@ -23,42 +23,40 @@ impl MftHandler { let mut mft_fh = File::open(f).context(err::FailedToOpenFile { path: f.to_owned() })?; - debug!("Seek!"); // TODO: remove this, and find a better way let size = match mft_fh.seek(SeekFrom::End(0)) { Err(e) => panic!("Error: {}", e), Ok(size) => size, }; - debug!("After Seek!"); let filehandle = BufReader::with_capacity(4096, mft_fh); Ok(MftHandler { file: filehandle, path_enumerator: PathEnumerator::new(), - _entry_size: 1024, - _offset: 0, - _size: size, + entry_size: 1024, + offset: 0, + size, }) } pub fn set_entry_size(&mut self, entry_size: u32) { - self._entry_size = entry_size + self.entry_size = entry_size } pub fn get_entry_count(&self) -> u64 { - self._size / u64::from(self._entry_size) + self.size / u64::from(self.entry_size) } pub fn entry(&mut self, entry: u64) -> Result<MftEntry> { debug!("Reading entry {}", entry); self.file - .seek(SeekFrom::Start(entry * u64::from(self._entry_size)))?; + .seek(SeekFrom::Start(entry * u64::from(self.entry_size)))?; - let mut entry_buffer = vec![0; self._entry_size as usize]; + let mut entry_buffer = vec![0; self.entry_size as usize]; self.file.read_exact(&mut entry_buffer)?; - let mut mft_entry = self.entry_from_buffer(entry_buffer, entry)?; + let mft_entry = self.entry_from_buffer(entry_buffer, entry)?; // We need to set the path if dir if let Some(mapping) = mft_entry.get_pathmap() { @@ -69,7 +67,7 @@ impl MftHandler { } // TODO: don't do this mutably from here. -// mft_entry.set_full_names(self); + // mft_entry.set_full_names(self); Ok(mft_entry) } @@ -92,18 +90,18 @@ impl MftHandler { fn enumerate_path_stack(&mut self, name_stack: &mut Vec<String>, reference: MftReference) { // 1407374883553285 (5-5) - if reference.0 == 1_407_374_883_553_285 { + if reference.entry == 1_407_374_883_553_285 { } else { match self.path_enumerator.get_mapping(reference) { Some(mapping) => { - self.enumerate_path_stack(name_stack, mapping.parent.clone()); + self.enumerate_path_stack(name_stack, mapping.parent); name_stack.push(mapping.name.clone()); } None => { // Mapping not exists // Get entry number for this reference that does not exist - let entry = reference.get_entry_number(); + let entry = reference.entry; // Gat mapping for it match self.get_mapping_from_entry(entry) { Ok(mapping) => match mapping { @@ -126,9 +124,9 @@ impl MftHandler { fn get_mapping_from_entry(&mut self, entry: u64) -> Result<Option<PathMapping>> { self.file - .seek(SeekFrom::Start(entry * self._entry_size as u64))?; + .seek(SeekFrom::Start(entry * u64::from(self.entry_size)))?; - let mut entry_buffer = vec![0; self._entry_size as usize]; + let mut entry_buffer = vec![0; self.entry_size as usize]; self.file.read_exact(&mut entry_buffer)?; let mft_entry = self.entry_from_buffer(entry_buffer, entry)?; |