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