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:
Diffstat (limited to 'src/structured_values/file_name.rs')
-rw-r--r--src/structured_values/file_name.rs142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/structured_values/file_name.rs b/src/structured_values/file_name.rs
new file mode 100644
index 0000000..19f50cc
--- /dev/null
+++ b/src/structured_values/file_name.rs
@@ -0,0 +1,142 @@
+// 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::string::NtfsString;
+use crate::structured_values::NtfsFileAttributeFlags;
+use crate::time::NtfsTime;
+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;
+
+/// 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;
+
+#[allow(unused)]
+#[derive(BinRead, Clone, Debug)]
+struct FileNameHeader {
+ parent_directory_ref: u64,
+ creation_time: NtfsTime,
+ modification_time: NtfsTime,
+ mft_record_modification_time: NtfsTime,
+ access_time: NtfsTime,
+ allocated_size: u64,
+ data_size: u64,
+ file_attributes: u32,
+ reparse_point_tag: u32,
+ name_length: u8,
+ namespace: u8,
+}
+
+#[derive(Clone, Copy, Debug, Eq, N, PartialEq)]
+#[repr(u8)]
+pub enum NtfsFileNamespace {
+ Posix = 0,
+ Win32 = 1,
+ Dos = 2,
+ Win32AndDos = 3,
+}
+
+#[derive(Clone, Debug)]
+pub struct NtfsFileName {
+ header: FileNameHeader,
+ name_position: u64,
+}
+
+impl NtfsFileName {
+ 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 < FILE_NAME_MIN_SIZE {
+ return Err(NtfsError::InvalidAttributeSize {
+ position: attribute_position,
+ ty: NtfsAttributeType::FileName,
+ expected: FILE_NAME_MIN_SIZE,
+ actual: value_length,
+ });
+ }
+
+ let header = value_attached.read_le::<FileNameHeader>()?;
+ let name_position = value_attached.position() + FILE_NAME_HEADER_SIZE;
+
+ Ok(Self {
+ header,
+ name_position,
+ })
+ }
+
+ pub fn access_time(&self) -> NtfsTime {
+ self.header.access_time
+ }
+
+ pub fn allocated_size(&self) -> u64 {
+ self.header.allocated_size
+ }
+
+ pub fn creation_time(&self) -> NtfsTime {
+ self.header.creation_time
+ }
+
+ pub fn data_size(&self) -> u64 {
+ self.header.data_size
+ }
+
+ pub fn file_attributes(&self) -> NtfsFileAttributeFlags {
+ NtfsFileAttributeFlags::from_bits_truncate(self.header.file_attributes)
+ }
+
+ pub fn mft_record_modification_time(&self) -> NtfsTime {
+ self.header.mft_record_modification_time
+ }
+
+ pub fn modification_time(&self) -> NtfsTime {
+ self.header.modification_time
+ }
+
+ /// Returns the file name length, in bytes.
+ ///
+ /// A file name has a maximum length of 255 UTF-16 code points (510 bytes).
+ pub fn name_length(&self) -> usize {
+ self.header.name_length as usize * mem::size_of::<u16>()
+ }
+
+ /// Returns the namespace this name belongs to, or [`NtfsError::UnsupportedNtfsFileNamespace`]
+ /// 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,
+ actual: self.header.namespace,
+ })
+ }
+
+ /// Reads the file name into the given buffer, and returns an
+ /// [`NtfsString`] wrapping that buffer.
+ pub fn read_name<'a, T>(&self, fs: &mut T, buf: &'a mut [u8]) -> Result<NtfsString<'a>>
+ where
+ T: Read + Seek,
+ {
+ let name_length = self.name_length();
+ if buf.len() < name_length {
+ return Err(NtfsError::BufferTooSmall {
+ expected: name_length,
+ actual: buf.len(),
+ });
+ }
+
+ fs.seek(SeekFrom::Start(self.name_position))?;
+ fs.read_exact(&mut buf[..name_length])?;
+
+ Ok(NtfsString(&buf[..name_length]))
+ }
+}