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/attribute_value.rs')
-rw-r--r--src/attribute_value.rs59
1 files changed, 29 insertions, 30 deletions
diff --git a/src/attribute_value.rs b/src/attribute_value.rs
index 9516eaa..a41f1ca 100644
--- a/src/attribute_value.rs
+++ b/src/attribute_value.rs
@@ -4,6 +4,7 @@
use crate::error::{NtfsError, Result};
use crate::ntfs::Ntfs;
use crate::traits::NtfsReadSeek;
+use crate::types::Lcn;
use binread::io;
use binread::io::{Read, Seek, SeekFrom};
use binread::BinReaderExt;
@@ -132,12 +133,13 @@ impl NtfsDataRun {
}
}
- pub(crate) fn from_lcn_info(ntfs: &Ntfs, lcn_position: i64, lcn_count: u64) -> Self {
- debug_assert!(lcn_position >= 0);
- let position = lcn_position as u64 * ntfs.cluster_size() as u64;
- let length = lcn_count * ntfs.cluster_size() as u64;
+ pub(crate) fn from_lcn_info(ntfs: &Ntfs, lcn: Lcn, cluster_count: u64) -> Result<Self> {
+ let position = lcn.position(ntfs)?;
+ let length = cluster_count
+ .checked_mul(ntfs.cluster_size() as u64)
+ .ok_or(NtfsError::InvalidClusterCount { cluster_count })?;
- Self::from_byte_info(position, length)
+ Ok(Self::from_byte_info(position, length))
}
pub fn data_position(&self) -> u64 {
@@ -220,7 +222,7 @@ impl NtfsReadSeek for NtfsDataRun {
pub struct NtfsDataRuns<'n> {
ntfs: &'n Ntfs,
data_runs_range: Range<u64>,
- previous_lcn_position: i64,
+ previous_lcn: Lcn,
}
impl<'n> NtfsDataRuns<'n> {
@@ -228,7 +230,7 @@ impl<'n> NtfsDataRuns<'n> {
Self {
ntfs,
data_runs_range,
- previous_lcn_position: 0,
+ previous_lcn: Lcn::from(0),
}
}
@@ -259,35 +261,32 @@ impl<'n> NtfsDataRuns<'n> {
return None;
}
- // The lower nibble indicates the length of the following LCN count variable length integer.
- let lcn_count_byte_count = header & 0x0f;
- let lcn_count =
- iter_try!(self.read_variable_length_unsigned_integer(fs, lcn_count_byte_count));
- size += lcn_count_byte_count as u64;
-
- // The upper nibble indicates the length of the following LCN offset variable length integer.
- let lcn_offset_byte_count = (header & 0xf0) >> 4;
- let lcn_offset =
- iter_try!(self.read_variable_length_signed_integer(fs, lcn_offset_byte_count));
- size += lcn_offset_byte_count as u64;
-
- // The read LCN offset is relative to the previous one.
- // Turn it into an absolute one.
- let lcn_position = self.previous_lcn_position + lcn_offset;
- if lcn_position < 0 {
- return Some(Err(NtfsError::InvalidLcnPositionInDataRunHeader {
- position: self.data_runs_range.start,
- lcn_position,
- }));
- }
+ // The lower nibble indicates the length of the following cluster count variable length integer.
+ let cluster_count_byte_count = header & 0x0f;
+ let cluster_count =
+ iter_try!(self.read_variable_length_unsigned_integer(fs, cluster_count_byte_count));
+ size += cluster_count_byte_count as u64;
+
+ // The upper nibble indicates the length of the following VCN variable length integer.
+ let vcn_byte_count = (header & 0xf0) >> 4;
+ let vcn = iter_try!(self.read_variable_length_signed_integer(fs, vcn_byte_count)).into();
+ size += vcn_byte_count as u64;
- self.previous_lcn_position = lcn_position;
+ // Turn the read VCN into an absolute LCN.
+ let lcn = iter_try!(self.previous_lcn.checked_add(vcn).ok_or({
+ NtfsError::InvalidVcnInDataRunHeader {
+ position: self.data_runs_range.start,
+ vcn,
+ previous_lcn: self.previous_lcn,
+ }
+ }));
+ self.previous_lcn = lcn;
// Only increment `self.data_runs_range.start` after having checked for success.
// In case of an error, a subsequent call shall output the same error again.
self.data_runs_range.start += size;
- let data_run = NtfsDataRun::from_lcn_info(self.ntfs, lcn_position, lcn_count);
+ let data_run = iter_try!(NtfsDataRun::from_lcn_info(self.ntfs, lcn, cluster_count));
Some(Ok(data_run))
}