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

github.com/windirstat/RustyMft.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatthew seyer <matthew.seyer@gmail.com>2017-05-19 08:05:40 +0300
committermatthew seyer <matthew.seyer@gmail.com>2017-05-19 08:05:40 +0300
commit643c47b3c33e3e9a83eb3c5e3bc793321b2eb463 (patch)
treea2b972389b7121afc6d2eac1055ee561c1809ea2
parent129b129279c50125f20d2cda276bcb7b5b24b1c7 (diff)
Added fullname enumeration
-rw-r--r--src/attr_x30.rs3
-rw-r--r--src/entry.rs72
-rw-r--r--src/enumerator.rs44
-rw-r--r--src/lib.rs3
-rw-r--r--src/mft.rs98
5 files changed, 207 insertions, 13 deletions
diff --git a/src/attr_x30.rs b/src/attr_x30.rs
index 3d4503b..8b99e1e 100644
--- a/src/attr_x30.rs
+++ b/src/attr_x30.rs
@@ -23,7 +23,8 @@ pub struct FileNameAttribute {
pub reparse_value: u32,
pub name_length: u8,
pub namespace: u8,
- pub name: String
+ pub name: String,
+ pub fullname: Option<String>
}
impl FileNameAttribute {
pub fn new<R: Read>(mut reader: R) -> Result<FileNameAttribute,MftError> {
diff --git a/src/entry.rs b/src/entry.rs
index 0be1a1b..ec9978b 100644
--- a/src/entry.rs
+++ b/src/entry.rs
@@ -1,4 +1,6 @@
use errors::{MftError};
+use enumerator::{PathEnumerator,PathMapping};
+use mft::{MftHandler};
use attribute;
use utils;
use attr_x10;
@@ -48,7 +50,8 @@ pub struct EntryHeader{
#[serde(skip_serializing)]
pub padding: Option<u16>,
pub record_number: Option<u32>,
- pub update_sequence_value: u32
+ pub update_sequence_value: u32,
+ pub entry_reference: Option<MftReference>
}
impl EntryHeader{
pub fn new<R: Read>(mut reader: R, entry: Option<u64>) -> Result<EntryHeader,MftError> {
@@ -89,6 +92,15 @@ impl EntryHeader{
)
}
+ if entry_header.record_number.is_some(){
+ entry_header.entry_reference = Some(
+ MftReference::get_from_entry_and_seq(
+ entry_header.record_number.unwrap() as u64,
+ entry_header.sequence
+ )
+ );
+ }
+
Ok(entry_header)
}
}
@@ -123,12 +135,43 @@ impl MftEntry{
Ok(mft_entry)
}
- pub fn buffer_fixup(&self, mut buffer: &mut[u8]){
- // start offset (skip the first value (+2))
- let so = (self.header.usa_offset + 2) as usize;
- // array length
- let al = (self.header.usa_size - 1 * 2) as usize;
+ pub fn is_allocated(&self) -> bool {
+ if self.header.flags.bits() & 0x01 != 0 {
+ true
+ } else {
+ false
+ }
+ }
+
+ pub fn is_dir(&self) -> bool {
+ if self.header.flags.bits() & 0x02 != 0 {
+ true
+ } else {
+ false
+ }
+ }
+ pub fn get_pathmap(&self) -> Option<PathMapping> {
+ match self.attr_filename {
+ Some(ref attributes) => {
+ for attribute in attributes {
+ if attribute.namespace != 2 {
+ return Some(
+ PathMapping {
+ name: attribute.name.clone(),
+ parent: MftReference(attribute.parent.0)
+ }
+ );
+ }
+ }
+ },
+ _ => {}
+ }
+
+ None
+ }
+
+ pub fn buffer_fixup(&self, mut buffer: &mut[u8]){
let fixup_values = &buffer[
(self.header.usa_offset + 2) as usize..
((self.header.usa_offset + 2)+((self.header.usa_size - 1) * 2)) as usize
@@ -147,7 +190,7 @@ impl MftEntry{
)?;
let attr_count: u32 = 0;
- while true {
+ loop {
let attribute_header = attribute::AttributeHeader::new(
&mut buffer
)?;
@@ -189,6 +232,21 @@ impl MftEntry{
}
Ok(attr_count)
}
+
+ pub fn set_fullnames(&mut self, mft_handler: &mut MftHandler){
+ match self.attr_filename {
+ Some(ref mut attributes) => {
+ for attribute in attributes {
+ let fullpath = mft_handler.get_fullpath(
+ attribute.parent
+ );
+ let fullname = fullpath + "/" + attribute.name.as_str();
+ attribute.fullname = Some(fullname);
+ }
+ },
+ _ => {}
+ }
+ }
}
#[cfg(test)]
diff --git a/src/enumerator.rs b/src/enumerator.rs
new file mode 100644
index 0000000..70c4403
--- /dev/null
+++ b/src/enumerator.rs
@@ -0,0 +1,44 @@
+use std::collections::HashMap;
+use rwinstructs::reference::{MftReference};
+
+#[derive(Hash, Eq, PartialEq, Debug, Clone)]
+pub struct PathMapping {
+ pub name: String,
+ pub parent: MftReference,
+}
+
+pub struct PathEnumerator {
+ pub mapping: HashMap<MftReference,PathMapping>
+}
+
+impl PathEnumerator {
+ pub fn new() -> PathEnumerator {
+ PathEnumerator{
+ mapping: HashMap::new()
+ }
+ }
+
+ pub fn get_mapping(&self, reference: MftReference) -> Option<PathMapping> {
+ match self.mapping.get(&reference) {
+ Some(value) => Some(value.clone()),
+ None => None
+ }
+ }
+
+ pub fn print_mapping(&self){
+ println!("{:?}",self.mapping);
+ }
+
+ pub fn contains_mapping(&self, reference: MftReference) -> bool {
+ self.mapping.contains_key(
+ &reference
+ )
+ }
+
+ pub fn set_mapping(&mut self, reference: MftReference, mapping: PathMapping) {
+ self.mapping.insert(
+ reference,
+ mapping
+ );
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index dafa329..4a2d5d5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,5 @@
#[macro_use] extern crate serde_derive;
-#[macro_use] extern crate serde_json;
#[macro_use] extern crate bitflags;
-#[macro_use] extern crate log;
extern crate seek_bufread;
extern crate byteorder;
extern crate rwinstructs;
@@ -12,5 +10,6 @@ pub mod utils;
pub mod mft;
pub mod entry;
pub mod attribute;
+pub mod enumerator;
pub mod attr_x10;
pub mod attr_x30;
diff --git a/src/mft.rs b/src/mft.rs
index 6654f65..802f381 100644
--- a/src/mft.rs
+++ b/src/mft.rs
@@ -1,4 +1,6 @@
use seek_bufread::BufReader;
+use enumerator::{PathEnumerator,PathMapping};
+use rwinstructs::reference::{MftReference};
use errors::{MftError};
use entry::{MftEntry};
use std::fs::File;
@@ -9,6 +11,7 @@ use std::mem;
pub struct MftHandler {
filehandle: BufReader<File>,
+ path_enumerator: PathEnumerator,
_entry_size: u32,
_offset: u64,
_size: u64
@@ -55,17 +58,40 @@ impl MftHandler{
).unwrap();
let mut entry_buffer = vec![0; self._entry_size as usize];
- self.filehandle.read_exact(&mut entry_buffer)?;
+ self.filehandle.read_exact(
+ &mut entry_buffer
+ )?;
- let mft_entry = self.entry_from_buffer(
+ let mut mft_entry = self.entry_from_buffer(
entry_buffer,
entry
)?;
+ // We need to set the path if dir
+ match mft_entry.get_pathmap() {
+ Some(mapping) => {
+ if mft_entry.is_dir() {
+ &self.path_enumerator.set_mapping(
+ mft_entry.header.entry_reference.clone().unwrap(),
+ mapping.clone()
+ );
+ }
+ },
+ None => {},
+ }
+
+ mft_entry.set_fullnames(
+ self
+ );
+
Ok(mft_entry)
}
- pub fn entry_from_buffer(&mut self, mut buffer: Vec<u8>, entry: u64) -> Result<MftEntry,MftError> {
+ pub fn print_mapping(&self){
+ self.path_enumerator.print_mapping();
+ }
+
+ pub fn entry_from_buffer(&mut self, buffer: Vec<u8>, entry: u64) -> Result<MftEntry,MftError> {
let mft_entry = MftEntry::new(
buffer,
Some(entry)
@@ -73,4 +99,70 @@ impl MftHandler{
Ok(mft_entry)
}
+
+ pub fn get_fullpath(&mut self, reference: MftReference) -> String {
+ let mut path_stack = Vec::new();
+ self.enumerate_path_stack(
+ &mut path_stack,
+ reference
+ );
+ path_stack.join("/")
+ }
+
+ fn enumerate_path_stack(&mut self, name_stack: &mut Vec<String>, reference: MftReference) {
+ // 1407374883553285 (5-5)
+ if reference.0 == 1407374883553285 {
+
+ }
+ else {
+ match self.path_enumerator.get_mapping(reference){
+ Some(mapping) => {
+ self.enumerate_path_stack(
+ name_stack,
+ mapping.parent.clone()
+ );
+ 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();
+ // Gat mapping for it
+ match self.get_mapping_from_entry(entry) {
+ Some(mapping) => {
+ self.path_enumerator.set_mapping(
+ reference,
+ mapping.clone()
+ );
+ self.enumerate_path_stack(
+ name_stack,
+ reference
+ );
+ },
+ None => {}
+ }
+ }
+ }
+ }
+ }
+
+ fn get_mapping_from_entry(&mut self, entry: u64) -> Option<PathMapping>{
+ self.filehandle.seek(
+ SeekFrom::Start(entry * self._entry_size as u64)
+ );
+
+ let mut entry_buffer = vec![0; self._entry_size as usize];
+ self.filehandle.read_exact(
+ &mut entry_buffer
+ );
+
+ let mut mft_entry = self.entry_from_buffer(
+ entry_buffer,
+ entry
+ );
+
+ mft_entry.unwrap().get_pathmap()
+ }
}