// /*************************************************************************** // Aaru Data Preservation Suite // ---------------------------------------------------------------------------- // // Filename : Structs.cs // Author(s) : Natalia Portillo // // Component : Microsoft FAT filesystem plugin. // // --[ Description ] ---------------------------------------------------------- // // Microsoft FAT filesystem structures. // // --[ License ] -------------------------------------------------------------- // // This library is free software; you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 2.1 of the // License, or (at your option) any later version. // // This library 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, see . // // ---------------------------------------------------------------------------- // Copyright © 2011-2020 Natalia Portillo // ****************************************************************************/ using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; // ReSharper disable NotAccessedField.Local namespace Aaru.Filesystems { [SuppressMessage("ReSharper", "UnusedMember.Local")] public sealed partial class FAT { const int UMSDOS_MAXNAME = 220; /// BIOS Parameter Block as used by Atari ST GEMDOS on FAT12 volumes. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct AtariParameterBlock { /// 68000 BRA.S jump or x86 loop [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public readonly byte[] jump; /// OEM Name, 6 bytes, space-padded, "Loader" for Atari ST boot loader [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public readonly byte[] oem_name; /// Volume serial number [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] serial_no; /// Bytes per sector public readonly ushort bps; /// Sectors per cluster public readonly byte spc; /// Reserved sectors between BPB and FAT (inclusive) public readonly ushort rsectors; /// Number of FATs public readonly byte fats_no; /// Number of entries on root directory public readonly ushort root_ent; /// Sectors in volume public ushort sectors; /// Media descriptor, unused by GEMDOS public readonly byte media; /// Sectors per FAT public readonly ushort spfat; /// Sectors per track public readonly ushort sptrk; /// Heads public readonly ushort heads; /// Hidden sectors before BPB, unused by GEMDOS public readonly ushort hsectors; /// Word to be loaded in the cmdload system variable. Big-endian. public readonly ushort execflag; /// /// Word indicating load mode. If zero, file named is located and loaded. It not, sectors /// specified in and are loaded. Big endian. /// public readonly ushort ldmode; /// Starting sector of boot code. public readonly ushort ssect; /// Count of sectors of boot code. public readonly ushort sectcnt; /// Address where boot code should be loaded. public readonly ushort ldaaddr; /// Padding. public readonly ushort padding; /// Address where FAT and root directory sectors must be loaded. public readonly ushort fatbuf; /// Unknown. public readonly ushort unknown; /// Filename to be loaded for booting. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public readonly byte[] fname; /// Reserved public readonly ushort reserved; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 455)] public readonly byte[] boot_code; /// Big endian word to make big endian sum of all sector words be equal to 0x1234 if disk is bootable. public readonly ushort checksum; } /// BIOS Parameter Block as used by MSX-DOS 2. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct MsxParameterBlock { /// x86 loop [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] jump; /// OEM Name, 8 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] oem_name; /// Bytes per sector public readonly ushort bps; /// Sectors per cluster public readonly byte spc; /// Reserved sectors between BPB and FAT (inclusive) public readonly ushort rsectors; /// Number of FATs public readonly byte fats_no; /// Number of entries on root directory public readonly ushort root_ent; /// Sectors in volume public ushort sectors; /// Media descriptor public readonly byte media; /// Sectors per FAT public readonly ushort spfat; /// Sectors per track public readonly ushort sptrk; /// Heads public readonly ushort heads; /// Hidden sectors before BPB public readonly ushort hsectors; /// Jump for MSX-DOS 1 boot code public readonly ushort msxdos_jmp; /// Set to "VOL_ID" by MSX-DOS 2 [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public readonly byte[] vol_id; /// Bigger than 0 if there are deleted files (MSX-DOS 2) public readonly byte undelete_flag; /// Volume serial number (MSX-DOS 2) public readonly uint serial_no; /// Reserved (MSX-DOS 2) [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] public readonly byte[] reserved; /// Jump for MSX-DOS 2 boot code (MSX-DOS 2) public readonly ushort msxdos2_jmp; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 460)] public readonly byte[] boot_code; /// Always 0x55 0xAA. public readonly ushort boot_signature; } /// DOS 2.0 BIOS Parameter Block. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct BiosParameterBlock2 { /// x86 jump [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] jump; /// OEM Name, 8 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] oem_name; /// Bytes per sector public readonly ushort bps; /// Sectors per cluster public readonly byte spc; /// Reserved sectors between BPB and FAT public readonly ushort rsectors; /// Number of FATs public readonly byte fats_no; /// Number of entries on root directory public readonly ushort root_ent; /// Sectors in volume public ushort sectors; /// Media descriptor public readonly byte media; /// Sectors per FAT public readonly ushort spfat; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 486)] public readonly byte[] boot_code; /// 0x55 0xAA if bootable. public readonly ushort boot_signature; } /// DOS 3.0 BIOS Parameter Block. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct BiosParameterBlock30 { /// x86 jump [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] jump; /// OEM Name, 8 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] oem_name; /// Bytes per sector public readonly ushort bps; /// Sectors per cluster public readonly byte spc; /// Reserved sectors between BPB and FAT public readonly ushort rsectors; /// Number of FATs public readonly byte fats_no; /// Number of entries on root directory public readonly ushort root_ent; /// Sectors in volume public ushort sectors; /// Media descriptor public readonly byte media; /// Sectors per FAT public readonly ushort spfat; /// Sectors per track public readonly ushort sptrk; /// Heads public readonly ushort heads; /// Hidden sectors before BPB public readonly ushort hsectors; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 480)] public readonly byte[] boot_code; /// Always 0x55 0xAA. public readonly ushort boot_signature; } /// DOS 3.2 BIOS Parameter Block. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct BiosParameterBlock32 { /// x86 jump [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] jump; /// OEM Name, 8 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] oem_name; /// Bytes per sector public readonly ushort bps; /// Sectors per cluster public readonly byte spc; /// Reserved sectors between BPB and FAT public readonly ushort rsectors; /// Number of FATs public readonly byte fats_no; /// Number of entries on root directory public readonly ushort root_ent; /// Sectors in volume public ushort sectors; /// Media descriptor public readonly byte media; /// Sectors per FAT public readonly ushort spfat; /// Sectors per track public readonly ushort sptrk; /// Heads public readonly ushort heads; /// Hidden sectors before BPB public readonly ushort hsectors; /// Total sectors including hidden ones public readonly ushort total_sectors; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 478)] public readonly byte[] boot_code; /// Always 0x55 0xAA. public readonly ushort boot_signature; } /// DOS 3.31 BIOS Parameter Block. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct BiosParameterBlock33 { /// x86 jump [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] jump; /// OEM Name, 8 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] oem_name; /// Bytes per sector public readonly ushort bps; /// Sectors per cluster public readonly byte spc; /// Reserved sectors between BPB and FAT public readonly ushort rsectors; /// Number of FATs public readonly byte fats_no; /// Number of entries on root directory public readonly ushort root_ent; /// Sectors in volume public ushort sectors; /// Media descriptor public readonly byte media; /// Sectors per FAT public readonly ushort spfat; /// Sectors per track public readonly ushort sptrk; /// Heads public readonly ushort heads; /// Hidden sectors before BPB public readonly uint hsectors; /// Sectors in volume if > 65535 public uint big_sectors; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 474)] public readonly byte[] boot_code; /// Always 0x55 0xAA. public readonly ushort boot_signature; } /// DOS 3.4 BIOS Parameter Block. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct BiosParameterBlockShortEbpb { /// x86 jump [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] jump; /// OEM Name, 8 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] oem_name; /// Bytes per sector public readonly ushort bps; /// Sectors per cluster public readonly byte spc; /// Reserved sectors between BPB and FAT public readonly ushort rsectors; /// Number of FATs public readonly byte fats_no; /// Number of entries on root directory public readonly ushort root_ent; /// Sectors in volume public ushort sectors; /// Media descriptor public readonly byte media; /// Sectors per FAT public readonly ushort spfat; /// Sectors per track public readonly ushort sptrk; /// Heads public readonly ushort heads; /// Hidden sectors before BPB public readonly uint hsectors; /// Sectors in volume if > 65535 public uint big_sectors; /// Drive number public readonly byte drive_no; /// Volume flags public readonly byte flags; /// EPB signature, 0x28 public readonly byte signature; /// Volume serial number public readonly uint serial_no; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 467)] public readonly byte[] boot_code; /// Always 0x55 0xAA. public readonly ushort boot_signature; } /// DOS 4.0 or higher BIOS Parameter Block. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct BiosParameterBlockEbpb { /// x86 jump [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public byte[] jump; /// OEM Name, 8 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] oem_name; /// Bytes per sector public ushort bps; /// Sectors per cluster public byte spc; /// Reserved sectors between BPB and FAT public ushort rsectors; /// Number of FATs public byte fats_no; /// Number of entries on root directory public ushort root_ent; /// Sectors in volume public ushort sectors; /// Media descriptor public byte media; /// Sectors per FAT public ushort spfat; /// Sectors per track public ushort sptrk; /// Heads public ushort heads; /// Hidden sectors before BPB public uint hsectors; /// Sectors in volume if > 65535 public uint big_sectors; /// Drive number public byte drive_no; /// Volume flags public byte flags; /// EPB signature, 0x29 public byte signature; /// Volume serial number public uint serial_no; /// Volume label, 11 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public readonly byte[] volume_label; /// Filesystem type, 8 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] fs_type; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 448)] public byte[] boot_code; /// Always 0x55 0xAA. public ushort boot_signature; } /// FAT32 Parameter Block [StructLayout(LayoutKind.Sequential, Pack = 1)] struct Fat32ParameterBlockShort { /// x86 jump [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] jump; /// OEM Name, 8 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] oem_name; /// Bytes per sector public readonly ushort bps; /// Sectors per cluster public readonly byte spc; /// Reserved sectors between BPB and FAT public readonly ushort rsectors; /// Number of FATs public readonly byte fats_no; /// Number of entries on root directory, set to 0 public readonly ushort root_ent; /// Sectors in volume, set to 0 public ushort sectors; /// Media descriptor public readonly byte media; /// Sectors per FAT, set to 0 public readonly ushort spfat; /// Sectors per track public readonly ushort sptrk; /// Heads public readonly ushort heads; /// Hidden sectors before BPB public readonly uint hsectors; /// Sectors in volume public uint big_sectors; /// Sectors per FAT public readonly uint big_spfat; /// FAT flags public readonly ushort mirror_flags; /// FAT32 version public readonly ushort version; /// Cluster of root directory public readonly uint root_cluster; /// Sector of FSINFO structure public readonly ushort fsinfo_sector; /// Sector of FAT32PB backup public readonly ushort backup_sector; /// Reserved [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public readonly byte[] reserved; /// Drive number public readonly byte drive_no; /// Volume flags public readonly byte flags; /// Signature, should be 0x28 public readonly byte signature; /// Volume serial number public readonly uint serial_no; /// Volume label, 11 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public readonly byte[] reserved2; /// Sectors in volume if equals 0 public ulong huge_sectors; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 420)] public readonly byte[] boot_code; /// Always 0x55 0xAA. public readonly ushort boot_signature; } /// FAT32 Parameter Block [StructLayout(LayoutKind.Sequential, Pack = 1)] struct Fat32ParameterBlock { /// x86 jump [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] jump; /// OEM Name, 8 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] oem_name; /// Bytes per sector public ushort bps; /// Sectors per cluster public byte spc; /// Reserved sectors between BPB and FAT public readonly ushort rsectors; /// Number of FATs public readonly byte fats_no; /// Number of entries on root directory, set to 0 public readonly ushort root_ent; /// Sectors in volume, set to 0 public ushort sectors; /// Media descriptor public readonly byte media; /// Sectors per FAT, set to 0 public readonly ushort spfat; /// Sectors per track public ushort sptrk; /// Heads public readonly ushort heads; /// Hidden sectors before BPB public uint hsectors; /// Sectors in volume public uint big_sectors; /// Sectors per FAT public uint big_spfat; /// FAT flags public readonly ushort mirror_flags; /// FAT32 version public readonly ushort version; /// Cluster of root directory public readonly uint root_cluster; /// Sector of FSINFO structure public readonly ushort fsinfo_sector; /// Sector of FAT32PB backup public readonly ushort backup_sector; /// Reserved [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public readonly byte[] reserved; /// Drive number public readonly byte drive_no; /// Volume flags public readonly byte flags; /// Signature, should be 0x29 public readonly byte signature; /// Volume serial number public readonly uint serial_no; /// Volume label, 11 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public readonly byte[] volume_label; /// Filesystem type, 8 bytes, space-padded, must be "FAT32 " [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] fs_type; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 419)] public readonly byte[] boot_code; /// Always 0x55 0xAA. public readonly ushort boot_signature; } /// Apricot Label. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct ApricotLabel { /// Version of format which created disk [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] version; /// Operating system. public readonly byte operatingSystem; /// Software write protection. [MarshalAs(UnmanagedType.U1)] public readonly bool writeProtected; /// Copy protected. [MarshalAs(UnmanagedType.U1)] public readonly bool copyProtected; /// Boot type. public readonly byte bootType; /// Partitions. public readonly byte partitionCount; /// Is hard disk?. [MarshalAs(UnmanagedType.U1)] public readonly bool winchester; /// Sector size. public readonly ushort sectorSize; /// Sectors per track. public readonly ushort spt; /// Tracks per side. public readonly uint cylinders; /// Sides. public readonly byte heads; /// Interleave factor. public readonly byte interleave; /// Skew factor. public readonly ushort skew; /// Sector where boot code starts. public readonly uint bootLocation; /// Size in sectors of boot code. public readonly ushort bootSize; /// Address at which to load boot code. public readonly uint bootAddress; /// Offset where to jump to boot. public readonly ushort bootOffset; /// Segment where to jump to boot. public readonly ushort bootSegment; /// First data sector. public readonly uint firstDataBlock; /// Generation. public readonly ushort generation; /// Copy count. public readonly ushort copyCount; /// Maximum number of copies. public readonly ushort maxCopies; /// Serial number. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] serialNumber; /// Part number. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] partNumber; /// Copyright. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public readonly byte[] copyright; /// BPB for whole disk. public ApricotParameterBlock mainBPB; /// Name of FONT file. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public readonly byte[] fontName; /// Name of KEYBOARD file. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public readonly byte[] keyboardName; /// Minor BIOS version. public readonly byte biosMinorVersion; /// Major BIOS version. public readonly byte biosMajorVersion; /// Diagnostics enabled?. [MarshalAs(UnmanagedType.U1)] public readonly bool diagnosticsFlag; /// Printer device. public readonly byte prnDevice; /// Bell volume. public readonly byte bellVolume; /// Cache enabled?. [MarshalAs(UnmanagedType.U1)] public readonly bool enableCache; /// Graphics enabled?. [MarshalAs(UnmanagedType.U1)] public readonly bool enableGraphics; /// Length in sectors of DOS. public readonly byte dosLength; /// Length in sectors of FONT file. public readonly byte fontLength; /// Length in sectors of KEYBOARD file. public readonly byte keyboardLength; /// Starting sector of DOS. public readonly ushort dosStart; /// Starting sector of FONT file. public readonly ushort fontStart; /// Starting sector of KEYBOARD file. public readonly ushort keyboardStart; /// Keyboard click volume. public readonly byte keyboardVolume; /// Auto-repeat enabled?. [MarshalAs(UnmanagedType.U1)] public readonly bool autorepeat; /// Auto-repeat lead-in. public readonly byte autorepeatLeadIn; /// Auto-repeat interval. public readonly byte autorepeatInterval; /// Microscreen mode. public readonly byte microscreenMode; /// Spare area for keyboard values expansion. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public readonly byte[] spareKeyboard; /// Screen line mode. public readonly byte lineMode; /// Screen line width. public readonly byte lineWidth; /// Screen disabled?. [MarshalAs(UnmanagedType.U1)] public readonly bool imageOff; /// Spare area for screen values expansion. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] public readonly byte[] spareScreen; /// TX baud rate. public readonly byte txBaudRate; /// RX baud rate. public readonly byte rxBaudRate; /// TX bits. public readonly byte txBits; /// RX bits. public readonly byte rxBits; /// Stop bits. public readonly byte stopBits; /// Parity enabled?. [MarshalAs(UnmanagedType.U1)] public readonly bool parityCheck; /// Parity type. public readonly byte parityType; /// Xon/Xoff enabled on TX. [MarshalAs(UnmanagedType.U1)] public readonly bool txXonXoff; /// Xon/Xoff enabled on RX. [MarshalAs(UnmanagedType.U1)] public readonly bool rxXonXoff; /// Xon character. public readonly byte xonCharacter; /// Xoff character. public readonly byte xoffCharacter; /// Xon/Xoff buffer on RX. public readonly ushort rxXonXoffBuffer; /// DTR/DSR enabled?. [MarshalAs(UnmanagedType.U1)] public readonly bool dtrDsr; /// CTS/RTS enabled?. [MarshalAs(UnmanagedType.U1)] public readonly bool ctsRts; /// NULLs after CR. public readonly byte nullsAfterCr; /// NULLs after 0xFF. public readonly byte nullsAfterFF; /// Send LF after CR in serial port. [MarshalAs(UnmanagedType.U1)] public readonly bool lfAfterCRSerial; /// BIOS error report in serial port. [MarshalAs(UnmanagedType.U1)] public readonly bool biosErrorReportSerial; /// Spare area for serial port values expansion. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 13)] public readonly byte[] spareSerial; /// Send LF after CR in parallel port. [MarshalAs(UnmanagedType.U1)] public readonly bool lfAfterCrParallel; /// Select line supported?. [MarshalAs(UnmanagedType.U1)] public readonly bool selectLine; /// Paper empty supported?. [MarshalAs(UnmanagedType.U1)] public readonly bool paperEmpty; /// Fault line supported?. [MarshalAs(UnmanagedType.U1)] public readonly bool faultLine; /// BIOS error report in parallel port. [MarshalAs(UnmanagedType.U1)] public readonly bool biosErrorReportParallel; /// Spare area for parallel port values expansion. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] public readonly byte[] spareParallel; /// Spare area for Winchester values expansion. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)] public readonly byte[] spareWinchester; /// Parking enabled?. [MarshalAs(UnmanagedType.U1)] public readonly bool parkingEnabled; /// Format protection?. [MarshalAs(UnmanagedType.U1)] public readonly bool formatProtection; /// Spare area for RAM disk values expansion. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public readonly byte[] spareRamDisk; /// List of bad blocks. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public readonly ushort[] badBlocks; /// Array of partition BPBs. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly ApricotParameterBlock[] partitions; /// Spare area. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 63)] public readonly byte[] spare; /// CP/M double side indicator?. public readonly bool cpmDoubleSided; } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct ApricotParameterBlock { /// Bytes per sector public readonly ushort bps; /// Sectors per cluster public readonly byte spc; /// Reserved sectors between BPB and FAT public readonly ushort rsectors; /// Number of FATs public readonly byte fats_no; /// Number of entries on root directory public readonly ushort root_ent; /// Sectors in volume public ushort sectors; /// Media descriptor public readonly byte media; /// Sectors per FAT public readonly ushort spfat; /// Disk type public readonly byte diskType; /// Volume starting sector public readonly ushort startSector; } /// FAT32 FS Information Sector [StructLayout(LayoutKind.Sequential, Pack = 1)] struct FsInfoSector { /// Signature must be public readonly uint signature1; /// Reserved [MarshalAs(UnmanagedType.ByValArray, SizeConst = 480)] public readonly byte[] reserved1; /// Signature must be public readonly uint signature2; /// Free clusters public readonly uint free_clusters; /// cated cluster public readonly uint last_cluster; /// Reserved [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public readonly byte[] reserved2; /// Signature must be public readonly uint signature3; } /// Human68k Parameter Block, big endian, 512 bytes even on 256 bytes/sector. [StructLayout(LayoutKind.Sequential, Pack = 1)] struct HumanParameterBlock { /// 68k bra.S [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public readonly byte[] jump; /// OEM Name, 16 bytes, space-padded [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public readonly byte[] oem_name; /// Bytes per cluster public readonly ushort bpc; /// Unknown, seen 1, 2 and 16 public readonly byte unknown1; /// Unknown, always 512? public readonly ushort unknown2; /// Unknown, always 1? public readonly byte unknown3; /// Number of entries on root directory public readonly ushort root_ent; /// Clusters, set to 0 if more than 65536 public readonly ushort clusters; /// Media descriptor public readonly byte media; /// Clusters per FAT, set to 0 public readonly byte cpfat; /// Clustersin volume public readonly uint big_clusters; /// Boot code. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 478)] public readonly byte[] boot_code; } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct DirectoryEntry { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] filename; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] extension; public readonly FatAttributes attributes; public readonly CaseInfo caseinfo; public readonly byte ctime_ms; public readonly ushort ctime; public readonly ushort cdate; public readonly ushort adate; public readonly ushort ea_handle; public readonly ushort mtime; public readonly ushort mdate; public readonly ushort start_cluster; public readonly uint size; } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct HumanDirectoryEntry { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public readonly byte[] name1; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly byte[] extension; public readonly FatAttributes attributes; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public readonly byte[] name2; public readonly ushort mtime; public readonly ushort mdate; public readonly ushort start_cluster; public readonly uint size; } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct LfnEntry { public readonly byte sequence; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public readonly byte[] name1; public readonly FatAttributes attributes; public readonly byte type; public readonly byte checksum; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public readonly byte[] name2; public readonly ushort start_cluster; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public readonly byte[] name3; } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct EaHeader { public readonly ushort magic; public readonly ushort cluster; public readonly EaFlags flags; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public readonly byte[] filename; public readonly uint unknown; public readonly ushort zero; } /// This structure is 256 bytes large, depending on the name, only part of it is written to disk [StructLayout(LayoutKind.Sequential, Pack = 1)] struct UmsdosDirectoryEntry { /// if == 0, then this entry is not used public readonly byte name_len; /// UMSDOS_xxxx public readonly UmsdosFlags flags; /// How many hard links point to this entry public readonly ushort nlink; /// Owner user id public readonly int uid; /// Group id public readonly int gid; /// Access time public readonly int atime; /// Last modification time public readonly int mtime; /// Creation time public readonly int ctime; /// major and minor number of a device public readonly uint rdev; /* */ /// Standard UNIX permissions bits + type of public readonly ushort mode; /// unused bytes for future extensions [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] public readonly byte[] spare; /// /// Not '\0' terminated but '\0' padded, so it will allow for adding news fields in this record by reducing the /// size of name[] /// [MarshalAs(UnmanagedType.ByValArray, SizeConst = UMSDOS_MAXNAME)] public readonly byte[] name; } [SuppressMessage("ReSharper", "InconsistentNaming")] enum UmsdosFlags : byte { /// Never show this entry in directory search UMSDOS_HIDDEN = 1, /// It is a (pseudo) hard link UMSDOS_HLINK = 2 } class CompleteDirectoryEntry { public DirectoryEntry Dirent; public DirectoryEntry Fat32Ea; public HumanDirectoryEntry HumanDirent; public string HumanName; public string Lfn; public UmsdosDirectoryEntry LinuxDirent; public string LinuxName; public string Longname; public string Shortname; public override string ToString() { // This ensures UMSDOS takes preference when present if(!string.IsNullOrEmpty(LinuxName)) return LinuxName; // This ensures LFN takes preference when eCS is in use if(!string.IsNullOrEmpty(Lfn)) return Lfn; // This ensures Humans takes preference when present if(!string.IsNullOrEmpty(HumanName)) return HumanName; return !string.IsNullOrEmpty(Longname) ? Longname : Shortname; } } } }