diff options
author | Colin Finck <colin@reactos.org> | 2021-06-04 12:46:52 +0300 |
---|---|---|
committer | Colin Finck <colin@reactos.org> | 2021-06-04 12:46:52 +0300 |
commit | cba70d68b52025dda25d07e516d27ca7c73b607f (patch) | |
tree | 8e1b59d70ff04a8cf99e9f0be7406cc9ab47857f /src/structured_values/file_name.rs | |
parent | 98ffe4dec521551bb1b0ae904d730d360d3673eb (diff) |
Make all structured values ready for indexes and non-resident attributes
This introduces a `NewNtfsStructuredValue` trait for the `new` function of all structured values.
Indexes later need that to return the structured value specified by a type parameter.
We also have to pass an explicit length and can't just rely on the end of the passed `NtfsAttributeValue`/`NtfsAttributeValueAttached`.
For structured values of non-resident attributes, we have to store an `NtfsAttributeValue` instead of an absolute byte position, in order to let a structured value read additional data (e.g. the name of an `NtfsFileName`).
The `NtfsAttributeValue` properly moves between data runs while reading.
Diffstat (limited to 'src/structured_values/file_name.rs')
-rw-r--r-- | src/structured_values/file_name.rs | 85 |
1 files changed, 50 insertions, 35 deletions
diff --git a/src/structured_values/file_name.rs b/src/structured_values/file_name.rs index 06e3d2a..963896c 100644 --- a/src/structured_values/file_name.rs +++ b/src/structured_values/file_name.rs @@ -2,21 +2,21 @@ // SPDX-License-Identifier: GPL-2.0-or-later use crate::attribute::NtfsAttributeType; -use crate::attribute_value::NtfsAttributeValueAttached; +use crate::attribute_value::NtfsAttributeValue; use crate::error::{NtfsError, Result}; use crate::string::NtfsString; -use crate::structured_values::NtfsFileAttributeFlags; +use crate::structured_values::{NewNtfsStructuredValue, NtfsFileAttributeFlags}; use crate::time::NtfsTime; -use binread::io::{Read, Seek}; +use binread::io::{Read, Seek, SeekFrom}; use binread::{BinRead, BinReaderExt}; use core::mem; use enumn::N; /// Size of all [`FileNameHeader`] fields. -const FILE_NAME_HEADER_SIZE: u64 = 66; +const FILE_NAME_HEADER_SIZE: i64 = 66; /// The smallest FileName attribute has a name containing just a single character. -const FILE_NAME_MIN_SIZE: u64 = FILE_NAME_HEADER_SIZE + mem::size_of::<u16>() as u64; +const FILE_NAME_MIN_SIZE: u64 = FILE_NAME_HEADER_SIZE as u64 + mem::size_of::<u16>() as u64; #[allow(unused)] #[derive(BinRead, Clone, Debug)] @@ -44,37 +44,12 @@ pub enum NtfsFileNamespace { } #[derive(Clone, Debug)] -pub struct NtfsFileName { +pub struct NtfsFileName<'n> { header: FileNameHeader, - name_position: u64, + value: NtfsAttributeValue<'n>, } -impl NtfsFileName { - pub(crate) fn new<T>( - attribute_position: u64, - mut value_attached: NtfsAttributeValueAttached<'_, '_, T>, - ) -> Result<Self> - where - T: Read + Seek, - { - if value_attached.len() < FILE_NAME_MIN_SIZE { - return Err(NtfsError::InvalidAttributeSize { - position: attribute_position, - ty: NtfsAttributeType::FileName, - expected: FILE_NAME_MIN_SIZE, - actual: value_attached.len(), - }); - } - - let header = value_attached.read_le::<FileNameHeader>()?; - let name_position = value_attached.position() + FILE_NAME_HEADER_SIZE; - - Ok(Self { - header, - name_position, - }) - } - +impl<'n> NtfsFileName<'n> { pub fn access_time(&self) -> NtfsTime { self.header.access_time } @@ -114,7 +89,7 @@ impl NtfsFileName { /// if it's an unknown namespace. pub fn namespace(&self) -> Result<NtfsFileNamespace> { NtfsFileNamespace::n(self.header.namespace).ok_or(NtfsError::UnsupportedNtfsFileNamespace { - position: self.name_position, + position: self.value.data_position().unwrap(), actual: self.header.namespace, }) } @@ -125,7 +100,47 @@ impl NtfsFileName { where T: Read + Seek, { - NtfsString::read_from_fs(fs, self.name_position, self.name_length(), buf) + let mut value_attached = self.value.clone().attach(fs); + value_attached.seek(SeekFrom::Current(FILE_NAME_HEADER_SIZE))?; + NtfsString::from_reader(value_attached, self.name_length(), buf) + } + + fn validate_name_length(&self, length: u64) -> Result<()> { + let total_size = FILE_NAME_HEADER_SIZE as u64 + self.name_length() as u64; + + if total_size > length { + return Err(NtfsError::InvalidStructuredValueSize { + position: self.value.data_position().unwrap(), + ty: NtfsAttributeType::FileName, + expected: length, + actual: total_size, + }); + } + + Ok(()) + } +} + +impl<'n> NewNtfsStructuredValue<'n> for NtfsFileName<'n> { + fn new<T>(fs: &mut T, value: NtfsAttributeValue<'n>, length: u64) -> Result<Self> + where + T: Read + Seek, + { + if length < FILE_NAME_MIN_SIZE { + return Err(NtfsError::InvalidStructuredValueSize { + position: value.data_position().unwrap(), + ty: NtfsAttributeType::FileName, + expected: FILE_NAME_MIN_SIZE, + actual: length, + }); + } + + let mut value_attached = value.clone().attach(fs); + let header = value_attached.read_le::<FileNameHeader>()?; + let file_name = Self { header, value }; + file_name.validate_name_length(length)?; + + Ok(file_name) } } |