2 * Copyright (C) 2011-2012 Paulo Alcantara <pcacjr@gmail.com>
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.
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.
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.
29 uint8_t sec_per_clust
;
40 uint64_t total_sectors
;
42 uint64_t mft_mirr_lclust
;
43 int8_t clust_per_mft_record
;
45 uint8_t clust_per_idx_record
;
50 uint8_t pad
[428]; /* padding to a sector boundary (512 bytes) */
51 } __attribute__((__packed__
));
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
*,
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 */
64 uint8_t clust_per_idx_record
; /* Clusters per Index Record */
66 unsigned long long clusters
; /* Total number of clusters */
68 unsigned clust_shift
; /* Based on sectors */
69 unsigned clust_byte_shift
; /* Based on bytes */
73 uint8_t major_ver
; /* Major version from $Volume */
74 uint8_t minor_ver
; /* Minor version from $Volume */
76 /* NTFS-version-dependent MFT record lookup function to use */
77 f_mft_record_lookup
*mft_record_lookup
;
78 } __attribute__((__packed__
));
80 /* The NTFS in-memory inode structure */
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 */
88 union { /* Non-resident $DATA attribute */
89 struct { /* Used only if non_resident flags isn't set */
90 uint32_t offset
; /* Data offset */
92 struct { /* Used only if non_resident is set */
93 struct runlist
*rlist
;
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 */
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.
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 */
119 MAP_ALLOCATED
= 1 << 2,
120 MAP_UNALLOCATED
= 1 << 3,
121 MAP_MASK
= 0x0000000F,
124 struct mapping_chunk
{
131 /* System defined attributes (32-bit)
132 * Each attribute type has a corresponding attribute name (in Unicode)
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,
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,
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,
156 /* NTFS File Permissions (also called attributes in DOS terminology) */
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,
179 * Magic identifiers present at the beginning of all ntfs record containing
180 * records (like mft records for example).
183 /* Found in $MFT/$DATA */
184 NTFS_MAGIC_FILE
= 0x454C4946, /* MFT entry */
185 NTFS_MAGIC_INDX
= 0x58444E49, /* Index buffer */
186 NTFS_MAGIC_HOLE
= 0x454C4F48,
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 */
202 } __attribute__((__packed__
)) NTFS_RECORD
;
204 /* The $MFT metadata file types */
205 enum ntfs_system_file
{
218 FILE_reserved12
= 12,
219 FILE_reserved13
= 13,
220 FILE_reserved14
= 14,
221 FILE_reserved15
= 15,
222 FILE_reserved16
= 16,
226 MFT_RECORD_IN_USE
= 0x0001,
227 MFT_RECORD_IS_DIRECTORY
= 0x0002,
228 } __attribute__((__packed__
));
230 struct ntfs_mft_record
{
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
;
244 uint32_t mft_record_no
;
245 } __attribute__((__packed__
)); /* 48 bytes */
247 /* This is the version without the NTFS 3.1+ specific fields */
248 struct ntfs_mft_record_old
{
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 */
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,
273 struct ntfs_attr_record
{
274 uint32_t type
; /* Attr. type code */
276 uint8_t non_resident
;
278 uint16_t name_offset
;
279 uint16_t flags
; /* Attr. flags */
282 struct { /* Resident attribute */
284 uint16_t value_offset
;
285 uint8_t flags
; /* Flags of resident attributes */
287 } __attribute__((__packed__
)) resident
;
288 struct { /* Non-resident attributes */
290 uint64_t highest_vcn
;
291 uint16_t mapping_pairs_offset
;
292 uint8_t compression_unit
;
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.
300 int64_t initialized_size
;
301 int64_t compressed_size
;
302 } __attribute__((__packed__
)) non_resident
;
303 } __attribute__((__packed__
)) data
;
304 } __attribute__((__packed__
));
306 /* Attribute: Attribute List (0x20)
307 * Note: it can be either resident or non-resident
309 struct ntfs_attr_list_entry
{
318 } __attribute__((__packed__
));
320 #define NTFS_MAX_FILE_NAME_LEN 255
322 /* Possible namespaces for filenames in ntfs (8-bit) */
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__
));
330 /* Attribute: Filename (0x30)
331 * Note: always resident
333 struct ntfs_filename_attr
{
334 uint64_t parent_directory
;
339 uint64_t allocated_size
;
344 uint16_t packed_ea_size
;
345 uint16_t reserved
; /* reserved for alignment */
346 } __attribute__((__packed__
)) ea
;
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__
));
356 /* Attribute: Volume Name (0x60)
357 * Note: always resident
358 * Note: Present only in FILE_volume
360 struct ntfs_vol_name
{
361 uint16_t name
[0]; /* The name of the volume in Unicode */
362 } __attribute__((__packed__
));
364 /* Attribute: Volume Information (0x70)
365 * Note: always resident
366 * Note: present only in FILE_Volume
368 struct ntfs_vol_info
{
372 uint16_t flags
; /* Volume flags */
373 } __attribute__((__packed__
));
375 /* Attribute: Data attribute (0x80)
376 * Note: can be either resident or non-resident
378 struct ntfs_data_attr
{
380 } __attribute__((__packed__
));
382 /* Index header flags (8-bit) */
389 } __attribute__((__packed__
));
391 /* Header for the indexes, describing the INDEX_ENTRY records, which
392 * follow the struct ntfs_idx_header.
394 struct ntfs_idx_header
{
395 uint32_t entries_offset
;
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__
));
402 /* Attribute: Index Root (0x90)
403 * Note: always resident
405 struct ntfs_idx_root
{
406 uint32_t type
; /* It is $FILE_NAME for directories, zero for view indexes.
407 * No other values allowed.
409 uint32_t collation_rule
;
410 uint32_t index_block_size
;
411 uint8_t clust_per_index_block
;
413 struct ntfs_idx_header index
;
414 } __attribute__((__packed__
));
416 /* Attribute: Index allocation (0xA0)
417 * Note: always non-resident, of course! :-)
419 struct ntfs_idx_allocation
{
421 uint16_t usa_ofs
; /* Update Sequence Array offsets */
422 uint16_t usa_count
; /* Update Sequence Array number in bytes */
424 int64_t index_block_vcn
; /* Virtual cluster number of the index block */
425 struct ntfs_idx_header index
;
426 } __attribute__((__packed__
));
429 INDEX_ENTRY_NODE
= 1,
431 /* force enum bit width to 16-bit */
432 INDEX_ENTRY_SPACE_FILTER
= 0xFFFF,
433 } __attribute__((__packed__
));
435 struct ntfs_idx_entry_header
{
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
;
444 } __attribute__((__packed__
)) vi
;
445 } __attribute__((__packed__
)) data
;
448 uint16_t flags
; /* Index entry flags */
449 uint16_t reserved
; /* Align to 8-byte boundary */
450 } __attribute__((__packed__
));
452 struct ntfs_idx_entry
{
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
;
461 } __attribute__((__packed__
)) vi
;
462 } __attribute__((__packed__
)) data
;
465 uint16_t flags
; /* Index entry flags */
466 uint16_t reserved
; /* Align to 8-byte boundary */
468 struct ntfs_filename_attr file_name
;
472 //REPARSE_INDEX_KEY reparse;
475 } __attribute__((__packed__
)) key
;
476 } __attribute__((__packed__
));
478 static inline struct ntfs_sb_info
*NTFS_SB(struct fs_info
*fs
)
483 #define NTFS_PVT(i) ((struct ntfs_inode *)((i)->pvt))
485 #endif /* _NTFS_H_ */