mod common;
use fast_ntfs::{Ntfs, NtfsAttributeType, NtfsError};
const FILE_RECORD_DATA_SIZE_OFFSET: usize = 24;
fn truncate_root_record_after_first_attribute(
extra_bytes: u32,
) -> (Ntfs, std::io::Cursor<Vec<u8>>) {
let mut fs = common::testfs1();
let ntfs = Ntfs::new(&mut fs).unwrap();
let root = ntfs.root_directory(&mut fs).unwrap();
let root_position = root.position().value().unwrap().get() as usize;
let first_attribute = root.attributes_raw().next().unwrap().unwrap();
let first_attribute_end = first_attribute.position().value().unwrap().get()
- root.position().value().unwrap().get()
+ first_attribute.attribute_length() as u64;
let data_size = u32::try_from(first_attribute_end).unwrap() + extra_bytes;
fs.get_mut()[root_position + FILE_RECORD_DATA_SIZE_OFFSET
..root_position + FILE_RECORD_DATA_SIZE_OFFSET + size_of::<u32>()]
.copy_from_slice(&data_size.to_le_bytes());
(ntfs, fs)
}
#[test]
fn flattened_attribute_iterator_is_fused_after_completion() {
let mut fs = common::testfs1();
let ntfs = Ntfs::new(&mut fs).unwrap();
let root_directory = ntfs.root_directory(&mut fs).unwrap();
let mut attributes = root_directory.attributes();
let mut types = Vec::new();
while let Some(item) = attributes.next(&mut fs) {
types.push(item.unwrap().to_attribute().unwrap().ty().unwrap());
}
assert!(types.contains(&NtfsAttributeType::StandardInformation));
assert!(types.contains(&NtfsAttributeType::IndexRoot));
assert!(attributes.next(&mut fs).is_none());
assert!(attributes.next(&mut fs).is_none());
}
#[test]
fn raw_attributes_stop_when_less_than_a_type_field_remains() {
let (ntfs, mut fs) = truncate_root_record_after_first_attribute(2);
let root = ntfs.root_directory(&mut fs).unwrap();
let mut attributes = root.attributes_raw();
assert!(attributes.next().unwrap().is_ok());
assert!(attributes.next().is_none());
assert!(attributes.next().is_none());
}
#[test]
fn raw_attributes_reject_an_attribute_past_the_used_record_size() {
let mut fs = common::testfs1();
let ntfs = Ntfs::new(&mut fs).unwrap();
let (root_position, first_attribute_offset) = {
let root = ntfs.root_directory(&mut fs).unwrap();
let attribute = root.attributes_raw().next().unwrap().unwrap();
let root_position = root.position();
let first_attribute_offset =
attribute.position().value().unwrap().get() - root_position.value().unwrap().get();
(root_position, first_attribute_offset)
};
let truncated_size = u32::try_from(first_attribute_offset + 16).unwrap();
let absolute_position = root_position.value().unwrap().get() as usize;
fs.get_mut()[absolute_position + FILE_RECORD_DATA_SIZE_OFFSET
..absolute_position + FILE_RECORD_DATA_SIZE_OFFSET + size_of::<u32>()]
.copy_from_slice(&truncated_size.to_le_bytes());
let root = ntfs.root_directory(&mut fs).unwrap();
let error = root.attributes_raw().next().unwrap().unwrap_err();
assert!(matches!(error, NtfsError::InvalidAttributeLength { .. }));
}