1 /* 2 * Copyright (C) 2011-2012 Paulo Alcantara <pcacjr (at) 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 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