| /* |
| * Copyright (C) 2011-2012 Paulo Alcantara <pcacjr@gmail.com> |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the |
| * Free Software Foundation, Inc., |
| * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| */ |
| |
| #include "runlist.h" |
| |
| #ifndef _NTFS_H_ |
| #define _NTFS_H_ |
| |
| struct ntfs_bpb { |
| uint8_t jmp_boot[3]; |
| char oem_name[8]; |
| uint16_t sector_size; |
| uint8_t sec_per_clust; |
| uint16_t res_sectors; |
| uint8_t zero_0[3]; |
| uint16_t zero_1; |
| uint8_t media; |
| uint16_t zero_2; |
| uint16_t unused_0; |
| uint16_t unused_1; |
| uint32_t unused_2; |
| uint32_t zero_3; |
| uint32_t unused_3; |
| uint64_t total_sectors; |
| uint64_t mft_lclust; |
| uint64_t mft_mirr_lclust; |
| int8_t clust_per_mft_record; |
| uint8_t unused_4[3]; |
| uint8_t clust_per_idx_record; |
| uint8_t unused_5[3]; |
| uint64_t vol_serial; |
| uint32_t unused_6; |
| |
| uint8_t pad[428]; /* padding to a sector boundary (512 bytes) */ |
| } __attribute__((__packed__)); |
| |
| /* Function type for an NTFS-version-dependent MFT record lookup */ |
| struct ntfs_mft_record; |
| typedef struct ntfs_mft_record *f_mft_record_lookup(struct fs_info *, |
| uint32_t, block_t *); |
| |
| struct ntfs_sb_info { |
| block_t mft_blk; /* The first MFT record block */ |
| uint64_t mft_lcn; /* LCN of the first MFT record */ |
| unsigned mft_size; /* The MFT size in sectors */ |
| uint64_t mft_record_size; /* MFT record size in bytes */ |
| |
| uint8_t clust_per_idx_record; /* Clusters per Index Record */ |
| |
| unsigned long long clusters; /* Total number of clusters */ |
| |
| unsigned clust_shift; /* Based on sectors */ |
| unsigned clust_byte_shift; /* Based on bytes */ |
| unsigned clust_mask; |
| unsigned clust_size; |
| |
| uint8_t major_ver; /* Major version from $Volume */ |
| uint8_t minor_ver; /* Minor version from $Volume */ |
| |
| /* NTFS-version-dependent MFT record lookup function to use */ |
| f_mft_record_lookup *mft_record_lookup; |
| } __attribute__((__packed__)); |
| |
| /* The NTFS in-memory inode structure */ |
| struct ntfs_inode { |
| int64_t initialized_size; |
| int64_t allocated_size; |
| unsigned long mft_no; /* Number of the mft record / inode */ |
| uint16_t seq_no; /* Sequence number of the mft record */ |
| uint32_t type; /* Attribute type of this inode */ |
| uint8_t non_resident; |
| union { /* Non-resident $DATA attribute */ |
| struct { /* Used only if non_resident flags isn't set */ |
| uint32_t offset; /* Data offset */ |
| } resident; |
| struct { /* Used only if non_resident is set */ |
| struct runlist *rlist; |
| } non_resident; |
| } data; |
| uint32_t start_cluster; /* Starting cluster address */ |
| sector_t start; /* Starting sector */ |
| sector_t offset; /* Current sector offset */ |
| sector_t here; /* Sector corresponding to offset */ |
| }; |
| |
| /* This is structure is used to keep a state for ntfs_readdir() callers. |
| * As NTFS stores directory entries in a complex way, this is structure |
| * ends up saving a state required to find out where we must start from |
| * for the next ntfs_readdir() call. |
| */ |
| struct ntfs_readdir_state { |
| unsigned long mft_no; /* MFT record number */ |
| bool in_idx_root; /* It's true if we're still in the INDEX root */ |
| uint32_t idx_blks_count; /* Number of read INDX blocks */ |
| uint32_t entries_count; /* Number of read INDEX entries */ |
| int64_t last_vcn; /* Last VCN of the INDX block */ |
| }; |
| |
| enum { |
| MAP_UNSPEC, |
| MAP_START = 1 << 0, |
| MAP_END = 1 << 1, |
| MAP_ALLOCATED = 1 << 2, |
| MAP_UNALLOCATED = 1 << 3, |
| MAP_MASK = 0x0000000F, |
| }; |
| |
| struct mapping_chunk { |
| uint64_t vcn; |
| int64_t lcn; |
| uint64_t len; |
| uint32_t flags; |
| }; |
| |
| /* System defined attributes (32-bit) |
| * Each attribute type has a corresponding attribute name (in Unicode) |
| */ |
| enum { |
| NTFS_AT_UNUSED = 0x00, |
| NTFS_AT_STANDARD_INFORMATION = 0x10, |
| NTFS_AT_ATTR_LIST = 0x20, |
| NTFS_AT_FILENAME = 0x30, |
| NTFS_AT_OBJ_ID = 0x40, |
| NTFS_AT_SECURITY_DESCP = 0x50, |
| NTFS_AT_VOL_NAME = 0x60, |
| NTFS_AT_VOL_INFO = 0x70, |
| NTFS_AT_DATA = 0x80, |
| NTFS_AT_INDEX_ROOT = 0x90, |
| NTFS_AT_INDEX_ALLOCATION = 0xA0, |
| NTFS_AT_BITMAP = 0xB0, |
| NTFS_AT_REPARSE_POINT = 0xC0, |
| NTFS_AT_EA_INFO = 0xD0, |
| NTFS_AT_EA = 0xE0, |
| NTFS_AT_PROPERTY_SET = 0xF0, |
| NTFS_AT_LOGGED_UTIL_STREAM = 0x100, |
| NTFS_AT_FIRST_USER_DEFINED_ATTR = 0x1000, |
| NTFS_AT_END = 0xFFFFFFFF, |
| }; |
| |
| /* NTFS File Permissions (also called attributes in DOS terminology) */ |
| enum { |
| NTFS_FILE_ATTR_READONLY = 0x00000001, |
| NTFS_FILE_ATTR_HIDDEN = 0x00000002, |
| NTFS_FILE_ATTR_SYSTEM = 0x00000004, |
| NTFS_FILE_ATTR_DIRECTORY = 0x00000010, |
| NTFS_FILE_ATTR_ARCHIVE = 0x00000020, |
| NTFS_FILE_ATTR_DEVICE = 0x00000040, |
| NTFS_FILE_ATTR_NORMAL = 0x00000080, |
| NTFS_FILE_ATTR_TEMPORARY = 0x00000100, |
| NTFS_FILE_ATTR_SPARSE_FILE = 0x00000200, |
| NTFS_FILE_ATTR_REPARSE_POINT = 0x00000400, |
| NTFS_FILE_ATTR_COMPRESSED = 0x00000800, |
| NTFS_FILE_ATTR_OFFLINE = 0x00001000, |
| NTFS_FILE_ATTR_NOT_CONTENT_INDEXED = 0x00002000, |
| NTFS_FILE_ATTR_ENCRYPTED = 0x00004000, |
| NTFS_FILE_ATTR_VALID_FLAGS = 0x00007FB7, |
| NTFS_FILE_ATTR_VALID_SET_FLAGS = 0x000031A7, |
| NTFS_FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT = 0x10000000, |
| NTFS_FILE_ATTR_DUP_VIEW_INDEX_PRESENT = 0x20000000, |
| }; |
| |
| /* |
| * Magic identifiers present at the beginning of all ntfs record containing |
| * records (like mft records for example). |
| */ |
| enum { |
| /* Found in $MFT/$DATA */ |
| NTFS_MAGIC_FILE = 0x454C4946, /* MFT entry */ |
| NTFS_MAGIC_INDX = 0x58444E49, /* Index buffer */ |
| NTFS_MAGIC_HOLE = 0x454C4F48, |
| |
| /* Found in $LogFile/$DATA */ |
| NTFS_MAGIC_RSTR = 0x52545352, |
| NTFS_MAGIC_RCRD = 0x44524352, |
| /* Found in $LogFile/$DATA (May be found in $MFT/$DATA, also ?) */ |
| NTFS_MAGIC_CHKDSK = 0x444B4843, |
| /* Found in all ntfs record containing records. */ |
| NTFS_MAGIC_BAAD = 0x44414142, |
| NTFS_MAGIC_EMPTY = 0xFFFFFFFF, /* Record is empty */ |
| }; |
| |
| struct ntfs_record { |
| uint32_t magic; |
| uint16_t usa_ofs; |
| uint16_t usa_count; |
| } __attribute__((__packed__)) NTFS_RECORD; |
| |
| /* The $MFT metadata file types */ |
| enum ntfs_system_file { |
| FILE_MFT = 0, |
| FILE_MFTMirr = 1, |
| FILE_LogFile = 2, |
| FILE_Volume = 3, |
| FILE_AttrDef = 4, |
| FILE_root = 5, |
| FILE_Bitmap = 6, |
| FILE_Boot = 7, |
| FILE_BadClus = 8, |
| FILE_Secure = 9, |
| FILE_UpCase = 10, |
| FILE_Extend = 11, |
| FILE_reserved12 = 12, |
| FILE_reserved13 = 13, |
| FILE_reserved14 = 14, |
| FILE_reserved15 = 15, |
| FILE_reserved16 = 16, |
| }; |
| |
| enum { |
| MFT_RECORD_IN_USE = 0x0001, |
| MFT_RECORD_IS_DIRECTORY = 0x0002, |
| } __attribute__((__packed__)); |
| |
| struct ntfs_mft_record { |
| uint32_t magic; |
| uint16_t usa_ofs; |
| uint16_t usa_count; |
| uint64_t lsn; |
| uint16_t seq_no; |
| uint16_t link_count; |
| uint16_t attrs_offset; |
| uint16_t flags; /* MFT record flags */ |
| uint32_t bytes_in_use; |
| uint32_t bytes_allocated; |
| uint64_t base_mft_record; |
| uint16_t next_attr_instance; |
| uint16_t reserved; |
| uint32_t mft_record_no; |
| } __attribute__((__packed__)); /* 48 bytes */ |
| |
| /* This is the version without the NTFS 3.1+ specific fields */ |
| struct ntfs_mft_record_old { |
| uint32_t magic; |
| uint16_t usa_ofs; |
| uint16_t usa_count; |
| uint64_t lsn; |
| uint16_t seq_no; |
| uint16_t link_count; |
| uint16_t attrs_offset; |
| uint16_t flags; /* MFT record flags */ |
| uint32_t bytes_in_use; |
| uint32_t bytes_allocated; |
| uint64_t base_mft_record; |
| uint16_t next_attr_instance; |
| } __attribute__((__packed__)); /* 42 bytes */ |
| |
| enum { |
| ATTR_DEF_INDEXABLE = 0x02, |
| ATTR_DEF_MULTIPLE = 0x04, |
| ATTR_DEF_NOT_ZERO = 0x08, |
| ATTR_DEF_INDEXED_UNIQUE = 0x10, |
| ATTR_DEF_NAMED_UNIQUE = 0x20, |
| ATTR_DEF_RESIDENT = 0x40, |
| ATTR_DEF_ALWAYS_LOG = 0x80, |
| }; |
| |
| struct ntfs_attr_record { |
| uint32_t type; /* Attr. type code */ |
| uint32_t len; |
| uint8_t non_resident; |
| uint8_t name_len; |
| uint16_t name_offset; |
| uint16_t flags; /* Attr. flags */ |
| uint16_t instance; |
| union { |
| struct { /* Resident attribute */ |
| uint32_t value_len; |
| uint16_t value_offset; |
| uint8_t flags; /* Flags of resident attributes */ |
| int8_t reserved; |
| } __attribute__((__packed__)) resident; |
| struct { /* Non-resident attributes */ |
| uint64_t lowest_vcn; |
| uint64_t highest_vcn; |
| uint16_t mapping_pairs_offset; |
| uint8_t compression_unit; |
| uint8_t reserved[5]; |
| int64_t allocated_size; |
| int64_t data_size; /* Byte size of the attribute value. |
| * Note: it can be larger than |
| * allocated_size if attribute value is |
| * compressed or sparse. |
| */ |
| int64_t initialized_size; |
| int64_t compressed_size; |
| } __attribute__((__packed__)) non_resident; |
| } __attribute__((__packed__)) data; |
| } __attribute__((__packed__)); |
| |
| /* Attribute: Attribute List (0x20) |
| * Note: it can be either resident or non-resident |
| */ |
| struct ntfs_attr_list_entry { |
| uint32_t type; |
| uint16_t length; |
| uint8_t name_length; |
| uint8_t name_offset; |
| uint64_t lowest_vcn; |
| uint64_t mft_ref; |
| uint16_t instance; |
| uint16_t name[0]; |
| } __attribute__((__packed__)); |
| |
| #define NTFS_MAX_FILE_NAME_LEN 255 |
| |
| /* Possible namespaces for filenames in ntfs (8-bit) */ |
| enum { |
| FILE_NAME_POSIX = 0x00, |
| FILE_NAME_WIN32 = 0x01, |
| FILE_NAME_DOS = 0x02, |
| FILE_NAME_WIN32_AND_DOS = 0x03, |
| } __attribute__((__packed__)); |
| |
| /* Attribute: Filename (0x30) |
| * Note: always resident |
| */ |
| struct ntfs_filename_attr { |
| uint64_t parent_directory; |
| int64_t ctime; |
| int64_t atime; |
| int64_t mtime; |
| int64_t rtime; |
| uint64_t allocated_size; |
| uint64_t data_size; |
| uint32_t file_attrs; |
| union { |
| struct { |
| uint16_t packed_ea_size; |
| uint16_t reserved; /* reserved for alignment */ |
| } __attribute__((__packed__)) ea; |
| struct { |
| uint32_t reparse_point_tag; |
| } __attribute__((__packed__)) rp; |
| } __attribute__((__packed__)) type; |
| uint8_t file_name_len; |
| uint8_t file_name_type; |
| uint16_t file_name[0]; /* File name in Unicode */ |
| } __attribute__((__packed__)); |
| |
| /* Attribute: Volume Name (0x60) |
| * Note: always resident |
| * Note: Present only in FILE_volume |
| */ |
| struct ntfs_vol_name { |
| uint16_t name[0]; /* The name of the volume in Unicode */ |
| } __attribute__((__packed__)); |
| |
| /* Attribute: Volume Information (0x70) |
| * Note: always resident |
| * Note: present only in FILE_Volume |
| */ |
| struct ntfs_vol_info { |
| uint64_t reserved; |
| uint8_t major_ver; |
| uint8_t minor_ver; |
| uint16_t flags; /* Volume flags */ |
| } __attribute__((__packed__)); |
| |
| /* Attribute: Data attribute (0x80) |
| * Note: can be either resident or non-resident |
| */ |
| struct ntfs_data_attr { |
| uint8_t data[0]; |
| } __attribute__((__packed__)); |
| |
| /* Index header flags (8-bit) */ |
| enum { |
| SMALL_INDEX = 0, |
| LARGE_INDEX = 1, |
| LEAF_NODE = 0, |
| INDEX_NODE = 1, |
| NODE_MASK = 1, |
| } __attribute__((__packed__)); |
| |
| /* Header for the indexes, describing the INDEX_ENTRY records, which |
| * follow the struct ntfs_idx_header. |
| */ |
| struct ntfs_idx_header { |
| uint32_t entries_offset; |
| uint32_t index_len; |
| uint32_t allocated_size; |
| uint8_t flags; /* Index header flags */ |
| uint8_t reserved[3]; /* Align to 8-byte boundary */ |
| } __attribute__((__packed__)); |
| |
| /* Attribute: Index Root (0x90) |
| * Note: always resident |
| */ |
| struct ntfs_idx_root { |
| uint32_t type; /* It is $FILE_NAME for directories, zero for view indexes. |
| * No other values allowed. |
| */ |
| uint32_t collation_rule; |
| uint32_t index_block_size; |
| uint8_t clust_per_index_block; |
| uint8_t reserved[3]; |
| struct ntfs_idx_header index; |
| } __attribute__((__packed__)); |
| |
| /* Attribute: Index allocation (0xA0) |
| * Note: always non-resident, of course! :-) |
| */ |
| struct ntfs_idx_allocation { |
| uint32_t magic; |
| uint16_t usa_ofs; /* Update Sequence Array offsets */ |
| uint16_t usa_count; /* Update Sequence Array number in bytes */ |
| int64_t lsn; |
| int64_t index_block_vcn; /* Virtual cluster number of the index block */ |
| struct ntfs_idx_header index; |
| } __attribute__((__packed__)); |
| |
| enum { |
| INDEX_ENTRY_NODE = 1, |
| INDEX_ENTRY_END = 2, |
| /* force enum bit width to 16-bit */ |
| INDEX_ENTRY_SPACE_FILTER = 0xFFFF, |
| } __attribute__((__packed__)); |
| |
| struct ntfs_idx_entry_header { |
| union { |
| struct { /* Only valid when INDEX_ENTRY_END is not set */ |
| uint64_t indexed_file; |
| } __attribute__((__packed__)) dir; |
| struct { /* Used for views/indexes to find the entry's data */ |
| uint16_t data_offset; |
| uint16_t data_len; |
| uint32_t reservedV; |
| } __attribute__((__packed__)) vi; |
| } __attribute__((__packed__)) data; |
| uint16_t len; |
| uint16_t key_len; |
| uint16_t flags; /* Index entry flags */ |
| uint16_t reserved; /* Align to 8-byte boundary */ |
| } __attribute__((__packed__)); |
| |
| struct ntfs_idx_entry { |
| union { |
| struct { /* Only valid when INDEX_ENTRY_END is not set */ |
| uint64_t indexed_file; |
| } __attribute__((__packed__)) dir; |
| struct { /* Used for views/indexes to find the entry's data */ |
| uint16_t data_offset; |
| uint16_t data_len; |
| uint32_t reservedV; |
| } __attribute__((__packed__)) vi; |
| } __attribute__((__packed__)) data; |
| uint16_t len; |
| uint16_t key_len; |
| uint16_t flags; /* Index entry flags */ |
| uint16_t reserved; /* Align to 8-byte boundary */ |
| union { |
| struct ntfs_filename_attr file_name; |
| //SII_INDEX_KEY sii; |
| //SDH_INDEX_KEY sdh; |
| //GUID object_id; |
| //REPARSE_INDEX_KEY reparse; |
| //SID sid; |
| uint32_t owner_id; |
| } __attribute__((__packed__)) key; |
| } __attribute__((__packed__)); |
| |
| static inline struct ntfs_sb_info *NTFS_SB(struct fs_info *fs) |
| { |
| return fs->fs_info; |
| } |
| |
| #define NTFS_PVT(i) ((struct ntfs_inode *)((i)->pvt)) |
| |
| #endif /* _NTFS_H_ */ |