Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  *
0004  * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
0005  *
0006  * on-disk ntfs structs
0007  */
0008 
0009 // clang-format off
0010 #ifndef _LINUX_NTFS3_NTFS_H
0011 #define _LINUX_NTFS3_NTFS_H
0012 
0013 #include <linux/blkdev.h>
0014 #include <linux/build_bug.h>
0015 #include <linux/kernel.h>
0016 #include <linux/stddef.h>
0017 #include <linux/string.h>
0018 #include <linux/types.h>
0019 
0020 #include "debug.h"
0021 
0022 /* TODO: Check 4K MFT record and 512 bytes cluster. */
0023 
0024 /* Check each run for marked clusters. */
0025 #define NTFS3_CHECK_FREE_CLST
0026 
0027 #define NTFS_NAME_LEN 255
0028 
0029 /*
0030  * ntfs.sys used 500 maximum links on-disk struct allows up to 0xffff.
0031  * xfstest generic/041 creates 3003 hardlinks.
0032  */
0033 #define NTFS_LINK_MAX 4000
0034 
0035 /*
0036  * Activate to use 64 bit clusters instead of 32 bits in ntfs.sys.
0037  * Logical and virtual cluster number if needed, may be
0038  * redefined to use 64 bit value.
0039  */
0040 //#define CONFIG_NTFS3_64BIT_CLUSTER
0041 
0042 #define NTFS_LZNT_MAX_CLUSTER   4096
0043 #define NTFS_LZNT_CUNIT     4
0044 #define NTFS_LZNT_CLUSTERS  (1u<<NTFS_LZNT_CUNIT)
0045 
0046 struct GUID {
0047     __le32 Data1;
0048     __le16 Data2;
0049     __le16 Data3;
0050     u8 Data4[8];
0051 };
0052 
0053 /*
0054  * This struct repeats layout of ATTR_FILE_NAME
0055  * at offset 0x40.
0056  * It used to store global constants NAME_MFT/NAME_MIRROR...
0057  * most constant names are shorter than 10.
0058  */
0059 struct cpu_str {
0060     u8 len;
0061     u8 unused;
0062     u16 name[10];
0063 };
0064 
0065 struct le_str {
0066     u8 len;
0067     u8 unused;
0068     __le16 name[];
0069 };
0070 
0071 static_assert(SECTOR_SHIFT == 9);
0072 
0073 #ifdef CONFIG_NTFS3_64BIT_CLUSTER
0074 typedef u64 CLST;
0075 static_assert(sizeof(size_t) == 8);
0076 #else
0077 typedef u32 CLST;
0078 #endif
0079 
0080 #define SPARSE_LCN64   ((u64)-1)
0081 #define SPARSE_LCN     ((CLST)-1)
0082 #define RESIDENT_LCN   ((CLST)-2)
0083 #define COMPRESSED_LCN ((CLST)-3)
0084 
0085 #define COMPRESSION_UNIT     4
0086 #define COMPRESS_MAX_CLUSTER 0x1000
0087 #define MFT_INCREASE_CHUNK   1024
0088 
0089 enum RECORD_NUM {
0090     MFT_REC_MFT     = 0,
0091     MFT_REC_MIRR        = 1,
0092     MFT_REC_LOG     = 2,
0093     MFT_REC_VOL     = 3,
0094     MFT_REC_ATTR        = 4,
0095     MFT_REC_ROOT        = 5,
0096     MFT_REC_BITMAP      = 6,
0097     MFT_REC_BOOT        = 7,
0098     MFT_REC_BADCLUST    = 8,
0099     //MFT_REC_QUOTA     = 9,
0100     MFT_REC_SECURE      = 9, // NTFS 3.0
0101     MFT_REC_UPCASE      = 10,
0102     MFT_REC_EXTEND      = 11, // NTFS 3.0
0103     MFT_REC_RESERVED    = 11,
0104     MFT_REC_FREE        = 16,
0105     MFT_REC_USER        = 24,
0106 };
0107 
0108 enum ATTR_TYPE {
0109     ATTR_ZERO       = cpu_to_le32(0x00),
0110     ATTR_STD        = cpu_to_le32(0x10),
0111     ATTR_LIST       = cpu_to_le32(0x20),
0112     ATTR_NAME       = cpu_to_le32(0x30),
0113     // ATTR_VOLUME_VERSION on Nt4
0114     ATTR_ID         = cpu_to_le32(0x40),
0115     ATTR_SECURE     = cpu_to_le32(0x50),
0116     ATTR_LABEL      = cpu_to_le32(0x60),
0117     ATTR_VOL_INFO       = cpu_to_le32(0x70),
0118     ATTR_DATA       = cpu_to_le32(0x80),
0119     ATTR_ROOT       = cpu_to_le32(0x90),
0120     ATTR_ALLOC      = cpu_to_le32(0xA0),
0121     ATTR_BITMAP     = cpu_to_le32(0xB0),
0122     // ATTR_SYMLINK on Nt4
0123     ATTR_REPARSE        = cpu_to_le32(0xC0),
0124     ATTR_EA_INFO        = cpu_to_le32(0xD0),
0125     ATTR_EA         = cpu_to_le32(0xE0),
0126     ATTR_PROPERTYSET    = cpu_to_le32(0xF0),
0127     ATTR_LOGGED_UTILITY_STREAM = cpu_to_le32(0x100),
0128     ATTR_END        = cpu_to_le32(0xFFFFFFFF)
0129 };
0130 
0131 static_assert(sizeof(enum ATTR_TYPE) == 4);
0132 
0133 enum FILE_ATTRIBUTE {
0134     FILE_ATTRIBUTE_READONLY     = cpu_to_le32(0x00000001),
0135     FILE_ATTRIBUTE_HIDDEN       = cpu_to_le32(0x00000002),
0136     FILE_ATTRIBUTE_SYSTEM       = cpu_to_le32(0x00000004),
0137     FILE_ATTRIBUTE_ARCHIVE      = cpu_to_le32(0x00000020),
0138     FILE_ATTRIBUTE_DEVICE       = cpu_to_le32(0x00000040),
0139     FILE_ATTRIBUTE_TEMPORARY    = cpu_to_le32(0x00000100),
0140     FILE_ATTRIBUTE_SPARSE_FILE  = cpu_to_le32(0x00000200),
0141     FILE_ATTRIBUTE_REPARSE_POINT    = cpu_to_le32(0x00000400),
0142     FILE_ATTRIBUTE_COMPRESSED   = cpu_to_le32(0x00000800),
0143     FILE_ATTRIBUTE_OFFLINE      = cpu_to_le32(0x00001000),
0144     FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = cpu_to_le32(0x00002000),
0145     FILE_ATTRIBUTE_ENCRYPTED    = cpu_to_le32(0x00004000),
0146     FILE_ATTRIBUTE_VALID_FLAGS  = cpu_to_le32(0x00007fb7),
0147     FILE_ATTRIBUTE_DIRECTORY    = cpu_to_le32(0x10000000),
0148 };
0149 
0150 static_assert(sizeof(enum FILE_ATTRIBUTE) == 4);
0151 
0152 extern const struct cpu_str NAME_MFT;
0153 extern const struct cpu_str NAME_MIRROR;
0154 extern const struct cpu_str NAME_LOGFILE;
0155 extern const struct cpu_str NAME_VOLUME;
0156 extern const struct cpu_str NAME_ATTRDEF;
0157 extern const struct cpu_str NAME_ROOT;
0158 extern const struct cpu_str NAME_BITMAP;
0159 extern const struct cpu_str NAME_BOOT;
0160 extern const struct cpu_str NAME_BADCLUS;
0161 extern const struct cpu_str NAME_QUOTA;
0162 extern const struct cpu_str NAME_SECURE;
0163 extern const struct cpu_str NAME_UPCASE;
0164 extern const struct cpu_str NAME_EXTEND;
0165 extern const struct cpu_str NAME_OBJID;
0166 extern const struct cpu_str NAME_REPARSE;
0167 extern const struct cpu_str NAME_USNJRNL;
0168 
0169 extern const __le16 I30_NAME[4];
0170 extern const __le16 SII_NAME[4];
0171 extern const __le16 SDH_NAME[4];
0172 extern const __le16 SO_NAME[2];
0173 extern const __le16 SQ_NAME[2];
0174 extern const __le16 SR_NAME[2];
0175 
0176 extern const __le16 BAD_NAME[4];
0177 extern const __le16 SDS_NAME[4];
0178 extern const __le16 WOF_NAME[17];   /* WofCompressedData */
0179 
0180 /* MFT record number structure. */
0181 struct MFT_REF {
0182     __le32 low; // The low part of the number.
0183     __le16 high;    // The high part of the number.
0184     __le16 seq; // The sequence number of MFT record.
0185 };
0186 
0187 static_assert(sizeof(__le64) == sizeof(struct MFT_REF));
0188 
0189 static inline CLST ino_get(const struct MFT_REF *ref)
0190 {
0191 #ifdef CONFIG_NTFS3_64BIT_CLUSTER
0192     return le32_to_cpu(ref->low) | ((u64)le16_to_cpu(ref->high) << 32);
0193 #else
0194     return le32_to_cpu(ref->low);
0195 #endif
0196 }
0197 
0198 struct NTFS_BOOT {
0199     u8 jump_code[3];    // 0x00: Jump to boot code.
0200     u8 system_id[8];    // 0x03: System ID, equals "NTFS    "
0201 
0202     // NOTE: This member is not aligned(!)
0203     // bytes_per_sector[0] must be 0.
0204     // bytes_per_sector[1] must be multiplied by 256.
0205     u8 bytes_per_sector[2]; // 0x0B: Bytes per sector.
0206 
0207     u8 sectors_per_clusters;// 0x0D: Sectors per cluster.
0208     u8 unused1[7];
0209     u8 media_type;      // 0x15: Media type (0xF8 - harddisk)
0210     u8 unused2[2];
0211     __le16 sct_per_track;   // 0x18: number of sectors per track.
0212     __le16 heads;       // 0x1A: number of heads per cylinder.
0213     __le32 hidden_sectors;  // 0x1C: number of 'hidden' sectors.
0214     u8 unused3[4];
0215     u8 bios_drive_num;  // 0x24: BIOS drive number =0x80.
0216     u8 unused4;
0217     u8 signature_ex;    // 0x26: Extended BOOT signature =0x80.
0218     u8 unused5;
0219     __le64 sectors_per_volume;// 0x28: Size of volume in sectors.
0220     __le64 mft_clst;    // 0x30: First cluster of $MFT
0221     __le64 mft2_clst;   // 0x38: First cluster of $MFTMirr
0222     s8 record_size;     // 0x40: Size of MFT record in clusters(sectors).
0223     u8 unused6[3];
0224     s8 index_size;      // 0x44: Size of INDX record in clusters(sectors).
0225     u8 unused7[3];
0226     __le64 serial_num;  // 0x48: Volume serial number
0227     __le32 check_sum;   // 0x50: Simple additive checksum of all
0228                 // of the u32's which precede the 'check_sum'.
0229 
0230     u8 boot_code[0x200 - 0x50 - 2 - 4]; // 0x54:
0231     u8 boot_magic[2];   // 0x1FE: Boot signature =0x55 + 0xAA
0232 };
0233 
0234 static_assert(sizeof(struct NTFS_BOOT) == 0x200);
0235 
0236 enum NTFS_SIGNATURE {
0237     NTFS_FILE_SIGNATURE = cpu_to_le32(0x454C4946), // 'FILE'
0238     NTFS_INDX_SIGNATURE = cpu_to_le32(0x58444E49), // 'INDX'
0239     NTFS_CHKD_SIGNATURE = cpu_to_le32(0x444B4843), // 'CHKD'
0240     NTFS_RSTR_SIGNATURE = cpu_to_le32(0x52545352), // 'RSTR'
0241     NTFS_RCRD_SIGNATURE = cpu_to_le32(0x44524352), // 'RCRD'
0242     NTFS_BAAD_SIGNATURE = cpu_to_le32(0x44414142), // 'BAAD'
0243     NTFS_HOLE_SIGNATURE = cpu_to_le32(0x454C4F48), // 'HOLE'
0244     NTFS_FFFF_SIGNATURE = cpu_to_le32(0xffffffff),
0245 };
0246 
0247 static_assert(sizeof(enum NTFS_SIGNATURE) == 4);
0248 
0249 /* MFT Record header structure. */
0250 struct NTFS_RECORD_HEADER {
0251     /* Record magic number, equals 'FILE'/'INDX'/'RSTR'/'RCRD'. */
0252     enum NTFS_SIGNATURE sign; // 0x00:
0253     __le16 fix_off;     // 0x04:
0254     __le16 fix_num;     // 0x06:
0255     __le64 lsn;     // 0x08: Log file sequence number,
0256 };
0257 
0258 static_assert(sizeof(struct NTFS_RECORD_HEADER) == 0x10);
0259 
0260 static inline int is_baad(const struct NTFS_RECORD_HEADER *hdr)
0261 {
0262     return hdr->sign == NTFS_BAAD_SIGNATURE;
0263 }
0264 
0265 /* Possible bits in struct MFT_REC.flags. */
0266 enum RECORD_FLAG {
0267     RECORD_FLAG_IN_USE  = cpu_to_le16(0x0001),
0268     RECORD_FLAG_DIR     = cpu_to_le16(0x0002),
0269     RECORD_FLAG_SYSTEM  = cpu_to_le16(0x0004),
0270     RECORD_FLAG_UNKNOWN = cpu_to_le16(0x0008),
0271 };
0272 
0273 /* MFT Record structure. */
0274 struct MFT_REC {
0275     struct NTFS_RECORD_HEADER rhdr; // 'FILE'
0276 
0277     __le16 seq;     // 0x10: Sequence number for this record.
0278     __le16 hard_links;  // 0x12: The number of hard links to record.
0279     __le16 attr_off;    // 0x14: Offset to attributes.
0280     __le16 flags;       // 0x16: See RECORD_FLAG.
0281     __le32 used;        // 0x18: The size of used part.
0282     __le32 total;       // 0x1C: Total record size.
0283 
0284     struct MFT_REF parent_ref; // 0x20: Parent MFT record.
0285     __le16 next_attr_id;    // 0x28: The next attribute Id.
0286 
0287     __le16 res;     // 0x2A: High part of MFT record?
0288     __le32 mft_record;  // 0x2C: Current MFT record number.
0289     __le16 fixups[];    // 0x30:
0290 };
0291 
0292 #define MFTRECORD_FIXUP_OFFSET_1 offsetof(struct MFT_REC, res)
0293 #define MFTRECORD_FIXUP_OFFSET_3 offsetof(struct MFT_REC, fixups)
0294 
0295 static_assert(MFTRECORD_FIXUP_OFFSET_1 == 0x2A);
0296 static_assert(MFTRECORD_FIXUP_OFFSET_3 == 0x30);
0297 
0298 static inline bool is_rec_base(const struct MFT_REC *rec)
0299 {
0300     const struct MFT_REF *r = &rec->parent_ref;
0301 
0302     return !r->low && !r->high && !r->seq;
0303 }
0304 
0305 static inline bool is_mft_rec5(const struct MFT_REC *rec)
0306 {
0307     return le16_to_cpu(rec->rhdr.fix_off) >=
0308            offsetof(struct MFT_REC, fixups);
0309 }
0310 
0311 static inline bool is_rec_inuse(const struct MFT_REC *rec)
0312 {
0313     return rec->flags & RECORD_FLAG_IN_USE;
0314 }
0315 
0316 static inline bool clear_rec_inuse(struct MFT_REC *rec)
0317 {
0318     return rec->flags &= ~RECORD_FLAG_IN_USE;
0319 }
0320 
0321 /* Possible values of ATTR_RESIDENT.flags */
0322 #define RESIDENT_FLAG_INDEXED 0x01
0323 
0324 struct ATTR_RESIDENT {
0325     __le32 data_size;   // 0x10: The size of data.
0326     __le16 data_off;    // 0x14: Offset to data.
0327     u8 flags;       // 0x16: Resident flags ( 1 - indexed ).
0328     u8 res;         // 0x17:
0329 }; // sizeof() = 0x18
0330 
0331 struct ATTR_NONRESIDENT {
0332     __le64 svcn;        // 0x10: Starting VCN of this segment.
0333     __le64 evcn;        // 0x18: End VCN of this segment.
0334     __le16 run_off;     // 0x20: Offset to packed runs.
0335     //  Unit of Compression size for this stream, expressed
0336     //  as a log of the cluster size.
0337     //
0338     //  0 means file is not compressed
0339     //  1, 2, 3, and 4 are potentially legal values if the
0340     //      stream is compressed, however the implementation
0341     //      may only choose to use 4, or possibly 3.  Note
0342     //      that 4 means cluster size time 16.  If convenient
0343     //      the implementation may wish to accept a
0344     //      reasonable range of legal values here (1-5?),
0345     //      even if the implementation only generates
0346     //      a smaller set of values itself.
0347     u8 c_unit;      // 0x22:
0348     u8 res1[5];     // 0x23:
0349     __le64 alloc_size;  // 0x28: The allocated size of attribute in bytes.
0350                 // (multiple of cluster size)
0351     __le64 data_size;   // 0x30: The size of attribute  in bytes <= alloc_size.
0352     __le64 valid_size;  // 0x38: The size of valid part in bytes <= data_size.
0353     __le64 total_size;  // 0x40: The sum of the allocated clusters for a file.
0354                 // (present only for the first segment (0 == vcn)
0355                 // of compressed attribute)
0356 
0357 }; // sizeof()=0x40 or 0x48 (if compressed)
0358 
0359 /* Possible values of ATTRIB.flags: */
0360 #define ATTR_FLAG_COMPRESSED      cpu_to_le16(0x0001)
0361 #define ATTR_FLAG_COMPRESSED_MASK cpu_to_le16(0x00FF)
0362 #define ATTR_FLAG_ENCRYPTED   cpu_to_le16(0x4000)
0363 #define ATTR_FLAG_SPARSED     cpu_to_le16(0x8000)
0364 
0365 struct ATTRIB {
0366     enum ATTR_TYPE type;    // 0x00: The type of this attribute.
0367     __le32 size;        // 0x04: The size of this attribute.
0368     u8 non_res;     // 0x08: Is this attribute non-resident?
0369     u8 name_len;        // 0x09: This attribute name length.
0370     __le16 name_off;    // 0x0A: Offset to the attribute name.
0371     __le16 flags;       // 0x0C: See ATTR_FLAG_XXX.
0372     __le16 id;      // 0x0E: Unique id (per record).
0373 
0374     union {
0375         struct ATTR_RESIDENT res;     // 0x10
0376         struct ATTR_NONRESIDENT nres; // 0x10
0377     };
0378 };
0379 
0380 /* Define attribute sizes. */
0381 #define SIZEOF_RESIDENT         0x18
0382 #define SIZEOF_NONRESIDENT_EX       0x48
0383 #define SIZEOF_NONRESIDENT      0x40
0384 
0385 #define SIZEOF_RESIDENT_LE      cpu_to_le16(0x18)
0386 #define SIZEOF_NONRESIDENT_EX_LE    cpu_to_le16(0x48)
0387 #define SIZEOF_NONRESIDENT_LE       cpu_to_le16(0x40)
0388 
0389 static inline u64 attr_ondisk_size(const struct ATTRIB *attr)
0390 {
0391     return attr->non_res ? ((attr->flags &
0392                  (ATTR_FLAG_COMPRESSED | ATTR_FLAG_SPARSED)) ?
0393                     le64_to_cpu(attr->nres.total_size) :
0394                     le64_to_cpu(attr->nres.alloc_size))
0395                  : ALIGN(le32_to_cpu(attr->res.data_size), 8);
0396 }
0397 
0398 static inline u64 attr_size(const struct ATTRIB *attr)
0399 {
0400     return attr->non_res ? le64_to_cpu(attr->nres.data_size) :
0401                    le32_to_cpu(attr->res.data_size);
0402 }
0403 
0404 static inline bool is_attr_encrypted(const struct ATTRIB *attr)
0405 {
0406     return attr->flags & ATTR_FLAG_ENCRYPTED;
0407 }
0408 
0409 static inline bool is_attr_sparsed(const struct ATTRIB *attr)
0410 {
0411     return attr->flags & ATTR_FLAG_SPARSED;
0412 }
0413 
0414 static inline bool is_attr_compressed(const struct ATTRIB *attr)
0415 {
0416     return attr->flags & ATTR_FLAG_COMPRESSED;
0417 }
0418 
0419 static inline bool is_attr_ext(const struct ATTRIB *attr)
0420 {
0421     return attr->flags & (ATTR_FLAG_SPARSED | ATTR_FLAG_COMPRESSED);
0422 }
0423 
0424 static inline bool is_attr_indexed(const struct ATTRIB *attr)
0425 {
0426     return !attr->non_res && (attr->res.flags & RESIDENT_FLAG_INDEXED);
0427 }
0428 
0429 static inline __le16 const *attr_name(const struct ATTRIB *attr)
0430 {
0431     return Add2Ptr(attr, le16_to_cpu(attr->name_off));
0432 }
0433 
0434 static inline u64 attr_svcn(const struct ATTRIB *attr)
0435 {
0436     return attr->non_res ? le64_to_cpu(attr->nres.svcn) : 0;
0437 }
0438 
0439 /* The size of resident attribute by its resident size. */
0440 #define BYTES_PER_RESIDENT(b) (0x18 + (b))
0441 
0442 static_assert(sizeof(struct ATTRIB) == 0x48);
0443 static_assert(sizeof(((struct ATTRIB *)NULL)->res) == 0x08);
0444 static_assert(sizeof(((struct ATTRIB *)NULL)->nres) == 0x38);
0445 
0446 static inline void *resident_data_ex(const struct ATTRIB *attr, u32 datasize)
0447 {
0448     u32 asize, rsize;
0449     u16 off;
0450 
0451     if (attr->non_res)
0452         return NULL;
0453 
0454     asize = le32_to_cpu(attr->size);
0455     off = le16_to_cpu(attr->res.data_off);
0456 
0457     if (asize < datasize + off)
0458         return NULL;
0459 
0460     rsize = le32_to_cpu(attr->res.data_size);
0461     if (rsize < datasize)
0462         return NULL;
0463 
0464     return Add2Ptr(attr, off);
0465 }
0466 
0467 static inline void *resident_data(const struct ATTRIB *attr)
0468 {
0469     return Add2Ptr(attr, le16_to_cpu(attr->res.data_off));
0470 }
0471 
0472 static inline void *attr_run(const struct ATTRIB *attr)
0473 {
0474     return Add2Ptr(attr, le16_to_cpu(attr->nres.run_off));
0475 }
0476 
0477 /* Standard information attribute (0x10). */
0478 struct ATTR_STD_INFO {
0479     __le64 cr_time;     // 0x00: File creation file.
0480     __le64 m_time;      // 0x08: File modification time.
0481     __le64 c_time;      // 0x10: Last time any attribute was modified.
0482     __le64 a_time;      // 0x18: File last access time.
0483     enum FILE_ATTRIBUTE fa; // 0x20: Standard DOS attributes & more.
0484     __le32 max_ver_num; // 0x24: Maximum Number of Versions.
0485     __le32 ver_num;     // 0x28: Version Number.
0486     __le32 class_id;    // 0x2C: Class Id from bidirectional Class Id index.
0487 };
0488 
0489 static_assert(sizeof(struct ATTR_STD_INFO) == 0x30);
0490 
0491 #define SECURITY_ID_INVALID 0x00000000
0492 #define SECURITY_ID_FIRST 0x00000100
0493 
0494 struct ATTR_STD_INFO5 {
0495     __le64 cr_time;     // 0x00: File creation file.
0496     __le64 m_time;      // 0x08: File modification time.
0497     __le64 c_time;      // 0x10: Last time any attribute was modified.
0498     __le64 a_time;      // 0x18: File last access time.
0499     enum FILE_ATTRIBUTE fa; // 0x20: Standard DOS attributes & more.
0500     __le32 max_ver_num; // 0x24: Maximum Number of Versions.
0501     __le32 ver_num;     // 0x28: Version Number.
0502     __le32 class_id;    // 0x2C: Class Id from bidirectional Class Id index.
0503 
0504     __le32 owner_id;    // 0x30: Owner Id of the user owning the file.
0505     __le32 security_id; // 0x34: The Security Id is a key in the $SII Index and $SDS.
0506     __le64 quota_charge;    // 0x38:
0507     __le64 usn;     // 0x40: Last Update Sequence Number of the file. This is a direct
0508                 // index into the file $UsnJrnl. If zero, the USN Journal is
0509                 // disabled.
0510 };
0511 
0512 static_assert(sizeof(struct ATTR_STD_INFO5) == 0x48);
0513 
0514 /* Attribute list entry structure (0x20) */
0515 struct ATTR_LIST_ENTRY {
0516     enum ATTR_TYPE type;    // 0x00: The type of attribute.
0517     __le16 size;        // 0x04: The size of this record.
0518     u8 name_len;        // 0x06: The length of attribute name.
0519     u8 name_off;        // 0x07: The offset to attribute name.
0520     __le64 vcn;     // 0x08: Starting VCN of this attribute.
0521     struct MFT_REF ref; // 0x10: MFT record number with attribute.
0522     __le16 id;      // 0x18: struct ATTRIB ID.
0523     __le16 name[3];     // 0x1A: Just to align. To get real name can use bNameOffset.
0524 
0525 }; // sizeof(0x20)
0526 
0527 static_assert(sizeof(struct ATTR_LIST_ENTRY) == 0x20);
0528 
0529 static inline u32 le_size(u8 name_len)
0530 {
0531     return ALIGN(offsetof(struct ATTR_LIST_ENTRY, name) +
0532              name_len * sizeof(short), 8);
0533 }
0534 
0535 /* Returns 0 if 'attr' has the same type and name. */
0536 static inline int le_cmp(const struct ATTR_LIST_ENTRY *le,
0537              const struct ATTRIB *attr)
0538 {
0539     return le->type != attr->type || le->name_len != attr->name_len ||
0540            (!le->name_len &&
0541         memcmp(Add2Ptr(le, le->name_off),
0542                Add2Ptr(attr, le16_to_cpu(attr->name_off)),
0543                le->name_len * sizeof(short)));
0544 }
0545 
0546 static inline __le16 const *le_name(const struct ATTR_LIST_ENTRY *le)
0547 {
0548     return Add2Ptr(le, le->name_off);
0549 }
0550 
0551 /* File name types (the field type in struct ATTR_FILE_NAME). */
0552 #define FILE_NAME_POSIX   0
0553 #define FILE_NAME_UNICODE 1
0554 #define FILE_NAME_DOS     2
0555 #define FILE_NAME_UNICODE_AND_DOS (FILE_NAME_DOS | FILE_NAME_UNICODE)
0556 
0557 /* Filename attribute structure (0x30). */
0558 struct NTFS_DUP_INFO {
0559     __le64 cr_time;     // 0x00: File creation file.
0560     __le64 m_time;      // 0x08: File modification time.
0561     __le64 c_time;      // 0x10: Last time any attribute was modified.
0562     __le64 a_time;      // 0x18: File last access time.
0563     __le64 alloc_size;  // 0x20: Data attribute allocated size, multiple of cluster size.
0564     __le64 data_size;   // 0x28: Data attribute size <= Dataalloc_size.
0565     enum FILE_ATTRIBUTE fa; // 0x30: Standard DOS attributes & more.
0566     __le16 ea_size;     // 0x34: Packed EAs.
0567     __le16 reparse;     // 0x36: Used by Reparse.
0568 
0569 }; // 0x38
0570 
0571 struct ATTR_FILE_NAME {
0572     struct MFT_REF home;    // 0x00: MFT record for directory.
0573     struct NTFS_DUP_INFO dup;// 0x08:
0574     u8 name_len;        // 0x40: File name length in words.
0575     u8 type;        // 0x41: File name type.
0576     __le16 name[];      // 0x42: File name.
0577 };
0578 
0579 static_assert(sizeof(((struct ATTR_FILE_NAME *)NULL)->dup) == 0x38);
0580 static_assert(offsetof(struct ATTR_FILE_NAME, name) == 0x42);
0581 #define SIZEOF_ATTRIBUTE_FILENAME     0x44
0582 #define SIZEOF_ATTRIBUTE_FILENAME_MAX (0x42 + 255 * 2)
0583 
0584 static inline struct ATTRIB *attr_from_name(struct ATTR_FILE_NAME *fname)
0585 {
0586     return (struct ATTRIB *)((char *)fname - SIZEOF_RESIDENT);
0587 }
0588 
0589 static inline u16 fname_full_size(const struct ATTR_FILE_NAME *fname)
0590 {
0591     /* Don't return struct_size(fname, name, fname->name_len); */
0592     return offsetof(struct ATTR_FILE_NAME, name) +
0593            fname->name_len * sizeof(short);
0594 }
0595 
0596 static inline u8 paired_name(u8 type)
0597 {
0598     if (type == FILE_NAME_UNICODE)
0599         return FILE_NAME_DOS;
0600     if (type == FILE_NAME_DOS)
0601         return FILE_NAME_UNICODE;
0602     return FILE_NAME_POSIX;
0603 }
0604 
0605 /* Index entry defines ( the field flags in NtfsDirEntry ). */
0606 #define NTFS_IE_HAS_SUBNODES    cpu_to_le16(1)
0607 #define NTFS_IE_LAST        cpu_to_le16(2)
0608 
0609 /* Directory entry structure. */
0610 struct NTFS_DE {
0611     union {
0612         struct MFT_REF ref; // 0x00: MFT record number with this file.
0613         struct {
0614             __le16 data_off;  // 0x00:
0615             __le16 data_size; // 0x02:
0616             __le32 res;   // 0x04: Must be 0.
0617         } view;
0618     };
0619     __le16 size;        // 0x08: The size of this entry.
0620     __le16 key_size;    // 0x0A: The size of File name length in bytes + 0x42.
0621     __le16 flags;       // 0x0C: Entry flags: NTFS_IE_XXX.
0622     __le16 res;     // 0x0E:
0623 
0624     // Here any indexed attribute can be placed.
0625     // One of them is:
0626     // struct ATTR_FILE_NAME AttrFileName;
0627     //
0628 
0629     // The last 8 bytes of this structure contains
0630     // the VBN of subnode.
0631     // !!! Note !!!
0632     // This field is presented only if (flags & NTFS_IE_HAS_SUBNODES)
0633     // __le64 vbn;
0634 };
0635 
0636 static_assert(sizeof(struct NTFS_DE) == 0x10);
0637 
0638 static inline void de_set_vbn_le(struct NTFS_DE *e, __le64 vcn)
0639 {
0640     __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64));
0641 
0642     *v = vcn;
0643 }
0644 
0645 static inline void de_set_vbn(struct NTFS_DE *e, CLST vcn)
0646 {
0647     __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64));
0648 
0649     *v = cpu_to_le64(vcn);
0650 }
0651 
0652 static inline __le64 de_get_vbn_le(const struct NTFS_DE *e)
0653 {
0654     return *(__le64 *)Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64));
0655 }
0656 
0657 static inline CLST de_get_vbn(const struct NTFS_DE *e)
0658 {
0659     __le64 *v = Add2Ptr(e, le16_to_cpu(e->size) - sizeof(__le64));
0660 
0661     return le64_to_cpu(*v);
0662 }
0663 
0664 static inline struct NTFS_DE *de_get_next(const struct NTFS_DE *e)
0665 {
0666     return Add2Ptr(e, le16_to_cpu(e->size));
0667 }
0668 
0669 static inline struct ATTR_FILE_NAME *de_get_fname(const struct NTFS_DE *e)
0670 {
0671     return le16_to_cpu(e->key_size) >= SIZEOF_ATTRIBUTE_FILENAME ?
0672                Add2Ptr(e, sizeof(struct NTFS_DE)) :
0673                NULL;
0674 }
0675 
0676 static inline bool de_is_last(const struct NTFS_DE *e)
0677 {
0678     return e->flags & NTFS_IE_LAST;
0679 }
0680 
0681 static inline bool de_has_vcn(const struct NTFS_DE *e)
0682 {
0683     return e->flags & NTFS_IE_HAS_SUBNODES;
0684 }
0685 
0686 static inline bool de_has_vcn_ex(const struct NTFS_DE *e)
0687 {
0688     return (e->flags & NTFS_IE_HAS_SUBNODES) &&
0689            (u64)(-1) != *((u64 *)Add2Ptr(e, le16_to_cpu(e->size) -
0690                             sizeof(__le64)));
0691 }
0692 
0693 #define MAX_BYTES_PER_NAME_ENTRY \
0694     ALIGN(sizeof(struct NTFS_DE) + \
0695           offsetof(struct ATTR_FILE_NAME, name) + \
0696           NTFS_NAME_LEN * sizeof(short), 8)
0697 
0698 struct INDEX_HDR {
0699     __le32 de_off;  // 0x00: The offset from the start of this structure
0700             // to the first NTFS_DE.
0701     __le32 used;    // 0x04: The size of this structure plus all
0702             // entries (quad-word aligned).
0703     __le32 total;   // 0x08: The allocated size of for this structure plus all entries.
0704     u8 flags;   // 0x0C: 0x00 = Small directory, 0x01 = Large directory.
0705     u8 res[3];
0706 
0707     //
0708     // de_off + used <= total
0709     //
0710 };
0711 
0712 static_assert(sizeof(struct INDEX_HDR) == 0x10);
0713 
0714 static inline struct NTFS_DE *hdr_first_de(const struct INDEX_HDR *hdr)
0715 {
0716     u32 de_off = le32_to_cpu(hdr->de_off);
0717     u32 used = le32_to_cpu(hdr->used);
0718     struct NTFS_DE *e = Add2Ptr(hdr, de_off);
0719     u16 esize;
0720 
0721     if (de_off >= used || de_off >= le32_to_cpu(hdr->total))
0722         return NULL;
0723 
0724     esize = le16_to_cpu(e->size);
0725     if (esize < sizeof(struct NTFS_DE) || de_off + esize > used)
0726         return NULL;
0727 
0728     return e;
0729 }
0730 
0731 static inline struct NTFS_DE *hdr_next_de(const struct INDEX_HDR *hdr,
0732                       const struct NTFS_DE *e)
0733 {
0734     size_t off = PtrOffset(hdr, e);
0735     u32 used = le32_to_cpu(hdr->used);
0736     u16 esize;
0737 
0738     if (off >= used)
0739         return NULL;
0740 
0741     esize = le16_to_cpu(e->size);
0742 
0743     if (esize < sizeof(struct NTFS_DE) ||
0744         off + esize + sizeof(struct NTFS_DE) > used)
0745         return NULL;
0746 
0747     return Add2Ptr(e, esize);
0748 }
0749 
0750 static inline bool hdr_has_subnode(const struct INDEX_HDR *hdr)
0751 {
0752     return hdr->flags & 1;
0753 }
0754 
0755 struct INDEX_BUFFER {
0756     struct NTFS_RECORD_HEADER rhdr; // 'INDX'
0757     __le64 vbn; // 0x10: vcn if index >= cluster or vsn id index < cluster
0758     struct INDEX_HDR ihdr; // 0x18:
0759 };
0760 
0761 static_assert(sizeof(struct INDEX_BUFFER) == 0x28);
0762 
0763 static inline bool ib_is_empty(const struct INDEX_BUFFER *ib)
0764 {
0765     const struct NTFS_DE *first = hdr_first_de(&ib->ihdr);
0766 
0767     return !first || de_is_last(first);
0768 }
0769 
0770 static inline bool ib_is_leaf(const struct INDEX_BUFFER *ib)
0771 {
0772     return !(ib->ihdr.flags & 1);
0773 }
0774 
0775 /* Index root structure ( 0x90 ). */
0776 enum COLLATION_RULE {
0777     NTFS_COLLATION_TYPE_BINARY  = cpu_to_le32(0),
0778     // $I30
0779     NTFS_COLLATION_TYPE_FILENAME    = cpu_to_le32(0x01),
0780     // $SII of $Secure and $Q of Quota
0781     NTFS_COLLATION_TYPE_UINT    = cpu_to_le32(0x10),
0782     // $O of Quota
0783     NTFS_COLLATION_TYPE_SID     = cpu_to_le32(0x11),
0784     // $SDH of $Secure
0785     NTFS_COLLATION_TYPE_SECURITY_HASH = cpu_to_le32(0x12),
0786     // $O of ObjId and "$R" for Reparse
0787     NTFS_COLLATION_TYPE_UINTS   = cpu_to_le32(0x13)
0788 };
0789 
0790 static_assert(sizeof(enum COLLATION_RULE) == 4);
0791 
0792 //
0793 struct INDEX_ROOT {
0794     enum ATTR_TYPE type;    // 0x00: The type of attribute to index on.
0795     enum COLLATION_RULE rule; // 0x04: The rule.
0796     __le32 index_block_size;// 0x08: The size of index record.
0797     u8 index_block_clst;    // 0x0C: The number of clusters or sectors per index.
0798     u8 res[3];
0799     struct INDEX_HDR ihdr;  // 0x10:
0800 };
0801 
0802 static_assert(sizeof(struct INDEX_ROOT) == 0x20);
0803 static_assert(offsetof(struct INDEX_ROOT, ihdr) == 0x10);
0804 
0805 #define VOLUME_FLAG_DIRTY       cpu_to_le16(0x0001)
0806 #define VOLUME_FLAG_RESIZE_LOG_FILE cpu_to_le16(0x0002)
0807 
0808 struct VOLUME_INFO {
0809     __le64 res1;    // 0x00
0810     u8 major_ver;   // 0x08: NTFS major version number (before .)
0811     u8 minor_ver;   // 0x09: NTFS minor version number (after .)
0812     __le16 flags;   // 0x0A: Volume flags, see VOLUME_FLAG_XXX
0813 
0814 }; // sizeof=0xC
0815 
0816 #define SIZEOF_ATTRIBUTE_VOLUME_INFO 0xc
0817 
0818 #define NTFS_LABEL_MAX_LENGTH       (0x100 / sizeof(short))
0819 #define NTFS_ATTR_INDEXABLE     cpu_to_le32(0x00000002)
0820 #define NTFS_ATTR_DUPALLOWED        cpu_to_le32(0x00000004)
0821 #define NTFS_ATTR_MUST_BE_INDEXED   cpu_to_le32(0x00000010)
0822 #define NTFS_ATTR_MUST_BE_NAMED     cpu_to_le32(0x00000020)
0823 #define NTFS_ATTR_MUST_BE_RESIDENT  cpu_to_le32(0x00000040)
0824 #define NTFS_ATTR_LOG_ALWAYS        cpu_to_le32(0x00000080)
0825 
0826 /* $AttrDef file entry. */
0827 struct ATTR_DEF_ENTRY {
0828     __le16 name[0x40];  // 0x00: Attr name.
0829     enum ATTR_TYPE type;    // 0x80: struct ATTRIB type.
0830     __le32 res;     // 0x84:
0831     enum COLLATION_RULE rule; // 0x88:
0832     __le32 flags;       // 0x8C: NTFS_ATTR_XXX (see above).
0833     __le64 min_sz;      // 0x90: Minimum attribute data size.
0834     __le64 max_sz;      // 0x98: Maximum attribute data size.
0835 };
0836 
0837 static_assert(sizeof(struct ATTR_DEF_ENTRY) == 0xa0);
0838 
0839 /* Object ID (0x40) */
0840 struct OBJECT_ID {
0841     struct GUID ObjId;  // 0x00: Unique Id assigned to file.
0842     struct GUID BirthVolumeId; // 0x10: Birth Volume Id is the Object Id of the Volume on.
0843                 // which the Object Id was allocated. It never changes.
0844     struct GUID BirthObjectId; // 0x20: Birth Object Id is the first Object Id that was
0845                 // ever assigned to this MFT Record. I.e. If the Object Id
0846                 // is changed for some reason, this field will reflect the
0847                 // original value of the Object Id.
0848     struct GUID DomainId;   // 0x30: Domain Id is currently unused but it is intended to be
0849                 // used in a network environment where the local machine is
0850                 // part of a Windows 2000 Domain. This may be used in a Windows
0851                 // 2000 Advanced Server managed domain.
0852 };
0853 
0854 static_assert(sizeof(struct OBJECT_ID) == 0x40);
0855 
0856 /* O Directory entry structure ( rule = 0x13 ) */
0857 struct NTFS_DE_O {
0858     struct NTFS_DE de;
0859     struct GUID ObjId;  // 0x10: Unique Id assigned to file.
0860     struct MFT_REF ref; // 0x20: MFT record number with this file.
0861     struct GUID BirthVolumeId; // 0x28: Birth Volume Id is the Object Id of the Volume on
0862                 // which the Object Id was allocated. It never changes.
0863     struct GUID BirthObjectId; // 0x38: Birth Object Id is the first Object Id that was
0864                 // ever assigned to this MFT Record. I.e. If the Object Id
0865                 // is changed for some reason, this field will reflect the
0866                 // original value of the Object Id.
0867                 // This field is valid if data_size == 0x48.
0868     struct GUID BirthDomainId; // 0x48: Domain Id is currently unused but it is intended
0869                 // to be used in a network environment where the local
0870                 // machine is part of a Windows 2000 Domain. This may be
0871                 // used in a Windows 2000 Advanced Server managed domain.
0872 };
0873 
0874 static_assert(sizeof(struct NTFS_DE_O) == 0x58);
0875 
0876 #define NTFS_OBJECT_ENTRY_DATA_SIZE1                           \
0877     0x38 // struct NTFS_DE_O.BirthDomainId is not used
0878 #define NTFS_OBJECT_ENTRY_DATA_SIZE2                           \
0879     0x48 // struct NTFS_DE_O.BirthDomainId is used
0880 
0881 /* Q Directory entry structure ( rule = 0x11 ) */
0882 struct NTFS_DE_Q {
0883     struct NTFS_DE de;
0884     __le32 owner_id;    // 0x10: Unique Id assigned to file
0885     __le32 Version;     // 0x14: 0x02
0886     __le32 flags2;      // 0x18: Quota flags, see above
0887     __le64 BytesUsed;   // 0x1C:
0888     __le64 ChangeTime;  // 0x24:
0889     __le64 WarningLimit;    // 0x28:
0890     __le64 HardLimit;   // 0x34:
0891     __le64 ExceededTime;    // 0x3C:
0892 
0893     // SID is placed here
0894 }; // sizeof() = 0x44
0895 
0896 #define SIZEOF_NTFS_DE_Q 0x44
0897 
0898 #define SecurityDescriptorsBlockSize 0x40000 // 256K
0899 #define SecurityDescriptorMaxSize    0x20000 // 128K
0900 #define Log2OfSecurityDescriptorsBlockSize 18
0901 
0902 struct SECURITY_KEY {
0903     __le32 hash; //  Hash value for descriptor
0904     __le32 sec_id; //  Security Id (guaranteed unique)
0905 };
0906 
0907 /* Security descriptors (the content of $Secure::SDS data stream) */
0908 struct SECURITY_HDR {
0909     struct SECURITY_KEY key;    // 0x00: Security Key.
0910     __le64 off;         // 0x08: Offset of this entry in the file.
0911     __le32 size;            // 0x10: Size of this entry, 8 byte aligned.
0912     /*
0913      * Security descriptor itself is placed here.
0914      * Total size is 16 byte aligned.
0915      */
0916 } __packed;
0917 
0918 #define SIZEOF_SECURITY_HDR 0x14
0919 
0920 /* SII Directory entry structure */
0921 struct NTFS_DE_SII {
0922     struct NTFS_DE de;
0923     __le32 sec_id;          // 0x10: Key: sizeof(security_id) = wKeySize
0924     struct SECURITY_HDR sec_hdr;    // 0x14:
0925 } __packed;
0926 
0927 #define SIZEOF_SII_DIRENTRY 0x28
0928 
0929 /* SDH Directory entry structure */
0930 struct NTFS_DE_SDH {
0931     struct NTFS_DE de;
0932     struct SECURITY_KEY key;    // 0x10: Key
0933     struct SECURITY_HDR sec_hdr;    // 0x18: Data
0934     __le16 magic[2];        // 0x2C: 0x00490049 "I I"
0935 };
0936 
0937 #define SIZEOF_SDH_DIRENTRY 0x30
0938 
0939 struct REPARSE_KEY {
0940     __le32 ReparseTag;      // 0x00: Reparse Tag
0941     struct MFT_REF ref;     // 0x04: MFT record number with this file
0942 }; // sizeof() = 0x0C
0943 
0944 static_assert(offsetof(struct REPARSE_KEY, ref) == 0x04);
0945 #define SIZEOF_REPARSE_KEY 0x0C
0946 
0947 /* Reparse Directory entry structure */
0948 struct NTFS_DE_R {
0949     struct NTFS_DE de;
0950     struct REPARSE_KEY key;     // 0x10: Reparse Key.
0951     u32 zero;           // 0x1c:
0952 }; // sizeof() = 0x20
0953 
0954 static_assert(sizeof(struct NTFS_DE_R) == 0x20);
0955 
0956 /* CompressReparseBuffer.WofVersion */
0957 #define WOF_CURRENT_VERSION     cpu_to_le32(1)
0958 /* CompressReparseBuffer.WofProvider */
0959 #define WOF_PROVIDER_WIM        cpu_to_le32(1)
0960 /* CompressReparseBuffer.WofProvider */
0961 #define WOF_PROVIDER_SYSTEM     cpu_to_le32(2)
0962 /* CompressReparseBuffer.ProviderVer */
0963 #define WOF_PROVIDER_CURRENT_VERSION    cpu_to_le32(1)
0964 
0965 #define WOF_COMPRESSION_XPRESS4K    cpu_to_le32(0) // 4k
0966 #define WOF_COMPRESSION_LZX32K      cpu_to_le32(1) // 32k
0967 #define WOF_COMPRESSION_XPRESS8K    cpu_to_le32(2) // 8k
0968 #define WOF_COMPRESSION_XPRESS16K   cpu_to_le32(3) // 16k
0969 
0970 /*
0971  * ATTR_REPARSE (0xC0)
0972  *
0973  * The reparse struct GUID structure is used by all 3rd party layered drivers to
0974  * store data in a reparse point. For non-Microsoft tags, The struct GUID field
0975  * cannot be GUID_NULL.
0976  * The constraints on reparse tags are defined below.
0977  * Microsoft tags can also be used with this format of the reparse point buffer.
0978  */
0979 struct REPARSE_POINT {
0980     __le32 ReparseTag;  // 0x00:
0981     __le16 ReparseDataLength;// 0x04:
0982     __le16 Reserved;
0983 
0984     struct GUID Guid;   // 0x08:
0985 
0986     //
0987     // Here GenericReparseBuffer is placed
0988     //
0989 };
0990 
0991 static_assert(sizeof(struct REPARSE_POINT) == 0x18);
0992 
0993 /* Maximum allowed size of the reparse data. */
0994 #define MAXIMUM_REPARSE_DATA_BUFFER_SIZE    (16 * 1024)
0995 
0996 /*
0997  * The value of the following constant needs to satisfy the following
0998  * conditions:
0999  *  (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 
1051 enum 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) */
1110 struct 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  */
1164 struct 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 
1170 static_assert(sizeof(struct EA_INFO) == 8);
1171 
1172 /* ATTR_EA (0xE0) */
1173 struct 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 
1181 static_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 
1188 struct 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 };
1197 static_assert(sizeof(struct SECURITY_DESCRIPTOR_RELATIVE) == 0x14);
1198 
1199 struct ACE_HEADER {
1200     u8 AceType;
1201     u8 AceFlags;
1202     __le16 AceSize;
1203 };
1204 static_assert(sizeof(struct ACE_HEADER) == 4);
1205 
1206 struct ACL {
1207     u8 AclRevision;
1208     u8 Sbz1;
1209     __le16 AclSize;
1210     __le16 AceCount;
1211     __le16 Sbz2;
1212 };
1213 static_assert(sizeof(struct ACL) == 8);
1214 
1215 struct SID {
1216     u8 Revision;
1217     u8 SubAuthorityCount;
1218     u8 IdentifierAuthority[6];
1219     __le32 SubAuthority[];
1220 };
1221 static_assert(offsetof(struct SID, SubAuthority) == 8);
1222 
1223 #endif /* _LINUX_NTFS3_NTFS_H */
1224 // clang-format on