diff options
Diffstat (limited to 'src/attribute/mod.rs')
-rw-r--r-- | src/attribute/mod.rs | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/src/attribute/mod.rs b/src/attribute/mod.rs index 8ac11ce..481d69c 100644 --- a/src/attribute/mod.rs +++ b/src/attribute/mod.rs @@ -10,6 +10,8 @@ pub mod x90; use crate::err::Result; use crate::{impl_serialize_for_bitflags, ReadSeek}; +use std::io::Cursor; + use bitflags::bitflags; use crate::attribute::raw::RawAttribute; @@ -39,9 +41,26 @@ impl MftAttributeContent { MftAttributeType::StandardInformation => Ok(MftAttributeContent::AttrX10( StandardInfoAttr::from_reader(stream)?, )), - MftAttributeType::AttributeList => Ok(MftAttributeContent::AttrX20( - AttributeListAttr::from_stream(stream)?, - )), + MftAttributeType::AttributeList => { + // An attribute list is a buffer of attribute entries which are varying sizes if + // the attributes contain names. Thus, we must know when to stop reading. To + // do this, we will create a buffer of the attribute, and stop reading attribute + // entries when we reach the end of the buffer. + let content_size = resident.data_size; + + let mut attribute_buffer = vec![0; content_size as usize]; + stream.read_exact(&mut attribute_buffer)?; + + // Create a new stream that the attribute will read from. + let mut new_stream = Cursor::new(attribute_buffer); + + let attr_list = AttributeListAttr::from_stream( + &mut new_stream, + Some(content_size as u64) + )?; + + Ok(MftAttributeContent::AttrX20(attr_list)) + }, MftAttributeType::FileName => Ok(MftAttributeContent::AttrX30( FileNameAttr::from_stream(stream)?, )), @@ -67,6 +86,14 @@ impl MftAttributeContent { } } + /// Converts the given attributes into a 'AttributeListAttr', consuming the object attribute object. + pub fn into_attribute_list(self) -> Option<AttributeListAttr> { + match self { + MftAttributeContent::AttrX20(content) => Some(content), + _ => None, + } + } + /// Converts the given attributes into a `IndexRootAttr`, consuming the object attribute object. pub fn into_index_root(self) -> Option<IndexRootAttr> { match self { @@ -109,11 +136,11 @@ impl MftAttributeContent { #[serde(untagged)] pub enum MftAttributeContent { Raw(RawAttribute), - AttrX80(DataAttr), AttrX10(StandardInfoAttr), AttrX20(AttributeListAttr), AttrX30(FileNameAttr), AttrX40(ObjectIdAttr), + AttrX80(DataAttr), AttrX90(IndexRootAttr), /// Empty - used when data is non resident. None, @@ -158,10 +185,15 @@ pub enum MftAttributeType { } bitflags! { + /// Flag sources: + /// https://github.com/EricZimmerman/MFT/blob/3bed2626ee85e9a96a6db70a17407d0c3696056a/MFT/Attributes/StandardInfo.cs#L10 + /// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/ca28ec38-f155-4768-81d6-4bfeb8586fc9 + /// pub struct FileAttributeFlags: u32 { const FILE_ATTRIBUTE_READONLY = 0x0000_0001; const FILE_ATTRIBUTE_HIDDEN = 0x0000_0002; const FILE_ATTRIBUTE_SYSTEM = 0x0000_0004; + const FILE_ATTRIBUTE_DIRECTORY = 0x0000_0010; const FILE_ATTRIBUTE_ARCHIVE = 0x0000_0020; const FILE_ATTRIBUTE_DEVICE = 0x0000_0040; const FILE_ATTRIBUTE_NORMAL = 0x0000_0080; @@ -172,6 +204,11 @@ bitflags! { const FILE_ATTRIBUTE_OFFLINE = 0x0000_1000; const FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x0000_2000; const FILE_ATTRIBUTE_ENCRYPTED = 0x0000_4000; + const FILE_ATTRIBUTE_INTEGRITY_STREAM = 0x0000_8000; + const FILE_ATTRIBUTE_NO_SCRUB_DATA = 0x0002_0000; + const FILE_ATTRIBUTE_HAS_EA = 0x0004_0000; + const FILE_ATTRIBUTE_IS_DIRECTORY = 0x1000_0000; + const FILE_ATTRIBUTE_INDEX_VIEW = 0x2000_0000; } } |