diff options
Diffstat (limited to 'src/index_record.rs')
-rw-r--r-- | src/index_record.rs | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/src/index_record.rs b/src/index_record.rs index d73827d..016727a 100644 --- a/src/index_record.rs +++ b/src/index_record.rs @@ -35,6 +35,17 @@ pub(crate) struct IndexNodeHeader { pub(crate) flags: u8, } +/// A single NTFS Index Record. +/// +/// These records are denoted via an `INDX` signature on the filesystem. +/// +/// NTFS uses B-tree indexes to quickly look up directories, Object IDs, Reparse Points, Security Descriptors, etc. +/// An Index Record is further comprised of Index Entries, which contain the actual key/data (see [`NtfsIndexEntry`], +/// iterated via [`NtfsIndexNodeEntries`]). +/// +/// [`NtfsIndexEntry`]: crate::NtfsIndexEntry +/// +/// Reference: <https://flatcap.github.io/linux-ntfs/ntfs/concepts/index_record.html> #[derive(Debug)] pub struct NtfsIndexRecord<'n> { record: Record<'n>, @@ -69,6 +80,9 @@ impl<'n> NtfsIndexRecord<'n> { Ok(index_record) } + /// Returns an iterator over all entries of this Index Record (cf. [`NtfsIndexEntry`]). + /// + /// [`NtfsIndexEntry`]: crate::NtfsIndexEntry pub fn entries<'r, E>(&'r self) -> Result<NtfsIndexNodeEntries<'r, E>> where E: NtfsIndexEntryType, @@ -81,7 +95,7 @@ impl<'n> NtfsIndexRecord<'n> { fn entries_range_and_position(&self) -> (Range<usize>, u64) { let start = INDEX_RECORD_HEADER_SIZE as usize + self.index_entries_offset() as usize; - let end = INDEX_RECORD_HEADER_SIZE as usize + self.index_used_size() as usize; + let end = INDEX_RECORD_HEADER_SIZE as usize + self.index_data_size() as usize; let position = self.record.position() + start as u64; (start..end, position) @@ -95,18 +109,20 @@ impl<'n> NtfsIndexRecord<'n> { (flags & HAS_SUBNODES_FLAG) != 0 } + /// Returns the allocated size of this NTFS Index Record, in bytes. pub fn index_allocated_size(&self) -> u32 { let start = INDEX_RECORD_HEADER_SIZE as usize + offset_of!(IndexNodeHeader, allocated_size); LittleEndian::read_u32(&self.record.data()[start..]) } - pub(crate) fn index_entries_offset(&self) -> u32 { - let start = INDEX_RECORD_HEADER_SIZE as usize + offset_of!(IndexNodeHeader, entries_offset); + /// Returns the size actually used by index data within this NTFS Index Record, in bytes. + pub fn index_data_size(&self) -> u32 { + let start = INDEX_RECORD_HEADER_SIZE as usize + offset_of!(IndexNodeHeader, index_size); LittleEndian::read_u32(&self.record.data()[start..]) } - pub fn index_used_size(&self) -> u32 { - let start = INDEX_RECORD_HEADER_SIZE as usize + offset_of!(IndexNodeHeader, index_size); + pub(crate) fn index_entries_offset(&self) -> u32 { + let start = INDEX_RECORD_HEADER_SIZE as usize + offset_of!(IndexNodeHeader, entries_offset); LittleEndian::read_u32(&self.record.data()[start..]) } @@ -136,7 +152,7 @@ impl<'n> NtfsIndexRecord<'n> { fn validate_sizes(&self) -> Result<()> { let index_record_size = self.record.len() as u32; - // The total size allocated for this index record must not be larger than + // The total size allocated for this Index Record must not be larger than // the size defined for all index records of this index. let total_allocated_size = INDEX_RECORD_HEADER_SIZE + self.index_allocated_size(); if total_allocated_size > index_record_size { @@ -147,20 +163,26 @@ impl<'n> NtfsIndexRecord<'n> { }); } - // Furthermore, the total used size for this index record must not be + // Furthermore, the total used size for this Index Record must not be // larger than the total allocated size. - let total_used_size = INDEX_RECORD_HEADER_SIZE + self.index_used_size(); - if total_used_size > total_allocated_size { + let total_data_size = INDEX_RECORD_HEADER_SIZE + self.index_data_size(); + if total_data_size > total_allocated_size { return Err(NtfsError::InvalidIndexUsedSize { position: self.record.position(), expected: total_allocated_size, - actual: total_used_size, + actual: total_data_size, }); } Ok(()) } + /// Returns the Virtual Cluster Number (VCN) of this Index Record, as reported by the header of this Index Record. + /// + /// This can be used to double-check that an Index Record is the actually requested one. + /// [`NtfsIndexAllocation::record_from_vcn`] uses it for that purpose. + /// + /// [`NtfsIndexAllocation::record_from_vcn`]: crate::structured_values::NtfsIndexAllocation::record_from_vcn pub fn vcn(&self) -> Vcn { let start = offset_of!(IndexRecordHeader, vcn); Vcn::from(LittleEndian::read_i64(&self.record.data()[start..])) |