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/value/slice.rs')
-rw-r--r--src/value/slice.rs86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/value/slice.rs b/src/value/slice.rs
new file mode 100644
index 0000000..abfb0f9
--- /dev/null
+++ b/src/value/slice.rs
@@ -0,0 +1,86 @@
+// Copyright 2021 Colin Finck <colin@reactos.org>
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+//! This module implements a reader for a value that is already in memory and can therefore be accessed via a slice.
+//! This is the case for all resident attribute values and index record values.
+//! Such values are part of NTFS records. NTFS records can't be directly read from the filesystem, which is why they
+//! are always read into a buffer first and then fixed up in memory.
+//! Further accesses to the record data can then happen via slices.
+
+use binread::io::{Read, Seek, SeekFrom};
+
+use super::seek_contiguous;
+use crate::error::Result;
+use crate::traits::NtfsReadSeek;
+
+#[derive(Clone, Debug)]
+pub struct NtfsSliceValue<'f> {
+ data: &'f [u8],
+ position: u64,
+ stream_position: u64,
+}
+
+impl<'f> NtfsSliceValue<'f> {
+ pub(crate) fn new(data: &'f [u8], position: u64) -> Self {
+ Self {
+ data,
+ position,
+ stream_position: 0,
+ }
+ }
+
+ pub fn data(&self) -> &'f [u8] {
+ self.data
+ }
+
+ /// Returns the absolute current data seek position within the filesystem, in bytes.
+ /// This may be `None` if the current seek position is outside the valid range.
+ pub fn data_position(&self) -> Option<u64> {
+ if self.stream_position < self.len() {
+ Some(self.position + self.stream_position)
+ } else {
+ None
+ }
+ }
+
+ pub fn len(&self) -> u64 {
+ self.data.len() as u64
+ }
+
+ fn remaining_len(&self) -> u64 {
+ self.len().saturating_sub(self.stream_position)
+ }
+}
+
+impl<'f> NtfsReadSeek for NtfsSliceValue<'f> {
+ fn read<T>(&mut self, _fs: &mut T, buf: &mut [u8]) -> Result<usize>
+ where
+ T: Read + Seek,
+ {
+ if self.remaining_len() == 0 {
+ return Ok(0);
+ }
+
+ let bytes_to_read = usize::min(buf.len(), self.remaining_len() as usize);
+ let work_slice = &mut buf[..bytes_to_read];
+
+ let start = self.stream_position as usize;
+ let end = start + bytes_to_read;
+ work_slice.copy_from_slice(&self.data[start..end]);
+
+ self.stream_position += bytes_to_read as u64;
+ Ok(bytes_to_read)
+ }
+
+ fn seek<T>(&mut self, _fs: &mut T, pos: SeekFrom) -> Result<u64>
+ where
+ T: Read + Seek,
+ {
+ let length = self.len();
+ seek_contiguous(&mut self.stream_position, length, pos)
+ }
+
+ fn stream_position(&self) -> u64 {
+ self.stream_position
+ }
+}