aboutsummaryrefslogtreecommitdiff
path: root/fs/ntfs/layout.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/ntfs/layout.h
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'fs/ntfs/layout.h')
-rw-r--r--fs/ntfs/layout.h2413
1 files changed, 2413 insertions, 0 deletions
diff --git a/fs/ntfs/layout.h b/fs/ntfs/layout.h
new file mode 100644
index 00000000000..47b33899992
--- /dev/null
+++ b/fs/ntfs/layout.h
@@ -0,0 +1,2413 @@
+/*
+ * layout.h - All NTFS associated on-disk structures. Part of the Linux-NTFS
+ * project.
+ *
+ * Copyright (c) 2001-2004 Anton Altaparmakov
+ * Copyright (c) 2002 Richard Russon
+ *
+ * This program/include file 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/include file 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 (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LINUX_NTFS_LAYOUT_H
+#define _LINUX_NTFS_LAYOUT_H
+
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/list.h>
+#include <asm/byteorder.h>
+
+#include "types.h"
+
+/*
+ * Constant endianness conversion defines.
+ */
+#define const_le16_to_cpu(x) __constant_le16_to_cpu(x)
+#define const_le32_to_cpu(x) __constant_le32_to_cpu(x)
+#define const_le64_to_cpu(x) __constant_le64_to_cpu(x)
+
+#define const_cpu_to_le16(x) __constant_cpu_to_le16(x)
+#define const_cpu_to_le32(x) __constant_cpu_to_le32(x)
+#define const_cpu_to_le64(x) __constant_cpu_to_le64(x)
+
+/* The NTFS oem_id "NTFS " */
+#define magicNTFS const_cpu_to_le64(0x202020205346544eULL)
+
+/*
+ * Location of bootsector on partition:
+ * The standard NTFS_BOOT_SECTOR is on sector 0 of the partition.
+ * On NT4 and above there is one backup copy of the boot sector to
+ * be found on the last sector of the partition (not normally accessible
+ * from within Windows as the bootsector contained number of sectors
+ * value is one less than the actual value!).
+ * On versions of NT 3.51 and earlier, the backup copy was located at
+ * number of sectors/2 (integer divide), i.e. in the middle of the volume.
+ */
+
+/*
+ * BIOS parameter block (bpb) structure.
+ */
+typedef struct {
+ le16 bytes_per_sector; /* Size of a sector in bytes. */
+ u8 sectors_per_cluster; /* Size of a cluster in sectors. */
+ le16 reserved_sectors; /* zero */
+ u8 fats; /* zero */
+ le16 root_entries; /* zero */
+ le16 sectors; /* zero */
+ u8 media_type; /* 0xf8 = hard disk */
+ le16 sectors_per_fat; /* zero */
+ le16 sectors_per_track; /* irrelevant */
+ le16 heads; /* irrelevant */
+ le32 hidden_sectors; /* zero */
+ le32 large_sectors; /* zero */
+} __attribute__ ((__packed__)) BIOS_PARAMETER_BLOCK;
+
+/*
+ * NTFS boot sector structure.
+ */
+typedef struct {
+ u8 jump[3]; /* Irrelevant (jump to boot up code).*/
+ le64 oem_id; /* Magic "NTFS ". */
+ BIOS_PARAMETER_BLOCK bpb; /* See BIOS_PARAMETER_BLOCK. */
+ u8 unused[4]; /* zero, NTFS diskedit.exe states that
+ this is actually:
+ __u8 physical_drive; // 0x80
+ __u8 current_head; // zero
+ __u8 extended_boot_signature;
+ // 0x80
+ __u8 unused; // zero
+ */
+/*0x28*/sle64 number_of_sectors; /* Number of sectors in volume. Gives
+ maximum volume size of 2^63 sectors.
+ Assuming standard sector size of 512
+ bytes, the maximum byte size is
+ approx. 4.7x10^21 bytes. (-; */
+ sle64 mft_lcn; /* Cluster location of mft data. */
+ sle64 mftmirr_lcn; /* Cluster location of copy of mft. */
+ s8 clusters_per_mft_record; /* Mft record size in clusters. */
+ u8 reserved0[3]; /* zero */
+ s8 clusters_per_index_record; /* Index block size in clusters. */
+ u8 reserved1[3]; /* zero */
+ le64 volume_serial_number; /* Irrelevant (serial number). */
+ le32 checksum; /* Boot sector checksum. */
+/*0x54*/u8 bootstrap[426]; /* Irrelevant (boot up code). */
+ le16 end_of_sector_marker; /* End of bootsector magic. Always is
+ 0xaa55 in little endian. */
+/* sizeof() = 512 (0x200) bytes */
+} __attribute__ ((__packed__)) NTFS_BOOT_SECTOR;
+
+/*
+ * Magic identifiers present at the beginning of all ntfs record containing
+ * records (like mft records for example).
+ */
+enum {
+ /* Found in $MFT/$DATA. */
+ magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */
+ magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */
+ magic_HOLE = const_cpu_to_le32(0x454c4f48), /* ? (NTFS 3.0+?) */
+
+ /* Found in $LogFile/$DATA. */
+ magic_RSTR = const_cpu_to_le32(0x52545352), /* Restart page. */
+ magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */
+
+ /* Found in $LogFile/$DATA. (May be found in $MFT/$DATA, also?) */
+ magic_CHKD = const_cpu_to_le32(0x424b4843), /* Modified by chkdsk. */
+
+ /* Found in all ntfs record containing records. */
+ magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector
+ transfer was detected. */
+ /*
+ * Found in $LogFile/$DATA when a page is full of 0xff bytes and is
+ * thus not initialized. Page must be initialized before using it.
+ */
+ magic_empty = const_cpu_to_le32(0xffffffff) /* Record is empty. */
+};
+
+typedef le32 NTFS_RECORD_TYPE;
+
+/*
+ * Generic magic comparison macros. Finally found a use for the ## preprocessor
+ * operator! (-8
+ */
+
+static inline BOOL __ntfs_is_magic(le32 x, NTFS_RECORD_TYPE r)
+{
+ return (x == r);
+}
+#define ntfs_is_magic(x, m) __ntfs_is_magic(x, magic_##m)
+
+static inline BOOL __ntfs_is_magicp(le32 *p, NTFS_RECORD_TYPE r)
+{
+ return (*p == r);
+}
+#define ntfs_is_magicp(p, m) __ntfs_is_magicp(p, magic_##m)
+
+/*
+ * Specialised magic comparison macros for the NTFS_RECORD_TYPEs defined above.
+ */
+#define ntfs_is_file_record(x) ( ntfs_is_magic (x, FILE) )
+#define ntfs_is_file_recordp(p) ( ntfs_is_magicp(p, FILE) )
+#define ntfs_is_mft_record(x) ( ntfs_is_file_record (x) )
+#define ntfs_is_mft_recordp(p) ( ntfs_is_file_recordp(p) )
+#define ntfs_is_indx_record(x) ( ntfs_is_magic (x, INDX) )
+#define ntfs_is_indx_recordp(p) ( ntfs_is_magicp(p, INDX) )
+#define ntfs_is_hole_record(x) ( ntfs_is_magic (x, HOLE) )
+#define ntfs_is_hole_recordp(p) ( ntfs_is_magicp(p, HOLE) )
+
+#define ntfs_is_rstr_record(x) ( ntfs_is_magic (x, RSTR) )
+#define ntfs_is_rstr_recordp(p) ( ntfs_is_magicp(p, RSTR) )
+#define ntfs_is_rcrd_record(x) ( ntfs_is_magic (x, RCRD) )
+#define ntfs_is_rcrd_recordp(p) ( ntfs_is_magicp(p, RCRD) )
+
+#define ntfs_is_chkd_record(x) ( ntfs_is_magic (x, CHKD) )
+#define ntfs_is_chkd_recordp(p) ( ntfs_is_magicp(p, CHKD) )
+
+#define ntfs_is_baad_record(x) ( ntfs_is_magic (x, BAAD) )
+#define ntfs_is_baad_recordp(p) ( ntfs_is_magicp(p, BAAD) )
+
+#define ntfs_is_empty_record(x) ( ntfs_is_magic (x, empty) )
+#define ntfs_is_empty_recordp(p) ( ntfs_is_magicp(p, empty) )
+
+/*
+ * The Update Sequence Array (usa) is an array of the le16 values which belong
+ * to the end of each sector protected by the update sequence record in which
+ * this array is contained. Note that the first entry is the Update Sequence
+ * Number (usn), a cyclic counter of how many times the protected record has
+ * been written to disk. The values 0 and -1 (ie. 0xffff) are not used. All
+ * last le16's of each sector have to be equal to the usn (during reading) or
+ * are set to it (during writing). If they are not, an incomplete multi sector
+ * transfer has occurred when the data was written.
+ * The maximum size for the update sequence array is fixed to:
+ * maximum size = usa_ofs + (usa_count * 2) = 510 bytes
+ * The 510 bytes comes from the fact that the last le16 in the array has to
+ * (obviously) finish before the last le16 of the first 512-byte sector.
+ * This formula can be used as a consistency check in that usa_ofs +
+ * (usa_count * 2) has to be less than or equal to 510.
+ */
+typedef struct {
+ NTFS_RECORD_TYPE magic; /* A four-byte magic identifying the record
+ type and/or status. */
+ le16 usa_ofs; /* Offset to the Update Sequence Array (usa)
+ from the start of the ntfs record. */
+ le16 usa_count; /* Number of le16 sized entries in the usa
+ including the Update Sequence Number (usn),
+ thus the number of fixups is the usa_count
+ minus 1. */
+} __attribute__ ((__packed__)) NTFS_RECORD;
+
+/*
+ * System files mft record numbers. All these files are always marked as used
+ * in the bitmap attribute of the mft; presumably in order to avoid accidental
+ * allocation for random other mft records. Also, the sequence number for each
+ * of the system files is always equal to their mft record number and it is
+ * never modified.
+ */
+typedef enum {
+ FILE_MFT = 0, /* Master file table (mft). Data attribute
+ contains the entries and bitmap attribute
+ records which ones are in use (bit==1). */
+ FILE_MFTMirr = 1, /* Mft mirror: copy of first four mft records
+ in data attribute. If cluster size > 4kiB,
+ copy of first N mft records, with
+ N = cluster_size / mft_record_size. */
+ FILE_LogFile = 2, /* Journalling log in data attribute. */
+ FILE_Volume = 3, /* Volume name attribute and volume information
+ attribute (flags and ntfs version). Windows
+ refers to this file as volume DASD (Direct
+ Access Storage Device). */
+ FILE_AttrDef = 4, /* Array of attribute definitions in data
+ attribute. */
+ FILE_root = 5, /* Root directory. */
+ FILE_Bitmap = 6, /* Allocation bitmap of all clusters (lcns) in
+ data attribute. */
+ FILE_Boot = 7, /* Boot sector (always at cluster 0) in data
+ attribute. */
+ FILE_BadClus = 8, /* Contains all bad clusters in the non-resident
+ data attribute. */
+ FILE_Secure = 9, /* Shared security descriptors in data attribute
+ and two indexes into the descriptors.
+ Appeared in Windows 2000. Before that, this
+ file was named $Quota but was unused. */
+ FILE_UpCase = 10, /* Uppercase equivalents of all 65536 Unicode
+ characters in data attribute. */
+ FILE_Extend = 11, /* Directory containing other system files (eg.
+ $ObjId, $Quota, $Reparse and $UsnJrnl). This
+ is new to NTFS3.0. */
+ FILE_reserved12 = 12, /* Reserved for future use (records 12-15). */
+ FILE_reserved13 = 13,
+ FILE_reserved14 = 14,
+ FILE_reserved15 = 15,
+ FILE_first_user = 16, /* First user file, used as test limit for
+ whether to allow opening a file or not. */
+} NTFS_SYSTEM_FILES;
+
+/*
+ * These are the so far known MFT_RECORD_* flags (16-bit) which contain
+ * information about the mft record in which they are present.
+ */
+enum {
+ MFT_RECORD_IN_USE = const_cpu_to_le16(0x0001),
+ MFT_RECORD_IS_DIRECTORY = const_cpu_to_le16(0x0002),
+} __attribute__ ((__packed__));
+
+typedef le16 MFT_RECORD_FLAGS;
+
+/*
+ * mft references (aka file references or file record segment references) are
+ * used whenever a structure needs to refer to a record in the mft.
+ *
+ * A reference consists of a 48-bit index into the mft and a 16-bit sequence
+ * number used to detect stale references.
+ *
+ * For error reporting purposes we treat the 48-bit index as a signed quantity.
+ *
+ * The sequence number is a circular counter (skipping 0) describing how many
+ * times the referenced mft record has been (re)used. This has to match the
+ * sequence number of the mft record being referenced, otherwise the reference
+ * is considered stale and removed (FIXME: only ntfsck or the driver itself?).
+ *
+ * If the sequence number is zero it is assumed that no sequence number
+ * consistency checking should be performed.
+ *
+ * FIXME: Since inodes are 32-bit as of now, the driver needs to always check
+ * for high_part being 0 and if not either BUG(), cause a panic() or handle
+ * the situation in some other way. This shouldn't be a problem as a volume has
+ * to become HUGE in order to need more than 32-bits worth of mft records.
+ * Assuming the standard mft record size of 1kb only the records (never mind
+ * the non-resident attributes, etc.) would require 4Tb of space on their own
+ * for the first 32 bits worth of records. This is only if some strange person
+ * doesn't decide to foul play and make the mft sparse which would be a really
+ * horrible thing to do as it would trash our current driver implementation. )-:
+ * Do I hear screams "we want 64-bit inodes!" ?!? (-;
+ *
+ * FIXME: The mft zone is defined as the first 12% of the volume. This space is
+ * reserved so that the mft can grow contiguously and hence doesn't become
+ * fragmented. Volume free space includes the empty part of the mft zone and
+ * when the volume's free 88% are used up, the mft zone is shrunk by a factor
+ * of 2, thus making more space available for more files/data. This process is
+ * repeated everytime there is no more free space except for the mft zone until
+ * there really is no more free space.
+ */
+
+/*
+ * Typedef the MFT_REF as a 64-bit value for easier handling.
+ * Also define two unpacking macros to get to the reference (MREF) and
+ * sequence number (MSEQNO) respectively.
+ * The _LE versions are to be applied on little endian MFT_REFs.
+ * Note: The _LE versions will return a CPU endian formatted value!
+ */
+typedef enum {
+ MFT_REF_MASK_CPU = 0x0000ffffffffffffULL,
+ MFT_REF_MASK_LE = const_cpu_to_le64(0x0000ffffffffffffULL),
+} MFT_REF_CONSTS;
+
+typedef u64 MFT_REF;
+typedef le64 leMFT_REF;
+
+#define MK_MREF(m, s) ((MFT_REF)(((MFT_REF)(s) << 48) | \
+ ((MFT_REF)(m) & MFT_REF_MASK_CPU)))
+#define MK_LE_MREF(m, s) cpu_to_le64(MK_MREF(m, s))
+
+#define MREF(x) ((unsigned long)((x) & MFT_REF_MASK_CPU))
+#define MSEQNO(x) ((u16)(((x) >> 48) & 0xffff))
+#define MREF_LE(x) ((unsigned long)(le64_to_cpu(x) & MFT_REF_MASK_CPU))
+#define MSEQNO_LE(x) ((u16)((le64_to_cpu(x) >> 48) & 0xffff))
+
+#define IS_ERR_MREF(x) (((x) & 0x0000800000000000ULL) ? 1 : 0)
+#define ERR_MREF(x) ((u64)((s64)(x)))
+#define MREF_ERR(x) ((int)((s64)(x)))
+
+/*
+ * The mft record header present at the beginning of every record in the mft.
+ * This is followed by a sequence of variable length attribute records which
+ * is terminated by an attribute of type AT_END which is a truncated attribute
+ * in that it only consists of the attribute type code AT_END and none of the
+ * other members of the attribute structure are present.
+ */
+typedef struct {
+/*Ofs*/
+/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
+ NTFS_RECORD_TYPE magic; /* Usually the magic is "FILE". */
+ le16 usa_ofs; /* See NTFS_RECORD definition above. */
+ le16 usa_count; /* See NTFS_RECORD definition above. */
+
+/* 8*/ le64 lsn; /* $LogFile sequence number for this record.
+ Changed every time the record is modified. */
+/* 16*/ le16 sequence_number; /* Number of times this mft record has been
+ reused. (See description for MFT_REF
+ above.) NOTE: The increment (skipping zero)
+ is done when the file is deleted. NOTE: If
+ this is zero it is left zero. */
+/* 18*/ le16 link_count; /* Number of hard links, i.e. the number of
+ directory entries referencing this record.
+ NOTE: Only used in mft base records.
+ NOTE: When deleting a directory entry we
+ check the link_count and if it is 1 we
+ delete the file. Otherwise we delete the
+ FILE_NAME_ATTR being referenced by the
+ directory entry from the mft record and
+ decrement the link_count.
+ FIXME: Careful with Win32 + DOS names! */
+/* 20*/ le16 attrs_offset; /* Byte offset to the first attribute in this
+ mft record from the start of the mft record.
+ NOTE: Must be aligned to 8-byte boundary. */
+/* 22*/ MFT_RECORD_FLAGS flags; /* Bit array of MFT_RECORD_FLAGS. When a file
+ is deleted, the MFT_RECORD_IN_USE flag is
+ set to zero. */
+/* 24*/ le32 bytes_in_use; /* Number of bytes used in this mft record.
+ NOTE: Must be aligned to 8-byte boundary. */
+/* 28*/ le32 bytes_allocated; /* Number of bytes allocated for this mft
+ record. This should be equal to the mft
+ record size. */
+/* 32*/ leMFT_REF base_mft_record;/* This is zero for base mft records.
+ When it is not zero it is a mft reference
+ pointing to the base mft record to which
+ this record belongs (this is then used to
+ locate the attribute list attribute present
+ in the base record which describes this
+ extension record and hence might need
+ modification when the extension record
+ itself is modified, also locating the
+ attribute list also means finding the other
+ potential extents, belonging to the non-base
+ mft record). */
+/* 40*/ le16 next_attr_instance;/* The instance number that will be assigned to
+ the next attribute added to this mft record.
+ NOTE: Incremented each time after it is used.
+ NOTE: Every time the mft record is reused
+ this number is set to zero. NOTE: The first
+ instance number is always 0. */
+/* The below fields are specific to NTFS 3.1+ (Windows XP and above): */
+/* 42*/ le16 reserved; /* Reserved/alignment. */
+/* 44*/ le32 mft_record_number; /* Number of this mft record. */
+/* sizeof() = 48 bytes */
+/*
+ * When (re)using the mft record, we place the update sequence array at this
+ * offset, i.e. before we start with the attributes. This also makes sense,
+ * otherwise we could run into problems with the update sequence array
+ * containing in itself the last two bytes of a sector which would mean that
+ * multi sector transfer protection wouldn't work. As you can't protect data
+ * by overwriting it since you then can't get it back...
+ * When reading we obviously use the data from the ntfs record header.
+ */
+} __attribute__ ((__packed__)) MFT_RECORD;
+
+/* This is the version without the NTFS 3.1+ specific fields. */
+typedef struct {
+/*Ofs*/
+/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */
+ NTFS_RECORD_TYPE magic; /* Usually the magic is "FILE". */
+ le16 usa_ofs; /* See NTFS_RECORD definition above. */
+ le16 usa_count; /* See NTFS_RECORD definition above. */
+
+/* 8*/ le64 lsn; /* $LogFile sequence number for this record.
+ Changed every time the record is modified. */
+/* 16*/ le16 sequence_number; /* Number of times this mft record has been
+ reused. (See description for MFT_REF
+ above.) NOTE: The increment (skipping zero)
+ is done when the file is deleted. NOTE: If
+ this is zero it is left zero. */
+/* 18*/ le16 link_count; /* Number of hard links, i.e. the number of
+ directory entries referencing this record.
+ NOTE: Only used in mft base records.
+ NOTE: When deleting a directory entry we
+ check the link_count and if it is 1 we
+ delete the file. Otherwise we delete the
+ FILE_NAME_ATTR being referenced by the
+ directory entry from the mft record and
+ decrement the link_count.
+ FIXME: Careful with Win32 + DOS names! */
+/* 20*/ le16 attrs_offset; /* Byte offset to the first attribute in this
+ mft record from the start of the mft record.
+ NOTE: Must be aligned to 8-byte boundary. */
+/* 22*/ MFT_RECORD_FLAGS flags; /* Bit array of MFT_RECORD_FLAGS. When a file
+ is deleted, the MFT_RECORD_IN_USE flag is
+ set to zero. */
+/* 24*/ le32 bytes_in_use; /* Number of bytes used in this mft record.
+ NOTE: Must be aligned to 8-byte boundary. */
+/* 28*/ le32 bytes_allocated; /* Number of bytes allocated for this mft
+ record. This should be equal to the mft
+ record size. */
+/* 32*/ leMFT_REF base_mft_record;/* This is zero for base mft records.
+ When it is not zero it is a mft reference
+ pointing to the base mft record to which
+ this record belongs (this is then used to
+ locate the attribute list attribute present
+ in the base record which describes this
+ extension record and hence might need
+ modification when the extension record
+ itself is modified, also locating the
+ attribute list also means finding the other
+ potential extents, belonging to the non-base
+ mft record). */
+/* 40*/ le16 next_attr_instance;/* The instance number that will be assigned to
+ the next attribute added to this mft record.
+ NOTE: Incremented each time after it is used.
+ NOTE: Every time the mft record is reused
+ this number is set to zero. NOTE: The first
+ instance number is always 0. */
+/* sizeof() = 42 bytes */
+/*
+ * When (re)using the mft record, we place the update sequence array at this
+ * offset, i.e. before we start with the attributes. This also makes sense,
+ * otherwise we could run into problems with the update sequence array
+ * containing in itself the last two bytes of a sector which would mean that
+ * multi sector transfer protection wouldn't work. As you can't protect data
+ * by overwriting it since you then can't get it back...
+ * When reading we obviously use the data from the ntfs record header.
+ */
+} __attribute__ ((__packed__)) MFT_RECORD_OLD;
+
+/*
+ * System defined attributes (32-bit). Each attribute type has a corresponding
+ * attribute name (Unicode string of maximum 64 character length) as described
+ * by the attribute definitions present in the data attribute of the $AttrDef
+ * system file. On NTFS 3.0 volumes the names are just as the types are named
+ * in the below defines exchanging AT_ for the dollar sign ($). If that is not
+ * a revealing choice of symbol I do not know what is... (-;
+ */
+enum {
+ AT_UNUSED = const_cpu_to_le32( 0),
+ AT_STANDARD_INFORMATION = const_cpu_to_le32( 0x10),
+ AT_ATTRIBUTE_LIST = const_cpu_to_le32( 0x20),
+ AT_FILE_NAME = const_cpu_to_le32( 0x30),
+ AT_OBJECT_ID = const_cpu_to_le32( 0x40),
+ AT_SECURITY_DESCRIPTOR = const_cpu_to_le32( 0x50),
+ AT_VOLUME_NAME = const_cpu_to_le32( 0x60),
+ AT_VOLUME_INFORMATION = const_cpu_to_le32( 0x70),
+ AT_DATA = const_cpu_to_le32( 0x80),
+ AT_INDEX_ROOT = const_cpu_to_le32( 0x90),
+ AT_INDEX_ALLOCATION = const_cpu_to_le32( 0xa0),
+ AT_BITMAP = const_cpu_to_le32( 0xb0),
+ AT_REPARSE_POINT = const_cpu_to_le32( 0xc0),
+ AT_EA_INFORMATION = const_cpu_to_le32( 0xd0),
+ AT_EA = const_cpu_to_le32( 0xe0),
+ AT_PROPERTY_SET = const_cpu_to_le32( 0xf0),
+ AT_LOGGED_UTILITY_STREAM = const_cpu_to_le32( 0x100),
+ AT_FIRST_USER_DEFINED_ATTRIBUTE = const_cpu_to_le32( 0x1000),
+ AT_END = const_cpu_to_le32(0xffffffff)
+};
+
+typedef le32 ATTR_TYPE;
+
+/*
+ * The collation rules for sorting views/indexes/etc (32-bit).
+ *
+ * COLLATION_BINARY - Collate by binary compare where the first byte is most
+ * significant.
+ * COLLATION_UNICODE_STRING - Collate Unicode strings by comparing their binary
+ * Unicode values, except that when a character can be uppercased, the
+ * upper case value collates before the lower case one.
+ * COLLATION_FILE_NAME - Collate file names as Unicode strings. The collation
+ * is done very much like COLLATION_UNICODE_STRING. In fact I have no idea
+ * what the difference is. Perhaps the difference is that file names
+ * would treat some special characters in an odd way (see
+ * unistr.c::ntfs_collate_names() and unistr.c::legal_ansi_char_array[]
+ * for what I mean but COLLATION_UNICODE_STRING would not give any special
+ * treatment to any characters at all, but this is speculation.
+ * COLLATION_NTOFS_ULONG - Sorting is done according to ascending le32 key
+ * values. E.g. used for $SII index in FILE_Secure, which sorts by
+ * security_id (le32).
+ * COLLATION_NTOFS_SID - Sorting is done according to ascending SID values.
+ * E.g. used for $O index in FILE_Extend/$Quota.
+ * COLLATION_NTOFS_SECURITY_HASH - Sorting is done first by ascending hash
+ * values and second by ascending security_id values. E.g. used for $SDH
+ * index in FILE_Secure.
+ * COLLATION_NTOFS_ULONGS - Sorting is done according to a sequence of ascending
+ * le32 key values. E.g. used for $O index in FILE_Extend/$ObjId, which
+ * sorts by object_id (16-byte), by splitting up the object_id in four
+ * le32 values and using them as individual keys. E.g. take the following
+ * two security_ids, stored as follows on disk:
+ * 1st: a1 61 65 b7 65 7b d4 11 9e 3d 00 e0 81 10 42 59
+ * 2nd: 38 14 37 d2 d2 f3 d4 11 a5 21 c8 6b 79 b1 97 45
+ * To compare them, they are split into four le32 values each, like so:
+ * 1st: 0xb76561a1 0x11d47b65 0xe0003d9e 0x59421081
+ * 2nd: 0xd2371438 0x11d4f3d2 0x6bc821a5 0x4597b179
+ * Now, it is apparent why the 2nd object_id collates after the 1st: the
+ * first le32 value of the 1st object_id is less than the first le32 of
+ * the 2nd object_id. If the first le32 values of both object_ids were
+ * equal then the second le32 values would be compared, etc.
+ */
+enum {
+ COLLATION_BINARY = const_cpu_to_le32(0x00),
+ COLLATION_FILE_NAME = const_cpu_to_le32(0x01),
+ COLLATION_UNICODE_STRING = const_cpu_to_le32(0x02),
+ COLLATION_NTOFS_ULONG = const_cpu_to_le32(0x10),
+ COLLATION_NTOFS_SID = const_cpu_to_le32(0x11),
+ COLLATION_NTOFS_SECURITY_HASH = const_cpu_to_le32(0x12),
+ COLLATION_NTOFS_ULONGS = const_cpu_to_le32(0x13)
+};
+
+typedef le32 COLLATION_RULE;
+
+/*
+ * The flags (32-bit) describing attribute properties in the attribute
+ * definition structure. FIXME: This information is from Regis's information
+ * and, according to him, it is not certain and probably incomplete.
+ * The INDEXABLE flag is fairly certainly correct as only the file name
+ * attribute has this flag set and this is the only attribute indexed in NT4.
+ */
+enum {
+ INDEXABLE = const_cpu_to_le32(0x02), /* Attribute can be
+ indexed. */
+ NEED_TO_REGENERATE = const_cpu_to_le32(0x40), /* Need to regenerate
+ during regeneration
+ phase. */
+ CAN_BE_NON_RESIDENT = const_cpu_to_le32(0x80), /* Attribute can be
+ non-resident. */
+};
+
+typedef le32 ATTR_DEF_FLAGS;
+
+/*
+ * The data attribute of FILE_AttrDef contains a sequence of attribute
+ * definitions for the NTFS volume. With this, it is supposed to be safe for an
+ * older NTFS driver to mount a volume containing a newer NTFS version without
+ * damaging it (that's the theory. In practice it's: not damaging it too much).
+ * Entries are sorted by attribute type. The flags describe whether the
+ * attribute can be resident/non-resident and possibly other things, but the
+ * actual bits are unknown.
+ */
+typedef struct {
+/*hex ofs*/
+/* 0*/ ntfschar name[0x40]; /* Unicode name of the attribute. Zero
+ terminated. */
+/* 80*/ ATTR_TYPE type; /* Type of the attribute. */
+/* 84*/ le32 display_rule; /* Default display rule.
+ FIXME: What does it mean? (AIA) */
+/* 88*/ COLLATION_RULE collation_rule; /* Default collation rule. */
+/* 8c*/ ATTR_DEF_FLAGS flags; /* Flags describing the attribute. */
+/* 90*/ sle64 min_size; /* Optional minimum attribute size. */
+/* 98*/ sle64 max_size; /* Maximum size of attribute. */
+/* sizeof() = 0xa0 or 160 bytes */
+} __attribute__ ((__packed__)) ATTR_DEF;
+
+/*
+ * Attribute flags (16-bit).
+ */
+enum {
+ ATTR_IS_COMPRESSED = const_cpu_to_le16(0x0001),
+ ATTR_COMPRESSION_MASK = const_cpu_to_le16(0x00ff), /* Compression method
+ mask. Also, first
+ illegal value. */
+ ATTR_IS_ENCRYPTED = const_cpu_to_le16(0x4000),
+ ATTR_IS_SPARSE = const_cpu_to_le16(0x8000),
+} __attribute__ ((__packed__));
+
+typedef le16 ATTR_FLAGS;
+
+/*
+ * Attribute compression.
+ *
+ * Only the data attribute is ever compressed in the current ntfs driver in
+ * Windows. Further, compression is only applied when the data attribute is
+ * non-resident. Finally, to use compression, the maximum allowed cluster size
+ * on a volume is 4kib.
+ *
+ * The compression method is based on independently compressing blocks of X
+ * clusters, where X is determined from the compression_unit value found in the
+ * non-resident attribute record header (more precisely: X = 2^compression_unit
+ * clusters). On Windows NT/2k, X always is 16 clusters (compression_unit = 4).
+ *
+ * There are three different cases of how a compression block of X clusters
+ * can be stored:
+ *
+ * 1) The data in the block is all zero (a sparse block):
+ * This is stored as a sparse block in the runlist, i.e. the runlist
+ * entry has length = X and lcn = -1. The mapping pairs array actually
+ * uses a delta_lcn value length of 0, i.e. delta_lcn is not present at
+ * all, which is then interpreted by the driver as lcn = -1.
+ * NOTE: Even uncompressed files can be sparse on NTFS 3.0 volumes, then
+ * the same principles apply as above, except that the length is not
+ * restricted to being any particular value.
+ *
+ * 2) The data in the block is not compressed:
+ * This happens when compression doesn't reduce the size of the block
+ * in clusters. I.e. if compression has a small effect so that the
+ * compressed data still occupies X clusters, then the uncompressed data
+ * is stored in the block.
+ * This case is recognised by the fact that the runlist entry has
+ * length = X and lcn >= 0. The mapping pairs array stores this as
+ * normal with a run length of X and some specific delta_lcn, i.e.
+ * delta_lcn has to be present.
+ *
+ * 3) The data in the block is compressed:
+ * The common case. This case is recognised by the fact that the run
+ * list entry has length L < X and lcn >= 0. The mapping pairs array
+ * stores this as normal with a run length of X and some specific
+ * delta_lcn, i.e. delta_lcn has to be present. This runlist entry is
+ * immediately followed by a sparse entry with length = X - L and
+ * lcn = -1. The latter entry is to make up the vcn counting to the
+ * full compression block size X.
+ *
+ * In fact, life is more complicated because adjacent entries of the same type
+ * can be coalesced. This means that one has to keep track of the number of
+ * clusters handled and work on a basis of X clusters at a time being one
+ * block. An example: if length L > X this means that this particular runlist
+ * entry contains a block of length X and part of one or more blocks of length
+ * L - X. Another example: if length L < X, this does not necessarily mean that
+ * the block is compressed as it might be that the lcn changes inside the block
+ * and hence the following runlist entry describes the continuation of the
+ * potentially compressed block. The block would be compressed if the
+ * following runlist entry describes at least X - L sparse clusters, thus
+ * making up the compression block length as described in point 3 above. (Of
+ * course, there can be several runlist entries with small lengths so that the
+ * sparse entry does not follow the first data containing entry with
+ * length < X.)
+ *
+ * NOTE: At the end of the compressed attribute value, there most likely is not
+ * just the right amount of data to make up a compression block, thus this data
+ * is not even attempted to be compressed. It is just stored as is, unless
+ * the number of clusters it occupies is reduced when compressed in which case
+ * it is stored as a compressed compression block, complete with sparse
+ * clusters at the end.
+ */
+
+/*
+ * Flags of resident attributes (8-bit).
+ */
+enum {
+ RESIDENT_ATTR_IS_INDEXED = 0x01, /* Attribute is referenced in an index
+ (has implications for deleting and
+ modifying the attribute). */
+} __attribute__ ((__packed__));
+
+typedef u8 RESIDENT_ATTR_FLAGS;
+
+/*
+ * Attribute record header. Always aligned to 8-byte boundary.
+ */
+typedef struct {
+/*Ofs*/
+/* 0*/ ATTR_TYPE type; /* The (32-bit) type of the attribute. */
+/* 4*/ le32 length; /* Byte size of the resident part of the
+ attribute (aligned to 8-byte boundary).
+ Used to get to the next attribute. */
+/* 8*/ u8 non_resident; /* If 0, attribute is resident.
+ If 1, attribute is non-resident. */
+/* 9*/ u8 name_length; /* Unicode character size of name of attribute.
+ 0 if unnamed. */
+/* 10*/ le16 name_offset; /* If name_length != 0, the byte offset to the
+ beginning of the name from the attribute
+ record. Note that the name is stored as a
+ Unicode string. When creating, place offset
+ just at the end of the record header. Then,
+ follow with attribute value or mapping pairs
+ array, resident and non-resident attributes
+ respectively, aligning to an 8-byte
+ boundary. */
+/* 12*/ ATTR_FLAGS flags; /* Flags describing the attribute. */
+/* 14*/ le16 instance; /* The instance of this attribute record. This
+ number is unique within this mft record (see
+ MFT_RECORD/next_attribute_instance notes in
+ in mft.h for more details). */
+/* 16*/ union {
+ /* Resident attributes. */
+ struct {
+/* 16 */ le32 value_length;/* Byte size of attribute value. */
+/* 20 */ le16 value_offset;/* Byte offset of the attribute
+ value from the start of the
+ attribute record. When creating,
+ align to 8-byte boundary if we
+ have a name present as this might
+ not have a length of a multiple
+ of 8-bytes. */
+/* 22 */ RESIDENT_ATTR_FLAGS flags; /* See above. */
+/* 23 */ s8 reserved; /* Reserved/alignment to 8-byte
+ boundary. */
+ } __attribute__ ((__packed__)) resident;
+ /* Non-resident attributes. */
+ struct {
+/* 16*/ leVCN lowest_vcn;/* Lowest valid virtual cluster number
+ for this portion of the attribute value or
+ 0 if this is the only extent (usually the
+ case). - Only when an attribute list is used
+ does lowest_vcn != 0 ever occur. */
+/* 24*/ leVCN highest_vcn;/* Highest valid vcn of this extent of
+ the attribute value. - Usually there is only one
+ portion, so this usually equals the attribute
+ value size in clusters minus 1. Can be -1 for
+ zero length files. Can be 0 for "single extent"
+ attributes. */
+/* 32*/ le16 mapping_pairs_offset; /* Byte offset from the
+ beginning of the structure to the mapping pairs
+ array which contains the mappings between the
+ vcns and the logical cluster numbers (lcns).
+ When creating, place this at the end of this
+ record header aligned to 8-byte boundary. */
+/* 34*/ u8 compression_unit; /* The compression unit expressed
+ as the log to the base 2 of the number of
+ clusters in a compression unit. 0 means not
+ compressed. (This effectively limits the
+ compression unit size to be a power of two
+ clusters.) WinNT4 only uses a value of 4. */
+/* 35*/ u8 reserved[5]; /* Align to 8-byte boundary. */
+/* The sizes below are only used when lowest_vcn is zero, as otherwise it would
+ be difficult to keep them up-to-date.*/
+/* 40*/ sle64 allocated_size; /* Byte size of disk space
+ allocated to hold the attribute value. Always
+ is a multiple of the cluster size. When a file
+ is compressed, this field is a multiple of the
+ compression block size (2^compression_unit) and
+ it represents the logically allocated space
+ rather than the actual on disk usage. For this
+ use the compressed_size (see below). */
+/* 48*/ sle64 data_size; /* Byte size of the attribute
+ value. Can be larger than allocated_size if
+ attribute value is compressed or sparse. */
+/* 56*/ sle64 initialized_size; /* Byte size of initialized
+ portion of the attribute value. Usually equals
+ data_size. */
+/* sizeof(uncompressed attr) = 64*/
+/* 64*/ sle64 compressed_size; /* Byte size of the attribute
+ value after compression. Only present when
+ compressed. Always is a multiple of the
+ cluster size. Represents the actual amount of
+ disk space being used on the disk. */
+/* sizeof(compressed attr) = 72*/
+ } __attribute__ ((__packed__)) non_resident;
+ } __attribute__ ((__packed__)) data;
+} __attribute__ ((__packed__)) ATTR_RECORD;
+
+typedef ATTR_RECORD ATTR_REC;
+
+/*
+ * File attribute flags (32-bit).
+ */
+enum {
+ /*
+ * The following flags are only present in the STANDARD_INFORMATION
+ * attribute (in the field file_attributes).
+ */
+ FILE_ATTR_READONLY = const_cpu_to_le32(0x00000001),
+ FILE_ATTR_HIDDEN = const_cpu_to_le32(0x00000002),
+ FILE_ATTR_SYSTEM = const_cpu_to_le32(0x00000004),
+ /* Old DOS volid. Unused in NT. = const_cpu_to_le32(0x00000008), */
+
+ FILE_ATTR_DIRECTORY = const_cpu_to_le32(0x00000010),
+ /* Note, FILE_ATTR_DIRECTORY is not considered valid in NT. It is
+ reserved for the DOS SUBDIRECTORY flag. */
+ FILE_ATTR_ARCHIVE = const_cpu_to_le32(0x00000020),
+ FILE_ATTR_DEVICE = const_cpu_to_le32(0x00000040),
+ FILE_ATTR_NORMAL = const_cpu_to_le32(0x00000080),
+
+ FILE_ATTR_TEMPORARY = const_cpu_to_le32(0x00000100),
+ FILE_ATTR_SPARSE_FILE = const_cpu_to_le32(0x00000200),
+ FILE_ATTR_REPARSE_POINT = const_cpu_to_le32(0x00000400),
+ FILE_ATTR_COMPRESSED = const_cpu_to_le32(0x00000800),
+
+ FILE_ATTR_OFFLINE = const_cpu_to_le32(0x00001000),
+ FILE_ATTR_NOT_CONTENT_INDEXED = const_cpu_to_le32(0x00002000),
+ FILE_ATTR_ENCRYPTED = const_cpu_to_le32(0x00004000),
+
+ FILE_ATTR_VALID_FLAGS = const_cpu_to_le32(0x00007fb7),
+ /* Note, FILE_ATTR_VALID_FLAGS masks out the old DOS VolId and the
+ FILE_ATTR_DEVICE and preserves everything else. This mask is used
+ to obtain all flags that are valid for reading. */
+ FILE_ATTR_VALID_SET_FLAGS = const_cpu_to_le32(0x000031a7),
+ /* Note, FILE_ATTR_VALID_SET_FLAGS masks out the old DOS VolId, the
+ F_A_DEVICE, F_A_DIRECTORY, F_A_SPARSE_FILE, F_A_REPARSE_POINT,
+ F_A_COMPRESSED, and F_A_ENCRYPTED and preserves the rest. This mask
+ is used to to obtain all flags that are valid for setting. */
+
+ /*
+ * The following flags are only present in the FILE_NAME attribute (in
+ * the field file_attributes).
+ */
+ FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT = const_cpu_to_le32(0x10000000),
+ /* Note, this is a copy of the corresponding bit from the mft record,
+ telling us whether this is a directory or not, i.e. whether it has
+ an index root attribute or not. */
+ FILE_ATTR_DUP_VIEW_INDEX_PRESENT = const_cpu_to_le32(0x20000000),
+ /* Note, this is a copy of the corresponding bit from the mft record,
+ telling us whether this file has a view index present (eg. object id
+ index, quota index, one of the security indexes or the encrypting
+ file system related indexes). */
+};
+
+typedef le32 FILE_ATTR_FLAGS;
+
+/*
+ * NOTE on times in NTFS: All times are in MS standard time format, i.e. they
+ * are the number of 100-nanosecond intervals since 1st January 1601, 00:00:00
+ * universal coordinated time (UTC). (In Linux time starts 1st January 1970,
+ * 00:00:00 UTC and is stored as the number of 1-second intervals since then.)
+ */
+
+/*
+ * Attribute: Standard information (0x10).
+ *
+ * NOTE: Always resident.
+ * NOTE: Present in all base file records on a volume.
+ * NOTE: There is conflicting information about the meaning of each of the time
+ * fields but the meaning as defined below has been verified to be
+ * correct by practical experimentation on Windows NT4 SP6a and is hence
+ * assumed to be the one and only correct interpretation.
+ */
+typedef struct {
+/*Ofs*/
+/* 0*/ sle64 creation_time; /* Time file was created. Updated when<