linux/fs/ntfs3/ntfs.h

/* SPDX-License-Identifier: GPL-2.0 */
/*
 *
 * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
 *
 * on-disk ntfs structs
 */

// clang-format off
#ifndef _LINUX_NTFS3_NTFS_H
#define _LINUX_NTFS3_NTFS_H

#include <linux/blkdev.h>
#include <linux/build_bug.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/types.h>

#include "debug.h"

/* TODO: Check 4K MFT record and 512 bytes cluster. */

/* Check each run for marked clusters. */
#define NTFS3_CHECK_FREE_CLST

#define NTFS_NAME_LEN

/*
 * ntfs.sys used 500 maximum links on-disk struct allows up to 0xffff.
 * xfstest generic/041 creates 3003 hardlinks.
 */
#define NTFS_LINK_MAX

/*
 * Activate to use 64 bit clusters instead of 32 bits in ntfs.sys.
 * Logical and virtual cluster number if needed, may be
 * redefined to use 64 bit value.
 */
//#define CONFIG_NTFS3_64BIT_CLUSTER

#define NTFS_LZNT_MAX_CLUSTER
#define NTFS_LZNT_CUNIT
#define NTFS_LZNT_CLUSTERS

struct GUID {};

/*
 * This struct repeats layout of ATTR_FILE_NAME
 * at offset 0x40.
 * It used to store global constants NAME_MFT/NAME_MIRROR...
 * most constant names are shorter than 10.
 */
struct cpu_str {};

struct le_str {};

static_assert();

#ifdef CONFIG_NTFS3_64BIT_CLUSTER
CLST;
static_assert();
#else
typedef u32 CLST;
#endif

#define SPARSE_LCN64
#define SPARSE_LCN
#define RESIDENT_LCN
#define COMPRESSED_LCN

enum RECORD_NUM {};

enum ATTR_TYPE {};

static_assert();

enum FILE_ATTRIBUTE {};

static_assert();

extern const struct cpu_str NAME_MFT;
extern const struct cpu_str NAME_MIRROR;
extern const struct cpu_str NAME_LOGFILE;
extern const struct cpu_str NAME_VOLUME;
extern const struct cpu_str NAME_ATTRDEF;
extern const struct cpu_str NAME_ROOT;
extern const struct cpu_str NAME_BITMAP;
extern const struct cpu_str NAME_BOOT;
extern const struct cpu_str NAME_BADCLUS;
extern const struct cpu_str NAME_QUOTA;
extern const struct cpu_str NAME_SECURE;
extern const struct cpu_str NAME_UPCASE;
extern const struct cpu_str NAME_EXTEND;
extern const struct cpu_str NAME_OBJID;
extern const struct cpu_str NAME_REPARSE;
extern const struct cpu_str NAME_USNJRNL;

extern const __le16 I30_NAME[4];
extern const __le16 SII_NAME[4];
extern const __le16 SDH_NAME[4];
extern const __le16 SO_NAME[2];
extern const __le16 SQ_NAME[2];
extern const __le16 SR_NAME[2];

extern const __le16 BAD_NAME[4];
extern const __le16 SDS_NAME[4];
extern const __le16 WOF_NAME[17];	/* WofCompressedData */

/* MFT record number structure. */
struct MFT_REF {};

static_assert();

static inline CLST ino_get(const struct MFT_REF *ref)
{}

struct NTFS_BOOT {};

static_assert();

enum NTFS_SIGNATURE {};

static_assert();

/* MFT Record header structure. */
struct NTFS_RECORD_HEADER {};

static_assert();

static inline int is_baad(const struct NTFS_RECORD_HEADER *hdr)
{}

/* Possible bits in struct MFT_REC.flags. */
enum RECORD_FLAG {};

/* MFT Record structure. */
struct MFT_REC {};

