Home | History | Annotate | Download | only in ntfs
      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