/* MFT record number structure. */ struct MFT_REF {
__le32 low; // The low part of the number.
__le16 high; // The high part of the number.
__le16 seq; // The sequence number of MFT record.
};
struct NTFS_BOOT {
u8 jump_code[3]; // 0x00: Jump to boot code.
u8 system_id[8]; // 0x03: System ID, equals "NTFS "
// NOTE: This member is not aligned(!) // bytes_per_sector[0] must be 0. // bytes_per_sector[1] must be multiplied by 256.
u8 bytes_per_sector[2]; // 0x0B: Bytes per sector.
u8 sectors_per_clusters;// 0x0D: Sectors per cluster.
u8 unused1[7];
u8 media_type; // 0x15: Media type (0xF8 - harddisk)
u8 unused2[2];
__le16 sct_per_track; // 0x18: number of sectors per track.
__le16 heads; // 0x1A: number of heads per cylinder.
__le32 hidden_sectors; // 0x1C: number of 'hidden' sectors.
u8 unused3[4];
u8 bios_drive_num; // 0x24: BIOS drive number =0x80.
u8 unused4;
u8 signature_ex; // 0x26: Extended BOOT signature =0x80.
u8 unused5;
__le64 sectors_per_volume;// 0x28: Size of volume in sectors.
__le64 mft_clst; // 0x30: First cluster of $MFT
__le64 mft2_clst; // 0x38: First cluster of $MFTMirr
s8 record_size; // 0x40: Size of MFT record in clusters(sectors).
u8 unused6[3];
s8 index_size; // 0x44: Size of INDX record in clusters(sectors).
u8 unused7[3];
__le64 serial_num; // 0x48: Volume serial number
__le32 check_sum; // 0x50: Simple additive checksum of all // of the u32's which precede the 'check_sum'.
__le16 seq; // 0x10: Sequence number for this record.
__le16 hard_links; // 0x12: The number of hard links to record.
__le16 attr_off; // 0x14: Offset to attributes.
__le16 flags; // 0x16: See RECORD_FLAG.
__le32 used; // 0x18: The size of used part.
__le32 total; // 0x1C: Total record size.
struct MFT_REF parent_ref; // 0x20: Parent MFT record.
__le16 next_attr_id; // 0x28: The next attribute Id.
__le16 res; // 0x2A: High part of MFT record?
__le32 mft_record; // 0x2C: Current MFT record number.
__le16 fixups[]; // 0x30:
};
struct ATTR_NONRESIDENT {
__le64 svcn; // 0x10: Starting VCN of this segment.
__le64 evcn; // 0x18: End VCN of this segment.
__le16 run_off; // 0x20: Offset to packed runs. // Unit of Compression size for this stream, expressed // as a log of the cluster size. // // 0 means file is not compressed // 1, 2, 3, and 4 are potentially legal values if the // stream is compressed, however the implementation // may only choose to use 4, or possibly 3. // Note that 4 means cluster size time 16. // If convenient the implementation may wish to accept a // reasonable range of legal values here (1-5?), // even if the implementation only generates // a smaller set of values itself.
u8 c_unit; // 0x22:
u8 res1[5]; // 0x23:
__le64 alloc_size; // 0x28: The allocated size of attribute in bytes. // (multiple of cluster size)
__le64 data_size; // 0x30: The size of attribute in bytes <= alloc_size.
__le64 valid_size; // 0x38: The size of valid part in bytes <= data_size.
__le64 total_size; // 0x40: The sum of the allocated clusters for a file. // (present only for the first segment (0 == vcn) // of compressed attribute)
}; // sizeof()=0x40 or 0x48 (if compressed)
/* Possible values of ATTRIB.flags: */ #define ATTR_FLAG_COMPRESSED cpu_to_le16(0x0001) #define ATTR_FLAG_COMPRESSED_MASK cpu_to_le16(0x00FF) #define ATTR_FLAG_ENCRYPTED cpu_to_le16(0x4000) #define ATTR_FLAG_SPARSED cpu_to_le16(0x8000)
struct ATTRIB { enum ATTR_TYPE type; // 0x00: The type of this attribute.
__le32 size; // 0x04: The size of this attribute.
u8 non_res; // 0x08: Is this attribute non-resident?
u8 name_len; // 0x09: This attribute name length.
__le16 name_off; // 0x0A: Offset to the attribute name.
__le16 flags; // 0x0C: See ATTR_FLAG_XXX.
__le16 id; // 0x0E: Unique id (per record).
/* Standard information attribute (0x10). */ struct ATTR_STD_INFO {
__le64 cr_time; // 0x00: File creation file.
__le64 m_time; // 0x08: File modification time.
__le64 c_time; // 0x10: Last time any attribute was modified.
__le64 a_time; // 0x18: File last access time. enum FILE_ATTRIBUTE fa; // 0x20: Standard DOS attributes & more.
__le32 max_ver_num; // 0x24: Maximum Number of Versions.
__le32 ver_num; // 0x28: Version Number.
__le32 class_id; // 0x2C: Class Id from bidirectional Class Id index.
};
struct ATTR_STD_INFO5 {
__le64 cr_time; // 0x00: File creation file.
__le64 m_time; // 0x08: File modification time.
__le64 c_time; // 0x10: Last time any attribute was modified.
__le64 a_time; // 0x18: File last access time. enum FILE_ATTRIBUTE fa; // 0x20: Standard DOS attributes & more.
__le32 max_ver_num; // 0x24: Maximum Number of Versions.
__le32 ver_num; // 0x28: Version Number.
__le32 class_id; // 0x2C: Class Id from bidirectional Class Id index.
__le32 owner_id; // 0x30: Owner Id of the user owning the file.
__le32 security_id; // 0x34: The Security Id is a key in the $SII Index and $SDS.
__le64 quota_charge; // 0x38:
__le64 usn; // 0x40: Last Update Sequence Number of the file. This is a direct // index into the file $UsnJrnl. If zero, the USN Journal is // disabled.
};
/* Attribute list entry structure (0x20) */ struct ATTR_LIST_ENTRY { enum ATTR_TYPE type; // 0x00: The type of attribute.
__le16 size; // 0x04: The size of this record.
u8 name_len; // 0x06: The length of attribute name.
u8 name_off; // 0x07: The offset to attribute name.
__le64 vcn; // 0x08: Starting VCN of this attribute. struct MFT_REF ref; // 0x10: MFT record number with attribute.
__le16 id; // 0x18: struct ATTRIB ID.
__le16 name[]; // 0x1A: To get real name use name_off.
/* File name types (the field type in struct ATTR_FILE_NAME). */ #define FILE_NAME_POSIX 0 #define FILE_NAME_UNICODE 1 #define FILE_NAME_DOS 2 #define FILE_NAME_UNICODE_AND_DOS (FILE_NAME_DOS | FILE_NAME_UNICODE)
/* Filename attribute structure (0x30). */ struct NTFS_DUP_INFO {
__le64 cr_time; // 0x00: File creation file.
__le64 m_time; // 0x08: File modification time.
__le64 c_time; // 0x10: Last time any attribute was modified.
__le64 a_time; // 0x18: File last access time.
__le64 alloc_size; // 0x20: Data attribute allocated size, multiple of cluster size.
__le64 data_size; // 0x28: Data attribute size <= Dataalloc_size. enum FILE_ATTRIBUTE fa; // 0x30: Standard DOS attributes & more.
__le32 extend_data; // 0x34: Extended data.
}; // 0x38
struct ATTR_FILE_NAME { struct MFT_REF home; // 0x00: MFT record for directory. struct NTFS_DUP_INFO dup;// 0x08:
u8 name_len; // 0x40: File name length in words.
u8 type; // 0x41: File name type.
__le16 name[]; // 0x42: File name.
};
staticinline u8 paired_name(u8 type)
{ if (type == FILE_NAME_UNICODE) return FILE_NAME_DOS; if (type == FILE_NAME_DOS) return FILE_NAME_UNICODE; return FILE_NAME_POSIX;
}
/* Index entry defines ( the field flags in NtfsDirEntry ). */ #define NTFS_IE_HAS_SUBNODES cpu_to_le16(1) #define NTFS_IE_LAST cpu_to_le16(2)
/* Directory entry structure. */ struct NTFS_DE { union { struct MFT_REF ref; // 0x00: MFT record number with this file. struct {
__le16 data_off; // 0x00:
__le16 data_size; // 0x02:
__le32 res; // 0x04: Must be 0.
} view;
};
__le16 size; // 0x08: The size of this entry.
__le16 key_size; // 0x0A: The size of File name length in bytes + 0x42.
__le16 flags; // 0x0C: Entry flags: NTFS_IE_XXX.
__le16 res; // 0x0E:
// Here any indexed attribute can be placed. // One of them is: // struct ATTR_FILE_NAME AttrFileName; //
// The last 8 bytes of this structure contains // the VBN of subnode. // !!! Note !!! // This field is presented only if (flags & NTFS_IE_HAS_SUBNODES) // __le64 vbn;
};
struct INDEX_HDR {
__le32 de_off; // 0x00: The offset from the start of this structure // to the first NTFS_DE.
__le32 used; // 0x04: The size of this structure plus all // entries (quad-word aligned).
__le32 total; // 0x08: The allocated size of for this structure plus all entries.
__le32 flags; // 0x0C: 0x00 = Small directory, 0x01 = Large directory.
/* Index root structure ( 0x90 ). */ enum COLLATION_RULE {
NTFS_COLLATION_TYPE_BINARY = cpu_to_le32(0), // $I30
NTFS_COLLATION_TYPE_FILENAME = cpu_to_le32(0x01), // $SII of $Secure and $Q of Quota
NTFS_COLLATION_TYPE_UINT = cpu_to_le32(0x10), // $O of Quota
NTFS_COLLATION_TYPE_SID = cpu_to_le32(0x11), // $SDH of $Secure
NTFS_COLLATION_TYPE_SECURITY_HASH = cpu_to_le32(0x12), // $O of ObjId and "$R" for Reparse
NTFS_COLLATION_TYPE_UINTS = cpu_to_le32(0x13)
};
static_assert(sizeof(enum COLLATION_RULE) == 4);
// struct INDEX_ROOT { enum ATTR_TYPE type; // 0x00: The type of attribute to index on. enum COLLATION_RULE rule; // 0x04: The rule.
__le32 index_block_size;// 0x08: The size of index record.
u8 index_block_clst; // 0x0C: The number of clusters or sectors per index.
u8 res[3]; struct INDEX_HDR ihdr; // 0x10:
};
struct VOLUME_INFO {
__le64 res1; // 0x00
u8 major_ver; // 0x08: NTFS major version number (before .)
u8 minor_ver; // 0x09: NTFS minor version number (after .)
__le16 flags; // 0x0A: Volume flags, see VOLUME_FLAG_XXX
/* Object ID (0x40) */ struct OBJECT_ID { struct GUID ObjId; // 0x00: Unique Id assigned to file.
// Birth Volume Id is the Object Id of the Volume on. // which the Object Id was allocated. It never changes. struct GUID BirthVolumeId; //0x10:
// Birth Object Id is the first Object Id that was // ever assigned to this MFT Record. I.e. If the Object Id // is changed for some reason, this field will reflect the // original value of the Object Id. struct GUID BirthObjectId; // 0x20:
// Domain Id is currently unused but it is intended to be // used in a network environment where the local machine is // part of a Windows 2000 Domain. This may be used in a Windows // 2000 Advanced Server managed domain. struct GUID DomainId; // 0x30:
};
static_assert(sizeof(struct OBJECT_ID) == 0x40);
/* O Directory entry structure ( rule = 0x13 ) */ struct NTFS_DE_O { struct NTFS_DE de; struct GUID ObjId; // 0x10: Unique Id assigned to file. struct MFT_REF ref; // 0x20: MFT record number with this file.
// Birth Volume Id is the Object Id of the Volume on // which the Object Id was allocated. It never changes. struct GUID BirthVolumeId; // 0x28:
// Birth Object Id is the first Object Id that was // ever assigned to this MFT Record. I.e. If the Object Id // is changed for some reason, this field will reflect the // original value of the Object Id. // This field is valid if data_size == 0x48. struct GUID BirthObjectId; // 0x38:
// Domain Id is currently unused but it is intended // to be used in a network environment where the local // machine is part of a Windows 2000 Domain. This may be // used in a Windows 2000 Advanced Server managed domain. struct GUID BirthDomainId; // 0x48:
};
/* Macro to determine whether a reparse point tag is a name surrogate. */ #define IsReparseTagNameSurrogate(_tag) (((_tag)&IO_REPARSE_TAG_NAME_SURROGATE))
#define FILE_NEED_EA 0x80 // See ntifs.h /* *FILE_NEED_EA,indicatesthatthefiletowhichtheEAbelongscannotbe *interpretedwithoutunderstandingtheassociatedextendedattributes.
*/ struct EA_INFO {
__le16 size_pack; // 0x00: Size of buffer to hold in packed form.
__le16 count; // 0x02: Count of EA's with FILE_NEED_EA bit set.
__le32 size; // 0x04: Size of buffer to hold in unpacked form.
};