/* File: HFSVolumes.h Contains: On-disk data structures for HFS and HFS Plus volumes. Version: QuickTime 7.3 Copyright: (c) 2007 (c) 1984-2001 by Apple Computer, Inc. All rights reserved. Bugs?: For bug reports, consult the following page on the World Wide Web: http://developer.apple.com/bugreporter/ */ #ifndef __HFSVOLUMES__ #define __HFSVOLUMES__ #ifndef __MACTYPES__ #include #endif #ifndef __FILES__ #include #endif #ifndef __FINDER__ #include #endif #if PRAGMA_ONCE #pragma once #endif #if PRAGMA_IMPORT #pragma import on #endif #if PRAGMA_STRUCT_ALIGN #pragma options align=mac68k #elif PRAGMA_STRUCT_PACKPUSH #pragma pack(push, 2) #elif PRAGMA_STRUCT_PACK #pragma pack(2) #endif /* Signatures used to differentiate between HFS and HFS Plus volumes */ enum { kHFSSigWord = 0x4244, /* 'BD' in ASCII */ kHFSPlusSigWord = 0x482B, /* 'H+' in ASCII */ kHFSPlusVersion = 0x0004, /* will change as format changes (version 4 shipped with Mac OS 8.1) */ kHFSPlusMountVersion = FOUR_CHAR_CODE('8.10') /* will change as implementations change ('8.10' in Mac OS 8.1) */ }; /* CatalogNodeID is used to track catalog objects */ typedef UInt32 HFSCatalogNodeID; enum { kHFSMaxVolumeNameChars = 27, kHFSMaxFileNameChars = 31, kHFSPlusMaxFileNameChars = 255 }; /* Extent overflow file data structures */ /* HFS Extent key */ struct HFSExtentKey { UInt8 keyLength; /* length of key, excluding this field */ UInt8 forkType; /* 0 = data fork, FF = resource fork */ HFSCatalogNodeID fileID; /* file ID */ UInt16 startBlock; /* first file allocation block number in this extent */ }; typedef struct HFSExtentKey HFSExtentKey; /* HFS Plus Extent key */ struct HFSPlusExtentKey { UInt16 keyLength; /* length of key, excluding this field */ UInt8 forkType; /* 0 = data fork, FF = resource fork */ UInt8 pad; /* make the other fields align on 32-bit boundary */ HFSCatalogNodeID fileID; /* file ID */ UInt32 startBlock; /* first file allocation block number in this extent */ }; typedef struct HFSPlusExtentKey HFSPlusExtentKey; /* Number of extent descriptors per extent record */ enum { kHFSExtentDensity = 3, kHFSPlusExtentDensity = 8 }; /* HFS extent descriptor */ struct HFSExtentDescriptor { UInt16 startBlock; /* first allocation block */ UInt16 blockCount; /* number of allocation blocks */ }; typedef struct HFSExtentDescriptor HFSExtentDescriptor; /* HFS Plus extent descriptor */ struct HFSPlusExtentDescriptor { UInt32 startBlock; /* first allocation block */ UInt32 blockCount; /* number of allocation blocks */ }; typedef struct HFSPlusExtentDescriptor HFSPlusExtentDescriptor; /* HFS extent record */ typedef HFSExtentDescriptor HFSExtentRecord[3]; /* HFS Plus extent record */ typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[8]; /* Fork data info (HFS Plus only) - 80 bytes */ struct HFSPlusForkData { UInt64 logicalSize; /* fork's logical size in bytes */ UInt32 clumpSize; /* fork's clump size in bytes */ UInt32 totalBlocks; /* total blocks used by this fork */ HFSPlusExtentRecord extents; /* initial set of extents */ }; typedef struct HFSPlusForkData HFSPlusForkData; /* Permissions info (HFS Plus only) - 16 bytes */ struct HFSPlusPermissions { UInt32 ownerID; /* user or group ID of file/folder owner */ UInt32 groupID; /* additional user of group ID */ UInt32 permissions; /* permissions (bytes: unused, owner, group, everyone) */ UInt32 specialDevice; /* UNIX: device for character or block special file */ }; typedef struct HFSPlusPermissions HFSPlusPermissions; /* Catalog file data structures */ enum { kHFSRootParentID = 1, /* Parent ID of the root folder */ kHFSRootFolderID = 2, /* Folder ID of the root folder */ kHFSExtentsFileID = 3, /* File ID of the extents file */ kHFSCatalogFileID = 4, /* File ID of the catalog file */ kHFSBadBlockFileID = 5, /* File ID of the bad allocation block file */ kHFSAllocationFileID = 6, /* File ID of the allocation file (HFS Plus only) */ kHFSStartupFileID = 7, /* File ID of the startup file (HFS Plus only) */ kHFSAttributesFileID = 8, /* File ID of the attribute file (HFS Plus only) */ kHFSBogusExtentFileID = 15, /* Used for exchanging extents in extents file */ kHFSFirstUserCatalogNodeID = 16 }; /* HFS catalog key */ struct HFSCatalogKey { UInt8 keyLength; /* key length (in bytes) */ UInt8 reserved; /* reserved (set to zero) */ HFSCatalogNodeID parentID; /* parent folder ID */ Str31 nodeName; /* catalog node name */ }; typedef struct HFSCatalogKey HFSCatalogKey; /* HFS Plus catalog key */ struct HFSPlusCatalogKey { UInt16 keyLength; /* key length (in bytes) */ HFSCatalogNodeID parentID; /* parent folder ID */ HFSUniStr255 nodeName; /* catalog node name */ }; typedef struct HFSPlusCatalogKey HFSPlusCatalogKey; /* Catalog record types */ enum { /* HFS Catalog Records */ kHFSFolderRecord = 0x0100, /* Folder record */ kHFSFileRecord = 0x0200, /* File record */ kHFSFolderThreadRecord = 0x0300, /* Folder thread record */ kHFSFileThreadRecord = 0x0400, /* File thread record */ /* HFS Plus Catalog Records */ kHFSPlusFolderRecord = 1, /* Folder record */ kHFSPlusFileRecord = 2, /* File record */ kHFSPlusFolderThreadRecord = 3, /* Folder thread record */ kHFSPlusFileThreadRecord = 4 /* File thread record */ }; /* Catalog file record flags */ enum { kHFSFileLockedBit = 0x0000, /* file is locked and cannot be written to */ kHFSFileLockedMask = 0x0001, kHFSThreadExistsBit = 0x0001, /* a file thread record exists for this file */ kHFSThreadExistsMask = 0x0002 }; /* HFS catalog folder record - 70 bytes */ struct HFSCatalogFolder { SInt16 recordType; /* record type */ UInt16 flags; /* folder flags */ UInt16 valence; /* folder valence */ HFSCatalogNodeID folderID; /* folder ID */ UInt32 createDate; /* date and time of creation */ UInt32 modifyDate; /* date and time of last modification */ UInt32 backupDate; /* date and time of last backup */ DInfo userInfo; /* Finder information */ DXInfo finderInfo; /* additional Finder information */ UInt32 reserved[4]; /* reserved - set to zero */ }; typedef struct HFSCatalogFolder HFSCatalogFolder; /* HFS Plus catalog folder record - 88 bytes */ struct HFSPlusCatalogFolder { SInt16 recordType; /* record type = HFS Plus folder record */ UInt16 flags; /* file flags */ UInt32 valence; /* folder's valence (limited to 2^16 in Mac OS) */ HFSCatalogNodeID folderID; /* folder ID */ UInt32 createDate; /* date and time of creation */ UInt32 contentModDate; /* date and time of last content modification */ UInt32 attributeModDate; /* date and time of last attribute modification */ UInt32 accessDate; /* date and time of last access (Rhapsody only) */ UInt32 backupDate; /* date and time of last backup */ HFSPlusPermissions permissions; /* permissions (for Rhapsody) */ DInfo userInfo; /* Finder information */ DXInfo finderInfo; /* additional Finder information */ UInt32 textEncoding; /* hint for name conversions */ UInt32 reserved; /* reserved - set to zero */ }; typedef struct HFSPlusCatalogFolder HFSPlusCatalogFolder; /* HFS catalog file record - 102 bytes */ struct HFSCatalogFile { SInt16 recordType; /* record type */ UInt8 flags; /* file flags */ SInt8 fileType; /* file type (unused ?) */ FInfo userInfo; /* Finder information */ HFSCatalogNodeID fileID; /* file ID */ UInt16 dataStartBlock; /* not used - set to zero */ SInt32 dataLogicalSize; /* logical EOF of data fork */ SInt32 dataPhysicalSize; /* physical EOF of data fork */ UInt16 rsrcStartBlock; /* not used - set to zero */ SInt32 rsrcLogicalSize; /* logical EOF of resource fork */ SInt32 rsrcPhysicalSize; /* physical EOF of resource fork */ UInt32 createDate; /* date and time of creation */ UInt32 modifyDate; /* date and time of last modification */ UInt32 backupDate; /* date and time of last backup */ FXInfo finderInfo; /* additional Finder information */ UInt16 clumpSize; /* file clump size (not used) */ HFSExtentRecord dataExtents; /* first data fork extent record */ HFSExtentRecord rsrcExtents; /* first resource fork extent record */ UInt32 reserved; /* reserved - set to zero */ }; typedef struct HFSCatalogFile HFSCatalogFile; /* HFS Plus catalog file record - 248 bytes */ struct HFSPlusCatalogFile { SInt16 recordType; /* record type = HFS Plus file record */ UInt16 flags; /* file flags */ UInt32 reserved1; /* reserved - set to zero */ HFSCatalogNodeID fileID; /* file ID */ UInt32 createDate; /* date and time of creation */ UInt32 contentModDate; /* date and time of last content modification */ UInt32 attributeModDate; /* date and time of last attribute modification */ UInt32 accessDate; /* date and time of last access (Rhapsody only) */ UInt32 backupDate; /* date and time of last backup */ HFSPlusPermissions permissions; /* permissions (for Rhapsody) */ FInfo userInfo; /* Finder information */ FXInfo finderInfo; /* additional Finder information */ UInt32 textEncoding; /* hint for name conversions */ UInt32 reserved2; /* reserved - set to zero */ /* start on double long (64 bit) boundry */ HFSPlusForkData dataFork; /* size and block data for data fork */ HFSPlusForkData resourceFork; /* size and block data for resource fork */ }; typedef struct HFSPlusCatalogFile HFSPlusCatalogFile; /* HFS catalog thread record - 46 bytes */ struct HFSCatalogThread { SInt16 recordType; /* record type */ SInt32 reserved[2]; /* reserved - set to zero */ HFSCatalogNodeID parentID; /* parent ID for this catalog node */ Str31 nodeName; /* name of this catalog node */ }; typedef struct HFSCatalogThread HFSCatalogThread; /* HFS Plus catalog thread record -- 264 bytes */ struct HFSPlusCatalogThread { SInt16 recordType; /* record type */ SInt16 reserved; /* reserved - set to zero */ HFSCatalogNodeID parentID; /* parent ID for this catalog node */ HFSUniStr255 nodeName; /* name of this catalog node (variable length) */ }; typedef struct HFSPlusCatalogThread HFSPlusCatalogThread; /* These are the types of records in the attribute B-tree. The values were chosen so that they wouldn't conflict with the catalog record types. */ enum { kHFSPlusAttrInlineData = 0x10, /* if size < kAttrOverflowSize */ kHFSPlusAttrForkData = 0x20, /* if size >= kAttrOverflowSize */ kHFSPlusAttrExtents = 0x30 /* overflow extents for large attributes */ }; /* HFSPlusAttrInlineData For small attributes, whose entire value is stored within this one B-tree record. There would not be any other records for this attribute. */ struct HFSPlusAttrInlineData { UInt32 recordType; /* = kHFSPlusAttrInlineData*/ UInt32 reserved; UInt32 logicalSize; /* size in bytes of userData*/ UInt8 userData[2]; /* variable length; space allocated is a multiple of 2 bytes*/ }; typedef struct HFSPlusAttrInlineData HFSPlusAttrInlineData; /* HFSPlusAttrForkData For larger attributes, whose value is stored in allocation blocks. If the attribute has more than 8 extents, there will be additonal records (of type HFSPlusAttrExtents) for this attribute. */ struct HFSPlusAttrForkData { UInt32 recordType; /* = kHFSPlusAttrForkData*/ UInt32 reserved; HFSPlusForkData theFork; /* size and first extents of value*/ }; typedef struct HFSPlusAttrForkData HFSPlusAttrForkData; /* HFSPlusAttrExtents This record contains information about overflow extents for large, fragmented attributes. */ struct HFSPlusAttrExtents { UInt32 recordType; /* = kHFSPlusAttrExtents*/ UInt32 reserved; HFSPlusExtentRecord extents; /* additional extents*/ }; typedef struct HFSPlusAttrExtents HFSPlusAttrExtents; /* A generic Attribute Record*/ union HFSPlusAttrRecord { UInt32 recordType; HFSPlusAttrInlineData inlineData; HFSPlusAttrForkData forkData; HFSPlusAttrExtents overflowExtents; }; typedef union HFSPlusAttrRecord HFSPlusAttrRecord; /* Key and node lengths */ enum { kHFSPlusExtentKeyMaximumLength = sizeof(HFSPlusExtentKey) - sizeof(UInt16), kHFSExtentKeyMaximumLength = sizeof(HFSExtentKey) - sizeof(UInt8), kHFSPlusCatalogKeyMaximumLength = sizeof(HFSPlusCatalogKey) - sizeof(UInt16), kHFSPlusCatalogKeyMinimumLength = kHFSPlusCatalogKeyMaximumLength - sizeof(HFSUniStr255) + sizeof(UInt16), kHFSCatalogKeyMaximumLength = sizeof(HFSCatalogKey) - sizeof(UInt8), kHFSCatalogKeyMinimumLength = kHFSCatalogKeyMaximumLength - sizeof(Str31) + sizeof(UInt8), kHFSPlusCatalogMinNodeSize = 4096, kHFSPlusExtentMinNodeSize = 512, kHFSPlusAttrMinNodeSize = 4096 }; /* HFS and HFS Plus volume attribute bits */ enum { /* Bits 0-6 are reserved (always cleared by MountVol call) */ kHFSVolumeHardwareLockBit = 7, /* volume is locked by hardware */ kHFSVolumeUnmountedBit = 8, /* volume was successfully unmounted */ kHFSVolumeSparedBlocksBit = 9, /* volume has bad blocks spared */ kHFSVolumeNoCacheRequiredBit = 10, /* don't cache volume blocks (i.e. RAM or ROM disk) */ kHFSBootVolumeInconsistentBit = 11, /* boot volume is inconsistent (System 7.6 and later) */ /* Bits 12-14 are reserved for future use */ kHFSVolumeSoftwareLockBit = 15, /* volume is locked by software */ kHFSVolumeHardwareLockMask = 1 << kHFSVolumeHardwareLockBit, kHFSVolumeUnmountedMask = 1 << kHFSVolumeUnmountedBit, kHFSVolumeSparedBlocksMask = 1 << kHFSVolumeSparedBlocksBit, kHFSVolumeNoCacheRequiredMask = 1 << kHFSVolumeNoCacheRequiredBit, kHFSBootVolumeInconsistentMask = 1 << kHFSBootVolumeInconsistentBit, kHFSVolumeSoftwareLockMask = 1 << kHFSVolumeSoftwareLockBit, kHFSMDBAttributesMask = 0x8380 }; /* Master Directory Block (HFS only) - 162 bytes */ /* Stored at sector #2 (3rd sector) */ struct HFSMasterDirectoryBlock { /* These first fields are also used by MFS */ UInt16 drSigWord; /* volume signature */ UInt32 drCrDate; /* date and time of volume creation */ UInt32 drLsMod; /* date and time of last modification */ UInt16 drAtrb; /* volume attributes */ UInt16 drNmFls; /* number of files in root folder */ UInt16 drVBMSt; /* first block of volume bitmap */ UInt16 drAllocPtr; /* start of next allocation search */ UInt16 drNmAlBlks; /* number of allocation blocks in volume */ UInt32 drAlBlkSiz; /* size (in bytes) of allocation blocks */ UInt32 drClpSiz; /* default clump size */ UInt16 drAlBlSt; /* first allocation block in volume */ UInt32 drNxtCNID; /* next unused catalog node ID */ UInt16 drFreeBks; /* number of unused allocation blocks */ Str27 drVN; /* volume name */ /* Master Directory Block extensions for HFS */ UInt32 drVolBkUp; /* date and time of last backup */ UInt16 drVSeqNum; /* volume backup sequence number */ UInt32 drWrCnt; /* volume write count */ UInt32 drXTClpSiz; /* clump size for extents overflow file */ UInt32 drCTClpSiz; /* clump size for catalog file */ UInt16 drNmRtDirs; /* number of directories in root folder */ UInt32 drFilCnt; /* number of files in volume */ UInt32 drDirCnt; /* number of directories in volume */ SInt32 drFndrInfo[8]; /* information used by the Finder */ UInt16 drEmbedSigWord; /* embedded volume signature (formerly drVCSize) */ HFSExtentDescriptor drEmbedExtent; /* embedded volume location and size (formerly drVBMCSize and drCtlCSize) */ UInt32 drXTFlSize; /* size of extents overflow file */ HFSExtentRecord drXTExtRec; /* extent record for extents overflow file */ UInt32 drCTFlSize; /* size of catalog file */ HFSExtentRecord drCTExtRec; /* extent record for catalog file */ }; typedef struct HFSMasterDirectoryBlock HFSMasterDirectoryBlock; /* HFSPlusVolumeHeader (HFS Plus only) - 512 bytes */ /* Stored at sector #2 (3rd sector) and second-to-last sector. */ struct HFSPlusVolumeHeader { UInt16 signature; /* volume signature == 'H+' */ UInt16 version; /* current version is kHFSPlusVersion */ UInt32 attributes; /* volume attributes */ UInt32 lastMountedVersion; /* implementation version which last mounted volume */ UInt32 reserved; /* reserved - set to zero */ UInt32 createDate; /* date and time of volume creation */ UInt32 modifyDate; /* date and time of last modification */ UInt32 backupDate; /* date and time of last backup */ UInt32 checkedDate; /* date and time of last disk check */ UInt32 fileCount; /* number of files in volume */ UInt32 folderCount; /* number of directories in volume */ UInt32 blockSize; /* size (in bytes) of allocation blocks */ UInt32 totalBlocks; /* number of allocation blocks in volume (includes this header and VBM*/ UInt32 freeBlocks; /* number of unused allocation blocks */ UInt32 nextAllocation; /* start of next allocation search */ UInt32 rsrcClumpSize; /* default resource fork clump size */ UInt32 dataClumpSize; /* default data fork clump size */ HFSCatalogNodeID nextCatalogID; /* next unused catalog node ID */ UInt32 writeCount; /* volume write count */ UInt64 encodingsBitmap; /* which encodings have been use on this volume */ UInt8 finderInfo[32]; /* information used by the Finder */ HFSPlusForkData allocationFile; /* allocation bitmap file */ HFSPlusForkData extentsFile; /* extents B-tree file */ HFSPlusForkData catalogFile; /* catalog B-tree file */ HFSPlusForkData attributesFile; /* extended attributes B-tree file */ HFSPlusForkData startupFile; /* boot file */ }; typedef struct HFSPlusVolumeHeader HFSPlusVolumeHeader; /* ---------- HFS and HFS Plus B-tree structures ---------- */ /* BTNodeDescriptor -- Every B-tree node starts with these fields. */ struct BTNodeDescriptor { UInt32 fLink; /* next node at this level*/ UInt32 bLink; /* previous node at this level*/ SInt8 kind; /* kind of node (leaf, index, header, map)*/ UInt8 height; /* zero for header, map; child is one more than parent*/ UInt16 numRecords; /* number of records in this node*/ UInt16 reserved; /* reserved; set to zero*/ }; typedef struct BTNodeDescriptor BTNodeDescriptor; /* Constants for BTNodeDescriptor kind */ enum { kBTLeafNode = -1, kBTIndexNode = 0, kBTHeaderNode = 1, kBTMapNode = 2 }; /* BTHeaderRec -- The first record of a B-tree header node */ struct BTHeaderRec { UInt16 treeDepth; /* maximum height (usually leaf nodes)*/ UInt32 rootNode; /* node number of root node*/ UInt32 leafRecords; /* number of leaf records in all leaf nodes*/ UInt32 firstLeafNode; /* node number of first leaf node*/ UInt32 lastLeafNode; /* node number of last leaf node*/ UInt16 nodeSize; /* size of a node, in bytes*/ UInt16 maxKeyLength; /* reserved*/ UInt32 totalNodes; /* total number of nodes in tree*/ UInt32 freeNodes; /* number of unused (free) nodes in tree*/ UInt16 reserved1; /* unused*/ UInt32 clumpSize; /* reserved*/ UInt8 btreeType; /* reserved*/ UInt8 reserved2; /* reserved*/ UInt32 attributes; /* persistent attributes about the tree*/ UInt32 reserved3[16]; /* reserved*/ }; typedef struct BTHeaderRec BTHeaderRec; /* Constants for BTHeaderRec attributes */ enum { kBTBadCloseMask = 0x00000001, /* reserved*/ kBTBigKeysMask = 0x00000002, /* key length field is 16 bits*/ kBTVariableIndexKeysMask = 0x00000004 /* keys in index nodes are variable length*/ }; #if PRAGMA_STRUCT_ALIGN #pragma options align=reset #elif PRAGMA_STRUCT_PACKPUSH #pragma pack(pop) #elif PRAGMA_STRUCT_PACK #pragma pack() #endif #ifdef PRAGMA_IMPORT_OFF #pragma import off #elif PRAGMA_IMPORT #pragma import reset #endif #endif /* __HFSVOLUMES__ */