180bca3d3SAxel Dörfler/*
280bca3d3SAxel Dörfler * layout.h - Ntfs on-disk layout structures.  Originated from the Linux-NTFS project.
380bca3d3SAxel Dörfler *
480bca3d3SAxel Dörfler * Copyright (c) 2000-2005 Anton Altaparmakov
580bca3d3SAxel Dörfler * Copyright (c)      2005 Yura Pakhuchiy
680bca3d3SAxel Dörfler * Copyright (c) 2005-2006 Szabolcs Szakacsits
780bca3d3SAxel Dörfler *
880bca3d3SAxel Dörfler * This program/include file is free software; you can redistribute it and/or
980bca3d3SAxel Dörfler * modify it under the terms of the GNU General Public License as published
1080bca3d3SAxel Dörfler * by the Free Software Foundation; either version 2 of the License, or
1180bca3d3SAxel Dörfler * (at your option) any later version.
1280bca3d3SAxel Dörfler *
1380bca3d3SAxel Dörfler * This program/include file is distributed in the hope that it will be
1480bca3d3SAxel Dörfler * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1580bca3d3SAxel Dörfler * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1680bca3d3SAxel Dörfler * GNU General Public License for more details.
1780bca3d3SAxel Dörfler *
1880bca3d3SAxel Dörfler * You should have received a copy of the GNU General Public License
1980bca3d3SAxel Dörfler * along with this program (in the main directory of the NTFS-3G
2080bca3d3SAxel Dörfler * distribution in the file COPYING); if not, write to the Free Software
2180bca3d3SAxel Dörfler * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
2280bca3d3SAxel Dörfler */
2380bca3d3SAxel Dörfler
2480bca3d3SAxel Dörfler#ifndef _NTFS_LAYOUT_H
2580bca3d3SAxel Dörfler#define _NTFS_LAYOUT_H
2680bca3d3SAxel Dörfler
2780bca3d3SAxel Dörfler#include "types.h"
2880bca3d3SAxel Dörfler#include "endians.h"
2980bca3d3SAxel Dörfler#include "support.h"
3080bca3d3SAxel Dörfler
3180bca3d3SAxel Dörfler/* The NTFS oem_id */
3280bca3d3SAxel Dörfler#define magicNTFS	const_cpu_to_le64(0x202020205346544e)	/* "NTFS    " */
3380bca3d3SAxel Dörfler#define NTFS_SB_MAGIC	0x5346544e				/* 'NTFS' */
3480bca3d3SAxel Dörfler
3580bca3d3SAxel Dörfler/*
3680bca3d3SAxel Dörfler * Location of bootsector on partition:
3780bca3d3SAxel Dörfler *	The standard NTFS_BOOT_SECTOR is on sector 0 of the partition.
3880bca3d3SAxel Dörfler *	On NT4 and above there is one backup copy of the boot sector to
3980bca3d3SAxel Dörfler *	be found on the last sector of the partition (not normally accessible
4080bca3d3SAxel Dörfler *	from within Windows as the bootsector contained number of sectors
4180bca3d3SAxel Dörfler *	value is one less than the actual value!).
4280bca3d3SAxel Dörfler *	On versions of NT 3.51 and earlier, the backup copy was located at
4380bca3d3SAxel Dörfler *	number of sectors/2 (integer divide), i.e. in the middle of the volume.
4480bca3d3SAxel Dörfler */
4580bca3d3SAxel Dörfler
4680bca3d3SAxel Dörfler/**
4780bca3d3SAxel Dörfler * struct BIOS_PARAMETER_BLOCK - BIOS parameter block (bpb) structure.
4880bca3d3SAxel Dörfler */
4980bca3d3SAxel Dörflertypedef struct {
500490778eSAugustin Cavalier	le16 bytes_per_sector;		/* Size of a sector in bytes. */
5180bca3d3SAxel Dörfler	u8  sectors_per_cluster;	/* Size of a cluster in sectors. */
520490778eSAugustin Cavalier	le16 reserved_sectors;		/* zero */
5380bca3d3SAxel Dörfler	u8  fats;			/* zero */
540490778eSAugustin Cavalier	le16 root_entries;		/* zero */
550490778eSAugustin Cavalier	le16 sectors;			/* zero */
5680bca3d3SAxel Dörfler	u8  media_type;			/* 0xf8 = hard disk */
570490778eSAugustin Cavalier	le16 sectors_per_fat;		/* zero */
580490778eSAugustin Cavalier/*0x0d*/le16 sectors_per_track;		/* Required to boot Windows. */
590490778eSAugustin Cavalier/*0x0f*/le16 heads;			/* Required to boot Windows. */
600490778eSAugustin Cavalier/*0x11*/le32 hidden_sectors;		/* Offset to the start of the partition
6180bca3d3SAxel Dörfler					   relative to the disk in sectors.
6280bca3d3SAxel Dörfler					   Required to boot Windows. */
630490778eSAugustin Cavalier/*0x15*/le32 large_sectors;		/* zero */
6480bca3d3SAxel Dörfler/* sizeof() = 25 (0x19) bytes */
6580bca3d3SAxel Dörfler} __attribute__((__packed__)) BIOS_PARAMETER_BLOCK;
6680bca3d3SAxel Dörfler
6780bca3d3SAxel Dörfler/**
6880bca3d3SAxel Dörfler * struct NTFS_BOOT_SECTOR - NTFS boot sector structure.
6980bca3d3SAxel Dörfler */
7080bca3d3SAxel Dörflertypedef struct {
7180bca3d3SAxel Dörfler	u8  jump[3];			/* Irrelevant (jump to boot up code).*/
720490778eSAugustin Cavalier	le64 oem_id;			/* Magic "NTFS    ". */
7380bca3d3SAxel Dörfler/*0x0b*/BIOS_PARAMETER_BLOCK bpb;	/* See BIOS_PARAMETER_BLOCK. */
7480bca3d3SAxel Dörfler	u8 physical_drive;		/* 0x00 floppy, 0x80 hard disk */
7580bca3d3SAxel Dörfler	u8 current_head;		/* zero */
7680bca3d3SAxel Dörfler	u8 extended_boot_signature; 	/* 0x80 */
7780bca3d3SAxel Dörfler	u8 reserved2;			/* zero */
780490778eSAugustin Cavalier/*0x28*/sle64 number_of_sectors;		/* Number of sectors in volume. Gives
7980bca3d3SAxel Dörfler					   maximum volume size of 2^63 sectors.
8080bca3d3SAxel Dörfler					   Assuming standard sector size of 512
8180bca3d3SAxel Dörfler					   bytes, the maximum byte size is
8280bca3d3SAxel Dörfler					   approx. 4.7x10^21 bytes. (-; */
830490778eSAugustin Cavalier	sle64 mft_lcn;			/* Cluster location of mft data. */
840490778eSAugustin Cavalier	sle64 mftmirr_lcn;		/* Cluster location of copy of mft. */
8580bca3d3SAxel Dörfler	s8  clusters_per_mft_record;	/* Mft record size in clusters. */
8680bca3d3SAxel Dörfler	u8  reserved0[3];		/* zero */
8780bca3d3SAxel Dörfler	s8  clusters_per_index_record;	/* Index block size in clusters. */
8880bca3d3SAxel Dörfler	u8  reserved1[3];		/* zero */
890490778eSAugustin Cavalier	le64 volume_serial_number;	/* Irrelevant (serial number). */
900490778eSAugustin Cavalier	le32 checksum;			/* Boot sector checksum. */
9180bca3d3SAxel Dörfler/*0x54*/u8  bootstrap[426];		/* Irrelevant (boot up code). */
920490778eSAugustin Cavalier	le16 end_of_sector_marker;	/* End of bootsector magic. Always is
9380bca3d3SAxel Dörfler					   0xaa55 in little endian. */
9480bca3d3SAxel Dörfler/* sizeof() = 512 (0x200) bytes */
9580bca3d3SAxel Dörfler} __attribute__((__packed__)) NTFS_BOOT_SECTOR;
9680bca3d3SAxel Dörfler
9780bca3d3SAxel Dörfler/**
9880bca3d3SAxel Dörfler * enum NTFS_RECORD_TYPES -
9980bca3d3SAxel Dörfler *
10080bca3d3SAxel Dörfler * Magic identifiers present at the beginning of all ntfs record containing
10180bca3d3SAxel Dörfler * records (like mft records for example).
10280bca3d3SAxel Dörfler */
10380bca3d3SAxel Dörflertypedef enum {
10480bca3d3SAxel Dörfler	/* Found in $MFT/$DATA. */
10580bca3d3SAxel Dörfler	magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */
10680bca3d3SAxel Dörfler	magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */
10780bca3d3SAxel Dörfler	magic_HOLE = const_cpu_to_le32(0x454c4f48), /* ? (NTFS 3.0+?) */
10880bca3d3SAxel Dörfler
10980bca3d3SAxel Dörfler	/* Found in $LogFile/$DATA. */
11080bca3d3SAxel Dörfler	magic_RSTR = const_cpu_to_le32(0x52545352), /* Restart page. */
11180bca3d3SAxel Dörfler	magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */
11280bca3d3SAxel Dörfler
11380bca3d3SAxel Dörfler	/* Found in $LogFile/$DATA.  (May be found in $MFT/$DATA, also?) */
11480bca3d3SAxel Dörfler	magic_CHKD = const_cpu_to_le32(0x444b4843), /* Modified by chkdsk. */
11580bca3d3SAxel Dörfler
11680bca3d3SAxel Dörfler	/* Found in all ntfs record containing records. */
11780bca3d3SAxel Dörfler	magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector
11880bca3d3SAxel Dörfler						       transfer was detected. */
11980bca3d3SAxel Dörfler
12080bca3d3SAxel Dörfler	/*
12180bca3d3SAxel Dörfler	 * Found in $LogFile/$DATA when a page is full or 0xff bytes and is
12280bca3d3SAxel Dörfler	 * thus not initialized.  User has to initialize the page before using
12380bca3d3SAxel Dörfler	 * it.
12480bca3d3SAxel Dörfler	 */
12580bca3d3SAxel Dörfler	magic_empty = const_cpu_to_le32(0xffffffff),/* Record is empty and has
12680bca3d3SAxel Dörfler						       to be initialized before
12780bca3d3SAxel Dörfler						       it can be used. */
12880bca3d3SAxel Dörfler} NTFS_RECORD_TYPES;
12980bca3d3SAxel Dörfler
13080bca3d3SAxel Dörfler/*
13180bca3d3SAxel Dörfler * Generic magic comparison macros. Finally found a use for the ## preprocessor
13280bca3d3SAxel Dörfler * operator! (-8
13380bca3d3SAxel Dörfler */
13480bca3d3SAxel Dörfler#define ntfs_is_magic(x, m)	(   (u32)(x) == (u32)magic_##m )
13580bca3d3SAxel Dörfler#define ntfs_is_magicp(p, m)	( *(u32*)(p) == (u32)magic_##m )
13680bca3d3SAxel Dörfler
13780bca3d3SAxel Dörfler/*
13880bca3d3SAxel Dörfler * Specialised magic comparison macros for the NTFS_RECORD_TYPES defined above.
13980bca3d3SAxel Dörfler */
14080bca3d3SAxel Dörfler#define ntfs_is_file_record(x)	( ntfs_is_magic (x, FILE) )
14180bca3d3SAxel Dörfler#define ntfs_is_file_recordp(p)	( ntfs_is_magicp(p, FILE) )
14280bca3d3SAxel Dörfler#define ntfs_is_mft_record(x)	( ntfs_is_file_record(x) )
14380bca3d3SAxel Dörfler#define ntfs_is_mft_recordp(p)	( ntfs_is_file_recordp(p) )
14480bca3d3SAxel Dörfler#define ntfs_is_indx_record(x)	( ntfs_is_magic (x, INDX) )
14580bca3d3SAxel Dörfler#define ntfs_is_indx_recordp(p)	( ntfs_is_magicp(p, INDX) )
14680bca3d3SAxel Dörfler#define ntfs_is_hole_record(x)	( ntfs_is_magic (x, HOLE) )
14780bca3d3SAxel Dörfler#define ntfs_is_hole_recordp(p)	( ntfs_is_magicp(p, HOLE) )
14880bca3d3SAxel Dörfler
14980bca3d3SAxel Dörfler#define ntfs_is_rstr_record(x)	( ntfs_is_magic (x, RSTR) )
15080bca3d3SAxel Dörfler#define ntfs_is_rstr_recordp(p)	( ntfs_is_magicp(p, RSTR) )
15180bca3d3SAxel Dörfler#define ntfs_is_rcrd_record(x)	( ntfs_is_magic (x, RCRD) )
15280bca3d3SAxel Dörfler#define ntfs_is_rcrd_recordp(p)	( ntfs_is_magicp(p, RCRD) )
15380bca3d3SAxel Dörfler
15480bca3d3SAxel Dörfler#define ntfs_is_chkd_record(x)	( ntfs_is_magic (x, CHKD) )
15580bca3d3SAxel Dörfler#define ntfs_is_chkd_recordp(p)	( ntfs_is_magicp(p, CHKD) )
15680bca3d3SAxel Dörfler
15780bca3d3SAxel Dörfler#define ntfs_is_baad_record(x)	( ntfs_is_magic (x, BAAD) )
15880bca3d3SAxel Dörfler#define ntfs_is_baad_recordp(p)	( ntfs_is_magicp(p, BAAD) )
15980bca3d3SAxel Dörfler
16080bca3d3SAxel Dörfler#define ntfs_is_empty_record(x)		( ntfs_is_magic (x, empty) )
16180bca3d3SAxel Dörfler#define ntfs_is_empty_recordp(p)	( ntfs_is_magicp(p, empty) )
16280bca3d3SAxel Dörfler
16380bca3d3SAxel Dörfler
1640490778eSAugustin Cavalier/*
1650490778eSAugustin Cavalier * The size of a logical sector in bytes, used as the sequence number stride for
1660490778eSAugustin Cavalier * multi-sector transfers.  This is intended to be less than or equal to the
1670490778eSAugustin Cavalier * physical sector size, since if this were greater than the physical sector
1680490778eSAugustin Cavalier * size, then incomplete multi-sector transfers may not be detected.
1690490778eSAugustin Cavalier */
17080bca3d3SAxel Dörfler#define NTFS_BLOCK_SIZE		512
17180bca3d3SAxel Dörfler#define NTFS_BLOCK_SIZE_BITS	9
17280bca3d3SAxel Dörfler
17380bca3d3SAxel Dörfler/**
17480bca3d3SAxel Dörfler * struct NTFS_RECORD -
17580bca3d3SAxel Dörfler *
1760490778eSAugustin Cavalier * The Update Sequence Array (usa) is an array of the le16 values which belong
17780bca3d3SAxel Dörfler * to the end of each sector protected by the update sequence record in which
17880bca3d3SAxel Dörfler * this array is contained. Note that the first entry is the Update Sequence
17980bca3d3SAxel Dörfler * Number (usn), a cyclic counter of how many times the protected record has
18080bca3d3SAxel Dörfler * been written to disk. The values 0 and -1 (ie. 0xffff) are not used. All
1810490778eSAugustin Cavalier * last le16's of each sector have to be equal to the usn (during reading) or
18280bca3d3SAxel Dörfler * are set to it (during writing). If they are not, an incomplete multi sector
18380bca3d3SAxel Dörfler * transfer has occurred when the data was written.
18480bca3d3SAxel Dörfler * The maximum size for the update sequence array is fixed to:
18580bca3d3SAxel Dörfler *	maximum size = usa_ofs + (usa_count * 2) = 510 bytes
1860490778eSAugustin Cavalier * The 510 bytes comes from the fact that the last le16 in the array has to
1870490778eSAugustin Cavalier * (obviously) finish before the last le16 of the first 512-byte sector.
18880bca3d3SAxel Dörfler * This formula can be used as a consistency check in that usa_ofs +
18980bca3d3SAxel Dörfler * (usa_count * 2) has to be less than or equal to 510.
19080bca3d3SAxel Dörfler */
19180bca3d3SAxel Dörflertypedef struct {
19280bca3d3SAxel Dörfler	NTFS_RECORD_TYPES magic;/* A four-byte magic identifying the
19380bca3d3SAxel Dörfler				   record type and/or status. */
1940490778eSAugustin Cavalier	le16 usa_ofs;		/* Offset to the Update Sequence Array (usa)
19580bca3d3SAxel Dörfler				   from the start of the ntfs record. */
1960490778eSAugustin Cavalier	le16 usa_count;		/* Number of le16 sized entries in the usa
19780bca3d3SAxel Dörfler				   including the Update Sequence Number (usn),
19880bca3d3SAxel Dörfler				   thus the number of fixups is the usa_count
19980bca3d3SAxel Dörfler				   minus 1. */
20080bca3d3SAxel Dörfler} __attribute__((__packed__)) NTFS_RECORD;
20180bca3d3SAxel Dörfler
20280bca3d3SAxel Dörfler/**
20380bca3d3SAxel Dörfler * enum NTFS_SYSTEM_FILES - System files mft record numbers.
20480bca3d3SAxel Dörfler *
20580bca3d3SAxel Dörfler * All these files are always marked as used in the bitmap attribute of the
20680bca3d3SAxel Dörfler * mft; presumably in order to avoid accidental allocation for random other
20780bca3d3SAxel Dörfler * mft records. Also, the sequence number for each of the system files is
20880bca3d3SAxel Dörfler * always equal to their mft record number and it is never modified.
20980bca3d3SAxel Dörfler */
21080bca3d3SAxel Dörflertypedef enum {
21180bca3d3SAxel Dörfler	FILE_MFT	= 0,	/* Master file table (mft). Data attribute
21280bca3d3SAxel Dörfler				   contains the entries and bitmap attribute
21380bca3d3SAxel Dörfler				   records which ones are in use (bit==1). */
21480bca3d3SAxel Dörfler	FILE_MFTMirr	= 1,	/* Mft mirror: copy of first four mft records
21580bca3d3SAxel Dörfler				   in data attribute. If cluster size > 4kiB,
21680bca3d3SAxel Dörfler				   copy of first N mft records, with
21780bca3d3SAxel Dörfler					N = cluster_size / mft_record_size. */
21880bca3d3SAxel Dörfler	FILE_LogFile	= 2,	/* Journalling log in data attribute. */
21980bca3d3SAxel Dörfler	FILE_Volume	= 3,	/* Volume name attribute and volume information
22080bca3d3SAxel Dörfler				   attribute (flags and ntfs version). Windows
22180bca3d3SAxel Dörfler				   refers to this file as volume DASD (Direct
22280bca3d3SAxel Dörfler				   Access Storage Device). */
22380bca3d3SAxel Dörfler	FILE_AttrDef	= 4,	/* Array of attribute definitions in data
22480bca3d3SAxel Dörfler				   attribute. */
22580bca3d3SAxel Dörfler	FILE_root	= 5,	/* Root directory. */
22680bca3d3SAxel Dörfler	FILE_Bitmap	= 6,	/* Allocation bitmap of all clusters (lcns) in
22780bca3d3SAxel Dörfler				   data attribute. */
22880bca3d3SAxel Dörfler	FILE_Boot	= 7,	/* Boot sector (always at cluster 0) in data
22980bca3d3SAxel Dörfler				   attribute. */
23080bca3d3SAxel Dörfler	FILE_BadClus	= 8,	/* Contains all bad clusters in the non-resident
23180bca3d3SAxel Dörfler				   data attribute. */
23280bca3d3SAxel Dörfler	FILE_Secure	= 9,	/* Shared security descriptors in data attribute
23380bca3d3SAxel Dörfler				   and two indexes into the descriptors.
23480bca3d3SAxel Dörfler				   Appeared in Windows 2000. Before that, this
23580bca3d3SAxel Dörfler				   file was named $Quota but was unused. */
23680bca3d3SAxel Dörfler	FILE_UpCase	= 10,	/* Uppercase equivalents of all 65536 Unicode
23780bca3d3SAxel Dörfler				   characters in data attribute. */
23880bca3d3SAxel Dörfler	FILE_Extend	= 11,	/* Directory containing other system files (eg.
23980bca3d3SAxel Dörfler				   $ObjId, $Quota, $Reparse and $UsnJrnl). This
24080bca3d3SAxel Dörfler				   is new to NTFS3.0. */
24180bca3d3SAxel Dörfler	FILE_reserved12	= 12,	/* Reserved for future use (records 12-15). */
24280bca3d3SAxel Dörfler	FILE_reserved13	= 13,
24380bca3d3SAxel Dörfler	FILE_reserved14	= 14,
2440490778eSAugustin Cavalier	FILE_mft_data	= 15,	/* Reserved for first extent of $MFT:$DATA */
24580bca3d3SAxel Dörfler	FILE_first_user	= 16,	/* First user file, used as test limit for
24680bca3d3SAxel Dörfler				   whether to allow opening a file or not. */
24780bca3d3SAxel Dörfler} NTFS_SYSTEM_FILES;
24880bca3d3SAxel Dörfler
24980bca3d3SAxel Dörfler/**
25080bca3d3SAxel Dörfler * enum MFT_RECORD_FLAGS -
25180bca3d3SAxel Dörfler *
25280bca3d3SAxel Dörfler * These are the so far known MFT_RECORD_* flags (16-bit) which contain
25380bca3d3SAxel Dörfler * information about the mft record in which they are present.
25480bca3d3SAxel Dörfler *
25580bca3d3SAxel Dörfler * MFT_RECORD_IS_4 exists on all $Extend sub-files.
25680bca3d3SAxel Dörfler * It seems that it marks it is a metadata file with MFT record >24, however,
25780bca3d3SAxel Dörfler * it is unknown if it is limited to metadata files only.
25880bca3d3SAxel Dörfler *
25980bca3d3SAxel Dörfler * MFT_RECORD_IS_VIEW_INDEX exists on every metafile with a non directory
26080bca3d3SAxel Dörfler * index, that means an INDEX_ROOT and an INDEX_ALLOCATION with a name other
26180bca3d3SAxel Dörfler * than "$I30". It is unknown if it is limited to metadata files only.
26280bca3d3SAxel Dörfler */
26380bca3d3SAxel Dörflertypedef enum {
26480bca3d3SAxel Dörfler	MFT_RECORD_IN_USE		= const_cpu_to_le16(0x0001),
26580bca3d3SAxel Dörfler	MFT_RECORD_IS_DIRECTORY		= const_cpu_to_le16(0x0002),
26680bca3d3SAxel Dörfler	MFT_RECORD_IS_4			= const_cpu_to_le16(0x0004),
26780bca3d3SAxel Dörfler	MFT_RECORD_IS_VIEW_INDEX	= const_cpu_to_le16(0x0008),
26880bca3d3SAxel Dörfler	MFT_REC_SPACE_FILLER		= 0xffff, /* Just to make flags
26980bca3d3SAxel Dörfler						     16-bit. */
27080bca3d3SAxel Dörfler} __attribute__((__packed__)) MFT_RECORD_FLAGS;
27180bca3d3SAxel Dörfler
27280bca3d3SAxel Dörfler/*
27380bca3d3SAxel Dörfler * mft references (aka file references or file record segment references) are
27480bca3d3SAxel Dörfler * used whenever a structure needs to refer to a record in the mft.
27580bca3d3SAxel Dörfler *
27680bca3d3SAxel Dörfler * A reference consists of a 48-bit index into the mft and a 16-bit sequence
27780bca3d3SAxel Dörfler * number used to detect stale references.
27880bca3d3SAxel Dörfler *
27980bca3d3SAxel Dörfler * For error reporting purposes we treat the 48-bit index as a signed quantity.
28080bca3d3SAxel Dörfler *
28180bca3d3SAxel Dörfler * The sequence number is a circular counter (skipping 0) describing how many
28280bca3d3SAxel Dörfler * times the referenced mft record has been (re)used. This has to match the
28380bca3d3SAxel Dörfler * sequence number of the mft record being referenced, otherwise the reference
28480bca3d3SAxel Dörfler * is considered stale and removed (FIXME: only ntfsck or the driver itself?).
28580bca3d3SAxel Dörfler *
28680bca3d3SAxel Dörfler * If the sequence number is zero it is assumed that no sequence number
28780bca3d3SAxel Dörfler * consistency checking should be performed.
28880bca3d3SAxel Dörfler *
28980bca3d3SAxel Dörfler * FIXME: Since inodes are 32-bit as of now, the driver needs to always check
29080bca3d3SAxel Dörfler * for high_part being 0 and if not either BUG(), cause a panic() or handle
29180bca3d3SAxel Dörfler * the situation in some other way. This shouldn't be a problem as a volume has
29280bca3d3SAxel Dörfler * to become HUGE in order to need more than 32-bits worth of mft records.
29380bca3d3SAxel Dörfler * Assuming the standard mft record size of 1kb only the records (never mind
29480bca3d3SAxel Dörfler * the non-resident attributes, etc.) would require 4Tb of space on their own
29580bca3d3SAxel Dörfler * for the first 32 bits worth of records. This is only if some strange person
29680bca3d3SAxel Dörfler * doesn't decide to foul play and make the mft sparse which would be a really
29780bca3d3SAxel Dörfler * horrible thing to do as it would trash our current driver implementation. )-:
29880bca3d3SAxel Dörfler * Do I hear screams "we want 64-bit inodes!" ?!? (-;
29980bca3d3SAxel Dörfler *
30080bca3d3SAxel Dörfler * FIXME: The mft zone is defined as the first 12% of the volume. This space is
30180bca3d3SAxel Dörfler * reserved so that the mft can grow contiguously and hence doesn't become
30280bca3d3SAxel Dörfler * fragmented. Volume free space includes the empty part of the mft zone and
30380bca3d3SAxel Dörfler * when the volume's free 88% are used up, the mft zone is shrunk by a factor
30480bca3d3SAxel Dörfler * of 2, thus making more space available for more files/data. This process is
30580bca3d3SAxel Dörfler * repeated every time there is no more free space except for the mft zone until
30680bca3d3SAxel Dörfler * there really is no more free space.
30780bca3d3SAxel Dörfler */
30880bca3d3SAxel Dörfler
30980bca3d3SAxel Dörfler/*
31080bca3d3SAxel Dörfler * Typedef the MFT_REF as a 64-bit value for easier handling.
31180bca3d3SAxel Dörfler * Also define two unpacking macros to get to the reference (MREF) and
31280bca3d3SAxel Dörfler * sequence number (MSEQNO) respectively.
31380bca3d3SAxel Dörfler * The _LE versions are to be applied on little endian MFT_REFs.
31480bca3d3SAxel Dörfler * Note: The _LE versions will return a CPU endian formatted value!
31580bca3d3SAxel Dörfler */
31680bca3d3SAxel Dörfler#define MFT_REF_MASK_CPU 0x0000ffffffffffffULL
31780bca3d3SAxel Dörfler#define MFT_REF_MASK_LE const_cpu_to_le64(MFT_REF_MASK_CPU)
31880bca3d3SAxel Dörfler
31980bca3d3SAxel Dörflertypedef u64 MFT_REF;
320a814d850Sthreedeyestypedef le64 leMFT_REF;   /* a little-endian MFT_MREF */
32180bca3d3SAxel Dörfler
32280bca3d3SAxel Dörfler#define MK_MREF(m, s)	((MFT_REF)(((MFT_REF)(s) << 48) |		\
32380bca3d3SAxel Dörfler					((MFT_REF)(m) & MFT_REF_MASK_CPU)))
32480bca3d3SAxel Dörfler#define MK_LE_MREF(m, s) const_cpu_to_le64(((MFT_REF)(((MFT_REF)(s) << 48) | \
32580bca3d3SAxel Dörfler					((MFT_REF)(m) & MFT_REF_MASK_CPU))))
32680bca3d3SAxel Dörfler
32780bca3d3SAxel Dörfler#define MREF(x)		((u64)((x) & MFT_REF_MASK_CPU))
32880bca3d3SAxel Dörfler#define MSEQNO(x)	((u16)(((x) >> 48) & 0xffff))
32980bca3d3SAxel Dörfler#define MREF_LE(x)	((u64)(const_le64_to_cpu(x) & MFT_REF_MASK_CPU))
33080bca3d3SAxel Dörfler#define MSEQNO_LE(x)	((u16)((const_le64_to_cpu(x) >> 48) & 0xffff))
33180bca3d3SAxel Dörfler
33280bca3d3SAxel Dörfler#define IS_ERR_MREF(x)	(((x) & 0x0000800000000000ULL) ? 1 : 0)
33380bca3d3SAxel Dörfler#define ERR_MREF(x)	((u64)((s64)(x)))
33480bca3d3SAxel Dörfler#define MREF_ERR(x)	((int)((s64)(x)))
33580bca3d3SAxel Dörfler
33680bca3d3SAxel Dörfler/**
33780bca3d3SAxel Dörfler * struct MFT_RECORD - An MFT record layout (NTFS 3.1+)
33880bca3d3SAxel Dörfler *
33980bca3d3SAxel Dörfler * The mft record header present at the beginning of every record in the mft.
34080bca3d3SAxel Dörfler * This is followed by a sequence of variable length attribute records which
34180bca3d3SAxel Dörfler * is terminated by an attribute of type AT_END which is a truncated attribute
34280bca3d3SAxel Dörfler * in that it only consists of the attribute type code AT_END and none of the
34380bca3d3SAxel Dörfler * other members of the attribute structure are present.
34480bca3d3SAxel Dörfler */
34580bca3d3SAxel Dörflertypedef struct {
34680bca3d3SAxel Dörfler/*Ofs*/
34780bca3d3SAxel Dörfler/*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
34880bca3d3SAxel Dörfler	NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */
3490490778eSAugustin Cavalier	le16 usa_ofs;		/* See NTFS_RECORD definition above. */
3500490778eSAugustin Cavalier	le16 usa_count;		/* See NTFS_RECORD definition above. */
35180bca3d3SAxel Dörfler
3520490778eSAugustin Cavalier/*  8*/	leLSN lsn;		/* $LogFile sequence number for this record.
35380bca3d3SAxel Dörfler				   Changed every time the record is modified. */
3540490778eSAugustin Cavalier/* 16*/	le16 sequence_number;	/* Number of times this mft record has been
35580bca3d3SAxel Dörfler				   reused. (See description for MFT_REF
35680bca3d3SAxel Dörfler				   above.) NOTE: The increment (skipping zero)
35780bca3d3SAxel Dörfler				   is done when the file is deleted. NOTE: If
35880bca3d3SAxel Dörfler				   this is zero it is left zero. */
3590490778eSAugustin Cavalier/* 18*/	le16 link_count;		/* Number of hard links, i.e. the number of
36080bca3d3SAxel Dörfler				   directory entries referencing this record.
36180bca3d3SAxel Dörfler				   NOTE: Only used in mft base records.
36280bca3d3SAxel Dörfler				   NOTE: When deleting a directory entry we
36380bca3d3SAxel Dörfler				   check the link_count and if it is 1 we
36480bca3d3SAxel Dörfler				   delete the file. Otherwise we delete the
36580bca3d3SAxel Dörfler				   FILE_NAME_ATTR being referenced by the
36680bca3d3SAxel Dörfler				   directory entry from the mft record and
36780bca3d3SAxel Dörfler				   decrement the link_count.
36880bca3d3SAxel Dörfler				   FIXME: Careful with Win32 + DOS names! */
3690490778eSAugustin Cavalier/* 20*/	le16 attrs_offset;	/* Byte offset to the first attribute in this
37080bca3d3SAxel Dörfler				   mft record from the start of the mft record.
37180bca3d3SAxel Dörfler				   NOTE: Must be aligned to 8-byte boundary. */
37280bca3d3SAxel Dörfler/* 22*/	MFT_RECORD_FLAGS flags;	/* Bit array of MFT_RECORD_FLAGS. When a file
37380bca3d3SAxel Dörfler				   is deleted, the MFT_RECORD_IN_USE flag is
37480bca3d3SAxel Dörfler				   set to zero. */
3750490778eSAugustin Cavalier/* 24*/	le32 bytes_in_use;	/* Number of bytes used in this mft record.
37680bca3d3SAxel Dörfler				   NOTE: Must be aligned to 8-byte boundary. */
3770490778eSAugustin Cavalier/* 28*/	le32 bytes_allocated;	/* Number of bytes allocated for this mft
37880bca3d3SAxel Dörfler				   record. This should be equal to the mft
37980bca3d3SAxel Dörfler				   record size. */
3800490778eSAugustin Cavalier/* 32*/	leMFT_REF base_mft_record;
3810490778eSAugustin Cavalier				/* This is zero for base mft records.
38280bca3d3SAxel Dörfler				   When it is not zero it is a mft reference
38380bca3d3SAxel Dörfler				   pointing to the base mft record to which
38480bca3d3SAxel Dörfler				   this record belongs (this is then used to
38580bca3d3SAxel Dörfler				   locate the attribute list attribute present
38680bca3d3SAxel Dörfler				   in the base record which describes this
38780bca3d3SAxel Dörfler				   extension record and hence might need
38880bca3d3SAxel Dörfler				   modification when the extension record
38980bca3d3SAxel Dörfler				   itself is modified, also locating the
39080bca3d3SAxel Dörfler				   attribute list also means finding the other
39180bca3d3SAxel Dörfler				   potential extents, belonging to the non-base
39280bca3d3SAxel Dörfler				   mft record). */
3930490778eSAugustin Cavalier/* 40*/	le16 next_attr_instance; /* The instance number that will be
39480bca3d3SAxel Dörfler				   assigned to the next attribute added to this
39580bca3d3SAxel Dörfler				   mft record. NOTE: Incremented each time
39680bca3d3SAxel Dörfler				   after it is used. NOTE: Every time the mft
39780bca3d3SAxel Dörfler				   record is reused this number is set to zero.
39880bca3d3SAxel Dörfler				   NOTE: The first instance number is always 0.
39980bca3d3SAxel Dörfler				 */
40080bca3d3SAxel Dörfler/* The below fields are specific to NTFS 3.1+ (Windows XP and above): */
4010490778eSAugustin Cavalier/* 42*/ le16 reserved;		/* Reserved/alignment. */
4020490778eSAugustin Cavalier/* 44*/ le32 mft_record_number;	/* Number of this mft record. */
40380bca3d3SAxel Dörfler/* sizeof() = 48 bytes */
40480bca3d3SAxel Dörfler/*
40580bca3d3SAxel Dörfler * When (re)using the mft record, we place the update sequence array at this
40680bca3d3SAxel Dörfler * offset, i.e. before we start with the attributes. This also makes sense,
40780bca3d3SAxel Dörfler * otherwise we could run into problems with the update sequence array
40880bca3d3SAxel Dörfler * containing in itself the last two bytes of a sector which would mean that
40980bca3d3SAxel Dörfler * multi sector transfer protection wouldn't work. As you can't protect data
41080bca3d3SAxel Dörfler * by overwriting it since you then can't get it back...
41180bca3d3SAxel Dörfler * When reading we obviously use the data from the ntfs record header.
41280bca3d3SAxel Dörfler */
41380bca3d3SAxel Dörfler} __attribute__((__packed__)) MFT_RECORD;
41480bca3d3SAxel Dörfler
41580bca3d3SAxel Dörfler/**
41680bca3d3SAxel Dörfler * struct MFT_RECORD_OLD - An MFT record layout (NTFS <=3.0)
41780bca3d3SAxel Dörfler *
41880bca3d3SAxel Dörfler * This is the version without the NTFS 3.1+ specific fields.
41980bca3d3SAxel Dörfler */
42080bca3d3SAxel Dörflertypedef struct {
42180bca3d3SAxel Dörfler/*Ofs*/
42280bca3d3SAxel Dörfler/*  0	NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
42380bca3d3SAxel Dörfler	NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */
4240490778eSAugustin Cavalier	le16 usa_ofs;		/* See NTFS_RECORD definition above. */
4250490778eSAugustin Cavalier	le16 usa_count;		/* See NTFS_RECORD definition above. */
42680bca3d3SAxel Dörfler
4270490778eSAugustin Cavalier/*  8*/	leLSN lsn;		/* $LogFile sequence number for this record.
42880bca3d3SAxel Dörfler				   Changed every time the record is modified. */
4290490778eSAugustin Cavalier/* 16*/	le16 sequence_number;	/* Number of times this mft record has been
43080bca3d3SAxel Dörfler				   reused. (See description for MFT_REF
43180bca3d3SAxel Dörfler				   above.) NOTE: The increment (skipping zero)
43280bca3d3SAxel Dörfler				   is done when the file is deleted. NOTE: If
43380bca3d3SAxel Dörfler				   this is zero it is left zero. */
4340490778eSAugustin Cavalier/* 18*/	le16 link_count;		/* Number of hard links, i.e. the number of
43580bca3d3SAxel Dörfler				   directory entries referencing this record.
43680bca3d3SAxel Dörfler				   NOTE: Only used in mft base records.
43780bca3d3SAxel Dörfler				   NOTE: When deleting a directory entry we
43880bca3d3SAxel Dörfler				   check the link_count and if it is 1 we
43980bca3d3SAxel Dörfler				   delete the file. Otherwise we delete the
44080bca3d3SAxel Dörfler				   FILE_NAME_ATTR being referenced by the
44180bca3d3SAxel Dörfler				   directory entry from the mft record and
44280bca3d3SAxel Dörfler				   decrement the link_count.
44380bca3d3SAxel Dörfler				   FIXME: Careful with Win32 + DOS names! */
4440490778eSAugustin Cavalier/* 20*/	le16 attrs_offset;	/* Byte offset to the first attribute in this
44580bca3d3SAxel Dörfler				   mft record from the start of the mft record.
44680bca3d3SAxel Dörfler				   NOTE: Must be aligned to 8-byte boundary. */
44780bca3d3SAxel Dörfler/* 22*/	MFT_RECORD_FLAGS flags;	/* Bit array of MFT_RECORD_FLAGS. When a file
44880bca3d3SAxel Dörfler				   is deleted, the MFT_RECORD_IN_USE flag is
44980bca3d3SAxel Dörfler				   set to zero. */
4500490778eSAugustin Cavalier/* 24*/	le32 bytes_in_use;	/* Number of bytes used in this mft record.
45180bca3d3SAxel Dörfler				   NOTE: Must be aligned to 8-byte boundary. */
4520490778eSAugustin Cavalier/* 28*/	le32 bytes_allocated;	/* Number of bytes allocated for this mft
45380bca3d3SAxel Dörfler				   record. This should be equal to the mft
45480bca3d3SAxel Dörfler				   record size. */
4550490778eSAugustin Cavalier/* 32*/	leMFT_REF base_mft_record;
4560490778eSAugustin Cavalier				/* This is zero for base mft records.
45780bca3d3SAxel Dörfler				   When it is not zero it is a mft reference
45880bca3d3SAxel Dörfler				   pointing to the base mft record to which
45980bca3d3SAxel Dörfler				   this record belongs (this is then used to
46080bca3d3SAxel Dörfler				   locate the attribute list attribute present
46180bca3d3SAxel Dörfler				   in the base record which describes this
46280bca3d3SAxel Dörfler				   extension record and hence might need
46380bca3d3SAxel Dörfler				   modification when the extension record
46480bca3d3SAxel Dörfler				   itself is modified, also locating the
46580bca3d3SAxel Dörfler				   attribute list also means finding the other
46680bca3d3SAxel Dörfler				   potential extents, belonging to the non-base
46780bca3d3SAxel Dörfler				   mft record). */
4680490778eSAugustin Cavalier/* 40*/	le16 next_attr_instance; /* The instance number that will be
46980bca3d3SAxel Dörfler				   assigned to the next attribute added to this
47080bca3d3SAxel Dörfler				   mft record. NOTE: Incremented each time
47180bca3d3SAxel Dörfler				   after it is used. NOTE: Every time the mft
47280bca3d3SAxel Dörfler				   record is reused this number is set to zero.
47380bca3d3SAxel Dörfler				   NOTE: The first instance number is always 0.
47480bca3d3SAxel Dörfler				 */
47580bca3d3SAxel Dörfler/* sizeof() = 42 bytes */
47680bca3d3SAxel Dörfler/*
47780bca3d3SAxel Dörfler * When (re)using the mft record, we place the update sequence array at this
47880bca3d3SAxel Dörfler * offset, i.e. before we start with the attributes. This also makes sense,
47980bca3d3SAxel Dörfler * otherwise we could run into problems with the update sequence array
48080bca3d3SAxel Dörfler * containing in itself the last two bytes of a sector which would mean that
48180bca3d3SAxel Dörfler * multi sector transfer protection wouldn't work. As you can't protect data
48280bca3d3SAxel Dörfler * by overwriting it since you then can't get it back...
48380bca3d3SAxel Dörfler * When reading we obviously use the data from the ntfs record header.
48480bca3d3SAxel Dörfler */
48580bca3d3SAxel Dörfler} __attribute__((__packed__)) MFT_RECORD_OLD;
48680bca3d3SAxel Dörfler
48780bca3d3SAxel Dörfler/**
48880bca3d3SAxel Dörfler * enum ATTR_TYPES - System defined attributes (32-bit).
48980bca3d3SAxel Dörfler *
49080bca3d3SAxel Dörfler * Each attribute type has a corresponding attribute name (Unicode string of
49180bca3d3SAxel Dörfler * maximum 64 character length) as described by the attribute definitions
49280bca3d3SAxel Dörfler * present in the data attribute of the $AttrDef system file.
49380bca3d3SAxel Dörfler *
49480bca3d3SAxel Dörfler * On NTFS 3.0 volumes the names are just as the types are named in the below
49580bca3d3SAxel Dörfler * enum exchanging AT_ for the dollar sign ($). If that isn't a revealing
49680bca3d3SAxel Dörfler * choice of symbol... (-;
49780bca3d3SAxel Dörfler */
49880bca3d3SAxel Dörflertypedef enum {
49980bca3d3SAxel Dörfler	AT_UNUSED			= const_cpu_to_le32(         0),
50080bca3d3SAxel Dörfler	AT_STANDARD_INFORMATION		= const_cpu_to_le32(      0x10),
50180bca3d3SAxel Dörfler	AT_ATTRIBUTE_LIST		= const_cpu_to_le32(      0x20),
50280bca3d3SAxel Dörfler	AT_FILE_NAME			= const_cpu_to_le32(      0x30),
50380bca3d3SAxel Dörfler	AT_OBJECT_ID			= const_cpu_to_le32(      0x40),
50480bca3d3SAxel Dörfler	AT_SECURITY_DESCRIPTOR		= const_cpu_to_le32(      0x50),
50580bca3d3SAxel Dörfler	AT_VOLUME_NAME			= const_cpu_to_le32(      0x60),
50680bca3d3SAxel Dörfler	AT_VOLUME_INFORMATION		= const_cpu_to_le32(      0x70),
50780bca3d3SAxel Dörfler	AT_DATA				= const_cpu_to_le32(      0x80),
50880bca3d3SAxel Dörfler	AT_INDEX_ROOT			= const_cpu_to_le32(      0x90),
50980bca3d3SAxel Dörfler	AT_INDEX_ALLOCATION		= const_cpu_to_le32(      0xa0),
51080bca3d3SAxel Dörfler	AT_BITMAP			= const_cpu_to_le32(      0xb0),
51180bca3d3SAxel Dörfler	AT_REPARSE_POINT		= const_cpu_to_le32(      0xc0),
51280bca3d3SAxel Dörfler	AT_EA_INFORMATION		= const_cpu_to_le32(      0xd0),
51380bca3d3SAxel Dörfler	AT_EA				= const_cpu_to_le32(      0xe0),
51480bca3d3SAxel Dörfler	AT_PROPERTY_SET			= const_cpu_to_le32(      0xf0),
51580bca3d3SAxel Dörfler	AT_LOGGED_UTILITY_STREAM	= const_cpu_to_le32(     0x100),
51680bca3d3SAxel Dörfler	AT_FIRST_USER_DEFINED_ATTRIBUTE	= const_cpu_to_le32(    0x1000),
51780bca3d3SAxel Dörfler	AT_END				= const_cpu_to_le32(0xffffffff),
51880bca3d3SAxel Dörfler} ATTR_TYPES;
51980bca3d3SAxel Dörfler
52080bca3d3SAxel Dörfler/**
52180bca3d3SAxel Dörfler * enum COLLATION_RULES - The collation rules for sorting views/indexes/etc
52280bca3d3SAxel Dörfler * (32-bit).
52380bca3d3SAxel Dörfler *
5240490778eSAugustin Cavalier * COLLATION_BINARY - Collate by binary compare where the first byte is most
5250490778eSAugustin Cavalier *	significant.
5260490778eSAugustin Cavalier * COLLATION_FILE_NAME - Collate Unicode strings by comparing their 16-bit
5270490778eSAugustin Cavalier *	coding units, primarily ignoring case using the volume's $UpCase table,
5280490778eSAugustin Cavalier *	but falling back to a case-sensitive comparison if the names are equal
5290490778eSAugustin Cavalier *	ignoring case.
5300490778eSAugustin Cavalier * COLLATION_UNICODE_STRING - TODO: this is not yet implemented and still needs
5310490778eSAugustin Cavalier *	to be properly documented --- is it really the same as
5320490778eSAugustin Cavalier *	COLLATION_FILE_NAME?
5330490778eSAugustin Cavalier * COLLATION_NTOFS_ULONG - Sorting is done according to ascending le32 key
53480bca3d3SAxel Dörfler *	values. E.g. used for $SII index in FILE_Secure, which sorts by
5350490778eSAugustin Cavalier *	security_id (le32).
53680bca3d3SAxel Dörfler * COLLATION_NTOFS_SID - Sorting is done according to ascending SID values.
53780bca3d3SAxel Dörfler *	E.g. used for $O index in FILE_Extend/$Quota.
53880bca3d3SAxel Dörfler * COLLATION_NTOFS_SECURITY_HASH - Sorting is done first by ascending hash
53980bca3d3SAxel Dörfler *	values and second by ascending security_id values. E.g. used for $SDH
54080bca3d3SAxel Dörfler *	index in FILE_Secure.
54180bca3d3SAxel Dörfler * COLLATION_NTOFS_ULONGS - Sorting is done according to a sequence of ascending
5420490778eSAugustin Cavalier *	le32 key values. E.g. used for $O index in FILE_Extend/$ObjId, which
54380bca3d3SAxel Dörfler *	sorts by object_id (16-byte), by splitting up the object_id in four
5440490778eSAugustin Cavalier *	le32 values and using them as individual keys. E.g. take the following
54580bca3d3SAxel Dörfler *	two security_ids, stored as follows on disk:
54680bca3d3SAxel Dörfler *		1st: a1 61 65 b7 65 7b d4 11 9e 3d 00 e0 81 10 42 59
54780bca3d3SAxel Dörfler *		2nd: 38 14 37 d2 d2 f3 d4 11 a5 21 c8 6b 79 b1 97 45
5480490778eSAugustin Cavalier *	To compare them, they are split into four le32 values each, like so:
54980bca3d3SAxel Dörfler *		1st: 0xb76561a1 0x11d47b65 0xe0003d9e 0x59421081
55080bca3d3SAxel Dörfler *		2nd: 0xd2371438 0x11d4f3d2 0x6bc821a5 0x4597b179
55180bca3d3SAxel Dörfler *	Now, it is apparent why the 2nd object_id collates after the 1st: the
5520490778eSAugustin Cavalier *	first le32 value of the 1st object_id is less than the first le32 of
5530490778eSAugustin Cavalier *	the 2nd object_id. If the first le32 values of both object_ids were
5540490778eSAugustin Cavalier *	equal then the second le32 values would be compared, etc.
55580bca3d3SAxel Dörfler */
55680bca3d3SAxel Dörflertypedef enum {
5570490778eSAugustin Cavalier	COLLATION_BINARY		= const_cpu_to_le32(0),
5580490778eSAugustin Cavalier	COLLATION_FILE_NAME		= const_cpu_to_le32(1),
5590490778eSAugustin Cavalier	COLLATION_UNICODE_STRING	= const_cpu_to_le32(2),
56080bca3d3SAxel Dörfler	COLLATION_NTOFS_ULONG		= const_cpu_to_le32(16),
56180bca3d3SAxel Dörfler	COLLATION_NTOFS_SID		= const_cpu_to_le32(17),
56280bca3d3SAxel Dörfler	COLLATION_NTOFS_SECURITY_HASH	= const_cpu_to_le32(18),
56380bca3d3SAxel Dörfler	COLLATION_NTOFS_ULONGS		= const_cpu_to_le32(19),
56480bca3d3SAxel Dörfler} COLLATION_RULES;
56580bca3d3SAxel Dörfler
56680bca3d3SAxel Dörfler/**
56780bca3d3SAxel Dörfler * enum ATTR_DEF_FLAGS -
56880bca3d3SAxel Dörfler *
56980bca3d3SAxel Dörfler * The flags (32-bit) describing attribute properties in the attribute
57080bca3d3SAxel Dörfler * definition structure.  FIXME: This information is based on Regis's
57180bca3d3SAxel Dörfler * information and, according to him, it is not certain and probably
57280bca3d3SAxel Dörfler * incomplete.  The INDEXABLE flag is fairly certainly correct as only the file
57380bca3d3SAxel Dörfler * name attribute has this flag set and this is the only attribute indexed in
57480bca3d3SAxel Dörfler * NT4.
57580bca3d3SAxel Dörfler */
57680bca3d3SAxel Dörflertypedef enum {
57780bca3d3SAxel Dörfler	ATTR_DEF_INDEXABLE	= const_cpu_to_le32(0x02), /* Attribute can be
57880bca3d3SAxel Dörfler					indexed. */
57980bca3d3SAxel Dörfler	ATTR_DEF_MULTIPLE	= const_cpu_to_le32(0x04), /* Attribute type
58080bca3d3SAxel Dörfler					can be present multiple times in the
58180bca3d3SAxel Dörfler					mft records of an inode. */
58280bca3d3SAxel Dörfler	ATTR_DEF_NOT_ZERO	= const_cpu_to_le32(0x08), /* Attribute value
58380bca3d3SAxel Dörfler					must contain at least one non-zero
58480bca3d3SAxel Dörfler					byte. */
58580bca3d3SAxel Dörfler	ATTR_DEF_INDEXED_UNIQUE	= const_cpu_to_le32(0x10), /* Attribute must be
58680bca3d3SAxel Dörfler					indexed and the attribute value must be
58780bca3d3SAxel Dörfler					unique for the attribute type in all of
58880bca3d3SAxel Dörfler					the mft records of an inode. */
58980bca3d3SAxel Dörfler	ATTR_DEF_NAMED_UNIQUE	= const_cpu_to_le32(0x20), /* Attribute must be
59080bca3d3SAxel Dörfler					named and the name must be unique for
59180bca3d3SAxel Dörfler					the attribute type in all of the mft
59280bca3d3SAxel Dörfler					records of an inode. */
59380bca3d3SAxel Dörfler	ATTR_DEF_RESIDENT	= const_cpu_to_le32(0x40), /* Attribute must be
59480bca3d3SAxel Dörfler					resident. */
59580bca3d3SAxel Dörfler	ATTR_DEF_ALWAYS_LOG	= const_cpu_to_le32(0x80), /* Always log
59680bca3d3SAxel Dörfler					modifications to this attribute,
59780bca3d3SAxel Dörfler					regardless of whether it is resident or
59880bca3d3SAxel Dörfler					non-resident.  Without this, only log
59980bca3d3SAxel Dörfler					modifications if the attribute is
60080bca3d3SAxel Dörfler					resident. */
60180bca3d3SAxel Dörfler} ATTR_DEF_FLAGS;
60280bca3d3SAxel Dörfler
60380bca3d3SAxel Dörfler/**
60480bca3d3SAxel Dörfler * struct ATTR_DEF -
60580bca3d3SAxel Dörfler *
60680bca3d3SAxel Dörfler * The data attribute of FILE_AttrDef contains a sequence of attribute
60780bca3d3SAxel Dörfler * definitions for the NTFS volume. With this, it is supposed to be safe for an
60880bca3d3SAxel Dörfler * older NTFS driver to mount a volume containing a newer NTFS version without
60980bca3d3SAxel Dörfler * damaging it (that's the theory. In practice it's: not damaging it too much).
61080bca3d3SAxel Dörfler * Entries are sorted by attribute type. The flags describe whether the
61180bca3d3SAxel Dörfler * attribute can be resident/non-resident and possibly other things, but the
61280bca3d3SAxel Dörfler * actual bits are unknown.
61380bca3d3SAxel Dörfler */
61480bca3d3SAxel Dörflertypedef struct {
61580bca3d3SAxel Dörfler/*hex ofs*/
61680bca3d3SAxel Dörfler/*  0*/	ntfschar name[0x40];		/* Unicode name of the attribute. Zero
61780bca3d3SAxel Dörfler					   terminated. */
61880bca3d3SAxel Dörfler/* 80*/	ATTR_TYPES type;		/* Type of the attribute. */
6190490778eSAugustin Cavalier/* 84*/	le32 display_rule;		/* Default display rule.
62080bca3d3SAxel Dörfler					   FIXME: What does it mean? (AIA) */
62180bca3d3SAxel Dörfler/* 88*/ COLLATION_RULES collation_rule;	/* Default collation rule. */
62280bca3d3SAxel Dörfler/* 8c*/	ATTR_DEF_FLAGS flags;		/* Flags describing the attribute. */
6230490778eSAugustin Cavalier/* 90*/	sle64 min_size;			/* Optional minimum attribute size. */
6240490778eSAugustin Cavalier/* 98*/	sle64 max_size;			/* Maximum size of attribute. */
62580bca3d3SAxel Dörfler/* sizeof() = 0xa0 or 160 bytes */
62680bca3d3SAxel Dörfler} __attribute__((__packed__)) ATTR_DEF;
62780bca3d3SAxel Dörfler
62880bca3d3SAxel Dörfler/**
62980bca3d3SAxel Dörfler * enum ATTR_FLAGS - Attribute flags (16-bit).
63080bca3d3SAxel Dörfler */
63180bca3d3SAxel Dörflertypedef enum {
63280bca3d3SAxel Dörfler	ATTR_IS_COMPRESSED	= const_cpu_to_le16(0x0001),
63380bca3d3SAxel Dörfler	ATTR_COMPRESSION_MASK	= const_cpu_to_le16(0x00ff),  /* Compression
63480bca3d3SAxel Dörfler						method mask. Also, first
63580bca3d3SAxel Dörfler						illegal value. */
63680bca3d3SAxel Dörfler	ATTR_IS_ENCRYPTED	= const_cpu_to_le16(0x4000),
63780bca3d3SAxel Dörfler	ATTR_IS_SPARSE		= const_cpu_to_le16(0x8000),
63880bca3d3SAxel Dörfler} __attribute__((__packed__)) ATTR_FLAGS;
63980bca3d3SAxel Dörfler
64080bca3d3SAxel Dörfler/*
64180bca3d3SAxel Dörfler * Attribute compression.
64280bca3d3SAxel Dörfler *
64380bca3d3SAxel Dörfler * Only the data attribute is ever compressed in the current ntfs driver in
64480bca3d3SAxel Dörfler * Windows. Further, compression is only applied when the data attribute is
64580bca3d3SAxel Dörfler * non-resident. Finally, to use compression, the maximum allowed cluster size
64680bca3d3SAxel Dörfler * on a volume is 4kib.
64780bca3d3SAxel Dörfler *
64880bca3d3SAxel Dörfler * The compression method is based on independently compressing blocks of X
64980bca3d3SAxel Dörfler * clusters, where X is determined from the compression_unit value found in the
65080bca3d3SAxel Dörfler * non-resident attribute record header (more precisely: X = 2^compression_unit
65180bca3d3SAxel Dörfler * clusters). On Windows NT/2k, X always is 16 clusters (compression_unit = 4).
65280bca3d3SAxel Dörfler *
65380bca3d3SAxel Dörfler * There are three different cases of how a compression block of X clusters
65480bca3d3SAxel Dörfler * can be stored:
65580bca3d3SAxel Dörfler *
65680bca3d3SAxel Dörfler *   1) The data in the block is all zero (a sparse block):
65780bca3d3SAxel Dörfler *	  This is stored as a sparse block in the runlist, i.e. the runlist
65880bca3d3SAxel Dörfler *	  entry has length = X and lcn = -1. The mapping pairs array actually
65980bca3d3SAxel Dörfler *	  uses a delta_lcn value length of 0, i.e. delta_lcn is not present at
66080bca3d3SAxel Dörfler *	  all, which is then interpreted by the driver as lcn = -1.
66180bca3d3SAxel Dörfler *	  NOTE: Even uncompressed files can be sparse on NTFS 3.0 volumes, then
66280bca3d3SAxel Dörfler *	  the same principles apply as above, except that the length is not
66380bca3d3SAxel Dörfler *	  restricted to being any particular value.
66480bca3d3SAxel Dörfler *
66580bca3d3SAxel Dörfler *   2) The data in the block is not compressed:
66680bca3d3SAxel Dörfler *	  This happens when compression doesn't reduce the size of the block
66780bca3d3SAxel Dörfler *	  in clusters. I.e. if compression has a small effect so that the
66880bca3d3SAxel Dörfler *	  compressed data still occupies X clusters, then the uncompressed data
66980bca3d3SAxel Dörfler *	  is stored in the block.
67080bca3d3SAxel Dörfler *	  This case is recognised by the fact that the runlist entry has
67180bca3d3SAxel Dörfler *	  length = X and lcn >= 0. The mapping pairs array stores this as
67280bca3d3SAxel Dörfler *	  normal with a run length of X and some specific delta_lcn, i.e.
67380bca3d3SAxel Dörfler *	  delta_lcn has to be present.
67480bca3d3SAxel Dörfler *
67580bca3d3SAxel Dörfler *   3) The data in the block is compressed:
67680bca3d3SAxel Dörfler *	  The common case. This case is recognised by the fact that the run
67780bca3d3SAxel Dörfler *	  list entry has length L < X and lcn >= 0. The mapping pairs array
67880bca3d3SAxel Dörfler *	  stores this as normal with a run length of X and some specific
67980bca3d3SAxel Dörfler *	  delta_lcn, i.e. delta_lcn has to be present. This runlist entry is
680