#define MFTRECORD_FIXUP_OFFSET_1
#define MFTRECORD_FIXUP_OFFSET_3
/*
 * define MFTRECORD_FIXUP_OFFSET as MFTRECORD_FIXUP_OFFSET_3 (0x30)
 * to format new mft records with bigger header (as current ntfs.sys does)
 *
 * define MFTRECORD_FIXUP_OFFSET as MFTRECORD_FIXUP_OFFSET_1 (0x2A)
 * to format new mft records with smaller header (as old ntfs.sys did)
 * Both variants are valid.
 */
#define MFTRECORD_FIXUP_OFFSET

static_assert();
static_assert();

static inline bool is_rec_base(const struct MFT_REC *rec)
{}

static inline bool is_mft_rec5(const struct MFT_REC *rec)
{}

static inline bool is_rec_inuse(const struct MFT_REC *rec)
{}

static inline bool clear_rec_inuse(struct MFT_REC *rec)
{}

/* Possible values of ATTR_RESIDENT.flags */
#define RESIDENT_FLAG_INDEXED

struct ATTR_RESIDENT {}; // sizeof() = 0x18

struct ATTR_NONRESIDENT {}; // sizeof()=0x40 or 0x48 (if compressed)

/* Possible values of ATTRIB.flags: */
#define ATTR_FLAG_COMPRESSED
#define ATTR_FLAG_COMPRESSED_MASK
#define ATTR_FLAG_ENCRYPTED
#define ATTR_FLAG_SPARSED

struct ATTRIB {};

/* Define attribute sizes. */
#define SIZEOF_RESIDENT
#define SIZEOF_NONRESIDENT_EX
#define SIZEOF_NONRESIDENT

#define SIZEOF_RESIDENT_LE
#define SIZEOF_NONRESIDENT_EX_LE
#define SIZEOF_NONRESIDENT_LE

static inline u64 attr_ondisk_size(const struct ATTRIB *attr)
{}

static inline u64 attr_size(const struct ATTRIB *attr)
{}

static inline bool is_attr_encrypted(const struct ATTRIB *attr)
{}

static inline bool is_attr_sparsed(const struct ATTRIB *attr)
{}

static inline bool is_attr_compressed(const struct ATTRIB *attr)
{}

static inline bool is_attr_ext(const struct ATTRIB *attr)
{}

static inline bool is_attr_indexed(const struct ATTRIB *attr)
{}

static inline __le16 const *attr_name(const struct ATTRIB *attr)
{}

static inline u64 attr_svcn(const struct ATTRIB *attr)
{}

static_assert();
static_assert();
static_assert();

static inline void *resident_data_ex(const struct ATTRIB *attr, u32 datasize)
{}

static inline void *resident_data(const struct ATTRIB *attr)
{}

static inline void *attr_run(const struct ATTRIB *attr)
{}

/* Standard information attribute (0x10). */
struct ATTR_STD_INFO {};

static_assert();

#define SECURITY_ID_INVALID
#define SECURITY_ID_FIRST

struct ATTR_STD_INFO5 {};

static_assert();

/* Attribute list entry structure (0x20) */
struct ATTR_LIST_ENTRY {}; // sizeof(0x20)

static inline u32 le_size(u8 name_len)
{}

/* Returns 0 if 'attr' has the same type and name. */
static inline int le_cmp(const struct ATTR_LIST_ENTRY *le,
			 const struct ATTRIB *attr)
{}

static inline __le16 const *le_name(const struct ATTR_LIST_ENTRY *le)
{}

/* File name types (the field type in struct ATTR_FILE_NAME). */
#define FILE_NAME_POSIX
#define FILE_NAME_UNICODE
#define FILE_NAME_DOS
#define FILE_NAME_UNICODE_AND_DOS

/* Filename attribute structure (0x30). */
struct NTFS_DUP_INFO {}; // 0x38

struct ATTR_FILE_NAME {};

static_assert();
static_assert();
#define SIZEOF_ATTRIBUTE_FILENAME
#define SIZEOF_ATTRIBUTE_FILENAME_MAX

static inline struct ATTRIB *attr_from_name(struct ATTR_FILE_NAME *fname)
{}

static inline u16 fname_full_size(const struct ATTR_FILE_NAME *fname)
{}

static inline u8 paired_name(u8 type)
{}

