From 659a3af5e432cef670290f690ec4ea33e3517822 Mon Sep 17 00:00:00 2001 From: matthew seyer Date: Mon, 6 Nov 2017 22:27:22 -0700 Subject: Parse attributes from buffer ref; Switched to doc-tests; Removed serialize derivative and added serialization method; --- src/attr_x10.rs | 137 +++++++++++++++++++++++++++++--------------------- src/attr_x30.rs | 151 ++++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 180 insertions(+), 108 deletions(-) diff --git a/src/attr_x10.rs b/src/attr_x10.rs index c3982bc..f012b21 100644 --- a/src/attr_x10.rs +++ b/src/attr_x10.rs @@ -1,11 +1,10 @@ use errors::{MftError}; use rwinstructs::timestamp::{WinTimestamp}; -use rwinstructs::serialize::{serialize_u64}; -use byteorder::{ReadBytesExt, LittleEndian}; -use std::io::Read; -use std::mem; +use byteorder::{ReadBytesExt,LittleEndian}; +use serde::ser::SerializeStruct; +use serde::ser; -#[derive(Serialize, Clone, Debug)] +#[derive(Debug, Clone)] pub struct StandardInfoAttr { pub created: WinTimestamp, pub modified: WinTimestamp, @@ -17,63 +16,91 @@ pub struct StandardInfoAttr { pub class_id: u32, pub owner_id: u32, pub security_id: u32, - #[serde(serialize_with = "serialize_u64")] pub quota: u64, - #[serde(serialize_with = "serialize_u64")] pub usn: u64 } impl StandardInfoAttr { - pub fn new(mut reader: R) -> Result { - let mut attribute: StandardInfoAttr = unsafe { - mem::zeroed() - }; + /// Parse a Standard Information attrbiute buffer. + /// + /// # Example + /// + /// Parse a raw buffer. + /// + /// ``` + /// use rustymft::attr_x10::StandardInfoAttr; + /// # fn test_standard_information() { + /// let attribute_buffer: &[u8] = &[ + /// 0x2F,0x6D,0xB6,0x6F,0x0C,0x97,0xCE,0x01,0x56,0xCD,0x1A,0x75,0x73,0xB5,0xCE,0x01, + /// 0x56,0xCD,0x1A,0x75,0x73,0xB5,0xCE,0x01,0x56,0xCD,0x1A,0x75,0x73,0xB5,0xCE,0x01, + /// 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /// 0x00,0x00,0x00,0x00,0xB0,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /// 0x68,0x58,0xA0,0x0A,0x02,0x00,0x00,0x00 + /// ]; + /// + /// let attribute = StandardInfoAttr::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.file_flags, 32); + /// assert_eq!(attribute.max_version, 0); + /// assert_eq!(attribute.version, 0); + /// assert_eq!(attribute.class_id, 0); + /// assert_eq!(attribute.security_id, 1456); + /// assert_eq!(attribute.quota, 0); + /// assert_eq!(attribute.usn, 8768215144); + /// # } + /// ``` + pub fn new(mut buffer: &[u8])->Result { + let created = WinTimestamp(buffer.read_u64::()?); + let modified = WinTimestamp(buffer.read_u64::()?); + let mft_modified = WinTimestamp(buffer.read_u64::()?); + let accessed = WinTimestamp(buffer.read_u64::()?); + let file_flags = buffer.read_u32::()?; + let max_version = buffer.read_u32::()?; + let version = buffer.read_u32::()?; + let class_id = buffer.read_u32::()?; + let owner_id = buffer.read_u32::()?; + let security_id = buffer.read_u32::()?; + let quota = buffer.read_u64::()?; + let usn = buffer.read_u64::()?; - attribute.created = WinTimestamp(reader.read_u64::()?); - attribute.modified = WinTimestamp(reader.read_u64::()?); - attribute.mft_modified = WinTimestamp(reader.read_u64::()?); - attribute.accessed = WinTimestamp(reader.read_u64::()?); - attribute.file_flags = reader.read_u32::()?; - attribute.max_version = reader.read_u32::()?; - attribute.version = reader.read_u32::()?; - attribute.class_id = reader.read_u32::()?; - attribute.owner_id = reader.read_u32::()?; - attribute.security_id = reader.read_u32::()?; - attribute.quota = reader.read_u64::()?; - attribute.usn = reader.read_u64::()?; - - Ok(attribute) + Ok( + StandardInfoAttr { + created: created, + modified: modified, + mft_modified: mft_modified, + accessed: accessed, + file_flags: file_flags, + max_version: max_version, + version: version, + class_id: class_id, + owner_id: owner_id, + security_id: security_id, + quota: quota, + usn: usn + } + ) } } -#[cfg(test)] -mod tests { - use super::StandardInfoAttr; - - #[test] - fn si_attribute_test_01() { - let attribute_buffer: &[u8] = &[ - 0x2F,0x6D,0xB6,0x6F,0x0C,0x97,0xCE,0x01,0x56,0xCD,0x1A,0x75,0x73,0xB5,0xCE,0x01, - 0x56,0xCD,0x1A,0x75,0x73,0xB5,0xCE,0x01,0x56,0xCD,0x1A,0x75,0x73,0xB5,0xCE,0x01, - 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xB0,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x68,0x58,0xA0,0x0A,0x02,0x00,0x00,0x00 - ]; - - let attribute = match StandardInfoAttr::new(attribute_buffer) { - Ok(attribute) => attribute, - Err(error) => panic!(error) - }; - - 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.file_flags, 32); - assert_eq!(attribute.max_version, 0); - assert_eq!(attribute.version, 0); - assert_eq!(attribute.class_id, 0); - assert_eq!(attribute.security_id, 1456); - assert_eq!(attribute.quota, 0); - assert_eq!(attribute.usn, 8768215144); +impl ser::Serialize for StandardInfoAttr { + fn serialize(&self, serializer: S) -> Result + where S: ser::Serializer + { + let mut state = serializer.serialize_struct("StandardInfoAttr", 5)?; + state.serialize_field("created", &format!("{}",&self.created))?; + state.serialize_field("modified", &format!("{}",&self.created))?; + state.serialize_field("mft_modified", &format!("{}",&self.created))?; + state.serialize_field("accessed", &format!("{}",&self.created))?; + state.serialize_field("file_flags", &self.file_flags)?; + state.serialize_field("max_version", &self.max_version)?; + state.serialize_field("class_id", &self.class_id)?; + state.serialize_field("owner_id", &self.owner_id)?; + state.serialize_field("security_id", &self.security_id)?; + state.serialize_field("quota", &format!("{}",&self.quota))?; + state.serialize_field("usn", &format!("{}",&self.usn))?; + state.end() } } diff --git a/src/attr_x30.rs b/src/attr_x30.rs index 9218156..2c722ac 100644 --- a/src/attr_x30.rs +++ b/src/attr_x30.rs @@ -1,23 +1,22 @@ use errors::{MftError}; use rwinstructs::timestamp::{WinTimestamp}; use rwinstructs::reference::{MftReference}; -use rwinstructs::serialize::{serialize_u64}; use byteorder::{ReadBytesExt, LittleEndian}; use encoding::{Encoding, DecoderTrap}; use encoding::all::UTF_16LE; use std::io::Read; use std::mem; +use serde::ser::SerializeStruct; +use serde::ser; -#[derive(Serialize, Clone, Debug)] +#[derive(Clone, Debug)] pub struct FileNameAttr { pub parent: MftReference, pub created: WinTimestamp, pub modified: WinTimestamp, pub mft_modified: WinTimestamp, pub accessed: WinTimestamp, - #[serde(serialize_with = "serialize_u64")] pub logical_size: u64, - #[serde(serialize_with = "serialize_u64")] pub physical_size: u64, pub flags: u32, pub reparse_value: u32, @@ -27,27 +26,60 @@ pub struct FileNameAttr { pub fullname: Option } impl FileNameAttr { - pub fn new(mut reader: R) -> Result { - let mut attribute: FileNameAttr = unsafe { - mem::zeroed() - }; - - attribute.parent = MftReference(reader.read_u64::()?); - attribute.created = WinTimestamp(reader.read_u64::()?); - attribute.modified = WinTimestamp(reader.read_u64::()?); - attribute.mft_modified = WinTimestamp(reader.read_u64::()?); - attribute.accessed = WinTimestamp(reader.read_u64::()?); - attribute.logical_size = reader.read_u64::()?; - attribute.physical_size = reader.read_u64::()?; - attribute.flags = reader.read_u32::()?; - attribute.reparse_value = reader.read_u32::()?; - attribute.name_length = reader.read_u8()?; - attribute.namespace = reader.read_u8()?; + /// Parse a Filename attrbiute buffer. + /// + /// # Example + /// + /// Parse a raw buffer. + /// + /// ``` + /// use rustymft::attr_x30::FileNameAttr; + /// # fn test_filename_attribute() { + /// let attribute_buffer: &[u8] = &[ + /// 0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0xD5,0x2D,0x48,0x58,0x43,0x5F,0xCE,0x01, + /// 0xD5,0x2D,0x48,0x58,0x43,0x5F,0xCE,0x01,0xD5,0x2D,0x48,0x58,0x43,0x5F,0xCE,0x01, + /// 0xD5,0x2D,0x48,0x58,0x43,0x5F,0xCE,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00, + /// 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + /// 0x08,0x03,0x24,0x00,0x4C,0x00,0x6F,0x00,0x67,0x00,0x46,0x00,0x69,0x00,0x6C,0x00, + /// 0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + /// ]; + /// + /// let attribute = match FileNameAttr::new(attribute_buffer) { + /// Ok(attribute) => attribute, + /// Err(error) => panic!(error) + /// }; + /// + /// 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.logical_size, 67108864); + /// assert_eq!(attribute.physical_size, 67108864); + /// assert_eq!(attribute.flags, 6); + /// assert_eq!(attribute.reparse_value, 0); + /// assert_eq!(attribute.name_length, 8); + /// assert_eq!(attribute.namespace, 3); + /// assert_eq!(attribute.name, "$LogFile"); + /// # } + /// ``` + pub fn new(mut buffer: &[u8]) -> Result { + let parent = MftReference(buffer.read_u64::()?); + let created = WinTimestamp(buffer.read_u64::()?); + let modified = WinTimestamp(buffer.read_u64::()?); + let mft_modified = WinTimestamp(buffer.read_u64::()?); + let accessed = WinTimestamp(buffer.read_u64::()?); + let logical_size = buffer.read_u64::()?; + let physical_size = buffer.read_u64::()?; + let flags = buffer.read_u32::()?; + let reparse_value = buffer.read_u32::()?; + let name_length = buffer.read_u8()?; + let namespace = buffer.read_u8()?; - let mut name_buffer = vec![0; (attribute.name_length as usize * 2) as usize]; - reader.read_exact(&mut name_buffer)?; + let mut name_buffer = vec![0; (name_length as usize * 2) as usize]; + buffer.read_exact(&mut name_buffer)?; - attribute.name = match UTF_16LE.decode(&name_buffer,DecoderTrap::Ignore){ + let name = match UTF_16LE.decode(&name_buffer,DecoderTrap::Ignore){ Ok(filename) => filename, Err(error) => return Err( MftError::decode_error( @@ -56,41 +88,54 @@ impl FileNameAttr { ) }; - Ok(attribute) + let fullname = None; + + Ok( + FileNameAttr { + parent: parent, + created: created, + modified: modified, + mft_modified: mft_modified, + accessed: accessed, + logical_size: logical_size, + physical_size: physical_size, + flags: flags, + reparse_value: reparse_value, + name_length: name_length, + namespace: namespace, + name: name, + fullname: fullname + } + ) } } -#[cfg(test)] -mod tests { - use super::FileNameAttr; +impl ser::Serialize for FileNameAttr { + fn serialize(&self, serializer: S) -> Result + where S: ser::Serializer + { + let mut state = serializer.serialize_struct("FileNameAttr", 13)?; - #[test] - fn fn_attribute_test_01() { - let attribute_buffer: &[u8] = &[ - 0x05,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0xD5,0x2D,0x48,0x58,0x43,0x5F,0xCE,0x01, - 0xD5,0x2D,0x48,0x58,0x43,0x5F,0xCE,0x01,0xD5,0x2D,0x48,0x58,0x43,0x5F,0xCE,0x01, - 0xD5,0x2D,0x48,0x58,0x43,0x5F,0xCE,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x08,0x03,0x24,0x00,0x4C,0x00,0x6F,0x00,0x67,0x00,0x46,0x00,0x69,0x00,0x6C,0x00, - 0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00 - ]; + state.serialize_field("parent",&self.parent)?; + state.serialize_field("created", &format!("{}",&self.created))?; + state.serialize_field("modified", &format!("{}",&self.modified))?; + state.serialize_field("mft_modified", &format!("{}",&self.mft_modified))?; + state.serialize_field("accessed", &self.accessed)?; + state.serialize_field("logical_size", &self.logical_size)?; + state.serialize_field("physical_size", &self.physical_size)?; + state.serialize_field("flags", &self.flags)?; + state.serialize_field("reparse_value", &self.reparse_value)?; + state.serialize_field("name_length", &self.name_length)?; + state.serialize_field("namespace", &self.namespace)?; + state.serialize_field("name", &format!("{}",&self.name))?; - let attribute = match FileNameAttr::new(attribute_buffer) { - Ok(attribute) => attribute, - Err(error) => panic!(error) - }; + match self.fullname { + Some(ref fullname) => { + state.serialize_field("fullname", &format!("{}",&fullname))?; + }, + None => {} + } - 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.logical_size, 67108864); - assert_eq!(attribute.physical_size, 67108864); - assert_eq!(attribute.flags, 6); - assert_eq!(attribute.reparse_value, 0); - assert_eq!(attribute.name_length, 8); - assert_eq!(attribute.namespace, 3); - assert_eq!(attribute.name, "$LogFile"); + state.end() } } -- cgit v1.2.3