Welcome to mirror list, hosted at ThFree Co, Russian Federation.

x20.rs « attribute « src - github.com/windirstat/mft.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 8437823fc7b0eaa6923c7b60848c61a2f27d4a68 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use crate::err::{Error, Result};
use crate::ReadSeek;
use log::trace;

use byteorder::{LittleEndian, ReadBytesExt};
use encoding::all::UTF_16LE;
use encoding::{DecoderTrap, Encoding};

use serde::Serialize;

use std::io::SeekFrom;
use winstructs::ntfs::mft_reference::MftReference;

#[derive(Serialize, Clone, Debug)]
pub struct AttributeListAttr {
    pub attribute_type: u32,
    pub record_length: u16,
    pub first_vcn: u64,
    pub base_reference: MftReference,
    pub attribute_id: u16,
    pub name: String,
}

impl AttributeListAttr {
    pub fn from_stream<S: ReadSeek>(stream: &mut S) -> Result<AttributeListAttr> {
        let start_offset = stream.tell()?;

        trace!("Offset {}: AttributeListAttr", start_offset);

        let attribute_type = stream.read_u32::<LittleEndian>()?;
        let record_length = stream.read_u16::<LittleEndian>()?;
        let name_length = stream.read_u8()?;
        let name_offset = stream.read_u8()?;
        let first_vcn = stream.read_u64::<LittleEndian>()?;
        let base_reference =
            MftReference::from_reader(stream).map_err(Error::failed_to_read_mft_reference)?;
        let attribute_id = stream.read_u16::<LittleEndian>()?;

        let name = if name_length > 0 {
            stream.seek(SeekFrom::Start(start_offset + u64::from(name_offset)))?;

            let mut name_buffer = vec![0; (name_length as usize * 2) as usize];
            stream.read_exact(&mut name_buffer)?;

            match UTF_16LE.decode(&name_buffer, DecoderTrap::Ignore) {
                Ok(s) => s,
                Err(_e) => return Err(Error::InvalidFilename {}),
            }
        } else {
            String::new()
        };

        Ok(AttributeListAttr {
            attribute_type,
            record_length,
            first_vcn,
            base_reference,
            attribute_id,
            name,
        })
    }
}