1
2
3
4
5
6
7
8
9
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
23
24
25#define NTFS3_CHECK_FREE_CLST
26
27#define NTFS_NAME_LEN 255
28
29
30
31
32
33#define NTFS_LINK_MAX 4000
34
35
36
37
38
39
40
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
55
56
57
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
100 MFT_REC_SECURE = 9,
101 MFT_REC_UPCASE = 10,
102 MFT_REC_EXTEND = 11,
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
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
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];
179
180
181struct MFT_REF {
182 __le32 low;
183 __le16 high;
184 __le16 seq;
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];
200 u8 system_id[8];
201
202
203
204
205 u8 bytes_per_sector[2];
206
207 u8 sectors_per_clusters;
208 u8 unused1[7];
209 u8 media_type;
210 u8 unused2[2];
211 __le16 sct_per_track;
212 __le16 heads;
213 __le32 hidden_sectors;
214 u8 unused3[4];
215 u8 bios_drive_num;
216 u8 unused4;
217 u8 signature_ex;
218 u8 unused5;
219 __le64 sectors_per_volume;
220 __le64 mft_clst;
221 __le64 mft2_clst;
222 s8 record_size;
223 u8 unused6[3];
224 s8 index_size;
225 u8 unused7[3];
226 __le64 serial_num;
227 __le32 check_sum;
228
229
230 u8 boot_code[0x200 - 0x50 - 2 - 4];
231 u8 boot_magic[2];
232};
233
234static_assert(sizeof(struct NTFS_BOOT) == 0x200);
235
236enum NTFS_SIGNATURE {
237 NTFS_FILE_SIGNATURE = cpu_to_le32(0x454C4946),
238 NTFS_INDX_SIGNATURE = cpu_to_le32(0x58444E49),
239 NTFS_CHKD_SIGNATURE = cpu_to_le32(0x444B4843),
240 NTFS_RSTR_SIGNATURE = cpu_to_le32(0x52545352),
241 NTFS_RCRD_SIGNATURE = cpu_to_le32(0x44524352),
242 NTFS_BAAD_SIGNATURE = cpu_to_le32(0x44414142),
243 NTFS_HOLE_SIGNATURE = cpu_to_le32(0x454C4F48),
244 NTFS_FFFF_SIGNATURE = cpu_to_le32(0xffffffff),
245};
246
247static_assert(sizeof(enum NTFS_SIGNATURE) == 4);
248
249
250struct NTFS_RECORD_HEADER {
251
252 enum NTFS_SIGNATURE sign;
253 __le16 fix_off;
254 __le16 fix_num;
255 __le64 lsn;
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
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
274struct MFT_REC {
275 struct NTFS_RECORD_HEADER rhdr;
276
277 __le16 seq;
278 __le16 hard_links;
279 __le16 attr_off;
280 __le16 flags;
281 __le32 used;
282 __le32 total;
283
284 struct MFT_REF parent_ref;
285 __le16 next_attr_id;
286
287 __le16 res;
288 __le32 mft_record;
289 __le16 fixups[];
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
322#define RESIDENT_FLAG_INDEXED 0x01
323
324struct ATTR_RESIDENT {
325 __le32 data_size;
326 __le16 data_off;
327 u8 flags;
328 u8 res;
329};
330
331struct ATTR_NONRESIDENT {
332 __le64 svcn;
333 __le64 evcn;
334 __le16 run_off;
335
336
337
338
339
340
341
342
343
344
345
346
347 u8 c_unit;
348 u8 res1[5];
349 __le64 alloc_size;
350
351 __le64 data_size;
352 __le64 valid_size;
353 __le64 total_size;
354
355
356
357};
358
359
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;
367 __le32 size;
368 u8 non_res;
369 u8 name_len;
370 __le16 name_off;
371 __le16 flags;
372 __le16 id;
373
374 union {
375 struct ATTR_RESIDENT res;
376 struct ATTR_NONRESIDENT nres;
377 };
378};
379
380
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
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
478struct ATTR_STD_INFO {
479 __le64 cr_time;
480 __le64 m_time;
481 __le64 c_time;
482 __le64 a_time;
483 enum FILE_ATTRIBUTE fa;
484 __le32 max_ver_num;
485 __le32 ver_num;
486 __le32 class_id;
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;
496 __le64 m_time;
497 __le64 c_time;
498 __le64 a_time;
499 enum FILE_ATTRIBUTE fa;
500 __le32 max_ver_num;
501 __le32 ver_num;
502 __le32 class_id;
503
504 __le32 owner_id;
505 __le32 security_id;
506 __le64 quota_charge;
507 __le64 usn;
508
509
510};
511
512static_assert(sizeof(struct ATTR_STD_INFO5) == 0x48);
513
514
515struct ATTR_LIST_ENTRY {
516 enum ATTR_TYPE type;
517 __le16 size;
518 u8 name_len;
519 u8 name_off;
520 __le64 vcn;
521 struct MFT_REF ref;
522 __le16 id;
523 __le16 name[3];
524
525};
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
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
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
558struct NTFS_DUP_INFO {
559 __le64 cr_time;
560 __le64 m_time;
561 __le64 c_time;
562 __le64 a_time;
563 __le64 alloc_size;
564 __le64 data_size;
565 enum FILE_ATTRIBUTE fa;
566 __le16 ea_size;
567 __le16 reparse;
568
569};
570
571struct ATTR_FILE_NAME {
572 struct MFT_REF home;
573 struct NTFS_DUP_INFO dup;
574 u8 name_len;
575 u8 type;
576 __le16 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
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
606#define NTFS_IE_HAS_SUBNODES cpu_to_le16(1)
607#define NTFS_IE_LAST cpu_to_le16(2)
608
609
610struct NTFS_DE {
611 union {
612 struct MFT_REF ref;
613 struct {
614 __le16 data_off;
615 __le16 data_size;
616 __le32 res;
617 } view;
618 };
619 __le16 size;
620 __le16 key_size;
621 __le16 flags;
622 __le16 res;
623
624
625
626
627
628
629
630
631
632
633
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;
700
701 __le32 used;
702
703 __le32 total;
704 u8 flags;
705 u8 res[3];
706
707
708
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;
757 __le64 vbn;
758 struct INDEX_HDR ihdr;
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
776enum COLLATION_RULE {
777 NTFS_COLLATION_TYPE_BINARY = cpu_to_le32(0),
778
779 NTFS_COLLATION_TYPE_FILENAME = cpu_to_le32(0x01),
780
781 NTFS_COLLATION_TYPE_UINT = cpu_to_le32(0x10),
782
783 NTFS_COLLATION_TYPE_SID = cpu_to_le32(0x11),
784
785 NTFS_COLLATION_TYPE_SECURITY_HASH = cpu_to_le32(0x12),
786
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;
795 enum COLLATION_RULE rule;
796 __le32 index_block_size;
797 u8 index_block_clst;
798 u8 res[3];
799 struct INDEX_HDR ihdr;
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;
810 u8 major_ver;
811 u8 minor_ver;
812 __le16 flags;
813
814};
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
827struct ATTR_DEF_ENTRY {
828 __le16 name[0x40];
829 enum ATTR_TYPE type;
830 __le32 res;
831 enum COLLATION_RULE rule;
832 __le32 flags;
833 __le64 min_sz;
834 __le64 max_sz;
835};
836
837static_assert(sizeof(struct ATTR_DEF_ENTRY) == 0xa0);
838
839
840struct OBJECT_ID {
841 struct GUID ObjId;
842 struct GUID BirthVolumeId;
843
844 struct GUID BirthObjectId;
845
846
847
848 struct GUID DomainId;
849
850
851
852};
853
854static_assert(sizeof(struct OBJECT_ID) == 0x40);
855
856
857struct NTFS_DE_O {
858 struct NTFS_DE de;
859 struct GUID ObjId;
860 struct MFT_REF ref;
861 struct GUID BirthVolumeId;
862
863 struct GUID BirthObjectId;
864
865
866
867
868 struct GUID BirthDomainId;
869
870
871
872};
873
874static_assert(sizeof(struct NTFS_DE_O) == 0x58);
875
876#define NTFS_OBJECT_ENTRY_DATA_SIZE1 \
877 0x38
878#define NTFS_OBJECT_ENTRY_DATA_SIZE2 \
879 0x48
880
881
882struct NTFS_DE_Q {
883 struct NTFS_DE de;
884 __le32 owner_id;
885 __le32 Version;
886 __le32 flags2;
887 __le64 BytesUsed;
888 __le64 ChangeTime;
889 __le64 WarningLimit;
890 __le64 HardLimit;
891 __le64 ExceededTime;
892
893
894};
895
896#define SIZEOF_NTFS_DE_Q 0x44
897
898#define SecurityDescriptorsBlockSize 0x40000
899#define SecurityDescriptorMaxSize 0x20000
900#define Log2OfSecurityDescriptorsBlockSize 18
901
902struct SECURITY_KEY {
903 __le32 hash;
904 __le32 sec_id;
905};
906
907
908struct SECURITY_HDR {
909 struct SECURITY_KEY key;
910 __le64 off;
911 __le32 size;
912
913
914
915
916} __packed;
917
918#define SIZEOF_SECURITY_HDR 0x14
919
920
921struct NTFS_DE_SII {
922 struct NTFS_DE de;
923 __le32 sec_id;
924 struct SECURITY_HDR sec_hdr;
925} __packed;
926
927#define SIZEOF_SII_DIRENTRY 0x28
928
929
930struct NTFS_DE_SDH {
931 struct NTFS_DE de;
932 struct SECURITY_KEY key;
933 struct SECURITY_HDR sec_hdr;
934 __le16 magic[2];
935};
936
937#define SIZEOF_SDH_DIRENTRY 0x30
938
939struct REPARSE_KEY {
940 __le32 ReparseTag;
941 struct MFT_REF ref;
942};
943
944static_assert(offsetof(struct REPARSE_KEY, ref) == 0x04);
945#define SIZEOF_REPARSE_KEY 0x0C
946
947
948struct NTFS_DE_R {
949 struct NTFS_DE de;
950 struct REPARSE_KEY key;
951 u32 zero;
952};
953
954static_assert(sizeof(struct NTFS_DE_R) == 0x20);
955
956
957#define WOF_CURRENT_VERSION cpu_to_le32(1)
958
959#define WOF_PROVIDER_WIM cpu_to_le32(1)
960
961#define WOF_PROVIDER_SYSTEM cpu_to_le32(2)
962
963#define WOF_PROVIDER_CURRENT_VERSION cpu_to_le32(1)
964
965#define WOF_COMPRESSION_XPRESS4K cpu_to_le32(0)
966#define WOF_COMPRESSION_LZX32K cpu_to_le32(1)
967#define WOF_COMPRESSION_XPRESS8K cpu_to_le32(2)
968#define WOF_COMPRESSION_XPRESS16K cpu_to_le32(3)
969
970
971
972
973
974
975
976
977
978
979struct REPARSE_POINT {
980 __le32 ReparseTag;
981 __le16 ReparseDataLength;
982 __le16 Reserved;
983
984 struct GUID Guid;
985
986
987
988
989};
990
991static_assert(sizeof(struct REPARSE_POINT) == 0x18);
992
993
994#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024)
995
996
997
998
999
1000
1001
1002#define IO_REPARSE_TAG_RESERVED_RANGE 1
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031#define IsReparseTagMicrosoft(_tag) (((_tag)&IO_REPARSE_TAG_MICROSOFT))
1032
1033
1034#define IsReparseTagNameSurrogate(_tag) (((_tag)&IO_REPARSE_TAG_NAME_SURROGATE))
1035
1036
1037
1038
1039
1040#define IO_REPARSE_TAG_VALID_VALUES 0xF000FFFF
1041
1042
1043
1044
1045#define IsReparseTagValid(_tag) \
1046 (!((_tag) & ~IO_REPARSE_TAG_VALID_VALUES) && \
1047 ((_tag) > IO_REPARSE_TAG_RESERVED_RANGE))
1048
1049
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
1064
1065
1066
1067
1068 IO_REPARSE_TAG_DFS = cpu_to_le32(0x8000000A),
1069
1070
1071 IO_REPARSE_TAG_FILTER_MANAGER = cpu_to_le32(0x8000000B),
1072
1073
1074
1075
1076 IO_REPARSE_TAG_IFSTEST_CONGRUENT = cpu_to_le32(0x00000009),
1077
1078
1079 IO_REPARSE_TAG_ARKIVIO = cpu_to_le32(0x0000000C),
1080
1081
1082 IO_REPARSE_TAG_SOLUTIONSOFT = cpu_to_le32(0x2000000D),
1083
1084
1085 IO_REPARSE_TAG_COMMVAULT = cpu_to_le32(0x0000000E),
1086
1087
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
1110struct REPARSE_DATA_BUFFER {
1111 __le32 ReparseTag;
1112 __le16 ReparseDataLength;
1113 __le16 Reserved;
1114
1115 union {
1116
1117 struct {
1118 __le16 SubstituteNameOffset;
1119 __le16 SubstituteNameLength;
1120 __le16 PrintNameOffset;
1121 __le16 PrintNameLength;
1122 __le16 PathBuffer[];
1123 } MountPointReparseBuffer;
1124
1125
1126
1127
1128
1129 struct {
1130 __le16 SubstituteNameOffset;
1131 __le16 SubstituteNameLength;
1132 __le16 PrintNameOffset;
1133 __le16 PrintNameLength;
1134
1135 __le32 Flags;
1136 __le16 PathBuffer[];
1137 } SymbolicLinkReparseBuffer;
1138
1139
1140 struct {
1141 __le32 WofVersion;
1142
1143
1144
1145
1146 __le32 WofProvider;
1147 __le32 ProviderVer;
1148 __le32 CompressionFormat;
1149 } CompressReparseBuffer;
1150
1151 struct {
1152 u8 DataBuffer[1];
1153 } GenericReparseBuffer;
1154 };
1155};
1156
1157
1158
1159#define FILE_NEED_EA 0x80
1160
1161
1162
1163
1164struct EA_INFO {
1165 __le16 size_pack;
1166 __le16 count;
1167 __le32 size;
1168};
1169
1170static_assert(sizeof(struct EA_INFO) == 8);
1171
1172
1173struct EA_FULL {
1174 __le32 size;
1175 u8 flags;
1176 u8 name_len;
1177 __le16 elength;
1178 u8 name[];
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
1224
1225