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 13:22:33 +0300
committerColin Finck <colin@reactos.org>2021-06-04 13:22:33 +0300
commit777cbb028f22c73541f9340f6b94c5dd375f4384 (patch)
tree06ff5f99ba9fabcb76096ecee255ddcf1e40ce92 /src/structured_values/index_root.rs
parentc3a4f05cfe3bf69d683c0c27a3f50f7b9af5a273 (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.rs77
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,
+ })
}
}