1
0
Fork 0
virtualbox/include/iprt/formats/fat.h
Daniel Baumann df1bda4fe9
Adding upstream version 7.0.20-dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 09:56:04 +02:00

759 lines
27 KiB
C

/* $Id: fat.h $ */
/** @file
* IPRT, File Allocation Table (FAT).
*/
/*
* Copyright (C) 2017-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program 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, in version 3 of the
* License.
*
* This program 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; if not, see <https://www.gnu.org/licenses>.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
* in the VirtualBox distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
*/
#ifndef IPRT_INCLUDED_formats_fat_h
#define IPRT_INCLUDED_formats_fat_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <iprt/types.h>
#include <iprt/assertcompile.h>
/** @defgroup grp_rt_formats_fat File Allocation Table (FAT) structures and definitions
* @ingroup grp_rt_formats
* @{
*/
/** @name FAT Media byte values
* @remarks This isn't as simple as it's made out to be here!
* @{ */
#define FATBPB_MEDIA_FLOPPY_8 UINT8_C(0xe5)
#define FATBPB_MEDIA_FLOPPY_5_DOT_25 UINT8_C(0xed)
#define FATBPB_MEDIA_FLOPPY_3_DOT_5 UINT8_C(0xf0)
/* incomplete, figure out as needed... */
/** Checks if @a a_bMedia is a valid media byte. */
#define FATBPB_MEDIA_IS_VALID(a_bMedia) ( (uint8_t)(a_bMedia) >= 0xf8 \
|| (uint8_t)(a_bMedia) == 0xf0 \
|| (uint8_t)(a_bMedia) == 0xf4 /* obscure - msdos 2.11 */ \
|| (uint8_t)(a_bMedia) == 0xf5 /* obscure - msdos 2.11 */ \
|| (uint8_t)(a_bMedia) == 0xed /* obscure - tandy 2000 */ \
|| (uint8_t)(a_bMedia) == 0xe5 /* obscure - tandy 2000 */ )
/** @} */
/** Checks if @a a_bFatId is a valid FAT ID byte.
* @todo uncertain whether 0xf4 and 0xf5 should be allowed here too. */
#define FAT_ID_IS_VALID(a_bFatId) ( (uint8_t)(a_bFatId) >= 0xf8 \
|| (uint8_t)(a_bFatId) == 0xf0 \
|| (uint8_t)(a_bFatId) == 0xf4 /* obscure - msdos 2.11 */ \
|| (uint8_t)(a_bFatId) == 0xf5 /* obscure - msdos 2.11 */ \
|| (uint8_t)(a_bFatId) == 0xed /* obscure, tandy 2000 */ \
|| (uint8_t)(a_bFatId) == 0xe5 /* obscure, tandy 2000 */ )
/**
* The DOS 2.0 BIOS parameter block (BPB).
*
* This was the first DOS version with a BPB.
*/
#pragma pack(1)
typedef struct FATBPB20
{
/** 0x0b / 0x00: The sector size in bytes. */
uint16_t cbSector;
/** 0x0d / 0x02: Number of sectors per cluster. */
uint8_t cSectorsPerCluster;
/** 0x0e / 0x03: Number of reserved sectors before the first FAT. */
uint16_t cReservedSectors;
/** 0x10 / 0x05: Number of FATs. */
uint8_t cFats;
/** 0x11 / 0x06: Max size of the root directory (0 for FAT32). */
uint16_t cMaxRootDirEntries;
/** 0x13 / 0x08: Total sector count, zero if 32-bit count is used. */
uint16_t cTotalSectors16;
/** 0x15 / 0x0a: Media ID. */
uint8_t bMedia;
/** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32). */
uint16_t cSectorsPerFat;
} FATBPB20;
#pragma pack()
AssertCompileSize(FATBPB20, 0xd);
/** Pointer to a DOS 2.0 BPB. */
typedef FATBPB20 *PFATBPB20;
/** Pointer to a const DOS 2.0 BPB. */
typedef FATBPB20 const *PCFATBPB20;
/**
* The DOS 3.0 BPB changes that survived.
*/
#pragma pack(1)
typedef struct FATBPB30CMN
{
/** DOS v2.0 BPB. */
FATBPB20 Bpb20;
/** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
uint16_t cSectorsPerTrack;
/** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
uint16_t cTracksPerCylinder;
} FATBPB30CMN;
#pragma pack()
AssertCompileSize(FATBPB30CMN, 0x11);
/**
* The DOS 3.0 BPB.
*/
#pragma pack(1)
typedef struct FATBPB30
{
/** DOS v3.0 BPB bits that survived. */
FATBPB30CMN Core30;
/** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
* on unpartitioned media. */
uint16_t cHiddenSectors;
} FATBPB30;
#pragma pack()
AssertCompileSize(FATBPB30, 0x13);
/** Pointer to a DOS 3.0 BPB. */
typedef FATBPB30 *PFATBPB30;
/** Pointer to a const DOS 3.0 BPB. */
typedef FATBPB30 const *PCFATBPB30;
/**
* The DOS 3.0 BPB, flattened structure.
*/
#pragma pack(1)
typedef struct FATBPB30FLAT
{
/** @name New in DOS 2.0
* @{ */
/** 0x0b / 0x00: The sector size in bytes. */
uint16_t cbSector;
/** 0x0d / 0x02: Number of sectors per cluster. */
uint8_t cSectorsPerCluster;
/** 0x0e / 0x03: Number of reserved sectors before the first FAT. */
uint16_t cReservedSectors;
/** 0x10 / 0x05: Number of FATs. */
uint8_t cFats;
/** 0x11 / 0x06: Max size of the root directory (0 for FAT32). */
uint16_t cMaxRootDirEntries;
/** 0x13 / 0x08: Total sector count, zero if 32-bit count is used. */
uint16_t cTotalSectors16;
/** 0x15 / 0x0a: Media ID. */
uint8_t bMedia;
/** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32). */
uint16_t cSectorsPerFat;
/** @} */
/** @name New in DOS 3.0
* @{ */
/** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
uint16_t cSectorsPerTrack;
/** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
uint16_t cTracksPerCylinder;
/** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
* on unpartitioned media. */
uint16_t cHiddenSectors;
/** @} */
} FATBPB30FLAT;
#pragma pack()
AssertCompileSize(FATBPB30FLAT, 0x13);
/** Pointer to a flattened DOS 3.0 BPB. */
typedef FATBPB30FLAT *PFATBPB30FLAT;
/** Pointer to a const flattened DOS 3.0 BPB. */
typedef FATBPB30FLAT const *PCFATBPB30FLAT;
/**
* The DOS 3.2 BPB.
*/
#pragma pack(1)
typedef struct FATBPB32
{
/** DOS v3.0 BPB. */
FATBPB30 Bpb30;
/** 0x1e / 0x13: Number of sectors, including the hidden ones. This is ZERO
* in DOS 3.31+. */
uint16_t cAnotherTotalSectors;
} FATBPB32;
#pragma pack()
AssertCompileSize(FATBPB32, 0x15);
/** Pointer to a DOS 3.2 BPB. */
typedef FATBPB32 *PFATBPB32;
/** Pointer to const a DOS 3.2 BPB. */
typedef FATBPB32 const *PCFATBPB32;
/**
* The DOS 3.2 BPB, flattened structure.
*/
#pragma pack(1)
typedef struct FATBPB32FLAT
{
/** @name New in DOS 2.0
* @{ */
/** 0x0b / 0x00: The sector size in bytes. */
uint16_t cbSector;
/** 0x0d / 0x02: Number of sectors per cluster. */
uint8_t cSectorsPerCluster;
/** 0x0e / 0x03: Number of reserved sectors before the first FAT. */
uint16_t cReservedSectors;
/** 0x10 / 0x05: Number of FATs. */
uint8_t cFats;
/** 0x11 / 0x06: Max size of the root directory (0 for FAT32). */
uint16_t cMaxRootDirEntries;
/** 0x13 / 0x08: Total sector count, zero if 32-bit count is used. */
uint16_t cTotalSectors16;
/** 0x15 / 0x0a: Media ID. */
uint8_t bMedia;
/** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32). */
uint16_t cSectorsPerFat;
/** @} */
/** @name New in DOS 3.0
* @{ */
/** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
uint16_t cSectorsPerTrack;
/** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
uint16_t cTracksPerCylinder;
/** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
* on unpartitioned media. */
uint16_t cHiddenSectors;
/** @} */
/** @name New in DOS 3.2
* @{ */
/** 0x1e / 0x13: Number of sectors, including the hidden ones. This is ZERO
* in DOS 3.31+. */
uint16_t cAnotherTotalSectors;
/** @} */
} FATBPB32FLAT;
#pragma pack()
AssertCompileSize(FATBPB32FLAT, 0x15);
/** Pointer to a flattened DOS 3.2 BPB. */
typedef FATBPB32FLAT *PFATBPB32FLAT;
/** Pointer to a const flattened DOS 3.2 BPB. */
typedef FATBPB32FLAT const *PCFATBPB32FLAT;
/**
* The DOS 3.31 BPB.
*/
#pragma pack(1)
typedef struct FATBPB331
{
/** DOS v3.0 BPB bits that survived. */
FATBPB30CMN Core30;
/** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
* on unpartitioned media. Values higher than 65535 are complicated due to
* the field overlapping FATBPB32::cAnotherTotalSectors */
uint32_t cHiddenSectors;
/** 0x20 / 0x15: Total logical sectors. Used if count >= 64K, otherwise
* FATBPB20::cTotalSectors16 is used. Zero if 64-bit value used with FAT32. */
uint32_t cTotalSectors32;
} FATBPB331;
#pragma pack()
AssertCompileSize(FATBPB331, 0x19);
/** Pointer to a DOS 3.31 BPB. */
typedef FATBPB331 *PFATBPB331;
/** Pointer to a const DOS 3.31 BPB. */
typedef FATBPB331 const *PCFATBPB331;
/**
* The DOS 3.31 BPB, flattened structure.
*/
#pragma pack(1)
typedef struct FATBPB331FLAT
{
/** @name New in DOS 2.0
* @{ */
/** 0x0b / 0x00: The sector size in bytes. */
uint16_t cbSector;
/** 0x0d / 0x02: Number of sectors per cluster. */
uint8_t cSectorsPerCluster;
/** 0x0e / 0x03: Number of reserved sectors before the first FAT (0 for
* NTFS). */
uint16_t cReservedSectors;
/** 0x10 / 0x05: Number of FATs (0 for NTFS). */
uint8_t cFats;
/** 0x11 / 0x06: Max size of the root directory (0 for FAT32 & NTFS). */
uint16_t cMaxRootDirEntries;
/** 0x13 / 0x08: Total sector count, zero if 32-bit count is used (and for
* NTFS). */
uint16_t cTotalSectors16;
/** 0x15 / 0x0a: Media ID. */
uint8_t bMedia;
/** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32 & NTFS). */
uint16_t cSectorsPerFat;
/** @} */
/** @name New in DOS 3.0
* @{ */
/** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
uint16_t cSectorsPerTrack;
/** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
uint16_t cTracksPerCylinder;
/** @} */
/** @name New in DOS 3.31
* @{ */
/** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
* on unpartitioned media. Values higher than 65535 are complicated due to
* the field overlapping FATBPB32::cAnotherTotalSectors */
uint32_t cHiddenSectors;
/** 0x20 / 0x15: Total logical sectors. Used if count >= 64K, otherwise
* FATBPB20::cTotalSectors16 is used. Zero if 64-bit value used with FAT32.
* (Zero for NTFS). */
uint32_t cTotalSectors32;
/** @} */
} FATBPB331FLAT;
#pragma pack()
AssertCompileSize(FATBPB331FLAT, 0x19);
/** Pointer to a flattened DOS 3.31 BPB. */
typedef FATBPB331FLAT *PFATBPB331FLAT;
/** Pointer to a const flattened DOS 3.31 BPB. */
typedef FATBPB331FLAT const *PCFATBPB331FLAT;
/**
* Extended BIOS parameter block (EBPB).
*/
#pragma pack(1)
typedef struct FATEBPB
{
/** The BPB. */
FATBPB331FLAT Bpb;
/** 0x24 / 0x19: BIOS INT13 pysical drive number. */
uint8_t bInt13Drive;
/** 0x25 / 0x1a: Reserved. NT used bit 0 for indicating dirty FS, and bit 1
* for surface scan. */
uint8_t bReserved;
/** 0x26 / 0x1b: Extended boot signature, FATEBPB_SIGNATURE or
* FATEBPB_SIGNATURE_OLD. */
uint8_t bExtSignature;
/** 0x27 / 0x1c: The volume serial number. */
uint32_t uSerialNumber;
/** 0x2b / 0x20: The volume label (space padded).
* @remarks Not available with FATEBPB_SIGNATURE_OLD */
char achLabel[11];
/** 0x36 / 0x2b: The file system type (space padded).
* @remarks Not available with FATEBPB_SIGNATURE_OLD */
char achType[8];
} FATEBPB;
#pragma pack()
AssertCompileSize(FATEBPB, 0x33);
/** Pointer to an extended BIOS parameter block. */
typedef FATEBPB *PFATEBPB;
/** Pointer to a const extended BIOS parameter block. */
typedef FATEBPB const *PCFATEBPB;
/** FATEBPB::bExtSignature value. */
#define FATEBPB_SIGNATURE UINT8_C(0x29)
/** FATEBPB::bExtSignature value used by OS/2 1.0-1.1 and PC DOS 3.4. These
* does not have the volume and file system type. */
#define FATEBPB_SIGNATURE_OLD UINT8_C(0x28)
/**FATEBPB::achType value for FAT12. */
#define FATEBPB_TYPE_FAT12 "FAT12 "
/**FATEBPB::achType value for FAT16. */
#define FATEBPB_TYPE_FAT16 "FAT16 "
/**FATEBPB::achType value for FAT12/FAT16. */
#define FATEBPB_TYPE_FAT "FAT32 "
/**
* FAT32 Extended BIOS parameter block (EBPB).
*/
#pragma pack(1)
typedef struct FAT32EBPB
{
/** The BPB. */
FATBPB331FLAT Bpb;
/** 0x24 / 0x19: Number of sectors per FAT.
* @note To avoid confusion with the FATEBPB signature, values which result in
* 0x00280000 or 0x00290000 when masked by 0x00ff0000 must not be used. */
uint32_t cSectorsPerFat32;
/** 0x28 / 0x1d: Flags pertaining to FAT mirroring and other stuff. */
uint16_t fFlags;
/** 0x2a / 0x1f: FAT32 version number (FAT32EBPB_VERSION_0_0). */
uint16_t uVersion;
/** 0x2c / 0x21: Cluster number of the root directory. */
uint32_t uRootDirCluster;
/** 0x30 / 0x25: Logical sector number of the information sector. */
uint16_t uInfoSectorNo;
/** 0x32 / 0x27: Logical sector number of boot sector copy. */
uint16_t uBootSectorCopySectorNo;
/** 0x34 / 0x29: Reserved, zero (or 0xf6) filled, preserve. */
uint8_t abReserved[12];
/** 0x40 / 0x35: BIOS INT13 pysical drive number
* @remarks Same as FATEBPB::bInt13Drive. */
uint8_t bInt13Drive;
/** 0x41 / 0x36: Reserved.
* @remarks Same as FATEBPB::bReserved. */
uint8_t bReserved;
/** 0x42 / 0x37: Extended boot signature (FATEBPB_SIGNATURE, or
* FATEBPB_SIGNATURE_OLD in some special cases).
* @remarks Same as FATEBPB::bExtSignature. */
uint8_t bExtSignature;
/** 0x43 / 0x38: The volume serial number.
* @remarks Same as FATEBPB::uSerialNumber. */
uint32_t uSerialNumber;
/** 0x47 / 0x3c: The volume label (space padded).
* @remarks Not available with FATEBPB_SIGNATURE_OLD
* @remarks Same as FATEBPB::achLabel. */
char achLabel[11];
/** 0x52 / 0x47: The file system type (space padded), or 64-bit logical sector
* count if both other count fields are zero. In the latter case, the type is
* moved to the OEM name field (FATBOOTSECTOR::achOemName).
*
* @remarks Not available with FATEBPB_SIGNATURE_OLD
* @remarks Same as FATEBPB::achType. */
union
{
/** Type string variant. */
char achType[8];
/** Total sector count if 4G or higher. */
uint64_t cTotalSectors64;
} u;
} FAT32EBPB;
#pragma pack()
AssertCompileSize(FAT32EBPB, 0x4f);
/** Pointer to a FAT32 extended BIOS parameter block. */
typedef FAT32EBPB *PFAT32EBPB;
/** Pointer to a const FAT32 extended BIOS parameter block. */
typedef FAT32EBPB const *PCFAT32EBPB;
/** FAT32 version 0.0 (FAT32EBPB::uVersion). */
#define FAT32EBPB_VERSION_0_0 UINT16_C(0x0000)
/**
* NTFS extended BIOS parameter block (NTFSEBPB).
*/
#pragma pack(1)
typedef struct NTFSEBPB
{
/** The BPB. */
FATBPB331FLAT Bpb;
/** 0x24 / 0x19: BIOS INT13 pysical drive number.
* @note Same location as FATEBPB::bInt13Drive. */
uint8_t bInt13Drive;
/** 0x25 / 0x1a: Reserved / flags */
uint8_t bReserved;
/** 0x26 / 0x1b: Extended boot signature (NTFSEBPB_SIGNATURE).
* @note Same location as FATEBPB::bExtSignature. */
uint8_t bExtSignature;
/** 0x27 / 0x1c: Reserved */
uint8_t bReserved2;
/** 0x28 / 0x1d: Number of sectors. */
uint64_t cSectors;
/** 0x30 / 0x25: Logical cluster number of the master file table (MFT). */
uint64_t uLcnMft;
/** 0x38 / 0x2d: Logical cluster number of the MFT mirror. */
uint64_t uLcnMftMirror;
/** 0x40 / 0x35: Logical clusters per file record segment.
* This is a shift count if negative. */
int8_t cClustersPerMftRecord;
/** 0x41 / 0x36: Reserved. */
uint8_t abReserved3[3];
/** 0x44 / 0x39: The default logical clusters count per index node.
* This is a shift count if negative. */
int8_t cClustersPerIndexNode;
/** 0x45 / 0x3a: Reserved. */
uint8_t abReserved4[3];
/** 0x48 / 0x3d: Volume serial number.
* @note This is larger than the the FAT serial numbers. */
uint64_t uSerialNumber;
/** 0x50 / 0x45: Checksum. */
uint32_t uChecksum;
} NTFSEBPB;
#pragma pack()
AssertCompileSize(NTFSEBPB, 0x49);
/** Pointer to a NTFS extended BIOS parameter block. */
typedef NTFSEBPB *PNTFSEBPB;
/** Pointer to a const NTFS extended BIOS parameter block. */
typedef NTFSEBPB const *PCNTFSEBPB;
/** NTFS EBPB signature (NTFSEBPB::bExtSignature). */
#define NTFSEBPB_SIGNATURE UINT8_C(0x80)
/**
* FAT boot sector layout.
*/
#pragma pack(1)
typedef struct FATBOOTSECTOR
{
/** 0x000: DOS 2.0+ jump sequence. */
uint8_t abJmp[3];
/** 0x003: OEM name (who formatted this volume). */
char achOemName[8];
/** 0x00b: The BIOS parameter block.
* This varies a lot in size. */
union
{
FATBPB20 Bpb20;
FATBPB30FLAT Bpb30;
FATBPB32FLAT Bpb32;
FATBPB331FLAT Bpb331;
FATEBPB Ebpb;
FAT32EBPB Fat32Ebpb;
NTFSEBPB Ntfs;
} Bpb;
/** 0x05a: Bootloader code/data/stuff. */
uint8_t abStuff[0x1a3];
/** 0x1fd: Old drive number location (DOS 3.2-3.31). */
uint8_t bOldInt13Drive;
/** 0x1fe: DOS signature (FATBOOTSECTOR_SIGNATURE). */
uint16_t uSignature;
} FATBOOTSECTOR;
#pragma pack()
AssertCompileSize(FATBOOTSECTOR, 0x200);
/** Pointer to a FAT boot sector. */
typedef FATBOOTSECTOR *PFATBOOTSECTOR;
/** Pointer to a const FAT boot sector. */
typedef FATBOOTSECTOR const *PCFATBOOTSECTOR;
/** Boot sector signature (FATBOOTSECTOR::uSignature). */
#define FATBOOTSECTOR_SIGNATURE UINT16_C(0xaa55)
/**
* FAT32 info sector (follows the boot sector).
*/
typedef struct FAT32INFOSECTOR
{
/** 0x000: Signature \#1 (FAT32INFOSECTOR_SIGNATURE_1). */
uint32_t uSignature1;
/** Reserved, should be zero. */
uint8_t abReserved1[0x1E0];
/** 0x1e4: Signature \#1 (FAT32INFOSECTOR_SIGNATURE_2). */
uint32_t uSignature2;
/** 0x1e8: Last known number of free clusters (informational). */
uint32_t cFreeClusters;
/** 0x1ec: Last allocated cluster number (informational). This could be used as
* an allocation hint when searching for a free cluster. */
uint32_t cLastAllocatedCluster;
/** 0x1f0: Reserved, should be zero, preserve. */
uint8_t abReserved2[12];
/** 0x1fc: Signature \#3 (FAT32INFOSECTOR_SIGNATURE_3). */
uint32_t uSignature3;
} FAT32INFOSECTOR;
AssertCompileSize(FAT32INFOSECTOR, 0x200);
/** Pointer to a FAT32 info sector. */
typedef FAT32INFOSECTOR *PFAT32INFOSECTOR;
/** Pointer to a const FAT32 info sector. */
typedef FAT32INFOSECTOR const *PCFAT32INFOSECTOR;
#define FAT32INFOSECTOR_SIGNATURE_1 UINT32_C(0x41615252)
#define FAT32INFOSECTOR_SIGNATURE_2 UINT32_C(0x61417272)
#define FAT32INFOSECTOR_SIGNATURE_3 UINT32_C(0xaa550000)
/** @name Special FAT cluster numbers and limits.
* @{ */
#define FAT_FIRST_DATA_CLUSTER 2 /**< The first data cluster. */
#define FAT_MAX_FAT12_TOTAL_CLUSTERS UINT32_C(0x00000ff6) /**< Maximum number of clusters in a 12-bit FAT . */
#define FAT_MAX_FAT16_TOTAL_CLUSTERS UINT32_C(0x0000fff6) /**< Maximum number of clusters in a 16-bit FAT . */
#define FAT_MAX_FAT32_TOTAL_CLUSTERS UINT32_C(0x0ffffff6) /**< Maximum number of clusters in a 32-bit FAT . */
#define FAT_LAST_FAT12_DATA_CLUSTER UINT32_C(0x00000ff5) /**< The last possible data cluster for FAT12. */
#define FAT_LAST_FAT16_DATA_CLUSTER UINT32_C(0x0000fff5) /**< The last possible data cluster for FAT16. */
#define FAT_LAST_FAT32_DATA_CLUSTER UINT32_C(0x0ffffff5) /**< The last possible data cluster for FAT32. */
#define FAT_MAX_FAT12_DATA_CLUSTERS UINT32_C(0x00000ff4) /**< Maximum number of data clusters for FAT12. */
#define FAT_MAX_FAT16_DATA_CLUSTERS UINT32_C(0x0000fff4) /**< Maximum number of data clusters for FAT16. */
#define FAT_MAX_FAT32_DATA_CLUSTERS UINT32_C(0x0ffffff4) /**< Maximum number of data clusters for FAT32. */
#define FAT_MIN_FAT12_DATA_CLUSTERS UINT32_C(0x00000001) /**< Maximum number of data clusters for FAT12. */
#define FAT_MIN_FAT16_DATA_CLUSTERS UINT32_C(0x00000ff5) /**< Maximum number of data clusters for FAT16. */
#define FAT_MIN_FAT32_DATA_CLUSTERS UINT32_C(0x0000fff5) /**< Maximum number of data clusters for FAT32. */
#define FAT_FIRST_FAT12_EOC UINT32_C(0x00000ff8) /**< The first end-of-file-cluster number for FAT12. */
#define FAT_FIRST_FAT16_EOC UINT32_C(0x0000fff8) /**< The first end-of-file-cluster number for FAT16. */
#define FAT_FIRST_FAT32_EOC UINT32_C(0x0ffffff8) /**< The first end-of-file-cluster number for FAT32. */
/** @} */
/**
* FAT directory entry.
*/
typedef struct FATDIRENTRY
{
/** 0x00: The directory entry name.
* First character serves as a flag to indicate deleted or not. */
uint8_t achName[8+3];
/** 0x0b: Attributes (FAT_ATTR_XXX). */
uint8_t fAttrib;
/** 0x0c: NT case flags (FATDIRENTRY_CASE_F_XXX). */
uint8_t fCase;
/** 0x0d: Birth milliseconds (DOS 7.0+ w/VFAT). */
uint8_t uBirthCentiseconds;
/** 0x0e: Birth time (DOS 7.0+ w/VFAT). */
uint16_t uBirthTime;
/** 0x10: Birth date (DOS 7.0+ w/VFAT). */
uint16_t uBirthDate;
/** 0x12: Access date (DOS 7.0+ w/ACCDATA in Config.sys). */
uint16_t uAccessDate;
union
{
/** 0x14: High cluster word for FAT32. */
uint16_t idxClusterHigh;
/** 0x14: Index of extended attributes (FAT16/FAT12). */
uint16_t idxEAs;
} u;
/** 0x16: Modify time (PC-DOS 1.1+, MS-DOS 1.20+). */
uint16_t uModifyTime;
/** 0x18: Modify date. */
uint16_t uModifyDate;
/** 0x1a: The data cluster index. */
uint16_t idxCluster;
/** 0x1c: The file size. */
uint32_t cbFile;
} FATDIRENTRY;
AssertCompileSize(FATDIRENTRY, 0x20);
AssertCompileMemberOffset(FATDIRENTRY, fAttrib, 0x0b);
AssertCompileMemberOffset(FATDIRENTRY, fCase, 0x0c);
AssertCompileMemberOffset(FATDIRENTRY, uBirthCentiseconds, 0x0d);
AssertCompileMemberOffset(FATDIRENTRY, uBirthTime, 0x0e);
AssertCompileMemberOffset(FATDIRENTRY, uBirthDate, 0x10);
AssertCompileMemberOffset(FATDIRENTRY, uAccessDate, 0x12);
AssertCompileMemberOffset(FATDIRENTRY, u, 0x14);
AssertCompileMemberOffset(FATDIRENTRY, uModifyTime, 0x16);
AssertCompileMemberOffset(FATDIRENTRY, uModifyDate, 0x18);
AssertCompileMemberOffset(FATDIRENTRY, idxCluster, 0x1a);
AssertCompileMemberOffset(FATDIRENTRY, cbFile, 0x1c);
/** Pointer to a FAT directory entry. */
typedef FATDIRENTRY *PFATDIRENTRY;
/** Pointer to a FAT directory entry. */
typedef FATDIRENTRY const *PCFATDIRENTRY;
/** @name FAT_ATTR_XXX - FATDIRENTRY::fAttrib flags.
* @{ */
#define FAT_ATTR_READONLY UINT8_C(0x01)
#define FAT_ATTR_HIDDEN UINT8_C(0x02)
#define FAT_ATTR_SYSTEM UINT8_C(0x04)
#define FAT_ATTR_VOLUME UINT8_C(0x08)
#define FAT_ATTR_DIRECTORY UINT8_C(0x10)
#define FAT_ATTR_ARCHIVE UINT8_C(0x20)
#define FAT_ATTR_DEVICE UINT8_C(0x40)
#define FAT_ATTR_RESERVED UINT8_C(0x80)
#define FAT_ATTR_NAME_SLOT UINT8_C(0x0f) /**< Special attribute value for FATDIRNAMESLOT. */
/** @} */
/** @name FATDIRENTRY_CASE_F_XXX - FATDIRENTRY::fCase flags.
* @{ */
/** Lower cased base name (first 8 chars). */
#define FATDIRENTRY_CASE_F_LOWER_BASE UINT8_C(0x08)
/** Lower cased filename extension (last 3 chars). */
#define FATDIRENTRY_CASE_F_LOWER_EXT UINT8_C(0x10)
/** @} */
/** @name FATDIRENTRY_CH0_XXX - FATDIRENTRY::achName[0]
* @{ */
/** Deleted entry. */
#define FATDIRENTRY_CH0_DELETED UINT8_C(0xe5)
/** End of used directory entries (MS-DOS 1.25+, PC-DOS 2.0+). */
#define FATDIRENTRY_CH0_END_OF_DIR UINT8_C(0x00)
/** The special dot or dot-dot dir aliases (MS-DOS 1.40+, PC-DOS 2.0+).
* @remarks 0x2e is the ascii table entry of the '.' character. */
#define FATDIRENTRY_CH0_DOT_ALIAS UINT8_C(0x2e)
/** Escaped 0xe5 leadcharacter (DOS 3.0+). */
#define FATDIRENTRY_CH0_ESC_E5 UINT8_C(0x05)
/** @} */
/**
* FAT directory alias name slot.
*
* Each slot holds 13 UTF-16 (/ UCS-2) characters, so it takes 20 slots to cover
* a 255 character long name.
*/
#pragma pack(1)
typedef struct FATDIRNAMESLOT
{
/** The slot sequence number. */
uint8_t idSlot;
/** The first 5 name chars.
* @remarks misaligned */
RTUTF16 awcName0[5];
/** Attributes (FAT_ATTR_XXX). */
uint8_t fAttrib;
/** Always zero. */
uint8_t fZero;
/** Alias checksum. */
uint8_t bChecksum;
/** The next 6 name chars. */
RTUTF16 awcName1[6];
/** Always zero (usually cluster entry). */
uint16_t idxZero;
/** The next 2 name chars. */
RTUTF16 awcName2[2];
} FATDIRNAMESLOT;
#pragma pack()
AssertCompileSize(FATDIRNAMESLOT, 0x20);
/** Pointer to a FAT directory entry. */
typedef FATDIRNAMESLOT *PFATDIRNAMESLOT;
/** Pointer to a FAT directory entry. */
typedef FATDIRNAMESLOT const *PCFATDIRNAMESLOT;
/** Slot ID flag indicating that it's the first slot. */
#define FATDIRNAMESLOT_FIRST_SLOT_FLAG UINT8_C(0x40)
/** Highest slot ID recognized. This allows for 260 characters, however many
* implementation limits it to 255 or 250. */
#define FATDIRNAMESLOT_HIGHEST_SLOT_ID UINT8_C(0x14)
/** Max number of slots recognized. (This is the same as the higest slot ID
* because the 0 isn't a valid ID.) */
#define FATDIRNAMESLOT_MAX_SLOTS FATDIRNAMESLOT_HIGHEST_SLOT_ID
/** Number of UTF-16 units per slot. */
#define FATDIRNAMESLOT_CHARS_PER_SLOT (5 + 6 + 2)
/**
* FAT directory entry union.
*/
typedef union FATDIRENTRYUNION
{
/** Regular entry view. */
FATDIRENTRY Entry;
/** Name slot view. */
FATDIRNAMESLOT Slot;
} FATDIRENTRYUNION;
AssertCompileSize(FATDIRENTRYUNION, 0x20);
/** Pointer to a FAT directory entry union. */
typedef FATDIRENTRYUNION *PFATDIRENTRYUNION;
/** Pointer to a const FAT directory entry union. */
typedef FATDIRENTRYUNION const *PCFATDIRENTRYUNION;
/** @} */
#endif /* !IPRT_INCLUDED_formats_fat_h */