/* Index entry defines ( the field flags in NtfsDirEntry ). */
#define NTFS_IE_HAS_SUBNODES
#define NTFS_IE_LAST

/* Directory entry structure. */
struct NTFS_DE {};

static_assert();

static inline void de_set_vbn_le(struct NTFS_DE *e, __le64 vcn)
{}

static inline void de_set_vbn(struct NTFS_DE *e, CLST vcn)
{}

static inline __le64 de_get_vbn_le(const struct NTFS_DE *e)
{}

static inline CLST de_get_vbn(const struct NTFS_DE *e)
{}

static inline struct NTFS_DE *de_get_next(const struct NTFS_DE *e)
{}

static inline struct ATTR_FILE_NAME *de_get_fname(const struct NTFS_DE *e)
{}

static inline bool de_is_last(const struct NTFS_DE *e)
{}

static inline bool de_has_vcn(const struct NTFS_DE *e)
{}

static inline bool de_has_vcn_ex(const struct NTFS_DE *e)
{}

#define MAX_BYTES_PER_NAME_ENTRY

#define NTFS_INDEX_HDR_HAS_SUBNODES

struct INDEX_HDR {};

static_assert();

static inline struct NTFS_DE *hdr_first_de(const struct INDEX_HDR *hdr)
{}

static inline struct NTFS_DE *hdr_next_de(const struct INDEX_HDR *hdr,
					  const struct NTFS_DE *e)
{}

static inline bool hdr_has_subnode(const struct INDEX_HDR *hdr)
{}

struct INDEX_BUFFER {};

static_assert();

static inline bool ib_is_empty(const struct INDEX_BUFFER *ib)
{}

static inline bool ib_is_leaf(const struct INDEX_BUFFER *ib)
{}

/* Index root structure ( 0x90 ). */
enum COLLATION_RULE {};

static_assert();

//
struct INDEX_ROOT {};

static_assert();
static_assert();

#define VOLUME_FLAG_DIRTY
#define VOLUME_FLAG_RESIZE_LOG_FILE

struct VOLUME_INFO {}; // sizeof=0xC

#define SIZEOF_ATTRIBUTE_VOLUME_INFO

#define NTFS_LABEL_MAX_LENGTH
#define NTFS_ATTR_INDEXABLE
#define NTFS_ATTR_DUPALLOWED
#define NTFS_ATTR_MUST_BE_INDEXED
#define NTFS_ATTR_MUST_BE_NAMED
#define NTFS_ATTR_MUST_BE_RESIDENT
#define NTFS_ATTR_LOG_ALWAYS

/* $AttrDef file entry. */
struct ATTR_DEF_ENTRY {};

static_assert();

/* Object ID (0x40) */
struct OBJECT_ID {};

static_assert();

/* O Directory entry structure ( rule = 0x13 ) */
struct NTFS_DE_O {};

static_assert();

/* Q Directory entry structure ( rule = 0x11 ) */
struct NTFS_DE_Q {
	struct NTFS_DE de;
	__le32 owner_id;	// 0x10: Unique Id assigned to file

	/* here is 0x30 bytes of user quota. NOTE: 4 byte aligned! */
	__le32 Version;		// 0x14: 0x02
	__le32 Flags;		// 0x18: Quota flags, see above
	__le64 BytesUsed;	// 0x1C:
	__le64 ChangeTime;	// 0x24:
	__le64 WarningLimit;	// 0x28:
	__le64 HardLimit;	// 0x34:
	__le64 ExceededTime;	// 0x3C:

	// SID is placed here
}__packed; // sizeof() = 0x44

static_assert();

#define SecurityDescriptorsBlockSize
#define SecurityDescriptorMaxSize
#define Log2OfSecurityDescriptorsBlockSize

struct SECURITY_KEY {};

/* Security descriptors (the content of $Secure::SDS data stream) */
struct SECURITY_HDR {} __packed;

static_assert();

/* SII Directory entry structure */
struct NTFS_DE_SII {} __packed;

static_assert();
static_assert();

