// /*************************************************************************** // The Disc Image Chef // ---------------------------------------------------------------------------- // // Filename : AppleHFS.cs // Author(s) : Natalia Portillo // // Component : Apple Hierarchical File System plugin. // // --[ Description ] ---------------------------------------------------------- // // Identifies the Apple Hierarchical File System and shows information. // // --[ 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.Runtime.InteropServices; // ReSharper disable IdentifierTypo // ReSharper disable MemberCanBePrivate.Local namespace DiscImageChef.Filesystems { // Information from Inside Macintosh // https://developer.apple.com/legacy/library/documentation/mac/pdf/Files/File_Manager.pdf public partial class AppleHFS { /// Master Directory Block, should be sector 2 in volume [StructLayout(LayoutKind.Sequential, Pack = 1)] struct HfsMasterDirectoryBlock // Should be sector 2 in volume { /// 0x000, Signature, 0x4244 public readonly ushort drSigWord; /// 0x002, Volume creation date public readonly uint drCrDate; /// 0x006, Volume last modification date public readonly uint drLsMod; /// 0x00A, Volume attributes public readonly AppleCommon.VolumeAttributes drAtrb; /// 0x00C, Files in root directory public readonly ushort drNmFls; /// 0x00E, Start 512-byte sector of volume bitmap public readonly ushort drVBMSt; /// 0x010, Allocation block to begin next allocation public readonly ushort drAllocPtr; /// 0x012, Allocation blocks public readonly ushort drNmAlBlks; /// 0x014, Bytes per allocation block public readonly uint drAlBlkSiz; /// 0x018, Bytes to allocate when extending a file public readonly uint drClpSiz; /// 0x01C, Start 512-byte sector of first allocation block public readonly ushort drAlBlSt; /// 0x01E, CNID for next file public readonly uint drNxtCNID; /// 0x022, Free allocation blocks public readonly ushort drFreeBks; /// 0x024, Volume name (28 bytes) [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] public readonly byte[] drVN; /// 0x040, Volume last backup time public readonly uint drVolBkUp; /// 0x044, Volume backup sequence number public readonly ushort drVSeqNum; /// 0x046, Filesystem write count public readonly uint drWrCnt; /// 0x04A, Bytes to allocate when extending the extents B-Tree public readonly uint drXTClpSiz; /// 0x04E, Bytes to allocate when extending the catalog B-Tree public readonly uint drCTClpSiz; /// 0x052, Number of directories in root directory public readonly ushort drNmRtDirs; /// 0x054, Number of files in the volume public readonly uint drFilCnt; /// 0x058, Number of directories in the volume public readonly uint drDirCnt; /// 0x05C, finderInfo[0], CNID for bootable system's directory public readonly uint drFndrInfo0; /// 0x060, finderInfo[1], CNID of the directory containing the boot application public readonly uint drFndrInfo1; /// 0x064, finderInfo[2], CNID of the directory that should be opened on boot public readonly uint drFndrInfo2; /// 0x068, finderInfo[3], CNID for Mac OS 8 or 9 directory public readonly uint drFndrInfo3; /// 0x06C, finderInfo[4], Reserved public readonly uint drFndrInfo4; /// 0x070, finderInfo[5], CNID for Mac OS X directory public readonly uint drFndrInfo5; /// 0x074, finderInfo[6], first part of Mac OS X volume ID public readonly uint drFndrInfo6; /// 0x078, finderInfo[7], second part of Mac OS X volume ID public readonly uint drFndrInfo7; // If wrapping HFS+ /// 0x07C, Embedded volume signature, "H+" if HFS+ is embedded ignore following two fields if not public readonly ushort drEmbedSigWord; /// 0x07E, Starting block number of embedded HFS+ volume public readonly ushort xdrStABNt; /// 0x080, Allocation blocks used by embedded volume public readonly ushort xdrNumABlks; // If not /// 0x07C, Size in blocks of volume cache public readonly ushort drVCSize; /// 0x07E, Size in blocks of volume bitmap cache public readonly ushort drVBMCSize; /// 0x080, Size in blocks of volume common cache public readonly ushort drCtlCSize; // End of variable variables :D /// 0x082, Bytes in the extents B-Tree 3 HFS extents following, 32 bits each public readonly uint drXTFlSize; /// 0x092, Bytes in the catalog B-Tree 3 HFS extents following, 32 bits each public readonly uint drCTFlSize; } [StructLayout(LayoutKind.Sequential, Pack = 1)] struct NodeDescriptor { /// A link to the next node of this type, or null if this is the last one. public readonly uint ndFLink; /// A link to the previous node of this type, or null if this is the first one. public readonly uint ndBLink; /// The type of this node. public readonly NodeType ndType; /// The depth of this node in the B*-tree hierarchy. Maximum depth is apparently 8. public readonly sbyte ndNHeight; /// The number of records contained in this node. public readonly ushort ndNRecs; /// Reserved, should be 0. public readonly ushort ndResv2; } /// B*-tree header [StructLayout(LayoutKind.Sequential, Pack = 1)] struct BTHdrRed { /// Current depth of tree. public readonly ushort bthDepth; /// Number of root node. public readonly uint bthRoot; /// Number of leaf records in tree. public readonly uint bthNRecs; /// Number of first leaf node. public readonly uint bthFNode; /// Number of last leaf node. public readonly uint bthLNode; /// Size of a node. public readonly ushort bthNodeSize; /// Maximum length of a key. public readonly ushort bthKeyLen; /// Total number of nodes in tree. public readonly uint bthNNodes; /// Number of free nodes. public readonly uint bthFree; /// Reserved [MarshalAs(UnmanagedType.ByValArray, SizeConst = 76)] public readonly sbyte[] bthResv; } /// Catalog key record [StructLayout(LayoutKind.Sequential, Pack = 1)] struct CatKeyRec { /// Key length. public readonly sbyte ckrKeyLen; /// Reserved. public readonly sbyte ckrResrv1; /// Parent directory ID. public readonly uint ckrParID; /// Catalog node name. Full 32 bytes in index nodes but only the needed bytes, padded to word, in leaf nodes. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public readonly byte[] ckrCName; } /// Catalog data record header [StructLayout(LayoutKind.Sequential, Pack = 1)] struct CatDataRec { public readonly CatDataType cdrType; public readonly sbyte cdrResvr2; } /// Directory record [StructLayout(LayoutKind.Sequential, Pack = 1)] struct CdrDirRec { public readonly CatDataRec dirHdr; /// Directory flags. public readonly ushort dirFlags; /// Directory valence. public readonly ushort dirVal; /// Directory ID. public readonly uint dirDirID; /// Date and time of creation. public readonly uint dirCrDat; /// Date and time of last modification. public readonly uint dirMdDat; /// Date and time of last backup. public readonly uint dirBkDat; /// Finder information. public readonly AppleCommon.DInfo dirUsrInfo; /// Additional Finder information. public readonly AppleCommon.DXInfo dirFndrInfo; /// Reserved [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public readonly uint[] dirResrv; } /// File record [StructLayout(LayoutKind.Sequential, Pack = 1)] struct CdrFilRec { public readonly CatDataRec filHdr; /// File flags. public readonly sbyte filFlags; /// File type. public readonly sbyte filType; /// Finder information. public readonly AppleCommon.FInfo filUsrWds; /// File ID. public readonly uint filFlNum; /// First allocation block of data fork. public readonly ushort filStBlk; /// Logical EOF of data fork. public readonly uint filLgLen; /// Physical EOF of data fork. public readonly uint filPyLen; /// First allocation block of resource fork. public readonly ushort filRStBlk; /// Logical EOF of resource fork. public readonly uint filRLgLen; /// Physical EOF of resource fork. public readonly uint filRPyLen; /// Date and time of creation. public readonly uint filCrDat; /// Date and time of last modification. public readonly uint filMdDat; /// Date and time of last backup. public readonly uint filBkDat; /// Additional Finder information. public readonly AppleCommon.FXInfo filFndrInfo; /// File clump size. public readonly ushort filClpSize; /// First data fork extent record. public readonly ExtDataRec filExtRec; /// First resource fork extent record. public readonly ExtDataRec filRExtRec; /// Reserved public readonly uint filResrv; } /// Directory thread record [StructLayout(LayoutKind.Sequential, Pack = 1)] struct CdrThdRec { public readonly CatDataRec thdHdr; /// Reserved. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public readonly uint[] thdResrv; /// Parent ID for this directory. public readonly uint thdParID; /// Name of this directory. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public readonly byte[] thdCName; } /// File thread record [StructLayout(LayoutKind.Sequential, Pack = 1)] struct CdrFThdRec { public readonly CatDataRec fthdHdr; /// Reserved. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public readonly uint[] fthdResrv; /// Parent ID for this file. public readonly uint fthdParID; /// Name of this file. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] public readonly byte[] fthdCName; } /// Extent descriptor [StructLayout(LayoutKind.Sequential, Pack = 1)] struct ExtDescriptor { /// First allocation block public readonly ushort xdrStABN; /// Number of allocation blocks public readonly ushort xdrNumABlks; } /// Extent data record [StructLayout(LayoutKind.Sequential, Pack = 1)] struct ExtDataRec { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] public readonly ExtDescriptor[] xdr; } /// Extent key record [StructLayout(LayoutKind.Sequential, Pack = 1)] struct ExtKeyRec { /// Key length. public readonly sbyte xkrKeyLen; /// Fork type. public readonly ForkType xkrFkType; /// File number. public readonly uint xkrFNum; /// Starting file allocation block. public readonly ushort xkrFABN; } } }