diff options
author | Colin Finck <colin@reactos.org> | 2021-06-04 13:22:33 +0300 |
---|---|---|
committer | Colin Finck <colin@reactos.org> | 2021-06-04 13:22:33 +0300 |
commit | 777cbb028f22c73541f9340f6b94c5dd375f4384 (patch) | |
tree | 06ff5f99ba9fabcb76096ecee255ddcf1e40ce92 /src/structured_values/index_root.rs | |
parent | c3a4f05cfe3bf69d683c0c27a3f50f7b9af5a273 (diff) |
Add `NtfsIndexAllocation`, iterators for Index Records and Index Entries
This allows iterating through all nodes of an arbitrary index.
Tested with a filesystem that has 512 directories in the root.
Still lacks functions to traverse an index in-order or find an item efficiently.
Diffstat (limited to 'src/structured_values/index_root.rs')
-rw-r--r-- | src/structured_values/index_root.rs | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/src/structured_values/index_root.rs b/src/structured_values/index_root.rs index 26c7115..5a97cda 100644 --- a/src/structured_values/index_root.rs +++ b/src/structured_values/index_root.rs @@ -4,34 +4,67 @@ use crate::attribute::NtfsAttributeType; use crate::attribute_value::NtfsAttributeValue; use crate::error::{NtfsError, Result}; +use crate::index_entry::NtfsIndexEntries; +use crate::index_record::{IndexNodeHeader, INDEX_NODE_HEADER_SIZE}; use crate::structured_values::NewNtfsStructuredValue; -use binread::io::{Read, Seek}; +use crate::traits::NtfsReadSeek; +use binread::io::{Read, Seek, SeekFrom}; use binread::{BinRead, BinReaderExt}; /// Size of all [`IndexRootHeader`] fields plus some reserved bytes. -const INDEX_ROOT_HEADER_SIZE: u64 = 32; - -#[derive(BinRead, Clone, Debug)] -struct IndexHeader { - entries_offset: u32, - index_size: u32, - allocated_size: u32, - flags: u8, -} +const INDEX_ROOT_HEADER_SIZE: u64 = 16; #[derive(BinRead, Clone, Debug)] struct IndexRootHeader { ty: u32, collation_rule: u32, - index_block_size: u32, - clusters_per_index_block: i8, - reserved: [u8; 3], - index: IndexHeader, + index_record_size: u32, + clusters_per_index_record: i8, } #[derive(Clone, Debug)] -pub struct NtfsIndexRoot { - header: IndexRootHeader, +pub struct NtfsIndexRoot<'n> { + value: NtfsAttributeValue<'n>, + index_root_header: IndexRootHeader, + index_node_header: IndexNodeHeader, +} + +const LARGE_INDEX_FLAG: u8 = 0x01; + +impl<'n> NtfsIndexRoot<'n> { + pub fn index_allocated_size(&self) -> u32 { + self.index_node_header.allocated_size + } + + pub fn entries<K, T>(&self, fs: &mut T) -> Result<NtfsIndexEntries<'n, K>> + where + K: NewNtfsStructuredValue<'n>, + T: Read + Seek, + { + let offset = self.value.stream_position() + INDEX_ROOT_HEADER_SIZE as u64; + let start = offset + self.index_node_header.entries_offset as u64; + let end = offset + self.index_used_size() as u64; + + let mut value = self.value.clone(); + value.seek(fs, SeekFrom::Start(start))?; + + Ok(NtfsIndexEntries::new(value, end)) + } + + pub fn index_record_size(&self) -> u32 { + self.index_root_header.index_record_size + } + + pub fn index_used_size(&self) -> u32 { + self.index_node_header.index_size + } + + /// Returns whether the index belonging to this Index Root is large enough + /// to need an extra Index Allocation attribute. + /// Otherwise, the entire index information is stored in this Index Root. + pub fn is_large_index(&self) -> bool { + (self.index_node_header.flags & LARGE_INDEX_FLAG) != 0 + } } impl<'n> NewNtfsStructuredValue<'n> for NtfsIndexRoot<'n> { @@ -39,7 +72,7 @@ impl<'n> NewNtfsStructuredValue<'n> for NtfsIndexRoot<'n> { where T: Read + Seek, { - if value.len() < INDEX_ROOT_HEADER_SIZE { + if value.len() < INDEX_ROOT_HEADER_SIZE + INDEX_NODE_HEADER_SIZE { return Err(NtfsError::InvalidStructuredValueSize { position: value.data_position().unwrap(), ty: NtfsAttributeType::IndexRoot, @@ -49,8 +82,14 @@ impl<'n> NewNtfsStructuredValue<'n> for NtfsIndexRoot<'n> { } let mut value_attached = value.clone().attach(fs); - let header = value_attached.read_le::<IndexRootHeader>()?; + let index_root_header = value_attached.read_le::<IndexRootHeader>()?; + value_attached.seek(SeekFrom::Start(INDEX_ROOT_HEADER_SIZE))?; + let index_node_header = value_attached.read_le::<IndexNodeHeader>()?; - Ok(Self { header }) + Ok(Self { + value, + index_root_header, + index_node_header, + }) } } |