• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011-2012 Paulo Alcantara <pcacjr@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc.,
17  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 
20 #include "runlist.h"
21 
22 #ifndef _NTFS_H_
23 #define _NTFS_H_
24 
25 struct ntfs_bpb {
26     uint8_t jmp_boot[3];
27     char oem_name[8];
28     uint16_t sector_size;
29     uint8_t sec_per_clust;
30     uint16_t res_sectors;
31     uint8_t zero_0[3];
32     uint16_t zero_1;
33     uint8_t media;
34     uint16_t zero_2;
35     uint16_t unused_0;
36     uint16_t unused_1;
37     uint32_t unused_2;
38     uint32_t zero_3;
39     uint32_t unused_3;
40     uint64_t total_sectors;
41     uint64_t mft_lclust;
42     uint64_t mft_mirr_lclust;
43     int8_t clust_per_mft_record;
44     uint8_t unused_4[3];
45     uint8_t clust_per_idx_record;
46     uint8_t unused_5[3];
47     uint64_t vol_serial;
48     uint32_t unused_6;
49 
50     uint8_t pad[428];       /* padding to a sector boundary (512 bytes) */
51 } __attribute__((__packed__));
52 
53 /* Function type for an NTFS-version-dependent MFT record lookup */
54 struct ntfs_mft_record;
55 typedef struct ntfs_mft_record *f_mft_record_lookup(struct fs_info *,
56                                                     uint32_t, block_t *);
57 
58 struct ntfs_sb_info {
59     block_t mft_blk;                /* The first MFT record block */
60     uint64_t mft_lcn;               /* LCN of the first MFT record */
61     unsigned mft_size;              /* The MFT size in sectors */
62     uint64_t mft_record_size;       /* MFT record size in bytes */
63 
64     uint8_t clust_per_idx_record;   /* Clusters per Index Record */
65 
66     unsigned long long clusters;    /* Total number of clusters */
67 
68     unsigned clust_shift;           /* Based on sectors */
69     unsigned clust_byte_shift;      /* Based on bytes */
70     unsigned clust_mask;
71     unsigned clust_size;
72 
73     uint8_t major_ver;              /* Major version from $Volume */
74     uint8_t minor_ver;              /* Minor version from $Volume */
75 
76     /* NTFS-version-dependent MFT record lookup function to use */
77     f_mft_record_lookup *mft_record_lookup;
78 } __attribute__((__packed__));
79 
80 /* The NTFS in-memory inode structure */
81 struct ntfs_inode {
82     int64_t initialized_size;
83     int64_t allocated_size;
84     unsigned long mft_no;       /* Number of the mft record / inode */
85     uint16_t seq_no;            /* Sequence number of the mft record */
86     uint32_t type;              /* Attribute type of this inode */
87     uint8_t non_resident;
88     union {                 /* Non-resident $DATA attribute */
89         struct {            /* Used only if non_resident flags isn't set */
90             uint32_t offset;    /* Data offset */
91         } resident;
92         struct {            /* Used only if non_resident is set */
93             struct runlist *rlist;
94         } non_resident;
95     } data;
96     uint32_t start_cluster; /* Starting cluster address */
97     sector_t start;         /* Starting sector */
98     sector_t offset;        /* Current sector offset */
99     sector_t here;          /* Sector corresponding to offset */
100 };
101 
102 /* This is structure is used to keep a state for ntfs_readdir() callers.
103  * As NTFS stores directory entries in a complex way, this is structure
104  * ends up saving a state required to find out where we must start from
105  * for the next ntfs_readdir() call.
106  */
107 struct ntfs_readdir_state {
108     unsigned long mft_no;       /* MFT record number */
109     bool in_idx_root;           /* It's true if we're still in the INDEX root */
110     uint32_t idx_blks_count;    /* Number of read INDX blocks */
111     uint32_t entries_count;     /* Number of read INDEX entries */
112     int64_t last_vcn;           /* Last VCN of the INDX block */
113 };
114 
115 enum {
116     MAP_UNSPEC,
117     MAP_START           = 1 << 0,
118     MAP_END             = 1 << 1,
119     MAP_ALLOCATED       = 1 << 2,
120     MAP_UNALLOCATED     = 1 << 3,
121     MAP_MASK            = 0x0000000F,
122 };
123 
124 struct mapping_chunk {
125     uint64_t vcn;
126     int64_t lcn;
127     uint64_t len;
128     uint32_t flags;
129 };
130 
131 /* System defined attributes (32-bit)
132  * Each attribute type has a corresponding attribute name (in Unicode)
133  */
134 enum {
135     NTFS_AT_UNUSED                      = 0x00,
136     NTFS_AT_STANDARD_INFORMATION        = 0x10,
137     NTFS_AT_ATTR_LIST                   = 0x20,
138     NTFS_AT_FILENAME                    = 0x30,
139     NTFS_AT_OBJ_ID                      = 0x40,
140     NTFS_AT_SECURITY_DESCP              = 0x50,
141     NTFS_AT_VOL_NAME                    = 0x60,
142     NTFS_AT_VOL_INFO                    = 0x70,
143     NTFS_AT_DATA                        = 0x80,
144     NTFS_AT_INDEX_ROOT                  = 0x90,
145     NTFS_AT_INDEX_ALLOCATION            = 0xA0,
146     NTFS_AT_BITMAP                      = 0xB0,
147     NTFS_AT_REPARSE_POINT               = 0xC0,
148     NTFS_AT_EA_INFO                     = 0xD0,
149     NTFS_AT_EA                          = 0xE0,
150     NTFS_AT_PROPERTY_SET                = 0xF0,
151     NTFS_AT_LOGGED_UTIL_STREAM          = 0x100,
152     NTFS_AT_FIRST_USER_DEFINED_ATTR     = 0x1000,
153     NTFS_AT_END                         = 0xFFFFFFFF,
154 };
155 
156 /* NTFS File Permissions (also called attributes in DOS terminology) */
157 enum {
158     NTFS_FILE_ATTR_READONLY                     = 0x00000001,
159     NTFS_FILE_ATTR_HIDDEN                       = 0x00000002,
160     NTFS_FILE_ATTR_SYSTEM                       = 0x00000004,
161     NTFS_FILE_ATTR_DIRECTORY                    = 0x00000010,
162     NTFS_FILE_ATTR_ARCHIVE                      = 0x00000020,
163     NTFS_FILE_ATTR_DEVICE                       = 0x00000040,
164     NTFS_FILE_ATTR_NORMAL                       = 0x00000080,
165     NTFS_FILE_ATTR_TEMPORARY                    = 0x00000100,
166     NTFS_FILE_ATTR_SPARSE_FILE                  = 0x00000200,
167     NTFS_FILE_ATTR_REPARSE_POINT                = 0x00000400,
168     NTFS_FILE_ATTR_COMPRESSED                   = 0x00000800,
169     NTFS_FILE_ATTR_OFFLINE                      = 0x00001000,
170     NTFS_FILE_ATTR_NOT_CONTENT_INDEXED          = 0x00002000,
171     NTFS_FILE_ATTR_ENCRYPTED                    = 0x00004000,
172     NTFS_FILE_ATTR_VALID_FLAGS                  = 0x00007FB7,
173     NTFS_FILE_ATTR_VALID_SET_FLAGS              = 0x000031A7,
174     NTFS_FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT  = 0x10000000,
175     NTFS_FILE_ATTR_DUP_VIEW_INDEX_PRESENT       = 0x20000000,
176 };
177 
178 /*
179  * Magic identifiers present at the beginning of all ntfs record containing
180  * records (like mft records for example).
181  */
182 enum {
183     /* Found in $MFT/$DATA */
184     NTFS_MAGIC_FILE     = 0x454C4946,   /* MFT entry */
185     NTFS_MAGIC_INDX     = 0x58444E49,   /* Index buffer */
186     NTFS_MAGIC_HOLE     = 0x454C4F48,
187 
188     /* Found in $LogFile/$DATA */
189     NTFS_MAGIC_RSTR     = 0x52545352,
190     NTFS_MAGIC_RCRD     = 0x44524352,
191     /* Found in $LogFile/$DATA (May be found in $MFT/$DATA, also ?) */
192     NTFS_MAGIC_CHKDSK   = 0x444B4843,
193     /* Found in all ntfs record containing records. */
194     NTFS_MAGIC_BAAD     = 0x44414142,
195     NTFS_MAGIC_EMPTY    = 0xFFFFFFFF,   /* Record is empty */
196 };
197 
198 struct ntfs_record {
199     uint32_t magic;
200     uint16_t usa_ofs;
201     uint16_t usa_count;
202 } __attribute__((__packed__)) NTFS_RECORD;
203 
204 /* The $MFT metadata file types */
205 enum ntfs_system_file {
206     FILE_MFT            = 0,
207     FILE_MFTMirr        = 1,
208     FILE_LogFile        = 2,
209     FILE_Volume         = 3,
210     FILE_AttrDef        = 4,
211     FILE_root           = 5,
212     FILE_Bitmap         = 6,
213     FILE_Boot           = 7,
214     FILE_BadClus        = 8,
215     FILE_Secure         = 9,
216     FILE_UpCase         = 10,
217     FILE_Extend         = 11,
218     FILE_reserved12     = 12,
219     FILE_reserved13     = 13,
220     FILE_reserved14     = 14,
221     FILE_reserved15     = 15,
222     FILE_reserved16     = 16,
223 };
224 
225 enum {
226     MFT_RECORD_IN_USE       = 0x0001,
227     MFT_RECORD_IS_DIRECTORY = 0x0002,
228 } __attribute__((__packed__));
229 
230 struct ntfs_mft_record {
231     uint32_t magic;
232     uint16_t usa_ofs;
233     uint16_t usa_count;
234     uint64_t lsn;
235     uint16_t seq_no;
236     uint16_t link_count;
237     uint16_t attrs_offset;
238     uint16_t flags;     /* MFT record flags */
239     uint32_t bytes_in_use;
240     uint32_t bytes_allocated;
241     uint64_t base_mft_record;
242     uint16_t next_attr_instance;
243     uint16_t reserved;
244     uint32_t mft_record_no;
245 } __attribute__((__packed__));   /* 48 bytes */
246 
247 /* This is the version without the NTFS 3.1+ specific fields */
248 struct ntfs_mft_record_old {
249     uint32_t magic;
250     uint16_t usa_ofs;
251     uint16_t usa_count;
252     uint64_t lsn;
253     uint16_t seq_no;
254     uint16_t link_count;
255     uint16_t attrs_offset;
256     uint16_t flags;     /* MFT record flags */
257     uint32_t bytes_in_use;
258     uint32_t bytes_allocated;
259     uint64_t base_mft_record;
260     uint16_t next_attr_instance;
261 } __attribute__((__packed__));   /* 42 bytes */
262 
263 enum {
264     ATTR_DEF_INDEXABLE          = 0x02,
265     ATTR_DEF_MULTIPLE           = 0x04,
266     ATTR_DEF_NOT_ZERO           = 0x08,
267     ATTR_DEF_INDEXED_UNIQUE     = 0x10,
268     ATTR_DEF_NAMED_UNIQUE       = 0x20,
269     ATTR_DEF_RESIDENT           = 0x40,
270     ATTR_DEF_ALWAYS_LOG         = 0x80,
271 };
272 
273 struct ntfs_attr_record {
274     uint32_t type;      /* Attr. type code */
275     uint32_t len;
276     uint8_t non_resident;
277     uint8_t name_len;
278     uint16_t name_offset;
279     uint16_t flags;     /* Attr. flags */
280     uint16_t instance;
281     union {
282         struct {    /* Resident attribute */
283             uint32_t value_len;
284             uint16_t value_offset;
285             uint8_t flags;  /* Flags of resident attributes */
286             int8_t reserved;
287         } __attribute__((__packed__)) resident;
288         struct {    /* Non-resident attributes */
289             uint64_t lowest_vcn;
290             uint64_t highest_vcn;
291             uint16_t mapping_pairs_offset;
292             uint8_t compression_unit;
293             uint8_t reserved[5];
294             int64_t allocated_size;
295             int64_t data_size; /* Byte size of the attribute value.
296                                 * Note: it can be larger than
297                                 * allocated_size if attribute value is
298                                 * compressed or sparse.
299                                 */
300             int64_t initialized_size;
301             int64_t compressed_size;
302         } __attribute__((__packed__)) non_resident;
303     } __attribute__((__packed__)) data;
304 } __attribute__((__packed__));
305 
306 /* Attribute: Attribute List (0x20)
307  * Note: it can be either resident or non-resident
308  */
309 struct ntfs_attr_list_entry {
310     uint32_t type;
311     uint16_t length;
312     uint8_t name_length;
313     uint8_t name_offset;
314     uint64_t lowest_vcn;
315     uint64_t mft_ref;
316     uint16_t instance;
317     uint16_t name[0];
318 } __attribute__((__packed__));
319 
320 #define NTFS_MAX_FILE_NAME_LEN 255
321 
322 /* Possible namespaces for filenames in ntfs (8-bit) */
323 enum {
324     FILE_NAME_POSIX             = 0x00,
325     FILE_NAME_WIN32             = 0x01,
326     FILE_NAME_DOS               = 0x02,
327     FILE_NAME_WIN32_AND_DOS     = 0x03,
328 } __attribute__((__packed__));
329 
330 /* Attribute: Filename (0x30)
331  * Note: always resident
332  */
333 struct ntfs_filename_attr {
334     uint64_t parent_directory;
335     int64_t ctime;
336     int64_t atime;
337     int64_t mtime;
338     int64_t rtime;
339     uint64_t allocated_size;
340     uint64_t data_size;
341     uint32_t file_attrs;
342     union {
343         struct {
344             uint16_t packed_ea_size;
345             uint16_t reserved;      /* reserved for alignment */
346         } __attribute__((__packed__)) ea;
347         struct {
348             uint32_t reparse_point_tag;
349         } __attribute__((__packed__)) rp;
350     } __attribute__((__packed__)) type;
351     uint8_t file_name_len;
352     uint8_t file_name_type;
353     uint16_t file_name[0];          /* File name in Unicode */
354 } __attribute__((__packed__));
355 
356 /* Attribute: Volume Name (0x60)
357  * Note: always resident
358  * Note: Present only in FILE_volume
359  */
360 struct ntfs_vol_name {
361     uint16_t name[0];       /* The name of the volume in Unicode */
362 } __attribute__((__packed__));
363 
364 /* Attribute: Volume Information (0x70)
365  * Note: always resident
366  * Note: present only in FILE_Volume
367  */
368 struct ntfs_vol_info {
369     uint64_t reserved;
370     uint8_t major_ver;
371     uint8_t minor_ver;
372     uint16_t flags;     /* Volume flags */
373 } __attribute__((__packed__));
374 
375 /* Attribute: Data attribute (0x80)
376  * Note: can be either resident or non-resident
377  */
378 struct ntfs_data_attr {
379     uint8_t data[0];
380 } __attribute__((__packed__));
381 
382 /* Index header flags (8-bit) */
383 enum {
384     SMALL_INDEX = 0,
385     LARGE_INDEX = 1,
386     LEAF_NODE   = 0,
387     INDEX_NODE  = 1,
388     NODE_MASK   = 1,
389 } __attribute__((__packed__));
390 
391 /* Header for the indexes, describing the INDEX_ENTRY records, which
392  * follow the struct ntfs_idx_header.
393  */
394 struct ntfs_idx_header {
395     uint32_t entries_offset;
396     uint32_t index_len;
397     uint32_t allocated_size;
398     uint8_t flags;              /* Index header flags */
399     uint8_t reserved[3];        /* Align to 8-byte boundary */
400 } __attribute__((__packed__));
401 
402 /* Attribute: Index Root (0x90)
403  * Note: always resident
404  */
405 struct ntfs_idx_root {
406     uint32_t type;  /* It is $FILE_NAME for directories, zero for view indexes.
407                      * No other values allowed.
408                      */
409     uint32_t collation_rule;
410     uint32_t index_block_size;
411     uint8_t clust_per_index_block;
412     uint8_t reserved[3];
413     struct ntfs_idx_header index;
414 } __attribute__((__packed__));
415 
416 /* Attribute: Index allocation (0xA0)
417  * Note: always non-resident, of course! :-)
418  */
419 struct ntfs_idx_allocation {
420     uint32_t magic;
421     uint16_t usa_ofs;           /* Update Sequence Array offsets */
422     uint16_t usa_count;         /* Update Sequence Array number in bytes */
423     int64_t lsn;
424     int64_t index_block_vcn;    /* Virtual cluster number of the index block */
425     struct ntfs_idx_header index;
426 } __attribute__((__packed__));
427 
428 enum {
429     INDEX_ENTRY_NODE            = 1,
430     INDEX_ENTRY_END             = 2,
431     /* force enum bit width to 16-bit */
432     INDEX_ENTRY_SPACE_FILTER    = 0xFFFF,
433 } __attribute__((__packed__));
434 
435 struct ntfs_idx_entry_header {
436     union {
437         struct { /* Only valid when INDEX_ENTRY_END is not set */
438             uint64_t indexed_file;
439         } __attribute__((__packed__)) dir;
440         struct { /* Used for views/indexes to find the entry's data */
441             uint16_t data_offset;
442             uint16_t data_len;
443             uint32_t reservedV;
444         } __attribute__((__packed__)) vi;
445     } __attribute__((__packed__)) data;
446     uint16_t len;
447     uint16_t key_len;
448     uint16_t flags;     /* Index entry flags */
449     uint16_t reserved;  /* Align to 8-byte boundary */
450 } __attribute__((__packed__));
451 
452 struct ntfs_idx_entry {
453     union {
454         struct { /* Only valid when INDEX_ENTRY_END is not set */
455             uint64_t indexed_file;
456         } __attribute__((__packed__)) dir;
457         struct { /* Used for views/indexes to find the entry's data */
458             uint16_t data_offset;
459             uint16_t data_len;
460             uint32_t reservedV;
461         } __attribute__((__packed__)) vi;
462     } __attribute__((__packed__)) data;
463     uint16_t len;
464     uint16_t key_len;
465     uint16_t flags;     /* Index entry flags */
466     uint16_t reserved;  /* Align to 8-byte boundary */
467     union {
468         struct ntfs_filename_attr file_name;
469         //SII_INDEX_KEY sii;
470         //SDH_INDEX_KEY sdh;
471         //GUID object_id;
472         //REPARSE_INDEX_KEY reparse;
473         //SID sid;
474         uint32_t owner_id;
475     } __attribute__((__packed__)) key;
476 } __attribute__((__packed__));
477 
NTFS_SB(struct fs_info * fs)478 static inline struct ntfs_sb_info *NTFS_SB(struct fs_info *fs)
479 {
480     return fs->fs_info;
481 }
482 
483 #define NTFS_PVT(i) ((struct ntfs_inode *)((i)->pvt))
484 
485 #endif /* _NTFS_H_ */
486