/* SDH Directory entry structure */
struct NTFS_DE_SDH {};

#define SIZEOF_SDH_DIRENTRY

struct REPARSE_KEY {}; // sizeof() = 0x0C

static_assert();
#define SIZEOF_REPARSE_KEY

/* Reparse Directory entry structure */
struct NTFS_DE_R {}; // sizeof() = 0x20

static_assert();

/* CompressReparseBuffer.WofVersion */
#define WOF_CURRENT_VERSION
/* CompressReparseBuffer.WofProvider */
#define WOF_PROVIDER_WIM
/* CompressReparseBuffer.WofProvider */
#define WOF_PROVIDER_SYSTEM
/* CompressReparseBuffer.ProviderVer */
#define WOF_PROVIDER_CURRENT_VERSION

#define WOF_COMPRESSION_XPRESS4K
#define WOF_COMPRESSION_LZX32K
#define WOF_COMPRESSION_XPRESS8K
#define WOF_COMPRESSION_XPRESS16K

/*
 * ATTR_REPARSE (0xC0)
 *
 * The reparse struct GUID structure is used by all 3rd party layered drivers to
 * store data in a reparse point. For non-Microsoft tags, The struct GUID field
 * cannot be GUID_NULL.
 * The constraints on reparse tags are defined below.
 * Microsoft tags can also be used with this format of the reparse point buffer.
 */
struct REPARSE_POINT {};

static_assert();

/*
 * The value of the following constant needs to satisfy the following
 * conditions:
 *  (1) Be at least as large as the largest of the reserved tags.
 *  (2) Be strictly smaller than all the tags in use.
 */
#define IO_REPARSE_TAG_RESERVED_RANGE

/*
 * The reparse tags are a ULONG. The 32 bits are laid out as follows:
 *
 *   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
 *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 *  +-+-+-+-+-----------------------+-------------------------------+
 *  |M|R|N|R|	  Reserved bits     |	    Reparse Tag Value	    |
 *  +-+-+-+-+-----------------------+-------------------------------+
 *
 * M is the Microsoft bit. When set to 1, it denotes a tag owned by Microsoft.
 *   All ISVs must use a tag with a 0 in this position.
 *   Note: If a Microsoft tag is used by non-Microsoft software, the
 *   behavior is not defined.
 *
 * R is reserved.  Must be zero for non-Microsoft tags.
 *
 * N is name surrogate. When set to 1, the file represents another named
 *   entity in the system.
 *
 * The M and N bits are OR-able.
 * The following macros check for the M and N bit values:
 */

/*
 * Macro to determine whether a reparse point tag corresponds to a tag
 * owned by Microsoft.
 */
#define IsReparseTagMicrosoft(_tag)

/* Macro to determine whether a reparse point tag is a name surrogate. */
#define IsReparseTagNameSurrogate(_tag)

/*
 * The following constant represents the bits that are valid to use in
 * reparse tags.
 */
#define IO_REPARSE_TAG_VALID_VALUES

/*
 * Macro to determine whether a reparse tag is a valid tag.
 */
#define IsReparseTagValid(_tag)

/* Microsoft tags for reparse points. */

enum IO_REPARSE_TAG {};

#define SYMLINK_FLAG_RELATIVE

/* Microsoft reparse buffer. (see DDK for details) */
struct REPARSE_DATA_BUFFER {};

/* ATTR_EA_INFO (0xD0) */

#define FILE_NEED_EA
/*
 * FILE_NEED_EA, indicates that the file to which the EA belongs cannot be
 * interpreted without understanding the associated extended attributes.
 */
struct EA_INFO {};

static_assert();

/* ATTR_EA (0xE0) */
struct EA_FULL {};

static_assert();

#define ACL_REVISION
#define ACL_REVISION_DS

#define SE_SELF_RELATIVE

struct SECURITY_DESCRIPTOR_RELATIVE {};
static_assert();

struct ACE_HEADER {};
static_assert();

struct ACL {};
static_assert();

struct SID {};
static_assert();

#endif /* _LINUX_NTFS3_NTFS_H */
// clang-format on