/* 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 255
/*
* ntfs.sys used 500 maximum links on-disk struct allows up to 0xffff.
* xfstest generic/041 creates 3003 hardlinks.
*/
#define NTFS_LINK_MAX 4000
/*
* 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 4096
#define NTFS_LZNT_CUNIT 4
#define NTFS_LZNT_CLUSTERS (1u<<NTFS_LZNT_CUNIT)
struct GUID {
__le32 Data1;
__le16 Data2;
__le16 Data3;
u8 Data4[8];
};
/*
* 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 {
u8 len;
u8 unused;
u16 name[10];
};
struct le_str {
u8 len;
u8 unused;
__le16 name[];
};
static_assert(SECTOR_SHIFT == 9);
#ifdef CONFIG_NTFS3_64BIT_CLUSTER
typedef u64 CLST;
static_assert(sizeof(size_t) == 8);
#else
typedef u32 CLST;
#endif
#define SPARSE_LCN64 ((u64)-1)
#define SPARSE_LCN ((CLST)-1)
#define RESIDENT_LCN ((CLST)-2)
#define COMPRESSED_LCN ((CLST)-3)
#define COMPRESSION_UNIT 4
#define COMPRESS_MAX_CLUSTER 0x1000
#define MFT_INCREASE_CHUNK 1024
enum RECORD_NUM {
MFT_REC_MFT = 0,
MFT_REC_MIRR = 1,
MFT_REC_LOG = 2,
MFT_REC_VOL = 3,
MFT_REC_ATTR = 4,
MFT_REC_ROOT = 5,
MFT_REC_BITMAP = 6,
MFT_REC_BOOT = 7,
MFT_REC_BADCLUST = 8,
//MFT_REC_QUOTA = 9,
MFT_REC_SECURE = 9, // NTFS 3.0
MFT_REC_UPCASE = 10,
MFT_REC_EXTEND = 11, // NTFS 3.0
MFT_REC_RESERVED = 11,
MFT_REC_FREE = 16,
MFT_REC_USER = 24,
};
enum ATTR_TYPE {
ATTR_ZERO = cpu_to_le32(0x00),
ATTR_STD = cpu_to_le32(0x10),
ATTR_LIST = cpu_to_le32(0x20),
ATTR_NAME = cpu_to_le32(0x30),
// ATTR_VOLUME_VERSION on Nt4
ATTR_ID = cpu_to_le32(0x40),
ATTR_SECURE = cpu_to_le32(0x50),
ATTR_LABEL = cpu_to_le32(0x60),
ATTR_VOL_INFO = cpu_to_le32(0x70),
ATTR_DATA = cpu_to_le32(0x80),
ATTR_ROOT = cpu_to_le32(0x90),
ATTR_ALLOC = cpu_to_le32(0xA0),
ATTR_BITMAP = cpu_to_le32(0xB0),
// ATTR_SYMLINK on Nt4
ATTR_REPARSE = cpu_to_le32(0xC0),
ATTR_EA_INFO = cpu_to_le32(0xD0),
ATTR_EA = cpu_to_le32(0xE0),
ATTR_PROPERTYSET = cpu_to_le32(0xF0),
ATTR_LOGGED_UTILITY_STREAM = cpu_to_le32(0x100),
ATTR_END = cpu_to_le32(0xFFFFFFFF)
};
static_assert(sizeof(enum ATTR_TYPE) == 4);
enum FILE_ATTRIBUTE {
FILE_ATTRIBUTE_READONLY = cpu_to_le32(0x00000001),
FILE_ATTRIBUTE_HIDDEN = cpu_to_le32(0x00000002),
FILE_ATTRIBUTE_SYSTEM = cpu_to_le32(0x00000004),
FILE_ATTRIBUTE_ARCHIVE = cpu_to_le32(0x00000020),
FILE_ATTRIBUTE_DEVICE = cpu_to_le32(0x00000040),
FILE_ATTRIBUTE_TEMPORARY = cpu_to_le32(0x00000100),
FILE_ATTRIBUTE_SPARSE_FILE = cpu_to_le32(0x00000200),
FILE_ATTRIBUTE_REPARSE_POINT = cpu_to_le32(0x00000400),
FILE_ATTRIBUTE_COMPRESSED = cpu_to_le32(0x00000800),
FILE_ATTRIBUTE_OFFLINE = cpu_to_le32(0x00001000),
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = cpu_to_le32(0x00002000),
FILE_ATTRIBUTE_ENCRYPTED = cpu_to_le32(0x00004000),
FILE_ATTRIBUTE_VALID_FLAGS = cpu_to_le32(0x00007fb7),
FILE_ATTRIBUTE_DIRECTORY = cpu_to_le32(0x10000000),
};
static_assert(sizeof(enum FILE_ATTRIBUTE) == 4);
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_st