162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * on-disk ntfs structs 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci// clang-format off 1062306a36Sopenharmony_ci#ifndef _LINUX_NTFS3_NTFS_H 1162306a36Sopenharmony_ci#define _LINUX_NTFS3_NTFS_H 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/blkdev.h> 1462306a36Sopenharmony_ci#include <linux/build_bug.h> 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/stddef.h> 1762306a36Sopenharmony_ci#include <linux/string.h> 1862306a36Sopenharmony_ci#include <linux/types.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include "debug.h" 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* TODO: Check 4K MFT record and 512 bytes cluster. */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* Check each run for marked clusters. */ 2562306a36Sopenharmony_ci#define NTFS3_CHECK_FREE_CLST 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define NTFS_NAME_LEN 255 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* 3062306a36Sopenharmony_ci * ntfs.sys used 500 maximum links on-disk struct allows up to 0xffff. 3162306a36Sopenharmony_ci * xfstest generic/041 creates 3003 hardlinks. 3262306a36Sopenharmony_ci */ 3362306a36Sopenharmony_ci#define NTFS_LINK_MAX 4000 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci * Activate to use 64 bit clusters instead of 32 bits in ntfs.sys. 3762306a36Sopenharmony_ci * Logical and virtual cluster number if needed, may be 3862306a36Sopenharmony_ci * redefined to use 64 bit value. 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_ci//#define CONFIG_NTFS3_64BIT_CLUSTER 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define NTFS_LZNT_MAX_CLUSTER 4096 4362306a36Sopenharmony_ci#define NTFS_LZNT_CUNIT 4 4462306a36Sopenharmony_ci#define NTFS_LZNT_CLUSTERS (1u<<NTFS_LZNT_CUNIT) 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct GUID { 4762306a36Sopenharmony_ci __le32 Data1; 4862306a36Sopenharmony_ci __le16 Data2; 4962306a36Sopenharmony_ci __le16 Data3; 5062306a36Sopenharmony_ci u8 Data4[8]; 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* 5462306a36Sopenharmony_ci * This struct repeats layout of ATTR_FILE_NAME 5562306a36Sopenharmony_ci * at offset 0x40. 5662306a36Sopenharmony_ci * It used to store global constants NAME_MFT/NAME_MIRROR... 5762306a36Sopenharmony_ci * most constant names are shorter than 10. 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_cistruct cpu_str { 6062306a36Sopenharmony_ci u8 len; 6162306a36Sopenharmony_ci u8 unused; 6262306a36Sopenharmony_ci u16 name[10]; 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistruct le_str { 6662306a36Sopenharmony_ci u8 len; 6762306a36Sopenharmony_ci u8 unused; 6862306a36Sopenharmony_ci __le16 name[]; 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic_assert(SECTOR_SHIFT == 9); 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#ifdef CONFIG_NTFS3_64BIT_CLUSTER 7462306a36Sopenharmony_citypedef u64 CLST; 7562306a36Sopenharmony_cistatic_assert(sizeof(size_t) == 8); 7662306a36Sopenharmony_ci#else 7762306a36Sopenharmony_citypedef u32 CLST; 7862306a36Sopenharmony_ci#endif 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define SPARSE_LCN64 ((u64)-1) 8162306a36Sopenharmony_ci#define SPARSE_LCN ((CLST)-1) 8262306a36Sopenharmony_ci#define RESIDENT_LCN ((CLST)-2) 8362306a36Sopenharmony_ci#define COMPRESSED_LCN ((CLST)-3) 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define COMPRESSION_UNIT 4 8662306a36Sopenharmony_ci#define COMPRESS_MAX_CLUSTER 0x1000 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cienum RECORD_NUM { 8962306a36Sopenharmony_ci MFT_REC_MFT = 0, 9062306a36Sopenharmony_ci MFT_REC_MIRR = 1, 9162306a36Sopenharmony_ci MFT_REC_LOG = 2, 9262306a36Sopenharmony_ci MFT_REC_VOL = 3, 9362306a36Sopenharmony_ci MFT_REC_ATTR = 4, 9462306a36Sopenharmony_ci MFT_REC_ROOT = 5, 9562306a36Sopenharmony_ci MFT_REC_BITMAP = 6, 9662306a36Sopenharmony_ci MFT_REC_BOOT = 7, 9762306a36Sopenharmony_ci MFT_REC_BADCLUST = 8, 9862306a36Sopenharmony_ci MFT_REC_SECURE = 9, 9962306a36Sopenharmony_ci MFT_REC_UPCASE = 10, 10062306a36Sopenharmony_ci MFT_REC_EXTEND = 11, 10162306a36Sopenharmony_ci MFT_REC_RESERVED = 12, 10262306a36Sopenharmony_ci MFT_REC_FREE = 16, 10362306a36Sopenharmony_ci MFT_REC_USER = 24, 10462306a36Sopenharmony_ci}; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cienum ATTR_TYPE { 10762306a36Sopenharmony_ci ATTR_ZERO = cpu_to_le32(0x00), 10862306a36Sopenharmony_ci ATTR_STD = cpu_to_le32(0x10), 10962306a36Sopenharmony_ci ATTR_LIST = cpu_to_le32(0x20), 11062306a36Sopenharmony_ci ATTR_NAME = cpu_to_le32(0x30), 11162306a36Sopenharmony_ci ATTR_ID = cpu_to_le32(0x40), 11262306a36Sopenharmony_ci ATTR_SECURE = cpu_to_le32(0x50), 11362306a36Sopenharmony_ci ATTR_LABEL = cpu_to_le32(0x60), 11462306a36Sopenharmony_ci ATTR_VOL_INFO = cpu_to_le32(0x70), 11562306a36Sopenharmony_ci ATTR_DATA = cpu_to_le32(0x80), 11662306a36Sopenharmony_ci ATTR_ROOT = cpu_to_le32(0x90), 11762306a36Sopenharmony_ci ATTR_ALLOC = cpu_to_le32(0xA0), 11862306a36Sopenharmony_ci ATTR_BITMAP = cpu_to_le32(0xB0), 11962306a36Sopenharmony_ci ATTR_REPARSE = cpu_to_le32(0xC0), 12062306a36Sopenharmony_ci ATTR_EA_INFO = cpu_to_le32(0xD0), 12162306a36Sopenharmony_ci ATTR_EA = cpu_to_le32(0xE0), 12262306a36Sopenharmony_ci ATTR_PROPERTYSET = cpu_to_le32(0xF0), 12362306a36Sopenharmony_ci ATTR_LOGGED_UTILITY_STREAM = cpu_to_le32(0x100), 12462306a36Sopenharmony_ci ATTR_END = cpu_to_le32(0xFFFFFFFF) 12562306a36Sopenharmony_ci}; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic_assert(sizeof(enum ATTR_TYPE) == 4); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cienum FILE_ATTRIBUTE { 13062306a36Sopenharmony_ci FILE_ATTRIBUTE_READONLY = cpu_to_le32(0x00000001), 13162306a36Sopenharmony_ci FILE_ATTRIBUTE_HIDDEN = cpu_to_le32(0x00000002), 13262306a36Sopenharmony_ci FILE_ATTRIBUTE_SYSTEM = cpu_to_le32(0x00000004), 13362306a36Sopenharmony_ci FILE_ATTRIBUTE_ARCHIVE = cpu_to_le32(0x00000020), 13462306a36Sopenharmony_ci FILE_ATTRIBUTE_DEVICE = cpu_to_le32(0x00000040), 13562306a36Sopenharmony_ci FILE_ATTRIBUTE_TEMPORARY = cpu_to_le32(0x00000100), 13662306a36Sopenharmony_ci FILE_ATTRIBUTE_SPARSE_FILE = cpu_to_le32(0x00000200), 13762306a36Sopenharmony_ci FILE_ATTRIBUTE_REPARSE_POINT = cpu_to_le32(0x00000400), 13862306a36Sopenharmony_ci FILE_ATTRIBUTE_COMPRESSED = cpu_to_le32(0x00000800), 13962306a36Sopenharmony_ci FILE_ATTRIBUTE_OFFLINE = cpu_to_le32(0x00001000), 14062306a36Sopenharmony_ci FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = cpu_to_le32(0x00002000), 14162306a36Sopenharmony_ci FILE_ATTRIBUTE_ENCRYPTED = cpu_to_le32(0x00004000), 14262306a36Sopenharmony_ci FILE_ATTRIBUTE_VALID_FLAGS = cpu_to_le32(0x00007fb7), 14362306a36Sopenharmony_ci FILE_ATTRIBUTE_DIRECTORY = cpu_to_le32(0x10000000), 14462306a36Sopenharmony_ci FILE_ATTRIBUTE_INDEX = cpu_to_le32(0x20000000) 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic_assert(sizeof(enum FILE_ATTRIBUTE) == 4); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ciextern const struct cpu_str NAME_MFT; 15062306a36Sopenharmony_ciextern const struct cpu_str NAME_MIRROR; 15162306a36Sopenharmony_ciextern const struct cpu_str NAME_LOGFILE; 15262306a36Sopenharmony_ciextern const struct cpu_str NAME_VOLUME; 15362306a36Sopenharmony_ciextern const struct cpu_str NAME_ATTRDEF; 15462306a36Sopenharmony_ciextern const struct cpu_str NAME_ROOT; 15562306a36Sopenharmony_ciextern const struct cpu_str NAME_BITMAP; 15662306a36Sopenharmony_ciextern const struct cpu_str NAME_BOOT; 15762306a36Sopenharmony_ciextern const struct cpu_str NAME_BADCLUS; 15862306a36Sopenharmony_ciextern const struct cpu_str NAME_QUOTA; 15962306a36Sopenharmony_ciextern const struct cpu_str NAME_SECURE; 16062306a36Sopenharmony_ciextern const struct cpu_str NAME_UPCASE; 16162306a36Sopenharmony_ciextern const struct cpu_str NAME_EXTEND; 16262306a36Sopenharmony_ciextern const struct cpu_str NAME_OBJID; 16362306a36Sopenharmony_ciextern const struct cpu_str NAME_REPARSE; 16462306a36Sopenharmony_ciextern const struct cpu_str NAME_USNJRNL; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciextern const __le16 I30_NAME[4]; 16762306a36Sopenharmony_ciextern const __le16 SII_NAME[4]; 16862306a36Sopenharmony_ciextern const __le16 SDH_NAME[4]; 16962306a36Sopenharmony_ciextern const __le16 SO_NAME[2]; 17062306a36Sopenharmony_ciextern const __le16 SQ_NAME[2]; 17162306a36Sopenharmony_ciextern const __le16 SR_NAME[2]; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ciextern const __le16 BAD_NAME[4]; 17462306a36Sopenharmony_ciextern const __le16 SDS_NAME[4]; 17562306a36Sopenharmony_ciextern const __le16 WOF_NAME[17]; /* WofCompressedData */ 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci/* MFT record number structure. */ 17862306a36Sopenharmony_cistruct MFT_REF { 17962306a36Sopenharmony_ci __le32 low; // The low part of the number. 18062306a36Sopenharmony_ci __le16 high; // The high part of the number. 18162306a36Sopenharmony_ci __le16 seq; // The sequence number of MFT record. 18262306a36Sopenharmony_ci}; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic_assert(sizeof(__le64) == sizeof(struct MFT_REF)); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cistatic inline CLST ino_get(const struct MFT_REF *ref) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci#ifdef CONFIG_NTFS3_64BIT_CLUSTER 18962306a36Sopenharmony_ci return le32_to_cpu(ref->low) | ((u64)le16_to_cpu(ref->high) << 32); 19062306a36Sopenharmony_ci#else 19162306a36Sopenharmony_ci return le32_to_cpu(ref->low); 19262306a36Sopenharmony_ci#endif 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistruct NTFS_BOOT { 19662306a36Sopenharmony_ci u8 jump_code[3]; // 0x00: Jump to boot code. 19762306a36Sopenharmony_ci u8 system_id[8]; // 0x03: System ID, equals "NTFS " 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci // NOTE: This member is not aligned(!) 20062306a36Sopenharmony_ci // bytes_per_sector[0] must be 0. 20162306a36Sopenharmony_ci // bytes_per_sector[1] must be multiplied by 256. 20262306a36Sopenharmony_ci u8 bytes_per_sector[2]; // 0x0B: Bytes per sector. 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci u8 sectors_per_clusters;// 0x0D: Sectors per cluster. 20562306a36Sopenharmony_ci u8 unused1[7]; 20662306a36Sopenharmony_ci u8 media_type; // 0x15: Media type (0xF8 - harddisk) 20762306a36Sopenharmony_ci u8 unused2[2]; 20862306a36Sopenharmony_ci __le16 sct_per_track; // 0x18: number of sectors per track. 20962306a36Sopenharmony_ci __le16 heads; // 0x1A: number of heads per cylinder. 21062306a36Sopenharmony_ci __le32 hidden_sectors; // 0x1C: number of 'hidden' sectors. 21162306a36Sopenharmony_ci u8 unused3[4]; 21262306a36Sopenharmony_ci u8 bios_drive_num; // 0x24: BIOS drive number =0x80. 21362306a36Sopenharmony_ci u8 unused4; 21462306a36Sopenharmony_ci u8 signature_ex; // 0x26: Extended BOOT signature =0x80. 21562306a36Sopenharmony_ci u8 unused5; 21662306a36Sopenharmony_ci __le64 sectors_per_volume;// 0x28: Size of volume in sectors. 21762306a36Sopenharmony_ci __le64 mft_clst; // 0x30: First cluster of $MFT 21862306a36Sopenharmony_ci __le64 mft2_clst; // 0x38: First cluster of $MFTMirr 21962306a36Sopenharmony_ci s8 record_size; // 0x40: Size of MFT record in clusters(sectors). 22062306a36Sopenharmony_ci u8 unused6[3]; 22162306a36Sopenharmony_ci s8 index_size; // 0x44: Size of INDX record in clusters(sectors). 22262306a36Sopenharmony_ci u8 unused7[3]; 22362306a36Sopenharmony_ci __le64 serial_num; // 0x48: Volume serial number 22462306a36Sopenharmony_ci __le32 check_sum; // 0x50: Simple additive checksum of all 22562306a36Sopenharmony_ci // of the u32's which precede the 'check_sum'. 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci u8 boot_code[0x200 - 0x50 - 2 - 4]; // 0x54: 22862306a36Sopenharmony_ci u8 boot_magic[2]; // 0x1FE: Boot signature =0x55 + 0xAA 22962306a36Sopenharmony_ci}; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic_assert(sizeof(struct NTFS_BOOT) == 0x200); 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_cienum NTFS_SIGNATURE { 23462306a36Sopenharmony_ci NTFS_FILE_SIGNATURE = cpu_to_le32(0x454C4946), // 'FILE' 23562306a36Sopenharmony_ci NTFS_INDX_SIGNATURE = cpu_to_le32(0x58444E49), // 'INDX' 23662306a36Sopenharmony_ci NTFS_CHKD_SIGNATURE = cpu_to_le32(0x444B4843), // 'CHKD' 23762306a36Sopenharmony_ci NTFS_RSTR_SIGNATURE = cpu_to_le32(0x52545352), // 'RSTR' 23862306a36Sopenharmony_ci NTFS_RCRD_SIGNATURE = cpu_to_le32(0x44524352), // 'RCRD' 23962306a36Sopenharmony_ci NTFS_BAAD_SIGNATURE = cpu_to_le32(0x44414142), // 'BAAD' 24062306a36Sopenharmony_ci NTFS_HOLE_SIGNATURE = cpu_to_le32(0x454C4F48), // 'HOLE' 24162306a36Sopenharmony_ci NTFS_FFFF_SIGNATURE = cpu_to_le32(0xffffffff), 24262306a36Sopenharmony_ci}; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic_assert(sizeof(enum NTFS_SIGNATURE) == 4); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/* MFT Record header structure. */ 24762306a36Sopenharmony_cistruct NTFS_RECORD_HEADER { 24862306a36Sopenharmony_ci /* Record magic number, equals 'FILE'/'INDX'/'RSTR'/'RCRD'. */ 24962306a36Sopenharmony_ci enum NTFS_SIGNATURE sign; // 0x00: 25062306a36Sopenharmony_ci __le16 fix_off; // 0x04: 25162306a36Sopenharmony_ci __le16 fix_num; // 0x06: 25262306a36Sopenharmony_ci __le64 lsn; // 0x08: Log file sequence number, 25362306a36Sopenharmony_ci}; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic_assert(sizeof(struct NTFS_RECORD_HEADER) == 0x10); 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_cistatic inline int is_baad(const struct NTFS_RECORD_HEADER *hdr) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci return hdr->sign == NTFS_BAAD_SIGNATURE; 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci/* Possible bits in struct MFT_REC.flags. */ 26362306a36Sopenharmony_cienum RECORD_FLAG { 26462306a36Sopenharmony_ci RECORD_FLAG_IN_USE = cpu_to_le16(0x0001), 26562306a36Sopenharmony_ci RECORD_FLAG_DIR = cpu_to_le16(0x0002), 26662306a36Sopenharmony_ci RECORD_FLAG_SYSTEM = cpu_to_le16(0x0004), 26762306a36Sopenharmony_ci RECORD_FLAG_INDEX = cpu_to_le16(0x0008), 26862306a36Sopenharmony_ci}; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci/* MFT Record structure. */ 27162306a36Sopenharmony_cistruct MFT_REC { 27262306a36Sopenharmony_ci struct NTFS_RECORD_HEADER rhdr; // 'FILE' 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci __le16 seq; // 0x10: Sequence number for this record. 27562306a36Sopenharmony_ci __le16 hard_links; // 0x12: The number of hard links to record. 27662306a36Sopenharmony_ci __le16 attr_off; // 0x14: Offset to attributes. 27762306a36Sopenharmony_ci __le16 flags; // 0x16: See RECORD_FLAG. 27862306a36Sopenharmony_ci __le32 used; // 0x18: The size of used part. 27962306a36Sopenharmony_ci __le32 total; // 0x1C: Total record size. 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci struct MFT_REF parent_ref; // 0x20: Parent MFT record. 28262306a36Sopenharmony_ci __le16 next_attr_id; // 0x28: The next attribute Id. 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci __le16 res; // 0x2A: High part of MFT record? 28562306a36Sopenharmony_ci __le32 mft_record; // 0x2C: Current MFT record number. 28662306a36Sopenharmony_ci __le16 fixups[]; // 0x30: 28762306a36Sopenharmony_ci}; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci#define MFTRECORD_FIXUP_OFFSET_1 offsetof(struct MFT_REC, res) 29062306a36Sopenharmony_ci#define MFTRECORD_FIXUP_OFFSET_3 offsetof(struct MFT_REC, fixups) 29162306a36Sopenharmony_ci/* 29262306a36Sopenharmony_ci * define MFTRECORD_FIXUP_OFFSET as MFTRECORD_FIXUP_OFFSET_3 (0x30) 29362306a36Sopenharmony_ci * to format new mft records with bigger header (as current ntfs.sys does) 29462306a36Sopenharmony_ci * 29562306a36Sopenharmony_ci * define MFTRECORD_FIXUP_OFFSET as MFTRECORD_FIXUP_OFFSET_1 (0x2A) 29662306a36Sopenharmony_ci * to format new mft records with smaller header (as old ntfs.sys did) 29762306a36Sopenharmony_ci * Both variants are valid. 29862306a36Sopenharmony_ci */ 29962306a36Sopenharmony_ci#define MFTRECORD_FIXUP_OFFSET MFTRECORD_FIXUP_OFFSET_1 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic_assert(MFTRECORD_FIXUP_OFFSET_1 == 0x2A); 30262306a36Sopenharmony_cistatic_assert(MFTRECORD_FIXUP_OFFSET_3 == 0x30); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic inline bool is_rec_base(const struct MFT_REC *rec) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci const struct MFT_REF *r = &rec->parent_ref; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci return !r->low && !r->high && !r->seq; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic inline bool is_mft_rec5(const struct MFT_REC *rec) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci return le16_to_cpu(rec->rhdr.fix_off) >= 31462306a36Sopenharmony_ci offsetof(struct MFT_REC, fixups); 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic inline bool is_rec_inuse(const struct MFT_REC *rec) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci return rec->flags & RECORD_FLAG_IN_USE; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic inline bool clear_rec_inuse(struct MFT_REC *rec) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci return rec->flags &= ~RECORD_FLAG_IN_USE; 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci/* Possible values of ATTR_RESIDENT.flags */ 32862306a36Sopenharmony_ci#define RESIDENT_FLAG_INDEXED 0x01 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistruct ATTR_RESIDENT { 33162306a36Sopenharmony_ci __le32 data_size; // 0x10: The size of data. 33262306a36Sopenharmony_ci __le16 data_off; // 0x14: Offset to data. 33362306a36Sopenharmony_ci u8 flags; // 0x16: Resident flags ( 1 - indexed ). 33462306a36Sopenharmony_ci u8 res; // 0x17: 33562306a36Sopenharmony_ci}; // sizeof() = 0x18 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistruct ATTR_NONRESIDENT { 33862306a36Sopenharmony_ci __le64 svcn; // 0x10: Starting VCN of this segment. 33962306a36Sopenharmony_ci __le64 evcn; // 0x18: End VCN of this segment. 34062306a36Sopenharmony_ci __le16 run_off; // 0x20: Offset to packed runs. 34162306a36Sopenharmony_ci // Unit of Compression size for this stream, expressed 34262306a36Sopenharmony_ci // as a log of the cluster size. 34362306a36Sopenharmony_ci // 34462306a36Sopenharmony_ci // 0 means file is not compressed 34562306a36Sopenharmony_ci // 1, 2, 3, and 4 are potentially legal values if the 34662306a36Sopenharmony_ci // stream is compressed, however the implementation 34762306a36Sopenharmony_ci // may only choose to use 4, or possibly 3. 34862306a36Sopenharmony_ci // Note that 4 means cluster size time 16. 34962306a36Sopenharmony_ci // If convenient the implementation may wish to accept a 35062306a36Sopenharmony_ci // reasonable range of legal values here (1-5?), 35162306a36Sopenharmony_ci // even if the implementation only generates 35262306a36Sopenharmony_ci // a smaller set of values itself. 35362306a36Sopenharmony_ci u8 c_unit; // 0x22: 35462306a36Sopenharmony_ci u8 res1[5]; // 0x23: 35562306a36Sopenharmony_ci __le64 alloc_size; // 0x28: The allocated size of attribute in bytes. 35662306a36Sopenharmony_ci // (multiple of cluster size) 35762306a36Sopenharmony_ci __le64 data_size; // 0x30: The size of attribute in bytes <= alloc_size. 35862306a36Sopenharmony_ci __le64 valid_size; // 0x38: The size of valid part in bytes <= data_size. 35962306a36Sopenharmony_ci __le64 total_size; // 0x40: The sum of the allocated clusters for a file. 36062306a36Sopenharmony_ci // (present only for the first segment (0 == vcn) 36162306a36Sopenharmony_ci // of compressed attribute) 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci}; // sizeof()=0x40 or 0x48 (if compressed) 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci/* Possible values of ATTRIB.flags: */ 36662306a36Sopenharmony_ci#define ATTR_FLAG_COMPRESSED cpu_to_le16(0x0001) 36762306a36Sopenharmony_ci#define ATTR_FLAG_COMPRESSED_MASK cpu_to_le16(0x00FF) 36862306a36Sopenharmony_ci#define ATTR_FLAG_ENCRYPTED cpu_to_le16(0x4000) 36962306a36Sopenharmony_ci#define ATTR_FLAG_SPARSED cpu_to_le16(0x8000) 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistruct ATTRIB { 37262306a36Sopenharmony_ci enum ATTR_TYPE type; // 0x00: The type of this attribute. 37362306a36Sopenharmony_ci __le32 size; // 0x04: The size of this attribute. 37462306a36Sopenharmony_ci u8 non_res; // 0x08: Is this attribute non-resident? 37562306a36Sopenharmony_ci u8 name_len; // 0x09: This attribute name length. 37662306a36Sopenharmony_ci __le16 name_off; // 0x0A: Offset to the attribute name. 37762306a36Sopenharmony_ci __le16 flags; // 0x0C: See ATTR_FLAG_XXX. 37862306a36Sopenharmony_ci __le16 id; // 0x0E: Unique id (per record). 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci union { 38162306a36Sopenharmony_ci struct ATTR_RESIDENT res; // 0x10 38262306a36Sopenharmony_ci struct ATTR_NONRESIDENT nres; // 0x10 38362306a36Sopenharmony_ci }; 38462306a36Sopenharmony_ci}; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci/* Define attribute sizes. */ 38762306a36Sopenharmony_ci#define SIZEOF_RESIDENT 0x18 38862306a36Sopenharmony_ci#define SIZEOF_NONRESIDENT_EX 0x48 38962306a36Sopenharmony_ci#define SIZEOF_NONRESIDENT 0x40 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci#define SIZEOF_RESIDENT_LE cpu_to_le16(0x18) 39262306a36Sopenharmony_ci#define SIZEOF_NONRESIDENT_EX_LE cpu_to_le16(0x48) 39362306a36Sopenharmony_ci#define SIZEOF_NONRESIDENT_LE cpu_to_le16(0x40) 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cistatic inline u64 attr_ondisk_size(const struct ATTRIB *attr) 39662306a36Sopenharmony_ci{ 39762306a36Sopenharmony_ci return attr->non_res ? ((attr->flags & 39862306a36Sopenharmony_ci (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED)) ? 39962306a36Sopenharmony_ci le64_to_cpu(attr->nres.total_size) : 40062306a36Sopenharmony_ci le64_to_cpu(attr->nres.alloc_size)) 40162306a36Sopenharmony_ci : ALIGN(le32_to_cpu(attr->res.data_size), 8); 40262306a36Sopenharmony_ci} 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_cistatic inline u64 attr_size(const struct ATTRIB *attr) 40562306a36Sopenharmony_ci{ 40662306a36Sopenharmony_ci return attr->non_res ? le64_to_cpu(attr->nres.data_size) : 40762306a36Sopenharmony_ci le32_to_cpu(attr->res.data_size); 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistatic inline bool is_attr_encrypted(const struct ATTRIB *attr) 41162306a36Sopenharmony_ci{ 41262306a36Sopenharmony_ci return attr->flags & ATTR_FLAG_ENCRYPTED; 41362306a36Sopenharmony_ci} 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistatic inline bool is_attr_sparsed(const struct ATTRIB *attr) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci return attr->flags & ATTR_FLAG_SPARSED; 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic inline bool is_attr_compressed(const struct ATTRIB *attr) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci return attr->flags & ATTR_FLAG_COMPRESSED; 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic inline bool is_attr_ext(const struct ATTRIB *attr) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci return attr->flags & (ATTR_FLAG_SPARSED | ATTR_FLAG_COMPRESSED); 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic inline bool is_attr_indexed(const struct ATTRIB *attr) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci return !attr->non_res && (attr->res.flags & RESIDENT_FLAG_INDEXED); 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic inline __le16 const *attr_name(const struct ATTRIB *attr) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci return Add2Ptr(attr, le16_to_cpu(attr->name_off)); 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_cistatic inline u64 attr_svcn(const struct ATTRIB *attr) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci return attr->non_res ? le64_to_cpu(attr->nres.svcn) : 0; 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic_assert(sizeof(struct ATTRIB) == 0x48); 44662306a36Sopenharmony_cistatic_assert(sizeof(((struct ATTRIB *)NULL)->res) == 0x08); 44762306a36Sopenharmony_cistatic_assert(sizeof(((struct ATTRIB *)NULL)->nres) == 0x38); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic inline void *resident_data_ex(const struct ATTRIB *attr, u32 datasize) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci u32 asize, rsize; 45262306a36Sopenharmony_ci u16 off; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci if (attr->non_res) 45562306a36Sopenharmony_ci return NULL; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci asize = le32_to_cpu(attr->size); 45862306a36Sopenharmony_ci off = le16_to_cpu(attr->res.data_off); 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci if (asize < datasize + off) 46162306a36Sopenharmony_ci return NULL; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci rsize = le32_to_cpu(attr->res.data_size); 46462306a36Sopenharmony_ci if (rsize < datasize) 46562306a36Sopenharmony_ci return NULL; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci return Add2Ptr(attr, off); 46862306a36Sopenharmony_ci} 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_cistatic inline void *resident_data(const struct ATTRIB *attr) 47162306a36Sopenharmony_ci{ 47262306a36Sopenharmony_ci return Add2Ptr(attr, le16_to_cpu(attr->res.data_off)); 47362306a36Sopenharmony_ci} 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_cistatic inline void *attr_run(const struct ATTRIB *attr) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci return Add2Ptr(attr, le16_to_cpu(attr->nres.run_off)); 47862306a36Sopenharmony_ci} 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci/* Standard information attribute (0x10). */ 48162306a36Sopenharmony_cistruct ATTR_STD_INFO { 48262306a36Sopenharmony_ci __le64 cr_time; // 0x00: File creation file. 48362306a36Sopenharmony_ci __le64 m_time; // 0x08: File modification time. 48462306a36Sopenharmony_ci __le64 c_time; // 0x10: Last time any attribute was modified. 48562306a36Sopenharmony_ci __le64 a_time; // 0x18: File last access time. 48662306a36Sopenharmony_ci enum FILE_ATTRIBUTE fa; // 0x20: Standard DOS attributes & more. 48762306a36Sopenharmony_ci __le32 max_ver_num; // 0x24: Maximum Number of Versions. 48862306a36Sopenharmony_ci __le32 ver_num; // 0x28: Version Number. 48962306a36Sopenharmony_ci __le32 class_id; // 0x2C: Class Id from bidirectional Class Id index. 49062306a36Sopenharmony_ci}; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_cistatic_assert(sizeof(struct ATTR_STD_INFO) == 0x30); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci#define SECURITY_ID_INVALID 0x00000000 49562306a36Sopenharmony_ci#define SECURITY_ID_FIRST 0x00000100 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistruct ATTR_STD_INFO5 { 49862306a36Sopenharmony_ci __le64 cr_time; // 0x00: File creation file. 49962306a36Sopenharmony_ci __le64 m_time; // 0x08: File modification time. 50062306a36Sopenharmony_ci __le64 c_time; // 0x10: Last time any attribute was modified. 50162306a36Sopenharmony_ci __le64 a_time; // 0x18: File last access time. 50262306a36Sopenharmony_ci enum FILE_ATTRIBUTE fa; // 0x20: Standard DOS attributes & more. 50362306a36Sopenharmony_ci __le32 max_ver_num; // 0x24: Maximum Number of Versions. 50462306a36Sopenharmony_ci __le32 ver_num; // 0x28: Version Number. 50562306a36Sopenharmony_ci __le32 class_id; // 0x2C: Class Id from bidirectional Class Id index. 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci __le32 owner_id; // 0x30: Owner Id of the user owning the file. 50862306a36Sopenharmony_ci __le32 security_id; // 0x34: The Security Id is a key in the $SII Index and $SDS. 50962306a36Sopenharmony_ci __le64 quota_charge; // 0x38: 51062306a36Sopenharmony_ci __le64 usn; // 0x40: Last Update Sequence Number of the file. This is a direct 51162306a36Sopenharmony_ci // index into the file $UsnJrnl. If zero, the USN Journal is 51262306a36Sopenharmony_ci // disabled. 51362306a36Sopenharmony_ci}; 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_cistatic_assert(sizeof(struct ATTR_STD_INFO5) == 0x48); 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci/* Attribute list entry structure (0x20) */ 51862306a36Sopenharmony_cistruct ATTR_LIST_ENTRY { 51962306a36Sopenharmony_ci enum ATTR_TYPE type; // 0x00: The type of attribute. 52062306a36Sopenharmony_ci __le16 size; // 0x04: The size of this record. 52162306a36Sopenharmony_ci u8 name_len; // 0x06: The length of attribute name. 52262306a36Sopenharmony_ci u8 name_off; // 0x07: The offset to attribute name. 52362306a36Sopenharmony_ci __le64 vcn; // 0x08: Starting VCN of this attribute. 52462306a36Sopenharmony_ci struct MFT_REF ref; // 0x10: MFT record number with attribute. 52562306a36Sopenharmony_ci __le16 id; // 0x18: struct ATTRIB ID. 52662306a36Sopenharmony_ci __le16 name[]; // 0x1A: Just to align. To get real name can use name_off. 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci}; // sizeof(0x20) 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_cistatic inline u32 le_size(u8 name_len) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci return ALIGN(offsetof(struct ATTR_LIST_ENTRY, name) + 53362306a36Sopenharmony_ci name_len * sizeof(short), 8); 53462306a36Sopenharmony_ci} 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci/* Returns 0 if 'attr' has the same type and name. */ 53762306a36Sopenharmony_cistatic inline int le_cmp(const struct ATTR_LIST_ENTRY *le, 53862306a36Sopenharmony_ci const struct ATTRIB *attr) 53962306a36Sopenharmony_ci{ 54062306a36Sopenharmony_ci return le->type != attr->type || le->name_len != attr->name_len || 54162306a36Sopenharmony_ci (!le->name_len && 54262306a36Sopenharmony_ci memcmp(Add2Ptr(le, le->name_off), 54362306a36Sopenharmony_ci Add2Ptr(attr, le16_to_cpu(attr->name_off)), 54462306a36Sopenharmony_ci le->name_len * sizeof(short))); 54562306a36Sopenharmony_ci} 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_cistatic inline __le16 const *le_name(const struct ATTR_LIST_ENTRY *le) 54862306a36Sopenharmony_ci{ 54962306a36Sopenharmony_ci return Add2Ptr(le, le->name_off); 55062306a36Sopenharmony_ci} 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci/* File name types (the field type in struct ATTR_FILE_NAME). */ 55362306a36Sopenharmony_ci#define FILE_NAME_POSIX 0 55462306a36Sopenharmony_ci#define FILE_NAME_UNICODE 1 55562306a36Sopenharmony_ci#define FILE_NAME_DOS 2 55662306a36Sopenharmony_ci#define FILE_NAME_UNICODE_AND_DOS (FILE_NAME_DOS | FILE_NAME_UNICODE) 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci/* Filename attribute structure (0x30). */ 55962306a36Sopenharmony_cistruct NTFS_DUP_INFO { 56062306a36Sopenharmony_ci __le64 cr_time; // 0x00: File creation file. 56162306a36Sopenharmony_ci __le64 m_time; // 0x08: File modification time. 56262306a36Sopenharmony_ci __le64 c_time; // 0x10: Last time any attribute was modified. 56362306a36Sopenharmony_ci __le64 a_time; // 0x18: File last access time. 56462306a36Sopenharmony_ci __le64 alloc_size; // 0x20: Data attribute allocated size, multiple of cluster size. 56562306a36Sopenharmony_ci __le64 data_size; // 0x28: Data attribute size <= Dataalloc_size. 56662306a36Sopenharmony_ci enum FILE_ATTRIBUTE fa; // 0x30: Standard DOS attributes & more. 56762306a36Sopenharmony_ci __le16 ea_size; // 0x34: Packed EAs. 56862306a36Sopenharmony_ci __le16 reparse; // 0x36: Used by Reparse. 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci}; // 0x38 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_cistruct ATTR_FILE_NAME { 57362306a36Sopenharmony_ci struct MFT_REF home; // 0x00: MFT record for directory. 57462306a36Sopenharmony_ci struct NTFS_DUP_INFO dup;// 0x08: 57562306a36Sopenharmony_ci u8 name_len; // 0x40: File name length in words. 57662306a36Sopenharmony_ci u8 type; // 0x41: File name type. 57762306a36Sopenharmony_ci __le16 name[]; // 0x42: File name. 57862306a36Sopenharmony_ci}; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic_assert(sizeof(((struct ATTR_FILE_NAME *)NULL)->dup) == 0x38); 58162306a36Sopenharmony_cistatic_assert(offsetof(struct ATTR_FILE_NAME, name) == 0x42); 58262306a36Sopenharmony_ci#define SIZEOF_ATTRIBUTE_FILENAME 0x44 58362306a36Sopenharmony_ci#define SIZEOF_ATTRIBUTE_FILENAME_MAX (0x42 + 255 * 2) 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_cistatic inline struct ATTRIB *attr_from_name(struct ATTR_FILE_NAME *fname) 58662306a36Sopenharmony_ci{ 58762306a36Sopenharmony_ci return (struct ATTRIB *)((char *)fname - SIZEOF_RESIDENT); 58862306a36Sopenharmony_ci} 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_cistatic inline u16 fname_full_size(const struct ATTR_FILE_NAME *fname) 59162306a36Sopenharmony_ci{ 59262306a36Sopenharmony_ci /* Don't return struct_size(fname, name, fname->name_len); */ 59362306a36Sopenharmony_ci return offsetof(struct ATTR_FILE_NAME, name) + 59462306a36Sopenharmony_ci fname->name_len * sizeof(short); 59562306a36Sopenharmony_ci} 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_cistatic inline u8 paired_name(u8 type) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci if (type == FILE_NAME_UNICODE) 60062306a36Sopenharmony_ci return FILE_NAME_DOS; 60162306a36Sopenharmony_ci if (type == FILE_NAME_DOS) 60262306a36Sopenharmony_ci return FILE_NAME_UNICODE; 60362306a36Sopenharmony_ci return FILE_NAME_POSIX; 60462306a36Sopenharmony_ci} 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci/* Index entry defines ( the field flags in NtfsDirEntry ). */ 60762306a36Sopenharmony_ci#define NTFS_IE_HAS_SUBNODES cpu_to_le16(1) 60862306a36Sopenharmony_ci#define NTFS_IE_LAST cpu_to_le16(2) 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci/* Directory entry structure. */ 61162306a36Sopenharmony_cistruct NTFS_DE { 61262306a36Sopenharmony_ci union { 61362306a36Sopenharmony_ci struct MFT_REF ref; // 0x00: MFT record number with this file. 61462306a36Sopenharmony_ci struct { 61562306a36Sopenharmony_ci __le16 data_off; // 0x00: 61662306a36Sopenharmony_ci __le16 data_size; // 0x02: 61762306a36Sopenharmony_ci __le32 res; // 0x04: Must be 0. 61862306a36Sopenharmony_ci } view; 61962306a36Sopenharmony_ci }; 62062306a36Sopenharmony_ci __le16 size; // 0x08: The size of this entry. 62162306a36Sopenharmony_ci __le16 key_size; // 0x0A: The size of File name length in bytes + 0x42. 62262306a36Sopenharmony_ci __le16 flags; // 0x0C: Entry flags: NTFS_IE_XXX. 62362306a36Sopenharmony_ci __le16 res; // 0x0E: 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci // Here any indexed attribute can be placed. 62662306a36Sopenharmony_ci // One of them is: 62762306a36Sopenharmony_ci // struct ATTR_FILE_NAME AttrFileName; 62862306a36Sopenharmony_ci // 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci // The last 8 bytes of this structure contains 63162306a36Sopenharmony_ci // the VBN of subnode. 63262306a36Sopenharmony_ci // !!! Note !!! 63362306a36Sopenharmony_ci // This field is presented only if (flags & NTFS_IE_HAS_SUBNODES) 63462306a36Sopenharmony_ci // __le64 vbn; 63562306a36Sopenharmony_ci}; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_cistatic_assert(sizeof(struct NTFS_DE) == 0x10); 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_cistatic inline void de_set_vbn_le(struct NTFS_DE *e, __le64 vcn) 64062306a36Sopenharmony_ci{ 64162306a36Sopenharmony_ci __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64)); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci *v = vcn; 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cistatic inline void de_set_vbn(struct NTFS_DE *e, CLST vcn) 64762306a36Sopenharmony_ci{ 64862306a36Sopenharmony_ci __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64)); 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci *v = cpu_to_le64(vcn); 65162306a36Sopenharmony_ci} 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_cistatic inline __le64 de_get_vbn_le(const struct NTFS_DE *e) 65462306a36Sopenharmony_ci{ 65562306a36Sopenharmony_ci return *(__le64 *)Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64)); 65662306a36Sopenharmony_ci} 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_cistatic inline CLST de_get_vbn(const struct NTFS_DE *e) 65962306a36Sopenharmony_ci{ 66062306a36Sopenharmony_ci __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64)); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci return le64_to_cpu(*v); 66362306a36Sopenharmony_ci} 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_cistatic inline struct NTFS_DE *de_get_next(const struct NTFS_DE *e) 66662306a36Sopenharmony_ci{ 66762306a36Sopenharmony_ci return Add2Ptr(e, le16_to_cpu(e->size)); 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic inline struct ATTR_FILE_NAME *de_get_fname(const struct NTFS_DE *e) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci return le16_to_cpu(e->key_size) >= SIZEOF_ATTRIBUTE_FILENAME ? 67362306a36Sopenharmony_ci Add2Ptr(e, sizeof(struct NTFS_DE)) : 67462306a36Sopenharmony_ci NULL; 67562306a36Sopenharmony_ci} 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_cistatic inline bool de_is_last(const struct NTFS_DE *e) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci return e->flags & NTFS_IE_LAST; 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_cistatic inline bool de_has_vcn(const struct NTFS_DE *e) 68362306a36Sopenharmony_ci{ 68462306a36Sopenharmony_ci return e->flags & NTFS_IE_HAS_SUBNODES; 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_cistatic inline bool de_has_vcn_ex(const struct NTFS_DE *e) 68862306a36Sopenharmony_ci{ 68962306a36Sopenharmony_ci return (e->flags & NTFS_IE_HAS_SUBNODES) && 69062306a36Sopenharmony_ci (u64)(-1) != *((u64 *)Add2Ptr(e, le16_to_cpu(e->size) - 69162306a36Sopenharmony_ci sizeof(__le64))); 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci#define MAX_BYTES_PER_NAME_ENTRY \ 69562306a36Sopenharmony_ci ALIGN(sizeof(struct NTFS_DE) + \ 69662306a36Sopenharmony_ci offsetof(struct ATTR_FILE_NAME, name) + \ 69762306a36Sopenharmony_ci NTFS_NAME_LEN * sizeof(short), 8) 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_cistruct INDEX_HDR { 70062306a36Sopenharmony_ci __le32 de_off; // 0x00: The offset from the start of this structure 70162306a36Sopenharmony_ci // to the first NTFS_DE. 70262306a36Sopenharmony_ci __le32 used; // 0x04: The size of this structure plus all 70362306a36Sopenharmony_ci // entries (quad-word aligned). 70462306a36Sopenharmony_ci __le32 total; // 0x08: The allocated size of for this structure plus all entries. 70562306a36Sopenharmony_ci u8 flags; // 0x0C: 0x00 = Small directory, 0x01 = Large directory. 70662306a36Sopenharmony_ci u8 res[3]; 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci // 70962306a36Sopenharmony_ci // de_off + used <= total 71062306a36Sopenharmony_ci // 71162306a36Sopenharmony_ci}; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_cistatic_assert(sizeof(struct INDEX_HDR) == 0x10); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_cistatic inline struct NTFS_DE *hdr_first_de(const struct INDEX_HDR *hdr) 71662306a36Sopenharmony_ci{ 71762306a36Sopenharmony_ci u32 de_off = le32_to_cpu(hdr->de_off); 71862306a36Sopenharmony_ci u32 used = le32_to_cpu(hdr->used); 71962306a36Sopenharmony_ci struct NTFS_DE *e; 72062306a36Sopenharmony_ci u16 esize; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci if (de_off >= used || de_off + sizeof(struct NTFS_DE) > used ) 72362306a36Sopenharmony_ci return NULL; 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci e = Add2Ptr(hdr, de_off); 72662306a36Sopenharmony_ci esize = le16_to_cpu(e->size); 72762306a36Sopenharmony_ci if (esize < sizeof(struct NTFS_DE) || de_off + esize > used) 72862306a36Sopenharmony_ci return NULL; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci return e; 73162306a36Sopenharmony_ci} 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_cistatic inline struct NTFS_DE *hdr_next_de(const struct INDEX_HDR *hdr, 73462306a36Sopenharmony_ci const struct NTFS_DE *e) 73562306a36Sopenharmony_ci{ 73662306a36Sopenharmony_ci size_t off = PtrOffset(hdr, e); 73762306a36Sopenharmony_ci u32 used = le32_to_cpu(hdr->used); 73862306a36Sopenharmony_ci u16 esize; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci if (off >= used) 74162306a36Sopenharmony_ci return NULL; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci esize = le16_to_cpu(e->size); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci if (esize < sizeof(struct NTFS_DE) || 74662306a36Sopenharmony_ci off + esize + sizeof(struct NTFS_DE) > used) 74762306a36Sopenharmony_ci return NULL; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci return Add2Ptr(e, esize); 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic inline bool hdr_has_subnode(const struct INDEX_HDR *hdr) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci return hdr->flags & 1; 75562306a36Sopenharmony_ci} 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_cistruct INDEX_BUFFER { 75862306a36Sopenharmony_ci struct NTFS_RECORD_HEADER rhdr; // 'INDX' 75962306a36Sopenharmony_ci __le64 vbn; // 0x10: vcn if index >= cluster or vsn id index < cluster 76062306a36Sopenharmony_ci struct INDEX_HDR ihdr; // 0x18: 76162306a36Sopenharmony_ci}; 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_cistatic_assert(sizeof(struct INDEX_BUFFER) == 0x28); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_cistatic inline bool ib_is_empty(const struct INDEX_BUFFER *ib) 76662306a36Sopenharmony_ci{ 76762306a36Sopenharmony_ci const struct NTFS_DE *first = hdr_first_de(&ib->ihdr); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci return !first || de_is_last(first); 77062306a36Sopenharmony_ci} 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_cistatic inline bool ib_is_leaf(const struct INDEX_BUFFER *ib) 77362306a36Sopenharmony_ci{ 77462306a36Sopenharmony_ci return !(ib->ihdr.flags & 1); 77562306a36Sopenharmony_ci} 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci/* Index root structure ( 0x90 ). */ 77862306a36Sopenharmony_cienum COLLATION_RULE { 77962306a36Sopenharmony_ci NTFS_COLLATION_TYPE_BINARY = cpu_to_le32(0), 78062306a36Sopenharmony_ci // $I30 78162306a36Sopenharmony_ci NTFS_COLLATION_TYPE_FILENAME = cpu_to_le32(0x01), 78262306a36Sopenharmony_ci // $SII of $Secure and $Q of Quota 78362306a36Sopenharmony_ci NTFS_COLLATION_TYPE_UINT = cpu_to_le32(0x10), 78462306a36Sopenharmony_ci // $O of Quota 78562306a36Sopenharmony_ci NTFS_COLLATION_TYPE_SID = cpu_to_le32(0x11), 78662306a36Sopenharmony_ci // $SDH of $Secure 78762306a36Sopenharmony_ci NTFS_COLLATION_TYPE_SECURITY_HASH = cpu_to_le32(0x12), 78862306a36Sopenharmony_ci // $O of ObjId and "$R" for Reparse 78962306a36Sopenharmony_ci NTFS_COLLATION_TYPE_UINTS = cpu_to_le32(0x13) 79062306a36Sopenharmony_ci}; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_cistatic_assert(sizeof(enum COLLATION_RULE) == 4); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci// 79562306a36Sopenharmony_cistruct INDEX_ROOT { 79662306a36Sopenharmony_ci enum ATTR_TYPE type; // 0x00: The type of attribute to index on. 79762306a36Sopenharmony_ci enum COLLATION_RULE rule; // 0x04: The rule. 79862306a36Sopenharmony_ci __le32 index_block_size;// 0x08: The size of index record. 79962306a36Sopenharmony_ci u8 index_block_clst; // 0x0C: The number of clusters or sectors per index. 80062306a36Sopenharmony_ci u8 res[3]; 80162306a36Sopenharmony_ci struct INDEX_HDR ihdr; // 0x10: 80262306a36Sopenharmony_ci}; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_cistatic_assert(sizeof(struct INDEX_ROOT) == 0x20); 80562306a36Sopenharmony_cistatic_assert(offsetof(struct INDEX_ROOT, ihdr) == 0x10); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci#define VOLUME_FLAG_DIRTY cpu_to_le16(0x0001) 80862306a36Sopenharmony_ci#define VOLUME_FLAG_RESIZE_LOG_FILE cpu_to_le16(0x0002) 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_cistruct VOLUME_INFO { 81162306a36Sopenharmony_ci __le64 res1; // 0x00 81262306a36Sopenharmony_ci u8 major_ver; // 0x08: NTFS major version number (before .) 81362306a36Sopenharmony_ci u8 minor_ver; // 0x09: NTFS minor version number (after .) 81462306a36Sopenharmony_ci __le16 flags; // 0x0A: Volume flags, see VOLUME_FLAG_XXX 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci}; // sizeof=0xC 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci#define SIZEOF_ATTRIBUTE_VOLUME_INFO 0xc 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci#define NTFS_LABEL_MAX_LENGTH (0x100 / sizeof(short)) 82162306a36Sopenharmony_ci#define NTFS_ATTR_INDEXABLE cpu_to_le32(0x00000002) 82262306a36Sopenharmony_ci#define NTFS_ATTR_DUPALLOWED cpu_to_le32(0x00000004) 82362306a36Sopenharmony_ci#define NTFS_ATTR_MUST_BE_INDEXED cpu_to_le32(0x00000010) 82462306a36Sopenharmony_ci#define NTFS_ATTR_MUST_BE_NAMED cpu_to_le32(0x00000020) 82562306a36Sopenharmony_ci#define NTFS_ATTR_MUST_BE_RESIDENT cpu_to_le32(0x00000040) 82662306a36Sopenharmony_ci#define NTFS_ATTR_LOG_ALWAYS cpu_to_le32(0x00000080) 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci/* $AttrDef file entry. */ 82962306a36Sopenharmony_cistruct ATTR_DEF_ENTRY { 83062306a36Sopenharmony_ci __le16 name[0x40]; // 0x00: Attr name. 83162306a36Sopenharmony_ci enum ATTR_TYPE type; // 0x80: struct ATTRIB type. 83262306a36Sopenharmony_ci __le32 res; // 0x84: 83362306a36Sopenharmony_ci enum COLLATION_RULE rule; // 0x88: 83462306a36Sopenharmony_ci __le32 flags; // 0x8C: NTFS_ATTR_XXX (see above). 83562306a36Sopenharmony_ci __le64 min_sz; // 0x90: Minimum attribute data size. 83662306a36Sopenharmony_ci __le64 max_sz; // 0x98: Maximum attribute data size. 83762306a36Sopenharmony_ci}; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_cistatic_assert(sizeof(struct ATTR_DEF_ENTRY) == 0xa0); 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci/* Object ID (0x40) */ 84262306a36Sopenharmony_cistruct OBJECT_ID { 84362306a36Sopenharmony_ci struct GUID ObjId; // 0x00: Unique Id assigned to file. 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci // Birth Volume Id is the Object Id of the Volume on. 84662306a36Sopenharmony_ci // which the Object Id was allocated. It never changes. 84762306a36Sopenharmony_ci struct GUID BirthVolumeId; //0x10: 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci // Birth Object Id is the first Object Id that was 85062306a36Sopenharmony_ci // ever assigned to this MFT Record. I.e. If the Object Id 85162306a36Sopenharmony_ci // is changed for some reason, this field will reflect the 85262306a36Sopenharmony_ci // original value of the Object Id. 85362306a36Sopenharmony_ci struct GUID BirthObjectId; // 0x20: 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci // Domain Id is currently unused but it is intended to be 85662306a36Sopenharmony_ci // used in a network environment where the local machine is 85762306a36Sopenharmony_ci // part of a Windows 2000 Domain. This may be used in a Windows 85862306a36Sopenharmony_ci // 2000 Advanced Server managed domain. 85962306a36Sopenharmony_ci struct GUID DomainId; // 0x30: 86062306a36Sopenharmony_ci}; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_cistatic_assert(sizeof(struct OBJECT_ID) == 0x40); 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci/* O Directory entry structure ( rule = 0x13 ) */ 86562306a36Sopenharmony_cistruct NTFS_DE_O { 86662306a36Sopenharmony_ci struct NTFS_DE de; 86762306a36Sopenharmony_ci struct GUID ObjId; // 0x10: Unique Id assigned to file. 86862306a36Sopenharmony_ci struct MFT_REF ref; // 0x20: MFT record number with this file. 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci // Birth Volume Id is the Object Id of the Volume on 87162306a36Sopenharmony_ci // which the Object Id was allocated. It never changes. 87262306a36Sopenharmony_ci struct GUID BirthVolumeId; // 0x28: 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci // Birth Object Id is the first Object Id that was 87562306a36Sopenharmony_ci // ever assigned to this MFT Record. I.e. If the Object Id 87662306a36Sopenharmony_ci // is changed for some reason, this field will reflect the 87762306a36Sopenharmony_ci // original value of the Object Id. 87862306a36Sopenharmony_ci // This field is valid if data_size == 0x48. 87962306a36Sopenharmony_ci struct GUID BirthObjectId; // 0x38: 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci // Domain Id is currently unused but it is intended 88262306a36Sopenharmony_ci // to be used in a network environment where the local 88362306a36Sopenharmony_ci // machine is part of a Windows 2000 Domain. This may be 88462306a36Sopenharmony_ci // used in a Windows 2000 Advanced Server managed domain. 88562306a36Sopenharmony_ci struct GUID BirthDomainId; // 0x48: 88662306a36Sopenharmony_ci}; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_cistatic_assert(sizeof(struct NTFS_DE_O) == 0x58); 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci/* Q Directory entry structure ( rule = 0x11 ) */ 89162306a36Sopenharmony_cistruct NTFS_DE_Q { 89262306a36Sopenharmony_ci struct NTFS_DE de; 89362306a36Sopenharmony_ci __le32 owner_id; // 0x10: Unique Id assigned to file 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci /* here is 0x30 bytes of user quota. NOTE: 4 byte aligned! */ 89662306a36Sopenharmony_ci __le32 Version; // 0x14: 0x02 89762306a36Sopenharmony_ci __le32 Flags; // 0x18: Quota flags, see above 89862306a36Sopenharmony_ci __le64 BytesUsed; // 0x1C: 89962306a36Sopenharmony_ci __le64 ChangeTime; // 0x24: 90062306a36Sopenharmony_ci __le64 WarningLimit; // 0x28: 90162306a36Sopenharmony_ci __le64 HardLimit; // 0x34: 90262306a36Sopenharmony_ci __le64 ExceededTime; // 0x3C: 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci // SID is placed here 90562306a36Sopenharmony_ci}__packed; // sizeof() = 0x44 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_cistatic_assert(sizeof(struct NTFS_DE_Q) == 0x44); 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci#define SecurityDescriptorsBlockSize 0x40000 // 256K 91062306a36Sopenharmony_ci#define SecurityDescriptorMaxSize 0x20000 // 128K 91162306a36Sopenharmony_ci#define Log2OfSecurityDescriptorsBlockSize 18 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_cistruct SECURITY_KEY { 91462306a36Sopenharmony_ci __le32 hash; // Hash value for descriptor 91562306a36Sopenharmony_ci __le32 sec_id; // Security Id (guaranteed unique) 91662306a36Sopenharmony_ci}; 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci/* Security descriptors (the content of $Secure::SDS data stream) */ 91962306a36Sopenharmony_cistruct SECURITY_HDR { 92062306a36Sopenharmony_ci struct SECURITY_KEY key; // 0x00: Security Key. 92162306a36Sopenharmony_ci __le64 off; // 0x08: Offset of this entry in the file. 92262306a36Sopenharmony_ci __le32 size; // 0x10: Size of this entry, 8 byte aligned. 92362306a36Sopenharmony_ci /* 92462306a36Sopenharmony_ci * Security descriptor itself is placed here. 92562306a36Sopenharmony_ci * Total size is 16 byte aligned. 92662306a36Sopenharmony_ci */ 92762306a36Sopenharmony_ci} __packed; 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_cistatic_assert(sizeof(struct SECURITY_HDR) == 0x14); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci/* SII Directory entry structure */ 93262306a36Sopenharmony_cistruct NTFS_DE_SII { 93362306a36Sopenharmony_ci struct NTFS_DE de; 93462306a36Sopenharmony_ci __le32 sec_id; // 0x10: Key: sizeof(security_id) = wKeySize 93562306a36Sopenharmony_ci struct SECURITY_HDR sec_hdr; // 0x14: 93662306a36Sopenharmony_ci} __packed; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_cistatic_assert(offsetof(struct NTFS_DE_SII, sec_hdr) == 0x14); 93962306a36Sopenharmony_cistatic_assert(sizeof(struct NTFS_DE_SII) == 0x28); 94062306a36Sopenharmony_ci 94162306a36Sopenharmony_ci/* SDH Directory entry structure */ 94262306a36Sopenharmony_cistruct NTFS_DE_SDH { 94362306a36Sopenharmony_ci struct NTFS_DE de; 94462306a36Sopenharmony_ci struct SECURITY_KEY key; // 0x10: Key 94562306a36Sopenharmony_ci struct SECURITY_HDR sec_hdr; // 0x18: Data 94662306a36Sopenharmony_ci __le16 magic[2]; // 0x2C: 0x00490049 "I I" 94762306a36Sopenharmony_ci}; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci#define SIZEOF_SDH_DIRENTRY 0x30 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_cistruct REPARSE_KEY { 95262306a36Sopenharmony_ci __le32 ReparseTag; // 0x00: Reparse Tag 95362306a36Sopenharmony_ci struct MFT_REF ref; // 0x04: MFT record number with this file 95462306a36Sopenharmony_ci}; // sizeof() = 0x0C 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_cistatic_assert(offsetof(struct REPARSE_KEY, ref) == 0x04); 95762306a36Sopenharmony_ci#define SIZEOF_REPARSE_KEY 0x0C 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci/* Reparse Directory entry structure */ 96062306a36Sopenharmony_cistruct NTFS_DE_R { 96162306a36Sopenharmony_ci struct NTFS_DE de; 96262306a36Sopenharmony_ci struct REPARSE_KEY key; // 0x10: Reparse Key. 96362306a36Sopenharmony_ci u32 zero; // 0x1c: 96462306a36Sopenharmony_ci}; // sizeof() = 0x20 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_cistatic_assert(sizeof(struct NTFS_DE_R) == 0x20); 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci/* CompressReparseBuffer.WofVersion */ 96962306a36Sopenharmony_ci#define WOF_CURRENT_VERSION cpu_to_le32(1) 97062306a36Sopenharmony_ci/* CompressReparseBuffer.WofProvider */ 97162306a36Sopenharmony_ci#define WOF_PROVIDER_WIM cpu_to_le32(1) 97262306a36Sopenharmony_ci/* CompressReparseBuffer.WofProvider */ 97362306a36Sopenharmony_ci#define WOF_PROVIDER_SYSTEM cpu_to_le32(2) 97462306a36Sopenharmony_ci/* CompressReparseBuffer.ProviderVer */ 97562306a36Sopenharmony_ci#define WOF_PROVIDER_CURRENT_VERSION cpu_to_le32(1) 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci#define WOF_COMPRESSION_XPRESS4K cpu_to_le32(0) // 4k 97862306a36Sopenharmony_ci#define WOF_COMPRESSION_LZX32K cpu_to_le32(1) // 32k 97962306a36Sopenharmony_ci#define WOF_COMPRESSION_XPRESS8K cpu_to_le32(2) // 8k 98062306a36Sopenharmony_ci#define WOF_COMPRESSION_XPRESS16K cpu_to_le32(3) // 16k 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci/* 98362306a36Sopenharmony_ci * ATTR_REPARSE (0xC0) 98462306a36Sopenharmony_ci * 98562306a36Sopenharmony_ci * The reparse struct GUID structure is used by all 3rd party layered drivers to 98662306a36Sopenharmony_ci * store data in a reparse point. For non-Microsoft tags, The struct GUID field 98762306a36Sopenharmony_ci * cannot be GUID_NULL. 98862306a36Sopenharmony_ci * The constraints on reparse tags are defined below. 98962306a36Sopenharmony_ci * Microsoft tags can also be used with this format of the reparse point buffer. 99062306a36Sopenharmony_ci */ 99162306a36Sopenharmony_cistruct REPARSE_POINT { 99262306a36Sopenharmony_ci __le32 ReparseTag; // 0x00: 99362306a36Sopenharmony_ci __le16 ReparseDataLength;// 0x04: 99462306a36Sopenharmony_ci __le16 Reserved; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci struct GUID Guid; // 0x08: 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci // 99962306a36Sopenharmony_ci // Here GenericReparseBuffer is placed 100062306a36Sopenharmony_ci // 100162306a36Sopenharmony_ci}; 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_cistatic_assert(sizeof(struct REPARSE_POINT) == 0x18); 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci/* Maximum allowed size of the reparse data. */ 100662306a36Sopenharmony_ci#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024) 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci/* 100962306a36Sopenharmony_ci * The value of the following constant needs to satisfy the following 101062306a36Sopenharmony_ci * conditions: 101162306a36Sopenharmony_ci * (1) Be at least as large as the largest of the reserved tags. 101262306a36Sopenharmony_ci * (2) Be strictly smaller than all the tags in use. 101362306a36Sopenharmony_ci */ 101462306a36Sopenharmony_ci#define IO_REPARSE_TAG_RESERVED_RANGE 1 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci/* 101762306a36Sopenharmony_ci * The reparse tags are a ULONG. The 32 bits are laid out as follows: 101862306a36Sopenharmony_ci * 101962306a36Sopenharmony_ci * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 102062306a36Sopenharmony_ci * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 102162306a36Sopenharmony_ci * +-+-+-+-+-----------------------+-------------------------------+ 102262306a36Sopenharmony_ci * |M|R|N|R| Reserved bits | Reparse Tag Value | 102362306a36Sopenharmony_ci * +-+-+-+-+-----------------------+-------------------------------+ 102462306a36Sopenharmony_ci * 102562306a36Sopenharmony_ci * M is the Microsoft bit. When set to 1, it denotes a tag owned by Microsoft. 102662306a36Sopenharmony_ci * All ISVs must use a tag with a 0 in this position. 102762306a36Sopenharmony_ci * Note: If a Microsoft tag is used by non-Microsoft software, the 102862306a36Sopenharmony_ci * behavior is not defined. 102962306a36Sopenharmony_ci * 103062306a36Sopenharmony_ci * R is reserved. Must be zero for non-Microsoft tags. 103162306a36Sopenharmony_ci * 103262306a36Sopenharmony_ci * N is name surrogate. When set to 1, the file represents another named 103362306a36Sopenharmony_ci * entity in the system. 103462306a36Sopenharmony_ci * 103562306a36Sopenharmony_ci * The M and N bits are OR-able. 103662306a36Sopenharmony_ci * The following macros check for the M and N bit values: 103762306a36Sopenharmony_ci */ 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci/* 104062306a36Sopenharmony_ci * Macro to determine whether a reparse point tag corresponds to a tag 104162306a36Sopenharmony_ci * owned by Microsoft. 104262306a36Sopenharmony_ci */ 104362306a36Sopenharmony_ci#define IsReparseTagMicrosoft(_tag) (((_tag)&IO_REPARSE_TAG_MICROSOFT)) 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci/* Macro to determine whether a reparse point tag is a name surrogate. */ 104662306a36Sopenharmony_ci#define IsReparseTagNameSurrogate(_tag) (((_tag)&IO_REPARSE_TAG_NAME_SURROGATE)) 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci/* 104962306a36Sopenharmony_ci * The following constant represents the bits that are valid to use in 105062306a36Sopenharmony_ci * reparse tags. 105162306a36Sopenharmony_ci */ 105262306a36Sopenharmony_ci#define IO_REPARSE_TAG_VALID_VALUES 0xF000FFFF 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci/* 105562306a36Sopenharmony_ci * Macro to determine whether a reparse tag is a valid tag. 105662306a36Sopenharmony_ci */ 105762306a36Sopenharmony_ci#define IsReparseTagValid(_tag) \ 105862306a36Sopenharmony_ci (!((_tag) & ~IO_REPARSE_TAG_VALID_VALUES) && \ 105962306a36Sopenharmony_ci ((_tag) > IO_REPARSE_TAG_RESERVED_RANGE)) 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci/* Microsoft tags for reparse points. */ 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_cienum IO_REPARSE_TAG { 106462306a36Sopenharmony_ci IO_REPARSE_TAG_SYMBOLIC_LINK = cpu_to_le32(0), 106562306a36Sopenharmony_ci IO_REPARSE_TAG_NAME_SURROGATE = cpu_to_le32(0x20000000), 106662306a36Sopenharmony_ci IO_REPARSE_TAG_MICROSOFT = cpu_to_le32(0x80000000), 106762306a36Sopenharmony_ci IO_REPARSE_TAG_MOUNT_POINT = cpu_to_le32(0xA0000003), 106862306a36Sopenharmony_ci IO_REPARSE_TAG_SYMLINK = cpu_to_le32(0xA000000C), 106962306a36Sopenharmony_ci IO_REPARSE_TAG_HSM = cpu_to_le32(0xC0000004), 107062306a36Sopenharmony_ci IO_REPARSE_TAG_SIS = cpu_to_le32(0x80000007), 107162306a36Sopenharmony_ci IO_REPARSE_TAG_DEDUP = cpu_to_le32(0x80000013), 107262306a36Sopenharmony_ci IO_REPARSE_TAG_COMPRESS = cpu_to_le32(0x80000017), 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci /* 107562306a36Sopenharmony_ci * The reparse tag 0x80000008 is reserved for Microsoft internal use. 107662306a36Sopenharmony_ci * May be published in the future. 107762306a36Sopenharmony_ci */ 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci /* Microsoft reparse tag reserved for DFS */ 108062306a36Sopenharmony_ci IO_REPARSE_TAG_DFS = cpu_to_le32(0x8000000A), 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci /* Microsoft reparse tag reserved for the file system filter manager. */ 108362306a36Sopenharmony_ci IO_REPARSE_TAG_FILTER_MANAGER = cpu_to_le32(0x8000000B), 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci /* Non-Microsoft tags for reparse points */ 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci /* Tag allocated to CONGRUENT, May 2000. Used by IFSTEST. */ 108862306a36Sopenharmony_ci IO_REPARSE_TAG_IFSTEST_CONGRUENT = cpu_to_le32(0x00000009), 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci /* Tag allocated to ARKIVIO. */ 109162306a36Sopenharmony_ci IO_REPARSE_TAG_ARKIVIO = cpu_to_le32(0x0000000C), 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci /* Tag allocated to SOLUTIONSOFT. */ 109462306a36Sopenharmony_ci IO_REPARSE_TAG_SOLUTIONSOFT = cpu_to_le32(0x2000000D), 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci /* Tag allocated to COMMVAULT. */ 109762306a36Sopenharmony_ci IO_REPARSE_TAG_COMMVAULT = cpu_to_le32(0x0000000E), 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci /* OneDrive?? */ 110062306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD = cpu_to_le32(0x9000001A), 110162306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_1 = cpu_to_le32(0x9000101A), 110262306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_2 = cpu_to_le32(0x9000201A), 110362306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_3 = cpu_to_le32(0x9000301A), 110462306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_4 = cpu_to_le32(0x9000401A), 110562306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_5 = cpu_to_le32(0x9000501A), 110662306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_6 = cpu_to_le32(0x9000601A), 110762306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_7 = cpu_to_le32(0x9000701A), 110862306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_8 = cpu_to_le32(0x9000801A), 110962306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_9 = cpu_to_le32(0x9000901A), 111062306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_A = cpu_to_le32(0x9000A01A), 111162306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_B = cpu_to_le32(0x9000B01A), 111262306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_C = cpu_to_le32(0x9000C01A), 111362306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_D = cpu_to_le32(0x9000D01A), 111462306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_E = cpu_to_le32(0x9000E01A), 111562306a36Sopenharmony_ci IO_REPARSE_TAG_CLOUD_F = cpu_to_le32(0x9000F01A), 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci}; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci#define SYMLINK_FLAG_RELATIVE 1 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci/* Microsoft reparse buffer. (see DDK for details) */ 112262306a36Sopenharmony_cistruct REPARSE_DATA_BUFFER { 112362306a36Sopenharmony_ci __le32 ReparseTag; // 0x00: 112462306a36Sopenharmony_ci __le16 ReparseDataLength; // 0x04: 112562306a36Sopenharmony_ci __le16 Reserved; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci union { 112862306a36Sopenharmony_ci /* If ReparseTag == 0xA0000003 (IO_REPARSE_TAG_MOUNT_POINT) */ 112962306a36Sopenharmony_ci struct { 113062306a36Sopenharmony_ci __le16 SubstituteNameOffset; // 0x08 113162306a36Sopenharmony_ci __le16 SubstituteNameLength; // 0x0A 113262306a36Sopenharmony_ci __le16 PrintNameOffset; // 0x0C 113362306a36Sopenharmony_ci __le16 PrintNameLength; // 0x0E 113462306a36Sopenharmony_ci __le16 PathBuffer[]; // 0x10 113562306a36Sopenharmony_ci } MountPointReparseBuffer; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci /* 113862306a36Sopenharmony_ci * If ReparseTag == 0xA000000C (IO_REPARSE_TAG_SYMLINK) 113962306a36Sopenharmony_ci * https://msdn.microsoft.com/en-us/library/cc232006.aspx 114062306a36Sopenharmony_ci */ 114162306a36Sopenharmony_ci struct { 114262306a36Sopenharmony_ci __le16 SubstituteNameOffset; // 0x08 114362306a36Sopenharmony_ci __le16 SubstituteNameLength; // 0x0A 114462306a36Sopenharmony_ci __le16 PrintNameOffset; // 0x0C 114562306a36Sopenharmony_ci __le16 PrintNameLength; // 0x0E 114662306a36Sopenharmony_ci // 0-absolute path 1- relative path, SYMLINK_FLAG_RELATIVE 114762306a36Sopenharmony_ci __le32 Flags; // 0x10 114862306a36Sopenharmony_ci __le16 PathBuffer[]; // 0x14 114962306a36Sopenharmony_ci } SymbolicLinkReparseBuffer; 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_ci /* If ReparseTag == 0x80000017U */ 115262306a36Sopenharmony_ci struct { 115362306a36Sopenharmony_ci __le32 WofVersion; // 0x08 == 1 115462306a36Sopenharmony_ci /* 115562306a36Sopenharmony_ci * 1 - WIM backing provider ("WIMBoot"), 115662306a36Sopenharmony_ci * 2 - System compressed file provider 115762306a36Sopenharmony_ci */ 115862306a36Sopenharmony_ci __le32 WofProvider; // 0x0C: 115962306a36Sopenharmony_ci __le32 ProviderVer; // 0x10: == 1 WOF_FILE_PROVIDER_CURRENT_VERSION == 1 116062306a36Sopenharmony_ci __le32 CompressionFormat; // 0x14: 0, 1, 2, 3. See WOF_COMPRESSION_XXX 116162306a36Sopenharmony_ci } CompressReparseBuffer; 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci struct { 116462306a36Sopenharmony_ci u8 DataBuffer[1]; // 0x08: 116562306a36Sopenharmony_ci } GenericReparseBuffer; 116662306a36Sopenharmony_ci }; 116762306a36Sopenharmony_ci}; 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci/* ATTR_EA_INFO (0xD0) */ 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci#define FILE_NEED_EA 0x80 // See ntifs.h 117262306a36Sopenharmony_ci/* 117362306a36Sopenharmony_ci * FILE_NEED_EA, indicates that the file to which the EA belongs cannot be 117462306a36Sopenharmony_ci * interpreted without understanding the associated extended attributes. 117562306a36Sopenharmony_ci */ 117662306a36Sopenharmony_cistruct EA_INFO { 117762306a36Sopenharmony_ci __le16 size_pack; // 0x00: Size of buffer to hold in packed form. 117862306a36Sopenharmony_ci __le16 count; // 0x02: Count of EA's with FILE_NEED_EA bit set. 117962306a36Sopenharmony_ci __le32 size; // 0x04: Size of buffer to hold in unpacked form. 118062306a36Sopenharmony_ci}; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_cistatic_assert(sizeof(struct EA_INFO) == 8); 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci/* ATTR_EA (0xE0) */ 118562306a36Sopenharmony_cistruct EA_FULL { 118662306a36Sopenharmony_ci __le32 size; // 0x00: (not in packed) 118762306a36Sopenharmony_ci u8 flags; // 0x04: 118862306a36Sopenharmony_ci u8 name_len; // 0x05: 118962306a36Sopenharmony_ci __le16 elength; // 0x06: 119062306a36Sopenharmony_ci u8 name[]; // 0x08: 119162306a36Sopenharmony_ci}; 119262306a36Sopenharmony_ci 119362306a36Sopenharmony_cistatic_assert(offsetof(struct EA_FULL, name) == 8); 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci#define ACL_REVISION 2 119662306a36Sopenharmony_ci#define ACL_REVISION_DS 4 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci#define SE_SELF_RELATIVE cpu_to_le16(0x8000) 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_cistruct SECURITY_DESCRIPTOR_RELATIVE { 120162306a36Sopenharmony_ci u8 Revision; 120262306a36Sopenharmony_ci u8 Sbz1; 120362306a36Sopenharmony_ci __le16 Control; 120462306a36Sopenharmony_ci __le32 Owner; 120562306a36Sopenharmony_ci __le32 Group; 120662306a36Sopenharmony_ci __le32 Sacl; 120762306a36Sopenharmony_ci __le32 Dacl; 120862306a36Sopenharmony_ci}; 120962306a36Sopenharmony_cistatic_assert(sizeof(struct SECURITY_DESCRIPTOR_RELATIVE) == 0x14); 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_cistruct ACE_HEADER { 121262306a36Sopenharmony_ci u8 AceType; 121362306a36Sopenharmony_ci u8 AceFlags; 121462306a36Sopenharmony_ci __le16 AceSize; 121562306a36Sopenharmony_ci}; 121662306a36Sopenharmony_cistatic_assert(sizeof(struct ACE_HEADER) == 4); 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_cistruct ACL { 121962306a36Sopenharmony_ci u8 AclRevision; 122062306a36Sopenharmony_ci u8 Sbz1; 122162306a36Sopenharmony_ci __le16 AclSize; 122262306a36Sopenharmony_ci __le16 AceCount; 122362306a36Sopenharmony_ci __le16 Sbz2; 122462306a36Sopenharmony_ci}; 122562306a36Sopenharmony_cistatic_assert(sizeof(struct ACL) == 8); 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_cistruct SID { 122862306a36Sopenharmony_ci u8 Revision; 122962306a36Sopenharmony_ci u8 SubAuthorityCount; 123062306a36Sopenharmony_ci u8 IdentifierAuthority[6]; 123162306a36Sopenharmony_ci __le32 SubAuthority[]; 123262306a36Sopenharmony_ci}; 123362306a36Sopenharmony_cistatic_assert(offsetof(struct SID, SubAuthority) == 8); 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci#endif /* _LINUX_NTFS3_NTFS_H */ 123662306a36Sopenharmony_ci// clang-format on 1237