/* File: ntfs_struct.h Copyright (C) 2021 Christophe GRENIER This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _NTFS_STRUCT_H #define _NTFS_STRUCT_H #ifdef __cplusplus extern "C" { #endif #define NTFS_BOOT_SECTOR_SIZE 0x200 struct ntfs_boot_sector { uint8_t ignored[3]; /* 0x00 Boot strap short or near jump */ int8_t system_id[8]; /* 0x03 Name : NTFS */ uint8_t sector_size[2]; /* 0x0B bytes per logical sector */ uint8_t sectors_per_cluster; /* 0x0D sectors/cluster */ uint16_t reserved; /* 0x0E reserved sectors = 0 */ uint8_t fats; /* 0x10 number of FATs = 0 */ uint8_t dir_entries[2]; /* 0x11 root directory entries = 0 */ uint8_t sectors[2]; /* 0x13 number of sectors = 0 */ uint8_t media; /* 0x15 media code (unused) */ uint16_t fat_length; /* 0x16 sectors/FAT = 0 */ uint16_t secs_track; /* 0x18 sectors per track */ uint16_t heads; /* 0x1A number of heads */ uint32_t hidden; /* 0x1C hidden sectors (unused) */ uint32_t total_sect; /* 0x20 number of sectors = 0 */ uint8_t physical_drive; /* 0x24 physical drive number */ uint8_t unused; /* 0x25 */ uint16_t reserved2; /* 0x26 usually 0x80 */ uint64_t sectors_nbr; /* 0x28 total sectors nbr */ uint64_t mft_lcn; /* 0x30 Cluster location of mft data.*/ uint64_t mftmirr_lcn; /* 0x38 Cluster location of copy of mft.*/ int8_t clusters_per_mft_record; /* 0x40 */ uint8_t reserved0[3]; /* zero */ int8_t clusters_per_index_record; /* 0x44 clusters per index block */ uint8_t reserved1[3]; /* zero */ uint64_t volume_serial_number; /* 0x48 Irrelevant (serial number). */ uint32_t checksum; /* 0x50 Boot sector checksum. */ uint8_t bootstrap[426]; /* 0x54 Irrelevant (boot up code). */ uint16_t marker; /* 0x1FE */ } __attribute__ ((gcc_struct, __packed__)); #define NTFS_Magic 0x454c4946 /* FILE */ struct ntfs_mft_record { uint32_t magic; /* FILE */ uint16_t usa_ofs; uint16_t usa_count; uint64_t lsn; uint16_t sequence_number; uint16_t link_count; uint16_t attrs_offset; /* Must be aligned to 8-byte boundary */ uint16_t flags; uint32_t bytes_in_use; /* Must be aligned to 8-byte boundary */ uint32_t bytes_allocated; uint64_t base_mft_record; uint16_t next_attr_instance; uint16_t reserved; /* NTFS 3.1+ */ uint32_t mft_record_number; /* NTFS 3.1+ */ } __attribute__ ((gcc_struct, __packed__)); typedef struct ntfs_mft_record ntfs_recordheader; typedef struct _ntfs_attribheader { uint32_t type; /* Attribute Type (e.g. 0x10, 0x60) */ uint32_t cbAttribute; /* Length (including this header) */ uint8_t bNonResident; /* Non-resident flag */ uint8_t cName; /* Name length */ uint16_t offName; /* Offset to the Attribute */ uint16_t flags; /* Flags */ uint16_t idAttribute; /* Attribute Id (a) */ } ntfs_attribheader; typedef struct _ntfs_attribresident { ntfs_attribheader header; uint32_t cbAttribData; /* Length of the Attribute */ uint16_t offAttribData; /* Offset to the Attribute */ uint8_t bIndexed; /* Indexed flag */ uint8_t padding; /* 0x00 Padding */ } ntfs_attribresident; typedef struct _ntfs_attribnonresident { ntfs_attribheader header; uint64_t startVCN; /* Starting VCN */ uint64_t lastVCN; /* Last VCN */ uint16_t offDataRuns; /* Offset to the Data Runs */ uint16_t compUnitSize; /* Compression Unit Size (b) */ uint32_t padding; /* Padding */ uint64_t cbAllocated; /* Allocated size of the attribute (c) */ uint64_t cbAttribData; /* Real size of the attribute */ uint64_t cbInitData; /* Initialized data size of the stream (d) */ } ntfs_attribnonresident; /* The original definitions come from ntfs-3g/layout.h */ /** * struct INDEX_HEADER - * * This is the header for indexes, describing the INDEX_ENTRY records, which * follow the INDEX_HEADER. Together the index header and the index entries * make up a complete index. * * IMPORTANT NOTE: The offset, length and size structure members are counted * relative to the start of the index header structure and not relative to the * start of the index root or index allocation structures themselves. */ typedef struct { /* 0*/ uint32_t entries_offset;/* Byte offset from the INDEX_HEADER to first INDEX_ENTRY, aligned to 8-byte boundary. */ /* 4*/ uint32_t index_length; /* Data size in byte of the INDEX_ENTRY's, including the INDEX_HEADER, aligned to 8. */ /* 8*/ uint32_t allocated_size;/* Allocated byte size of this index (block), multiple of 8 bytes. See more below. */ /* For the index root attribute, the above two numbers are always equal, as the attribute is resident and it is resized as needed. For the index allocation attribute, the attribute is not resident and the allocated_size is equal to the index_block_size specified by the corresponding INDEX_ROOT attribute minus the INDEX_BLOCK size not counting the INDEX_HEADER part (i.e. minus -24). */ /* 12*/ uint8_t ih_flags; /* Bit field of INDEX_HEADER_FLAGS. */ /* 13*/ uint8_t reserved[3]; /* Reserved/align to 8-byte boundary.*/ /* sizeof() == 16 */ } __attribute__((gcc_struct, __packed__)) TD_INDEX_HEADER; /** * struct FILE_NAME_ATTR - Attribute: Filename (0x30). * * NOTE: Always resident. * NOTE: All fields, except the parent_directory, are only updated when the * filename is changed. Until then, they just become out of sync with * reality and the more up to date values are present in the standard * information attribute. * NOTE: There is conflicting information about the meaning of each of the time * fields but the meaning as defined below has been verified to be * correct by practical experimentation on Windows NT4 SP6a and is hence * assumed to be the one and only correct interpretation. */ typedef struct { /*hex ofs*/ /* 0*/ uint64_t parent_directory; /* Directory this filename is referenced from. */ /* 8*/ int64_t creation_time; /* Time file was created. */ /* 10*/ int64_t last_data_change_time; /* Time the data attribute was last modified. */ /* 18*/ int64_t last_mft_change_time; /* Time this mft record was last modified. */ /* 20*/ int64_t last_access_time; /* Last time this mft record was accessed. */ /* 28*/ int64_t allocated_size; /* Byte size of on-disk allocated space for the data attribute. So for normal $DATA, this is the allocated_size from the unnamed $DATA attribute and for compressed and/or sparse $DATA, this is the compressed_size from the unnamed $DATA attribute. NOTE: This is a multiple of the cluster size. */ /* 30*/ int64_t data_size; /* Byte size of actual data in data attribute. */ /* 38*/ uint32_t file_attributes; /* Flags describing the file. */ /* 3c*/ union { /* 3c*/ struct { /* 3c*/ uint16_t packed_ea_size; /* Size of the buffer needed to pack the extended attributes (EAs), if such are present.*/ /* 3e*/ uint16_t reserved; /* Reserved for alignment. */ } __attribute__((gcc_struct, __packed__)); /* 3c*/ uint32_t reparse_point_tag; /* Type of reparse point, present only in reparse points and only if there are no EAs. */ } __attribute__((gcc_struct, __packed__)); /* 40*/ uint8_t file_name_length; /* Length of file name in (Unicode) characters. */ /* 41*/ uint8_t file_name_type; /* Namespace of the file name.*/ #if !defined(__FRAMAC__) /* 42*/ char *file_name[0]; /* File name in Unicode. */ #endif } __attribute__((gcc_struct, __packed__)) TD_FILE_NAME_ATTR; /** * struct INDEX_ROOT - Attribute: Index root (0x90). * * NOTE: Always resident. * * This is followed by a sequence of index entries (INDEX_ENTRY structures) * as described by the index header. * * When a directory is small enough to fit inside the index root then this * is the only attribute describing the directory. When the directory is too * large to fit in the index root, on the other hand, two additional attributes * are present: an index allocation attribute, containing sub-nodes of the B+ * directory tree (see below), and a bitmap attribute, describing which virtual * cluster numbers (vcns) in the index allocation attribute are in use by an * index block. * * NOTE: The root directory (FILE_root) contains an entry for itself. Other * directories do not contain entries for themselves, though. */ typedef struct { /* 0*/ uint32_t type; /* Type of the indexed attribute. Is $FILE_NAME for directories, zero for view indexes. No other values allowed. */ /* 4*/ uint32_t collation_rule; /* Collation rule used to sort the index entries. If type is $FILE_NAME, this must be COLLATION_FILE_NAME. */ /* 8*/ uint32_t index_block_size; /* Size of index block in bytes (in the index allocation attribute). */ /* 12*/ int8_t clusters_per_index_block;/* Size of index block in clusters (in the index allocation attribute), when an index block is >= than a cluster, otherwise sectors per index block. */ /* 13*/ uint8_t reserved[3]; /* Reserved/align to 8-byte boundary. */ /* 16*/ TD_INDEX_HEADER index; /* Index header describing the following index entries. */ /* sizeof()= 32 bytes */ } __attribute__((gcc_struct, __packed__)) TD_INDEX_ROOT; #ifdef __cplusplus } /* closing brace for extern "C" */ #endif #endif