diff options
author | Colin Finck <colin@reactos.org> | 2021-04-21 22:40:33 +0300 |
---|---|---|
committer | Colin Finck <colin@reactos.org> | 2021-04-21 22:40:33 +0300 |
commit | 11be5cf34e0b455a4677c3eb8cf72032ac97fbe6 (patch) | |
tree | b59bac06904c224e54619736de27afe30c72d443 | |
parent | c815c5e771eb9f29291594c25ee247b365adcd68 (diff) |
Implement the `NtfsObjectId` structured value along with `NtfsGuid`.
-rw-r--r-- | src/attribute.rs | 9 | ||||
-rw-r--r-- | src/guid.rs | 53 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/structured_values/mod.rs | 1 | ||||
-rw-r--r-- | src/structured_values/object_id.rs | 75 |
5 files changed, 138 insertions, 2 deletions
diff --git a/src/attribute.rs b/src/attribute.rs index dd56811..9be8ebe 100644 --- a/src/attribute.rs +++ b/src/attribute.rs @@ -5,7 +5,9 @@ use crate::attribute_value::{NtfsAttributeResidentValue, NtfsAttributeValue}; use crate::error::{NtfsError, Result}; use crate::ntfs_file::NtfsFile; use crate::string::NtfsString; -use crate::structured_values::{NtfsFileName, NtfsStandardInformation, NtfsStructuredValue}; +use crate::structured_values::{ + NtfsFileName, NtfsObjectId, NtfsStandardInformation, NtfsStructuredValue, +}; use binread::io::{Read, Seek, SeekFrom}; use binread::{BinRead, BinReaderExt}; use bitflags::bitflags; @@ -246,7 +248,10 @@ impl NtfsAttribute { let inner = NtfsFileName::new(self.position, attached_value, self.value_length())?; Ok(NtfsStructuredValue::FileName(inner)) } - NtfsAttributeType::ObjectId => panic!("TODO"), + NtfsAttributeType::ObjectId => { + let inner = NtfsObjectId::new(self.position, attached_value, self.value_length())?; + Ok(NtfsStructuredValue::ObjectId(inner)) + } NtfsAttributeType::SecurityDescriptor => panic!("TODO"), NtfsAttributeType::VolumeName => panic!("TODO"), NtfsAttributeType::VolumeInformation => panic!("TODO"), diff --git a/src/guid.rs b/src/guid.rs new file mode 100644 index 0000000..4deee30 --- /dev/null +++ b/src/guid.rs @@ -0,0 +1,53 @@ +// Copyright 2021 Colin Finck <colin@reactos.org> +// SPDX-License-Identifier: GPL-2.0-or-later + +use binread::BinRead; +use core::fmt; + +/// Size of a single GUID on disk (= size of all GUID fields). +pub(crate) const GUID_SIZE: u64 = 16; + +#[derive(BinRead, Clone, Debug, Eq, PartialEq)] +pub struct NtfsGuid { + pub data1: u32, + pub data2: u16, + pub data3: u16, + pub data4: [u8; 8], +} + +impl fmt::Display for NtfsGuid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{:8X}-{:4X}-{:4X}-{:2X}{:2X}-{:2X}{:2X}{:2X}{:2X}{:2X}{:2X}", + self.data1, + self.data2, + self.data3, + self.data4[0], + self.data4[1], + self.data4[2], + self.data4[3], + self.data4[4], + self.data4[5], + self.data4[6], + self.data4[7] + ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_guid() { + let guid = NtfsGuid { + data1: 0x67c8770b, + data2: 0x44f1, + data3: 0x410a, + data4: [0xab, 0x9a, 0xf9, 0xb5, 0x44, 0x6f, 0x13, 0xee], + }; + let guid_string = guid.to_string(); + assert_eq!(guid_string, "67C8770B-44F1-410A-AB9A-F9B5446F13EE"); + } +} @@ -13,6 +13,7 @@ mod attribute; mod attribute_value; mod boot_sector; mod error; +mod guid; mod ntfs; mod ntfs_file; mod string; @@ -22,6 +23,7 @@ mod time; pub use crate::attribute::*; pub use crate::attribute_value::*; pub use crate::error::*; +pub use crate::guid::*; pub use crate::ntfs::*; pub use crate::ntfs_file::*; pub use crate::string::*; diff --git a/src/structured_values/mod.rs b/src/structured_values/mod.rs index df4aa90..4a18d91 100644 --- a/src/structured_values/mod.rs +++ b/src/structured_values/mod.rs @@ -41,4 +41,5 @@ bitflags! { pub enum NtfsStructuredValue { StandardInformation(NtfsStandardInformation), FileName(NtfsFileName), + ObjectId(NtfsObjectId), } diff --git a/src/structured_values/object_id.rs b/src/structured_values/object_id.rs index 53769a7..adc96c8 100644 --- a/src/structured_values/object_id.rs +++ b/src/structured_values/object_id.rs @@ -1,2 +1,77 @@ // Copyright 2021 Colin Finck <colin@reactos.org> // SPDX-License-Identifier: GPL-2.0-or-later + +use crate::attribute::NtfsAttributeType; +use crate::attribute_value::NtfsAttributeValueAttached; +use crate::error::{NtfsError, Result}; +use crate::guid::{NtfsGuid, GUID_SIZE}; +use binread::io::{Read, Seek}; +use binread::BinReaderExt; + +#[derive(Clone, Debug)] +pub struct NtfsObjectId { + object_id: NtfsGuid, + birth_volume_id: Option<NtfsGuid>, + birth_object_id: Option<NtfsGuid>, + domain_id: Option<NtfsGuid>, +} + +impl NtfsObjectId { + pub(crate) fn new<T>( + attribute_position: u64, + mut value_attached: NtfsAttributeValueAttached<'_, T>, + value_length: u64, + ) -> Result<Self> + where + T: Read + Seek, + { + if value_length < GUID_SIZE { + return Err(NtfsError::InvalidAttributeSize { + position: attribute_position, + ty: NtfsAttributeType::ObjectId, + expected: GUID_SIZE, + actual: value_length, + }); + } + + let object_id = value_attached.read_le::<NtfsGuid>()?; + + let mut birth_volume_id = None; + if value_length >= 2 * GUID_SIZE { + birth_volume_id = Some(value_attached.read_le::<NtfsGuid>()?); + } + + let mut birth_object_id = None; + if value_length >= 3 * GUID_SIZE { + birth_object_id = Some(value_attached.read_le::<NtfsGuid>()?); + } + + let mut domain_id = None; + if value_length >= 4 * GUID_SIZE { + domain_id = Some(value_attached.read_le::<NtfsGuid>()?); + } + + Ok(Self { + object_id, + birth_volume_id, + birth_object_id, + domain_id, + }) + } + + pub fn birth_object_id(&self) -> Option<&NtfsGuid> { + self.birth_object_id.as_ref() + } + + pub fn birth_volume_id(&self) -> Option<&NtfsGuid> { + self.birth_volume_id.as_ref() + } + + pub fn domain_id(&self) -> Option<&NtfsGuid> { + self.domain_id.as_ref() + } + + pub fn object_id(&self) -> &NtfsGuid { + &self.object_id + } +} |