ntfs.h (37068B)
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * 4 * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved. 5 * 6 * on-disk ntfs structs 7 */ 8 9// clang-format off 10#ifndef _LINUX_NTFS3_NTFS_H 11#define _LINUX_NTFS3_NTFS_H 12 13#include <linux/blkdev.h> 14#include <linux/build_bug.h> 15#include <linux/kernel.h> 16#include <linux/stddef.h> 17#include <linux/string.h> 18#include <linux/types.h> 19 20#include "debug.h" 21 22/* TODO: Check 4K MFT record and 512 bytes cluster. */ 23 24/* Check each run for marked clusters. */ 25#define NTFS3_CHECK_FREE_CLST 26 27#define NTFS_NAME_LEN 255 28 29/* 30 * ntfs.sys used 500 maximum links on-disk struct allows up to 0xffff. 31 * xfstest generic/041 creates 3003 hardlinks. 32 */ 33#define NTFS_LINK_MAX 4000 34 35/* 36 * Activate to use 64 bit clusters instead of 32 bits in ntfs.sys. 37 * Logical and virtual cluster number if needed, may be 38 * redefined to use 64 bit value. 39 */ 40//#define CONFIG_NTFS3_64BIT_CLUSTER 41 42#define NTFS_LZNT_MAX_CLUSTER 4096 43#define NTFS_LZNT_CUNIT 4 44#define NTFS_LZNT_CLUSTERS (1u<<NTFS_LZNT_CUNIT) 45 46struct GUID { 47 __le32 Data1; 48 __le16 Data2; 49 __le16 Data3; 50 u8 Data4[8]; 51}; 52 53/* 54 * This struct repeats layout of ATTR_FILE_NAME 55 * at offset 0x40. 56 * It used to store global constants NAME_MFT/NAME_MIRROR... 57 * most constant names are shorter than 10. 58 */ 59struct cpu_str { 60 u8 len; 61 u8 unused; 62 u16 name[10]; 63}; 64 65struct le_str { 66 u8 len; 67 u8 unused; 68 __le16 name[]; 69}; 70 71static_assert(SECTOR_SHIFT == 9); 72 73#ifdef CONFIG_NTFS3_64BIT_CLUSTER 74typedef u64 CLST; 75static_assert(sizeof(size_t) == 8); 76#else 77typedef u32 CLST; 78#endif 79 80#define SPARSE_LCN64 ((u64)-1) 81#define SPARSE_LCN ((CLST)-1) 82#define RESIDENT_LCN ((CLST)-2) 83#define COMPRESSED_LCN ((CLST)-3) 84 85#define COMPRESSION_UNIT 4 86#define COMPRESS_MAX_CLUSTER 0x1000 87#define MFT_INCREASE_CHUNK 1024 88 89enum RECORD_NUM { 90 MFT_REC_MFT = 0, 91 MFT_REC_MIRR = 1, 92 MFT_REC_LOG = 2, 93 MFT_REC_VOL = 3, 94 MFT_REC_ATTR = 4, 95 MFT_REC_ROOT = 5, 96 MFT_REC_BITMAP = 6, 97 MFT_REC_BOOT = 7, 98 MFT_REC_BADCLUST = 8, 99 //MFT_REC_QUOTA = 9, 100 MFT_REC_SECURE = 9, // NTFS 3.0 101 MFT_REC_UPCASE = 10, 102 MFT_REC_EXTEND = 11, // NTFS 3.0 103 MFT_REC_RESERVED = 11, 104 MFT_REC_FREE = 16, 105 MFT_REC_USER = 24, 106}; 107 108enum ATTR_TYPE { 109 ATTR_ZERO = cpu_to_le32(0x00), 110 ATTR_STD = cpu_to_le32(0x10), 111 ATTR_LIST = cpu_to_le32(0x20), 112 ATTR_NAME = cpu_to_le32(0x30), 113 // ATTR_VOLUME_VERSION on Nt4 114 ATTR_ID = cpu_to_le32(0x40), 115 ATTR_SECURE = cpu_to_le32(0x50), 116 ATTR_LABEL = cpu_to_le32(0x60), 117 ATTR_VOL_INFO = cpu_to_le32(0x70), 118 ATTR_DATA = cpu_to_le32(0x80), 119 ATTR_ROOT = cpu_to_le32(0x90), 120 ATTR_ALLOC = cpu_to_le32(0xA0), 121 ATTR_BITMAP = cpu_to_le32(0xB0), 122 // ATTR_SYMLINK on Nt4 123 ATTR_REPARSE = cpu_to_le32(0xC0), 124 ATTR_EA_INFO = cpu_to_le32(0xD0), 125 ATTR_EA = cpu_to_le32(0xE0), 126 ATTR_PROPERTYSET = cpu_to_le32(0xF0), 127 ATTR_LOGGED_UTILITY_STREAM = cpu_to_le32(0x100), 128 ATTR_END = cpu_to_le32(0xFFFFFFFF) 129}; 130 131static_assert(sizeof(enum ATTR_TYPE) == 4); 132 133enum FILE_ATTRIBUTE { 134 FILE_ATTRIBUTE_READONLY = cpu_to_le32(0x00000001), 135 FILE_ATTRIBUTE_HIDDEN = cpu_to_le32(0x00000002), 136 FILE_ATTRIBUTE_SYSTEM = cpu_to_le32(0x00000004), 137 FILE_ATTRIBUTE_ARCHIVE = cpu_to_le32(0x00000020), 138 FILE_ATTRIBUTE_DEVICE = cpu_to_le32(0x00000040), 139 FILE_ATTRIBUTE_TEMPORARY = cpu_to_le32(0x00000100), 140 FILE_ATTRIBUTE_SPARSE_FILE = cpu_to_le32(0x00000200), 141 FILE_ATTRIBUTE_REPARSE_POINT = cpu_to_le32(0x00000400), 142 FILE_ATTRIBUTE_COMPRESSED = cpu_to_le32(0x00000800), 143 FILE_ATTRIBUTE_OFFLINE = cpu_to_le32(0x00001000), 144 FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = cpu_to_le32(0x00002000), 145 FILE_ATTRIBUTE_ENCRYPTED = cpu_to_le32(0x00004000), 146 FILE_ATTRIBUTE_VALID_FLAGS = cpu_to_le32(0x00007fb7), 147 FILE_ATTRIBUTE_DIRECTORY = cpu_to_le32(0x10000000), 148}; 149 150static_assert(sizeof(enum FILE_ATTRIBUTE) == 4); 151 152extern const struct cpu_str NAME_MFT; 153extern const struct cpu_str NAME_MIRROR; 154extern const struct cpu_str NAME_LOGFILE; 155extern const struct cpu_str NAME_VOLUME; 156extern const struct cpu_str NAME_ATTRDEF; 157extern const struct cpu_str NAME_ROOT; 158extern const struct cpu_str NAME_BITMAP; 159extern const struct cpu_str NAME_BOOT; 160extern const struct cpu_str NAME_BADCLUS; 161extern const struct cpu_str NAME_QUOTA; 162extern const struct cpu_str NAME_SECURE; 163extern const struct cpu_str NAME_UPCASE; 164extern const struct cpu_str NAME_EXTEND; 165extern const struct cpu_str NAME_OBJID; 166extern const struct cpu_str NAME_REPARSE; 167extern const struct cpu_str NAME_USNJRNL; 168 169extern const __le16 I30_NAME[4]; 170extern const __le16 SII_NAME[4]; 171extern const __le16 SDH_NAME[4]; 172extern const __le16 SO_NAME[2]; 173extern const __le16 SQ_NAME[2]; 174extern const __le16 SR_NAME[2]; 175 176extern const __le16 BAD_NAME[4]; 177extern const __le16 SDS_NAME[4]; 178extern const __le16 WOF_NAME[17]; /* WofCompressedData */ 179 180/* MFT record number structure. */ 181struct MFT_REF { 182 __le32 low; // The low part of the number. 183 __le16 high; // The high part of the number. 184 __le16 seq; // The sequence number of MFT record. 185}; 186 187static_assert(sizeof(__le64) == sizeof(struct MFT_REF)); 188 189static inline CLST ino_get(const struct MFT_REF *ref) 190{ 191#ifdef CONFIG_NTFS3_64BIT_CLUSTER 192 return le32_to_cpu(ref->low) | ((u64)le16_to_cpu(ref->high) << 32); 193#else 194 return le32_to_cpu(ref->low); 195#endif 196} 197 198struct NTFS_BOOT { 199 u8 jump_code[3]; // 0x00: Jump to boot code. 200 u8 system_id[8]; // 0x03: System ID, equals "NTFS " 201 202 // NOTE: This member is not aligned(!) 203 // bytes_per_sector[0] must be 0. 204 // bytes_per_sector[1] must be multiplied by 256. 205 u8 bytes_per_sector[2]; // 0x0B: Bytes per sector. 206 207 u8 sectors_per_clusters;// 0x0D: Sectors per cluster. 208 u8 unused1[7]; 209 u8 media_type; // 0x15: Media type (0xF8 - harddisk) 210 u8 unused2[2]; 211 __le16 sct_per_track; // 0x18: number of sectors per track. 212 __le16 heads; // 0x1A: number of heads per cylinder. 213 __le32 hidden_sectors; // 0x1C: number of 'hidden' sectors. 214 u8 unused3[4]; 215 u8 bios_drive_num; // 0x24: BIOS drive number =0x80. 216 u8 unused4; 217 u8 signature_ex; // 0x26: Extended BOOT signature =0x80. 218 u8 unused5; 219 __le64 sectors_per_volume;// 0x28: Size of volume in sectors. 220 __le64 mft_clst; // 0x30: First cluster of $MFT 221 __le64 mft2_clst; // 0x38: First cluster of $MFTMirr 222 s8 record_size; // 0x40: Size of MFT record in clusters(sectors). 223 u8 unused6[3]; 224 s8 index_size; // 0x44: Size of INDX record in clusters(sectors). 225 u8 unused7[3]; 226 __le64 serial_num; // 0x48: Volume serial number 227 __le32 check_sum; // 0x50: Simple additive checksum of all 228 // of the u32's which precede the 'check_sum'. 229 230 u8 boot_code[0x200 - 0x50 - 2 - 4]; // 0x54: 231 u8 boot_magic[2]; // 0x1FE: Boot signature =0x55 + 0xAA 232}; 233 234static_assert(sizeof(struct NTFS_BOOT) == 0x200); 235 236enum NTFS_SIGNATURE { 237 NTFS_FILE_SIGNATURE = cpu_to_le32(0x454C4946), // 'FILE' 238 NTFS_INDX_SIGNATURE = cpu_to_le32(0x58444E49), // 'INDX' 239 NTFS_CHKD_SIGNATURE = cpu_to_le32(0x444B4843), // 'CHKD' 240 NTFS_RSTR_SIGNATURE = cpu_to_le32(0x52545352), // 'RSTR' 241 NTFS_RCRD_SIGNATURE = cpu_to_le32(0x44524352), // 'RCRD' 242 NTFS_BAAD_SIGNATURE = cpu_to_le32(0x44414142), // 'BAAD' 243 NTFS_HOLE_SIGNATURE = cpu_to_le32(0x454C4F48), // 'HOLE' 244 NTFS_FFFF_SIGNATURE = cpu_to_le32(0xffffffff), 245}; 246 247static_assert(sizeof(enum NTFS_SIGNATURE) == 4); 248 249/* MFT Record header structure. */ 250struct NTFS_RECORD_HEADER { 251 /* Record magic number, equals 'FILE'/'INDX'/'RSTR'/'RCRD'. */ 252 enum NTFS_SIGNATURE sign; // 0x00: 253 __le16 fix_off; // 0x04: 254 __le16 fix_num; // 0x06: 255 __le64 lsn; // 0x08: Log file sequence number, 256}; 257 258static_assert(sizeof(struct NTFS_RECORD_HEADER) == 0x10); 259 260static inline int is_baad(const struct NTFS_RECORD_HEADER *hdr) 261{ 262 return hdr->sign == NTFS_BAAD_SIGNATURE; 263} 264 265/* Possible bits in struct MFT_REC.flags. */ 266enum RECORD_FLAG { 267 RECORD_FLAG_IN_USE = cpu_to_le16(0x0001), 268 RECORD_FLAG_DIR = cpu_to_le16(0x0002), 269 RECORD_FLAG_SYSTEM = cpu_to_le16(0x0004), 270 RECORD_FLAG_UNKNOWN = cpu_to_le16(0x0008), 271}; 272 273/* MFT Record structure. */ 274struct MFT_REC { 275 struct NTFS_RECORD_HEADER rhdr; // 'FILE' 276 277 __le16 seq; // 0x10: Sequence number for this record. 278 __le16 hard_links; // 0x12: The number of hard links to record. 279 __le16 attr_off; // 0x14: Offset to attributes. 280 __le16 flags; // 0x16: See RECORD_FLAG. 281 __le32 used; // 0x18: The size of used part. 282 __le32 total; // 0x1C: Total record size. 283 284 struct MFT_REF parent_ref; // 0x20: Parent MFT record. 285 __le16 next_attr_id; // 0x28: The next attribute Id. 286 287 __le16 res; // 0x2A: High part of MFT record? 288 __le32 mft_record; // 0x2C: Current MFT record number. 289 __le16 fixups[]; // 0x30: 290}; 291 292#define MFTRECORD_FIXUP_OFFSET_1 offsetof(struct MFT_REC, res) 293#define MFTRECORD_FIXUP_OFFSET_3 offsetof(struct MFT_REC, fixups) 294 295static_assert(MFTRECORD_FIXUP_OFFSET_1 == 0x2A); 296static_assert(MFTRECORD_FIXUP_OFFSET_3 == 0x30); 297 298static inline bool is_rec_base(const struct MFT_REC *rec) 299{ 300 const struct MFT_REF *r = &rec->parent_ref; 301 302 return !r->low && !r->high && !r->seq; 303} 304 305static inline bool is_mft_rec5(const struct MFT_REC *rec) 306{ 307 return le16_to_cpu(rec->rhdr.fix_off) >= 308 offsetof(struct MFT_REC, fixups); 309} 310 311static inline bool is_rec_inuse(const struct MFT_REC *rec) 312{ 313 return rec->flags & RECORD_FLAG_IN_USE; 314} 315 316static inline bool clear_rec_inuse(struct MFT_REC *rec) 317{ 318 return rec->flags &= ~RECORD_FLAG_IN_USE; 319} 320 321/* Possible values of ATTR_RESIDENT.flags */ 322#define RESIDENT_FLAG_INDEXED 0x01 323 324struct ATTR_RESIDENT { 325 __le32 data_size; // 0x10: The size of data. 326 __le16 data_off; // 0x14: Offset to data. 327 u8 flags; // 0x16: Resident flags ( 1 - indexed ). 328 u8 res; // 0x17: 329}; // sizeof() = 0x18 330 331struct ATTR_NONRESIDENT { 332 __le64 svcn; // 0x10: Starting VCN of this segment. 333 __le64 evcn; // 0x18: End VCN of this segment. 334 __le16 run_off; // 0x20: Offset to packed runs. 335 // Unit of Compression size for this stream, expressed 336 // as a log of the cluster size. 337 // 338 // 0 means file is not compressed 339 // 1, 2, 3, and 4 are potentially legal values if the 340 // stream is compressed, however the implementation 341 // may only choose to use 4, or possibly 3. Note 342 // that 4 means cluster size time 16. If convenient 343 // the implementation may wish to accept a 344 // reasonable range of legal values here (1-5?), 345 // even if the implementation only generates 346 // a smaller set of values itself. 347 u8 c_unit; // 0x22: 348 u8 res1[5]; // 0x23: 349 __le64 alloc_size; // 0x28: The allocated size of attribute in bytes. 350 // (multiple of cluster size) 351 __le64 data_size; // 0x30: The size of attribute in bytes <= alloc_size. 352 __le64 valid_size; // 0x38: The size of valid part in bytes <= data_size. 353 __le64 total_size; // 0x40: The sum of the allocated clusters for a file. 354 // (present only for the first segment (0 == vcn) 355 // of compressed attribute) 356 357}; // sizeof()=0x40 or 0x48 (if compressed) 358 359/* Possible values of ATTRIB.flags: */ 360#define ATTR_FLAG_COMPRESSED cpu_to_le16(0x0001) 361#define ATTR_FLAG_COMPRESSED_MASK cpu_to_le16(0x00FF) 362#define ATTR_FLAG_ENCRYPTED cpu_to_le16(0x4000) 363#define ATTR_FLAG_SPARSED cpu_to_le16(0x8000) 364 365struct ATTRIB { 366 enum ATTR_TYPE type; // 0x00: The type of this attribute. 367 __le32 size; // 0x04: The size of this attribute. 368 u8 non_res; // 0x08: Is this attribute non-resident? 369 u8 name_len; // 0x09: This attribute name length. 370 __le16 name_off; // 0x0A: Offset to the attribute name. 371 __le16 flags; // 0x0C: See ATTR_FLAG_XXX. 372 __le16 id; // 0x0E: Unique id (per record). 373 374 union { 375 struct ATTR_RESIDENT res; // 0x10 376 struct ATTR_NONRESIDENT nres; // 0x10 377 }; 378}; 379 380/* Define attribute sizes. */ 381#define SIZEOF_RESIDENT 0x18 382#define SIZEOF_NONRESIDENT_EX 0x48 383#define SIZEOF_NONRESIDENT 0x40 384 385#define SIZEOF_RESIDENT_LE cpu_to_le16(0x18) 386#define SIZEOF_NONRESIDENT_EX_LE cpu_to_le16(0x48) 387#define SIZEOF_NONRESIDENT_LE cpu_to_le16(0x40) 388 389static inline u64 attr_ondisk_size(const struct ATTRIB *attr) 390{ 391 return attr->non_res ? ((attr->flags & 392 (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED)) ? 393 le64_to_cpu(attr->nres.total_size) : 394 le64_to_cpu(attr->nres.alloc_size)) 395 : ALIGN(le32_to_cpu(attr->res.data_size), 8); 396} 397 398static inline u64 attr_size(const struct ATTRIB *attr) 399{ 400 return attr->non_res ? le64_to_cpu(attr->nres.data_size) : 401 le32_to_cpu(attr->res.data_size); 402} 403 404static inline bool is_attr_encrypted(const struct ATTRIB *attr) 405{ 406 return attr->flags & ATTR_FLAG_ENCRYPTED; 407} 408 409static inline bool is_attr_sparsed(const struct ATTRIB *attr) 410{ 411 return attr->flags & ATTR_FLAG_SPARSED; 412} 413 414static inline bool is_attr_compressed(const struct ATTRIB *attr) 415{ 416 return attr->flags & ATTR_FLAG_COMPRESSED; 417} 418 419static inline bool is_attr_ext(const struct ATTRIB *attr) 420{ 421 return attr->flags & (ATTR_FLAG_SPARSED | ATTR_FLAG_COMPRESSED); 422} 423 424static inline bool is_attr_indexed(const struct ATTRIB *attr) 425{ 426 return !attr->non_res && (attr->res.flags & RESIDENT_FLAG_INDEXED); 427} 428 429static inline __le16 const *attr_name(const struct ATTRIB *attr) 430{ 431 return Add2Ptr(attr, le16_to_cpu(attr->name_off)); 432} 433 434static inline u64 attr_svcn(const struct ATTRIB *attr) 435{ 436 return attr->non_res ? le64_to_cpu(attr->nres.svcn) : 0; 437} 438 439/* The size of resident attribute by its resident size. */ 440#define BYTES_PER_RESIDENT(b) (0x18 + (b)) 441 442static_assert(sizeof(struct ATTRIB) == 0x48); 443static_assert(sizeof(((struct ATTRIB *)NULL)->res) == 0x08); 444static_assert(sizeof(((struct ATTRIB *)NULL)->nres) == 0x38); 445 446static inline void *resident_data_ex(const struct ATTRIB *attr, u32 datasize) 447{ 448 u32 asize, rsize; 449 u16 off; 450 451 if (attr->non_res) 452 return NULL; 453 454 asize = le32_to_cpu(attr->size); 455 off = le16_to_cpu(attr->res.data_off); 456 457 if (asize < datasize + off) 458 return NULL; 459 460 rsize = le32_to_cpu(attr->res.data_size); 461 if (rsize < datasize) 462 return NULL; 463 464 return Add2Ptr(attr, off); 465} 466 467static inline void *resident_data(const struct ATTRIB *attr) 468{ 469 return Add2Ptr(attr, le16_to_cpu(attr->res.data_off)); 470} 471 472static inline void *attr_run(const struct ATTRIB *attr) 473{ 474 return Add2Ptr(attr, le16_to_cpu(attr->nres.run_off)); 475} 476 477/* Standard information attribute (0x10). */ 478struct ATTR_STD_INFO { 479 __le64 cr_time; // 0x00: File creation file. 480 __le64 m_time; // 0x08: File modification time. 481 __le64 c_time; // 0x10: Last time any attribute was modified. 482 __le64 a_time; // 0x18: File last access time. 483 enum FILE_ATTRIBUTE fa; // 0x20: Standard DOS attributes & more. 484 __le32 max_ver_num; // 0x24: Maximum Number of Versions. 485 __le32 ver_num; // 0x28: Version Number. 486 __le32 class_id; // 0x2C: Class Id from bidirectional Class Id index. 487}; 488 489static_assert(sizeof(struct ATTR_STD_INFO) == 0x30); 490 491#define SECURITY_ID_INVALID 0x00000000 492#define SECURITY_ID_FIRST 0x00000100 493 494struct ATTR_STD_INFO5 { 495 __le64 cr_time; // 0x00: File creation file. 496 __le64 m_time; // 0x08: File modification time. 497 __le64 c_time; // 0x10: Last time any attribute was modified. 498 __le64 a_time; // 0x18: File last access time. 499 enum FILE_ATTRIBUTE fa; // 0x20: Standard DOS attributes & more. 500 __le32 max_ver_num; // 0x24: Maximum Number of Versions. 501 __le32 ver_num; // 0x28: Version Number. 502 __le32 class_id; // 0x2C: Class Id from bidirectional Class Id index. 503 504 __le32 owner_id; // 0x30: Owner Id of the user owning the file. 505 __le32 security_id; // 0x34: The Security Id is a key in the $SII Index and $SDS. 506 __le64 quota_charge; // 0x38: 507 __le64 usn; // 0x40: Last Update Sequence Number of the file. This is a direct 508 // index into the file $UsnJrnl. If zero, the USN Journal is 509 // disabled. 510}; 511 512static_assert(sizeof(struct ATTR_STD_INFO5) == 0x48); 513 514/* Attribute list entry structure (0x20) */ 515struct ATTR_LIST_ENTRY { 516 enum ATTR_TYPE type; // 0x00: The type of attribute. 517 __le16 size; // 0x04: The size of this record. 518 u8 name_len; // 0x06: The length of attribute name. 519 u8 name_off; // 0x07: The offset to attribute name. 520 __le64 vcn; // 0x08: Starting VCN of this attribute. 521 struct MFT_REF ref; // 0x10: MFT record number with attribute. 522 __le16 id; // 0x18: struct ATTRIB ID. 523 __le16 name[3]; // 0x1A: Just to align. To get real name can use bNameOffset. 524 525}; // sizeof(0x20) 526 527static_assert(sizeof(struct ATTR_LIST_ENTRY) == 0x20); 528 529static inline u32 le_size(u8 name_len) 530{ 531 return ALIGN(offsetof(struct ATTR_LIST_ENTRY, name) + 532 name_len * sizeof(short), 8); 533} 534 535/* Returns 0 if 'attr' has the same type and name. */ 536static inline int le_cmp(const struct ATTR_LIST_ENTRY *le, 537 const struct ATTRIB *attr) 538{ 539 return le->type != attr->type || le->name_len != attr->name_len || 540 (!le->name_len && 541 memcmp(Add2Ptr(le, le->name_off), 542 Add2Ptr(attr, le16_to_cpu(attr->name_off)), 543 le->name_len * sizeof(short))); 544} 545 546static inline __le16 const *le_name(const struct ATTR_LIST_ENTRY *le) 547{ 548 return Add2Ptr(le, le->name_off); 549} 550 551/* File name types (the field type in struct ATTR_FILE_NAME). */ 552#define FILE_NAME_POSIX 0 553#define FILE_NAME_UNICODE 1 554#define FILE_NAME_DOS 2 555#define FILE_NAME_UNICODE_AND_DOS (FILE_NAME_DOS | FILE_NAME_UNICODE) 556 557/* Filename attribute structure (0x30). */ 558struct NTFS_DUP_INFO { 559 __le64 cr_time; // 0x00: File creation file. 560 __le64 m_time; // 0x08: File modification time. 561 __le64 c_time; // 0x10: Last time any attribute was modified. 562 __le64 a_time; // 0x18: File last access time. 563 __le64 alloc_size; // 0x20: Data attribute allocated size, multiple of cluster size. 564 __le64 data_size; // 0x28: Data attribute size <= Dataalloc_size. 565 enum FILE_ATTRIBUTE fa; // 0x30: Standard DOS attributes & more. 566 __le16 ea_size; // 0x34: Packed EAs. 567 __le16 reparse; // 0x36: Used by Reparse. 568 569}; // 0x38 570 571struct ATTR_FILE_NAME { 572 struct MFT_REF home; // 0x00: MFT record for directory. 573 struct NTFS_DUP_INFO dup;// 0x08: 574 u8 name_len; // 0x40: File name length in words. 575 u8 type; // 0x41: File name type. 576 __le16 name[]; // 0x42: File name. 577}; 578 579static_assert(sizeof(((struct ATTR_FILE_NAME *)NULL)->dup) == 0x38); 580static_assert(offsetof(struct ATTR_FILE_NAME, name) == 0x42); 581#define SIZEOF_ATTRIBUTE_FILENAME 0x44 582#define SIZEOF_ATTRIBUTE_FILENAME_MAX (0x42 + 255 * 2) 583 584static inline struct ATTRIB *attr_from_name(struct ATTR_FILE_NAME *fname) 585{ 586 return (struct ATTRIB *)((char *)fname - SIZEOF_RESIDENT); 587} 588 589static inline u16 fname_full_size(const struct ATTR_FILE_NAME *fname) 590{ 591 /* Don't return struct_size(fname, name, fname->name_len); */ 592 return offsetof(struct ATTR_FILE_NAME, name) + 593 fname->name_len * sizeof(short); 594} 595 596static inline u8 paired_name(u8 type) 597{ 598 if (type == FILE_NAME_UNICODE) 599 return FILE_NAME_DOS; 600 if (type == FILE_NAME_DOS) 601 return FILE_NAME_UNICODE; 602 return FILE_NAME_POSIX; 603} 604 605/* Index entry defines ( the field flags in NtfsDirEntry ). */ 606#define NTFS_IE_HAS_SUBNODES cpu_to_le16(1) 607#define NTFS_IE_LAST cpu_to_le16(2) 608 609/* Directory entry structure. */ 610struct NTFS_DE { 611 union { 612 struct MFT_REF ref; // 0x00: MFT record number with this file. 613 struct { 614 __le16 data_off; // 0x00: 615 __le16 data_size; // 0x02: 616 __le32 res; // 0x04: Must be 0. 617 } view; 618 }; 619 __le16 size; // 0x08: The size of this entry. 620 __le16 key_size; // 0x0A: The size of File name length in bytes + 0x42. 621 __le16 flags; // 0x0C: Entry flags: NTFS_IE_XXX. 622 __le16 res; // 0x0E: 623 624 // Here any indexed attribute can be placed. 625 // One of them is: 626 // struct ATTR_FILE_NAME AttrFileName; 627 // 628 629 // The last 8 bytes of this structure contains 630 // the VBN of subnode. 631 // !!! Note !!! 632 // This field is presented only if (flags & NTFS_IE_HAS_SUBNODES) 633 // __le64 vbn; 634}; 635 636static_assert(sizeof(struct NTFS_DE) == 0x10); 637 638static inline void de_set_vbn_le(struct NTFS_DE *e, __le64 vcn) 639{ 640 __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64)); 641 642 *v = vcn; 643} 644 645static inline void de_set_vbn(struct NTFS_DE *e, CLST vcn) 646{ 647 __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64)); 648 649 *v = cpu_to_le64(vcn); 650} 651 652static inline __le64 de_get_vbn_le(const struct NTFS_DE *e) 653{ 654 return *(__le64 *)Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64)); 655} 656 657static inline CLST de_get_vbn(const struct NTFS_DE *e) 658{ 659 __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64)); 660 661 return le64_to_cpu(*v); 662} 663 664static inline struct NTFS_DE *de_get_next(const struct NTFS_DE *e) 665{ 666 return Add2Ptr(e, le16_to_cpu(e->size)); 667} 668 669static inline struct ATTR_FILE_NAME *de_get_fname(const struct NTFS_DE *e) 670{ 671 return le16_to_cpu(e->key_size) >= SIZEOF_ATTRIBUTE_FILENAME ? 672 Add2Ptr(e, sizeof(struct NTFS_DE)) : 673 NULL; 674} 675 676static inline bool de_is_last(const struct NTFS_DE *e) 677{ 678 return e->flags & NTFS_IE_LAST; 679} 680 681static inline bool de_has_vcn(const struct NTFS_DE *e) 682{ 683 return e->flags & NTFS_IE_HAS_SUBNODES; 684} 685 686static inline bool de_has_vcn_ex(const struct NTFS_DE *e) 687{ 688 return (e->flags & NTFS_IE_HAS_SUBNODES) && 689 (u64)(-1) != *((u64 *)Add2Ptr(e, le16_to_cpu(e->size) - 690 sizeof(__le64))); 691} 692 693#define MAX_BYTES_PER_NAME_ENTRY \ 694 ALIGN(sizeof(struct NTFS_DE) + \ 695 offsetof(struct ATTR_FILE_NAME, name) + \ 696 NTFS_NAME_LEN * sizeof(short), 8) 697 698struct INDEX_HDR { 699 __le32 de_off; // 0x00: The offset from the start of this structure 700 // to the first NTFS_DE. 701 __le32 used; // 0x04: The size of this structure plus all 702 // entries (quad-word aligned). 703 __le32 total; // 0x08: The allocated size of for this structure plus all entries. 704 u8 flags; // 0x0C: 0x00 = Small directory, 0x01 = Large directory. 705 u8 res[3]; 706 707 // 708 // de_off + used <= total 709 // 710}; 711 712static_assert(sizeof(struct INDEX_HDR) == 0x10); 713 714static inline struct NTFS_DE *hdr_first_de(const struct INDEX_HDR *hdr) 715{ 716 u32 de_off = le32_to_cpu(hdr->de_off); 717 u32 used = le32_to_cpu(hdr->used); 718 struct NTFS_DE *e = Add2Ptr(hdr, de_off); 719 u16 esize; 720 721 if (de_off >= used || de_off >= le32_to_cpu(hdr->total)) 722 return NULL; 723 724 esize = le16_to_cpu(e->size); 725 if (esize < sizeof(struct NTFS_DE) || de_off + esize > used) 726 return NULL; 727 728 return e; 729} 730 731static inline struct NTFS_DE *hdr_next_de(const struct INDEX_HDR *hdr, 732 const struct NTFS_DE *e) 733{ 734 size_t off = PtrOffset(hdr, e); 735 u32 used = le32_to_cpu(hdr->used); 736 u16 esize; 737 738 if (off >= used) 739 return NULL; 740 741 esize = le16_to_cpu(e->size); 742 743 if (esize < sizeof(struct NTFS_DE) || 744 off + esize + sizeof(struct NTFS_DE) > used) 745 return NULL; 746 747 return Add2Ptr(e, esize); 748} 749 750static inline bool hdr_has_subnode(const struct INDEX_HDR *hdr) 751{ 752 return hdr->flags & 1; 753} 754 755struct INDEX_BUFFER { 756 struct NTFS_RECORD_HEADER rhdr; // 'INDX' 757 __le64 vbn; // 0x10: vcn if index >= cluster or vsn id index < cluster 758 struct INDEX_HDR ihdr; // 0x18: 759}; 760 761static_assert(sizeof(struct INDEX_BUFFER) == 0x28); 762 763static inline bool ib_is_empty(const struct INDEX_BUFFER *ib) 764{ 765 const struct NTFS_DE *first = hdr_first_de(&ib->ihdr); 766 767 return !first || de_is_last(first); 768} 769 770static inline bool ib_is_leaf(const struct INDEX_BUFFER *ib) 771{ 772 return !(ib->ihdr.flags & 1); 773} 774 775/* Index root structure ( 0x90 ). */ 776enum COLLATION_RULE { 777 NTFS_COLLATION_TYPE_BINARY = cpu_to_le32(0), 778 // $I30 779 NTFS_COLLATION_TYPE_FILENAME = cpu_to_le32(0x01), 780 // $SII of $Secure and $Q of Quota 781 NTFS_COLLATION_TYPE_UINT = cpu_to_le32(0x10), 782 // $O of Quota 783 NTFS_COLLATION_TYPE_SID = cpu_to_le32(0x11), 784 // $SDH of $Secure 785 NTFS_COLLATION_TYPE_SECURITY_HASH = cpu_to_le32(0x12), 786 // $O of ObjId and "$R" for Reparse 787 NTFS_COLLATION_TYPE_UINTS = cpu_to_le32(0x13) 788}; 789 790static_assert(sizeof(enum COLLATION_RULE) == 4); 791 792// 793struct INDEX_ROOT { 794 enum ATTR_TYPE type; // 0x00: The type of attribute to index on. 795 enum COLLATION_RULE rule; // 0x04: The rule. 796 __le32 index_block_size;// 0x08: The size of index record. 797 u8 index_block_clst; // 0x0C: The number of clusters or sectors per index. 798 u8 res[3]; 799 struct INDEX_HDR ihdr; // 0x10: 800}; 801 802static_assert(sizeof(struct INDEX_ROOT) == 0x20); 803static_assert(offsetof(struct INDEX_ROOT, ihdr) == 0x10); 804 805#define VOLUME_FLAG_DIRTY cpu_to_le16(0x0001) 806#define VOLUME_FLAG_RESIZE_LOG_FILE cpu_to_le16(0x0002) 807 808struct VOLUME_INFO { 809 __le64 res1; // 0x00 810 u8 major_ver; // 0x08: NTFS major version number (before .) 811 u8 minor_ver; // 0x09: NTFS minor version number (after .) 812 __le16 flags; // 0x0A: Volume flags, see VOLUME_FLAG_XXX 813 814}; // sizeof=0xC 815 816#define SIZEOF_ATTRIBUTE_VOLUME_INFO 0xc 817 818#define NTFS_LABEL_MAX_LENGTH (0x100 / sizeof(short)) 819#define NTFS_ATTR_INDEXABLE cpu_to_le32(0x00000002) 820#define NTFS_ATTR_DUPALLOWED cpu_to_le32(0x00000004) 821#define NTFS_ATTR_MUST_BE_INDEXED cpu_to_le32(0x00000010) 822#define NTFS_ATTR_MUST_BE_NAMED cpu_to_le32(0x00000020) 823#define NTFS_ATTR_MUST_BE_RESIDENT cpu_to_le32(0x00000040) 824#define NTFS_ATTR_LOG_ALWAYS cpu_to_le32(0x00000080) 825 826/* $AttrDef file entry. */ 827struct ATTR_DEF_ENTRY { 828 __le16 name[0x40]; // 0x00: Attr name. 829 enum ATTR_TYPE type; // 0x80: struct ATTRIB type. 830 __le32 res; // 0x84: 831 enum COLLATION_RULE rule; // 0x88: 832 __le32 flags; // 0x8C: NTFS_ATTR_XXX (see above). 833 __le64 min_sz; // 0x90: Minimum attribute data size. 834 __le64 max_sz; // 0x98: Maximum attribute data size. 835}; 836 837static_assert(sizeof(struct ATTR_DEF_ENTRY) == 0xa0); 838 839/* Object ID (0x40) */ 840struct OBJECT_ID { 841 struct GUID ObjId; // 0x00: Unique Id assigned to file. 842 struct GUID BirthVolumeId; // 0x10: Birth Volume Id is the Object Id of the Volume on. 843 // which the Object Id was allocated. It never changes. 844 struct GUID BirthObjectId; // 0x20: Birth Object Id is the first Object Id that was 845 // ever assigned to this MFT Record. I.e. If the Object Id 846 // is changed for some reason, this field will reflect the 847 // original value of the Object Id. 848 struct GUID DomainId; // 0x30: Domain Id is currently unused but it is intended to be 849 // used in a network environment where the local machine is 850 // part of a Windows 2000 Domain. This may be used in a Windows 851 // 2000 Advanced Server managed domain. 852}; 853 854static_assert(sizeof(struct OBJECT_ID) == 0x40); 855 856/* O Directory entry structure ( rule = 0x13 ) */ 857struct NTFS_DE_O { 858 struct NTFS_DE de; 859 struct GUID ObjId; // 0x10: Unique Id assigned to file. 860 struct MFT_REF ref; // 0x20: MFT record number with this file. 861 struct GUID BirthVolumeId; // 0x28: Birth Volume Id is the Object Id of the Volume on 862 // which the Object Id was allocated. It never changes. 863 struct GUID BirthObjectId; // 0x38: Birth Object Id is the first Object Id that was 864 // ever assigned to this MFT Record. I.e. If the Object Id 865 // is changed for some reason, this field will reflect the 866 // original value of the Object Id. 867 // This field is valid if data_size == 0x48. 868 struct GUID BirthDomainId; // 0x48: Domain Id is currently unused but it is intended 869 // to be used in a network environment where the local 870 // machine is part of a Windows 2000 Domain. This may be 871 // used in a Windows 2000 Advanced Server managed domain. 872}; 873 874static_assert(sizeof(struct NTFS_DE_O) == 0x58); 875 876#define NTFS_OBJECT_ENTRY_DATA_SIZE1 \ 877 0x38 // struct NTFS_DE_O.BirthDomainId is not used 878#define NTFS_OBJECT_ENTRY_DATA_SIZE2 \ 879 0x48 // struct NTFS_DE_O.BirthDomainId is used 880 881/* Q Directory entry structure ( rule = 0x11 ) */ 882struct NTFS_DE_Q { 883 struct NTFS_DE de; 884 __le32 owner_id; // 0x10: Unique Id assigned to file 885 __le32 Version; // 0x14: 0x02 886 __le32 flags2; // 0x18: Quota flags, see above 887 __le64 BytesUsed; // 0x1C: 888 __le64 ChangeTime; // 0x24: 889 __le64 WarningLimit; // 0x28: 890 __le64 HardLimit; // 0x34: 891 __le64 ExceededTime; // 0x3C: 892 893 // SID is placed here 894}; // sizeof() = 0x44 895 896#define SIZEOF_NTFS_DE_Q 0x44 897 898#define SecurityDescriptorsBlockSize 0x40000 // 256K 899#define SecurityDescriptorMaxSize 0x20000 // 128K 900#define Log2OfSecurityDescriptorsBlockSize 18 901 902struct SECURITY_KEY { 903 __le32 hash; // Hash value for descriptor 904 __le32 sec_id; // Security Id (guaranteed unique) 905}; 906 907/* Security descriptors (the content of $Secure::SDS data stream) */ 908struct SECURITY_HDR { 909 struct SECURITY_KEY key; // 0x00: Security Key. 910 __le64 off; // 0x08: Offset of this entry in the file. 911 __le32 size; // 0x10: Size of this entry, 8 byte aligned. 912 /* 913 * Security descriptor itself is placed here. 914 * Total size is 16 byte aligned. 915 */ 916} __packed; 917 918#define SIZEOF_SECURITY_HDR 0x14 919 920/* SII Directory entry structure */ 921struct NTFS_DE_SII { 922 struct NTFS_DE de; 923 __le32 sec_id; // 0x10: Key: sizeof(security_id) = wKeySize 924 struct SECURITY_HDR sec_hdr; // 0x14: 925} __packed; 926 927#define SIZEOF_SII_DIRENTRY 0x28 928 929/* SDH Directory entry structure */ 930struct NTFS_DE_SDH { 931 struct NTFS_DE de; 932 struct SECURITY_KEY key; // 0x10: Key 933 struct SECURITY_HDR sec_hdr; // 0x18: Data 934 __le16 magic[2]; // 0x2C: 0x00490049 "I I" 935}; 936 937#define SIZEOF_SDH_DIRENTRY 0x30 938 939struct REPARSE_KEY { 940 __le32 ReparseTag; // 0x00: Reparse Tag 941 struct MFT_REF ref; // 0x04: MFT record number with this file 942}; // sizeof() = 0x0C 943 944static_assert(offsetof(struct REPARSE_KEY, ref) == 0x04); 945#define SIZEOF_REPARSE_KEY 0x0C 946 947/* Reparse Directory entry structure */ 948struct NTFS_DE_R { 949 struct NTFS_DE de; 950 struct REPARSE_KEY key; // 0x10: Reparse Key. 951 u32 zero; // 0x1c: 952}; // sizeof() = 0x20 953 954static_assert(sizeof(struct NTFS_DE_R) == 0x20); 955 956/* CompressReparseBuffer.WofVersion */ 957#define WOF_CURRENT_VERSION cpu_to_le32(1) 958/* CompressReparseBuffer.WofProvider */ 959#define WOF_PROVIDER_WIM cpu_to_le32(1) 960/* CompressReparseBuffer.WofProvider */ 961#define WOF_PROVIDER_SYSTEM cpu_to_le32(2) 962/* CompressReparseBuffer.ProviderVer */ 963#define WOF_PROVIDER_CURRENT_VERSION cpu_to_le32(1) 964 965#define WOF_COMPRESSION_XPRESS4K cpu_to_le32(0) // 4k 966#define WOF_COMPRESSION_LZX32K cpu_to_le32(1) // 32k 967#define WOF_COMPRESSION_XPRESS8K cpu_to_le32(2) // 8k 968#define WOF_COMPRESSION_XPRESS16K cpu_to_le32(3) // 16k 969 970/* 971 * ATTR_REPARSE (0xC0) 972 * 973 * The reparse struct GUID structure is used by all 3rd party layered drivers to 974 * store data in a reparse point. For non-Microsoft tags, The struct GUID field 975 * cannot be GUID_NULL. 976 * The constraints on reparse tags are defined below. 977 * Microsoft tags can also be used with this format of the reparse point buffer. 978 */ 979struct REPARSE_POINT { 980 __le32 ReparseTag; // 0x00: 981 __le16 ReparseDataLength;// 0x04: 982 __le16 Reserved; 983 984 struct GUID Guid; // 0x08: 985 986 // 987 // Here GenericReparseBuffer is placed 988 // 989}; 990 991static_assert(sizeof(struct REPARSE_POINT) == 0x18); 992 993/* Maximum allowed size of the reparse data. */ 994#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024) 995 996/* 997 * The value of the following constant needs to satisfy the following 998 * conditions: 999 * (1) Be at least as large as the largest of the reserved tags. 1000 * (2) Be strictly smaller than all the tags in use. 1001 */ 1002#define IO_REPARSE_TAG_RESERVED_RANGE 1 1003 1004/* 1005 * The reparse tags are a ULONG. The 32 bits are laid out as follows: 1006 * 1007 * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1008 * 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 1009 * +-+-+-+-+-----------------------+-------------------------------+ 1010 * |M|R|N|R| Reserved bits | Reparse Tag Value | 1011 * +-+-+-+-+-----------------------+-------------------------------+ 1012 * 1013 * M is the Microsoft bit. When set to 1, it denotes a tag owned by Microsoft. 1014 * All ISVs must use a tag with a 0 in this position. 1015 * Note: If a Microsoft tag is used by non-Microsoft software, the 1016 * behavior is not defined. 1017 * 1018 * R is reserved. Must be zero for non-Microsoft tags. 1019 * 1020 * N is name surrogate. When set to 1, the file represents another named 1021 * entity in the system. 1022 * 1023 * The M and N bits are OR-able. 1024 * The following macros check for the M and N bit values: 1025 */ 1026 1027/* 1028 * Macro to determine whether a reparse point tag corresponds to a tag 1029 * owned by Microsoft. 1030 */ 1031#define IsReparseTagMicrosoft(_tag) (((_tag)&IO_REPARSE_TAG_MICROSOFT)) 1032 1033/* Macro to determine whether a reparse point tag is a name surrogate. */ 1034#define IsReparseTagNameSurrogate(_tag) (((_tag)&IO_REPARSE_TAG_NAME_SURROGATE)) 1035 1036/* 1037 * The following constant represents the bits that are valid to use in 1038 * reparse tags. 1039 */ 1040#define IO_REPARSE_TAG_VALID_VALUES 0xF000FFFF 1041 1042/* 1043 * Macro to determine whether a reparse tag is a valid tag. 1044 */ 1045#define IsReparseTagValid(_tag) \ 1046 (!((_tag) & ~IO_REPARSE_TAG_VALID_VALUES) && \ 1047 ((_tag) > IO_REPARSE_TAG_RESERVED_RANGE)) 1048 1049/* Microsoft tags for reparse points. */ 1050 1051enum IO_REPARSE_TAG { 1052 IO_REPARSE_TAG_SYMBOLIC_LINK = cpu_to_le32(0), 1053 IO_REPARSE_TAG_NAME_SURROGATE = cpu_to_le32(0x20000000), 1054 IO_REPARSE_TAG_MICROSOFT = cpu_to_le32(0x80000000), 1055 IO_REPARSE_TAG_MOUNT_POINT = cpu_to_le32(0xA0000003), 1056 IO_REPARSE_TAG_SYMLINK = cpu_to_le32(0xA000000C), 1057 IO_REPARSE_TAG_HSM = cpu_to_le32(0xC0000004), 1058 IO_REPARSE_TAG_SIS = cpu_to_le32(0x80000007), 1059 IO_REPARSE_TAG_DEDUP = cpu_to_le32(0x80000013), 1060 IO_REPARSE_TAG_COMPRESS = cpu_to_le32(0x80000017), 1061 1062 /* 1063 * The reparse tag 0x80000008 is reserved for Microsoft internal use. 1064 * May be published in the future. 1065 */ 1066 1067 /* Microsoft reparse tag reserved for DFS */ 1068 IO_REPARSE_TAG_DFS = cpu_to_le32(0x8000000A), 1069 1070 /* Microsoft reparse tag reserved for the file system filter manager. */ 1071 IO_REPARSE_TAG_FILTER_MANAGER = cpu_to_le32(0x8000000B), 1072 1073 /* Non-Microsoft tags for reparse points */ 1074 1075 /* Tag allocated to CONGRUENT, May 2000. Used by IFSTEST. */ 1076 IO_REPARSE_TAG_IFSTEST_CONGRUENT = cpu_to_le32(0x00000009), 1077 1078 /* Tag allocated to ARKIVIO. */ 1079 IO_REPARSE_TAG_ARKIVIO = cpu_to_le32(0x0000000C), 1080 1081 /* Tag allocated to SOLUTIONSOFT. */ 1082 IO_REPARSE_TAG_SOLUTIONSOFT = cpu_to_le32(0x2000000D), 1083 1084 /* Tag allocated to COMMVAULT. */ 1085 IO_REPARSE_TAG_COMMVAULT = cpu_to_le32(0x0000000E), 1086 1087 /* OneDrive?? */ 1088 IO_REPARSE_TAG_CLOUD = cpu_to_le32(0x9000001A), 1089 IO_REPARSE_TAG_CLOUD_1 = cpu_to_le32(0x9000101A), 1090 IO_REPARSE_TAG_CLOUD_2 = cpu_to_le32(0x9000201A), 1091 IO_REPARSE_TAG_CLOUD_3 = cpu_to_le32(0x9000301A), 1092 IO_REPARSE_TAG_CLOUD_4 = cpu_to_le32(0x9000401A), 1093 IO_REPARSE_TAG_CLOUD_5 = cpu_to_le32(0x9000501A), 1094 IO_REPARSE_TAG_CLOUD_6 = cpu_to_le32(0x9000601A), 1095 IO_REPARSE_TAG_CLOUD_7 = cpu_to_le32(0x9000701A), 1096 IO_REPARSE_TAG_CLOUD_8 = cpu_to_le32(0x9000801A), 1097 IO_REPARSE_TAG_CLOUD_9 = cpu_to_le32(0x9000901A), 1098 IO_REPARSE_TAG_CLOUD_A = cpu_to_le32(0x9000A01A), 1099 IO_REPARSE_TAG_CLOUD_B = cpu_to_le32(0x9000B01A), 1100 IO_REPARSE_TAG_CLOUD_C = cpu_to_le32(0x9000C01A), 1101 IO_REPARSE_TAG_CLOUD_D = cpu_to_le32(0x9000D01A), 1102 IO_REPARSE_TAG_CLOUD_E = cpu_to_le32(0x9000E01A), 1103 IO_REPARSE_TAG_CLOUD_F = cpu_to_le32(0x9000F01A), 1104 1105}; 1106 1107#define SYMLINK_FLAG_RELATIVE 1 1108 1109/* Microsoft reparse buffer. (see DDK for details) */ 1110struct REPARSE_DATA_BUFFER { 1111 __le32 ReparseTag; // 0x00: 1112 __le16 ReparseDataLength; // 0x04: 1113 __le16 Reserved; 1114 1115 union { 1116 /* If ReparseTag == 0xA0000003 (IO_REPARSE_TAG_MOUNT_POINT) */ 1117 struct { 1118 __le16 SubstituteNameOffset; // 0x08 1119 __le16 SubstituteNameLength; // 0x0A 1120 __le16 PrintNameOffset; // 0x0C 1121 __le16 PrintNameLength; // 0x0E 1122 __le16 PathBuffer[]; // 0x10 1123 } MountPointReparseBuffer; 1124 1125 /* 1126 * If ReparseTag == 0xA000000C (IO_REPARSE_TAG_SYMLINK) 1127 * https://msdn.microsoft.com/en-us/library/cc232006.aspx 1128 */ 1129 struct { 1130 __le16 SubstituteNameOffset; // 0x08 1131 __le16 SubstituteNameLength; // 0x0A 1132 __le16 PrintNameOffset; // 0x0C 1133 __le16 PrintNameLength; // 0x0E 1134 // 0-absolute path 1- relative path, SYMLINK_FLAG_RELATIVE 1135 __le32 Flags; // 0x10 1136 __le16 PathBuffer[]; // 0x14 1137 } SymbolicLinkReparseBuffer; 1138 1139 /* If ReparseTag == 0x80000017U */ 1140 struct { 1141 __le32 WofVersion; // 0x08 == 1 1142 /* 1143 * 1 - WIM backing provider ("WIMBoot"), 1144 * 2 - System compressed file provider 1145 */ 1146 __le32 WofProvider; // 0x0C: 1147 __le32 ProviderVer; // 0x10: == 1 WOF_FILE_PROVIDER_CURRENT_VERSION == 1 1148 __le32 CompressionFormat; // 0x14: 0, 1, 2, 3. See WOF_COMPRESSION_XXX 1149 } CompressReparseBuffer; 1150 1151 struct { 1152 u8 DataBuffer[1]; // 0x08: 1153 } GenericReparseBuffer; 1154 }; 1155}; 1156 1157/* ATTR_EA_INFO (0xD0) */ 1158 1159#define FILE_NEED_EA 0x80 // See ntifs.h 1160/* 1161 *FILE_NEED_EA, indicates that the file to which the EA belongs cannot be 1162 * interpreted without understanding the associated extended attributes. 1163 */ 1164struct EA_INFO { 1165 __le16 size_pack; // 0x00: Size of buffer to hold in packed form. 1166 __le16 count; // 0x02: Count of EA's with FILE_NEED_EA bit set. 1167 __le32 size; // 0x04: Size of buffer to hold in unpacked form. 1168}; 1169 1170static_assert(sizeof(struct EA_INFO) == 8); 1171 1172/* ATTR_EA (0xE0) */ 1173struct EA_FULL { 1174 __le32 size; // 0x00: (not in packed) 1175 u8 flags; // 0x04: 1176 u8 name_len; // 0x05: 1177 __le16 elength; // 0x06: 1178 u8 name[]; // 0x08: 1179}; 1180 1181static_assert(offsetof(struct EA_FULL, name) == 8); 1182 1183#define ACL_REVISION 2 1184#define ACL_REVISION_DS 4 1185 1186#define SE_SELF_RELATIVE cpu_to_le16(0x8000) 1187 1188struct SECURITY_DESCRIPTOR_RELATIVE { 1189 u8 Revision; 1190 u8 Sbz1; 1191 __le16 Control; 1192 __le32 Owner; 1193 __le32 Group; 1194 __le32 Sacl; 1195 __le32 Dacl; 1196}; 1197static_assert(sizeof(struct SECURITY_DESCRIPTOR_RELATIVE) == 0x14); 1198 1199struct ACE_HEADER { 1200 u8 AceType; 1201 u8 AceFlags; 1202 __le16 AceSize; 1203}; 1204static_assert(sizeof(struct ACE_HEADER) == 4); 1205 1206struct ACL { 1207 u8 AclRevision; 1208 u8 Sbz1; 1209 __le16 AclSize; 1210 __le16 AceCount; 1211 __le16 Sbz2; 1212}; 1213static_assert(sizeof(struct ACL) == 8); 1214 1215struct SID { 1216 u8 Revision; 1217 u8 SubAuthorityCount; 1218 u8 IdentifierAuthority[6]; 1219 __le32 SubAuthority[]; 1220}; 1221static_assert(offsetof(struct SID, SubAuthority) == 8); 1222 1223#endif /* _LINUX_NTFS3_NTFS_H */ 1224// clang-format on