fast_ntfs 1.0.2

Forked a low-level NTFS filesystem library
Documentation
mod common;

use std::io::{self, Read, Seek, SeekFrom};

use fast_ntfs::indexes::NtfsFileNameIndex;
use fast_ntfs::{Ntfs, NtfsAttributeType, NtfsFile};

fn file_by_name<'n>(ntfs: &'n Ntfs, fs: &mut std::io::Cursor<Vec<u8>>, name: &str) -> NtfsFile<'n> {
    ntfs.read_upcase_table(fs).unwrap();
    let root = ntfs.root_directory(fs).unwrap();
    let index = root.directory_index(fs).unwrap();
    NtfsFileNameIndex::find(&mut index.finder(), ntfs, fs, name)
        .unwrap()
        .unwrap()
        .to_file(ntfs, fs)
        .unwrap()
}

#[test]
fn targeted_unnamed_data_matches_data_convenience_api() {
    let mut fs = common::testfs1();
    let ntfs = Ntfs::new(&mut fs).unwrap();

    for name in ["file-with-12345", "1000-bytes-file", "sparse-file"] {
        let file = file_by_name(&ntfs, &mut fs, name);
        let data_item = file.data(&mut fs, "").unwrap().unwrap();
        let targeted_item = file
            .find_attribute(&mut fs, NtfsAttributeType::Data, "")
            .unwrap()
            .unwrap();
        let data = data_item.to_attribute().unwrap();
        let targeted = targeted_item.to_attribute().unwrap();

        assert_eq!(targeted.ty().unwrap(), NtfsAttributeType::Data);
        assert!(targeted.name().unwrap().is_empty());
        assert_eq!(targeted.value_length(), data.value_length());
        assert_eq!(targeted.is_resident(), data.is_resident());
    }
}

#[derive(Default)]
struct DenyIo;

impl Read for DenyIo {
    fn read(&mut self, _buffer: &mut [u8]) -> io::Result<usize> {
        Err(io::Error::other("unexpected read"))
    }
}

impl Seek for DenyIo {
    fn seek(&mut self, _position: SeekFrom) -> io::Result<u64> {
        Err(io::Error::other("unexpected seek"))
    }
}

#[test]
fn resident_local_data_needs_no_filesystem_io() {
    let mut fs = common::testfs1();
    let ntfs = Ntfs::new(&mut fs).unwrap();
    let file = file_by_name(&ntfs, &mut fs, "file-with-12345");
    let mut deny_io = DenyIo;

    let item = file
        .find_attribute(&mut deny_io, NtfsAttributeType::Data, "")
        .unwrap()
        .unwrap();
    let attribute = item.to_attribute().unwrap();

    assert!(attribute.is_resident());
    assert_eq!(attribute.value_length(), 5);
}