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

github.com/windirstat/ntfs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Finck <colin@reactos.org>2021-06-04 12:46:52 +0300
committerColin Finck <colin@reactos.org>2021-06-04 12:46:52 +0300
commitcba70d68b52025dda25d07e516d27ca7c73b607f (patch)
tree8e1b59d70ff04a8cf99e9f0be7406cc9ab47857f /src/structured_values/file_name.rs
parent98ffe4dec521551bb1b0ae904d730d360d3673eb (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.rs85
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)
}
}