HFS Plus
HFS Plus, also known as Mac OS Extended or HFS+, is a proprietary file system developed by Apple Inc. for its classic Mac OS and macOS operating systems, serving as the successor to the original Hierarchical File System (HFS). Introduced in 1998 with Mac OS 8.1, it was designed to address HFS limitations by enabling more efficient use of disk space on large hard drives through increased allocation blocks and reduced minimum file sizes, while supporting international-friendly file names up to 255 Unicode characters and future expansions like named forks and non-Mac OS booting.[1][2] The volume format of HFS Plus begins 1024 bytes from the start of the disk and includes a volume header, an alternate header for redundancy, and five special files: the catalog file (a B-tree storing file and folder records), extents overflow file (for tracking fragmented file extents beyond the initial eight), allocation file (a bitmap replacing HFS's volume bitmap to manage block usage), attributes file (reserved for future metadata and named forks), and startup file (for boot information compatibility).[1] Allocation blocks are powers of two starting at 512 bytes, with 4 KB recommended as the minimum for optimal performance on modern hardware, allowing theoretical volume sizes up to 8 exabytes and file sizes up to 8 exabytes via 32-bit allocation addressing and 64-bit length fields.[1] By default, HFS Plus is case-insensitive and case-preserving for file names, though the HFSX variant (introduced in 2003 with Mac OS X 10.3) supports case-sensitivity.[1] A journaled variant of HFS Plus, added in Mac OS X 10.2.2 (2002), incorporates journaling to log file system changes for faster crash recovery and enhanced data integrity, becoming the standard for macOS installations and Time Machine backups.[3][4] HFS Plus volumes are backward-compatible with HFS via wrappers but require Mac OS 8.1 or later for native support, and it remained the primary file system for macOS until Apple deprecated it in favor of the Apple File System (APFS) with macOS High Sierra (10.13) in 2017, citing needs for modern features like snapshots, encryption, and SSD optimization.[3][5] Despite its replacement, HFS Plus persists for compatibility with older macOS versions (up to 10.13 and later via Disk Utility) and external drives.[3]History and Development
Origins and Design Goals
In the mid-1990s, Apple initiated the development of HFS Plus as a successor to the original Hierarchical File System (HFS) to overcome its growing limitations in handling larger storage capacities and diverse character encodings. The original HFS, introduced in 1986, relied on 16-bit allocation blocks that restricted volumes to a practical maximum of around 2 gigabytes when using the smallest 512-byte block size, while file sizes were capped at 2 gigabytes due to 32-bit length fields.[1] This became increasingly inadequate as hard drive capacities expanded into the gigabyte range during the 1990s, prompting Apple to design a file system capable of supporting much larger volumes through 32-bit addressing, enabling theoretical limits of up to 8 exabytes per volume depending on allocation block size.[1] A primary design goal was to enhance internationalization support, replacing HFS's reliance on the 8-bit MacRoman encoding—which limited filenames to 31 characters and struggled with non-Latin scripts—with Unicode (specifically UTF-16) for filenames up to 255 characters in length.[1] This shift aimed to accommodate global users and emerging multilingual computing needs without sacrificing the hierarchical structure familiar to Macintosh users. Additionally, the design incorporated options for case-insensitive filename handling by default, while allowing case-sensitive modes to align with standards like POSIX for better interoperability with Unix-like systems, including support for POSIX-compliant date and time semantics in volume metadata.[1] Backward compatibility with existing HFS volumes was a core objective, ensuring that HFS Plus could mount and read HFS-formatted disks seamlessly while providing a migration path for users.[1] The overall goals emphasized efficient disk space utilization through variable allocation block sizes (starting at 512 bytes but scalable to 64 kilobytes or more), preparation for future features like named resource forks, and simplified booting for non-Mac OS environments.[1] These motivations reflected Apple's broader transition to PowerPC processors and preparations for enhanced operating system capabilities in the late 1990s.Release and Adoption
HFS Plus was introduced as part of Mac OS 8.1, released on January 19, 1998, marking Apple's first implementation of a 32-bit capable file system to address limitations in the original Hierarchical File System (HFS).[6] This update was provided as a free download for existing Mac OS 8 users, allowing retrofitting on compatible hardware including older Power Macintosh models.[7] The file system first shipped on production hardware with the Power Macintosh G3 series, which received the OS 8.1 update shortly after launch, and notably on the original iMac G3, which began shipping in August 1998 pre-installed with Mac OS 8.1 and HFS Plus as the default format.[8] By the release of Mac OS 9 in October 1999, HFS Plus had become the standard file system for all new Macintosh computers, solidifying its role within Apple's ecosystem as volumes grew larger and multi-gigabyte drives became common. Software updates continued to enable HFS Plus on legacy systems, ensuring broad compatibility across the PowerPC-based Mac lineup through the late 1990s. Initially supporting boot volumes up to 2 terabytes—a significant increase over HFS's 2-gigabyte limit—this capacity was later expanded to 8 terabytes with Mac OS X 10.2 in 2002.[1] HFS Plus saw further integration with the debut of Mac OS X on March 24, 2001, where it served as the core file system, enabling the transition to a Unix-based architecture while maintaining backward compatibility with classic Mac applications. A key enhancement came in November 2002 with the Mac OS X 10.2.2 update (part of the Jaguar release), which introduced optional journaling to HFS Plus volumes, improving data integrity by logging changes to prevent corruption during unexpected shutdowns without requiring reformatting.[9] Beyond desktops, HFS Plus powered early portable media devices, including the original iPod launched in October 2001 through the fifth-generation model in 2005, where it managed music libraries and storage on Mac-formatted units.[10]Technical Design
Volume and Allocation Structure
HFS Plus volumes are structured around a fixed layout that begins with boot blocks in sectors 0 and 1, followed by the volume header starting at sector 2 (offset 1024 bytes from the volume's start).[1] The volume header is a 512-byte structure containing essential metadata about the volume, including the creation date recorded as a 32-bit unsigned integer representing seconds since midnight on January 1, 1904, in local time.[1] It also specifies the allocation block size, which must be a power of 2 ranging from 512 bytes to at least 4 KB (the default), and up to 64 KB in practice for larger volumes, as well as the total number of allocation blocks, a 32-bit field allowing up to 2³² blocks.[1] The allocation file, one of the five special files in an HFS Plus volume, manages disk space using a simple bitmap where each bit corresponds to one allocation block, indicating whether it is free or in use.[1] This bitmap enables efficient tracking of available space across the volume. To handle file fragmentation, HFS Plus employs extent records, which describe contiguous ranges of allocation blocks; each file can have up to eight primary extents stored directly in its catalog entry, with additional extents recorded in the separate extents overflow file if needed.[1] In evolving from the original HFS, the Master Directory Block (MDB) has been replaced by the more scalable volume header, which supports 32-bit addressing for allocation blocks instead of the 16-bit limitations of HFS, allowing for vastly larger volumes.[1] An alternate volume header, a duplicate copy, is maintained 1024 bytes before the end of the volume to aid in recovery during crashes or inconsistencies in the primary header.[1] The number of allocation blocks in a volume is calculated as the total volume size divided by the allocation block size, with the maximum volume capacity reaching 2³² blocks multiplied by the block size—for example, approximately 16 terabytes when using the default 4 KB block size.[1]File and Directory Organization
HFS Plus organizes files and directories hierarchically using two primary B-tree files: the catalog file and the extents overflow file. The catalog file serves as the central index for all files and folders on the volume, storing their metadata and enabling efficient lookups and traversals of the directory structure. Each file and directory is assigned a unique 32-bit Catalog Node ID (CNID), which acts as a persistent identifier across the volume.[1] The catalog file is implemented as a B-tree with nodes typically sized at 4 KB (a power of 2 between 512 bytes and 32 KB), each containing a header, a series of records, and free space for insertions. Keys in the catalog B-tree consist of a parent CNID (UInt32) followed by the Unicode name of the file or folder (up to 255 characters), allowing ordered indexing by parent directory and name. Records within leaf nodes are of three main types: file records (HFSPlusCatalogFile), which include details such as creation and modification dates, permissions (via BSD attributes), and pointers to the file's data and resource forks; folder records (HFSPlusCatalogFolder), which mirror file records but denote directories with their own CNID and parent ID; and thread records (HFSPlusCatalogThread), which link a CNID back to its parent ID and name for reverse lookups. This structure supports up to approximately 4.3 billion CNIDs (2³²) per volume, with CNIDs ranging from 16 to 2³²-1 for files and folders, and thread records facilitating quick navigation from a CNID to its hierarchical position.[1]
Directories in HFS Plus are treated as special types of files, represented by folder records in the catalog B-tree, which include a subfolder count and the folder's CNID as its identifier. The hierarchy is maintained through parent-child relationships encoded in the keys and records, enabling recursive traversal without native support for symbolic links—though hard links to files are supported using indirect node files in a hidden directory, each with a unique CNID referencing the target file, tracked by a link count in the target file record. For files exceeding the primary allocation (up to eight extents per fork, each a contiguous range of up to 2^32 allocation blocks), the extents overflow file provides additional indexing. This file is another B-tree (with 1 KB or 4 KB nodes), keyed by file CNID, fork type (data or resource), and starting block number, with records containing arrays of eight HFSPlusExtentDescriptor entries, each specifying a start block and block count (both UInt32). Extents are placed using the volume's allocation bitmap for free space tracking.[1]
| Component | Key Structure | Record Details |
|---|---|---|
| Catalog B-tree Node | Header (14 bytes) + Records + Free Space | File/Folder: CNID, timestamps, permissions, fork extents (first 8); Thread: Parent CNID and name |
| Extents B-tree Key | File CNID (UInt32) + Fork Type (UInt8) + Start Block (UInt32) | 8 Extents: Start Block (UInt32) + Block Count (UInt32) per descriptor |
| CNID | Unique 32-bit ID (root directory CNID 2; user files/folders from 16 to 2³²-1) | Reusable if volume flag set; used for hard links via indirect node references and linkCount > 1 |
Features and Capabilities
Improvements over HFS
HFS Plus addressed several key limitations of the original Hierarchical File System (HFS) by enhancing scalability and supporting modern computing needs. One major improvement was in file size capacity: while HFS limited files to a maximum of 2 gigabytes (2³¹ bytes) due to its 16-bit extent addressing, HFS Plus expanded this to 8 exabytes (2⁶³ bytes) per data or resource fork through 32-bit allocation block addressing, with each fork supporting eight primary extents and additional extents tracked in the extents overflow file.[1] This change enabled handling of large media files and other data-intensive applications that were impractical under HFS.[1] Filename support saw significant upgrades for internationalization and usability. HFS restricted names to 31 bytes in MacRoman encoding, limiting compatibility with non-Latin scripts. In contrast, HFS Plus allowed up to 255 characters encoded in UTF-16, with mandatory decomposition normalization to Unicode Normalization Form D (NFD), ensuring consistent representation across languages and reducing collation issues in B-tree structures.[1] Additionally, HFS Plus introduced optional case handling that is case-insensitive by default but preserves the original case in storage, unlike HFS, which was strictly case-insensitive and did not preserve case distinctions.[1] A case-sensitive variant, HFSX, extended this flexibility starting in Mac OS X 10.3.[1] Journaling was added as an optional feature to HFS Plus in Mac OS X 10.2.2 (2002), creating the journaled variant for better data integrity. This employs a circular write-ahead log, typically sized from 1 MB to 512 MB, to record metadata transactions before committing them to the volume, allowing rapid recovery from crashes or power failures without full file system checks.[1] The journal file, named ".journal," operates independently of the main volume structure, minimizing downtime in server and desktop environments.[1]Extended Attributes and Metadata
HFS Plus retains the dual-fork architecture inherited from its predecessor HFS, where each file consists of a data fork for primary content and a resource fork for Macintosh-specific resources such as icons, menus, and dialog templates.[1] The data fork stores the main file payload, while the resource fork holds ancillary data that enables applications to access platform-specific elements without altering the core content.[1] Each fork is described by anHFSPlusForkData structure in the catalog file, supporting logical sizes up to 263 bytes and initial allocation of up to eight extents, with overflow handled by the extents B-tree for larger files.[1] This model allows for flexible storage of binary resources, though its usage has diminished with the shift toward cross-platform formats.
Extended attributes in HFS Plus provide a mechanism for associating named metadata with files and directories beyond the basic forks, stored in a dedicated attributes B-tree file.[1] These attributes, implemented starting with Mac OS X 10.4, use keys up to 255 UTF-16 characters in length, enabling the attachment of arbitrary key-value pairs for additional file information.[1] Each attribute can hold up to 263 bytes of data, similar to fork limits, and supports three record types: inline data for small values (up to the B-tree node size, typically 4 KB), fork data referencing extents for larger inline storage, and extension records for further extent overflow.[1] This structure allows for extensible, named storage of metadata without modifying the core file system records.
Core metadata fields in HFS Plus include the Finder information, a 32-byte array in each catalog record that tracks details such as icon positions, view settings, and flags like invisibility (bit 0x4000 in fileFlags).[1] Legacy type and creator codes, four-character OSType values in the FileInfo structure, identify file types and associated applications for classic Mac OS compatibility, though these have been largely superseded by UTI-based systems.[1] In the HFSX variant, which supports case-sensitive naming via a volume signature of 'HX' and version 5, basic permissions are managed through the HFSPlusBSDInfo structure with owner ID, group ID, and POSIX-style mode bits (e.g., read/write/execute).[1]
Access Control Lists (ACLs) in HFS Plus, introduced in Mac OS X 10.4, extend permissions beyond traditional UNIX modes by allowing fine-grained access rights for multiple users and groups, such as read-only access without deletion privileges.[11] These ACLs are stored as extended attributes with the key "com.apple.system.Security", enabling inheritance on directories and integration with file server share points in Mac OS X Server.[11] HFSX volumes fully support ACLs alongside case-sensitive operations, providing enhanced security for multi-user environments while maintaining backward compatibility with standard HFS Plus.[1]
For extended attributes exceeding inline capacity, HFS Plus employs an attribute runlist mechanism, where large data is allocated via extents recorded in the extents overflow file B-tree.[1] The HFSPlusAttrForkData record references up to eight primary extents, with additional blocks tracked through HFSPlusExtentKey entries keyed by file ID, attribute type, and starting block.[1] This runlist approach mirrors file fork allocation, ensuring efficient storage for voluminous metadata without fragmenting the attributes B-tree.
Code signing metadata in HFS Plus leverages extended attributes to secure non-Mach-O files, such as scripts and bundles, by embedding signatures that verify integrity and origin.[12] Attributes like those prefixed with "com.apple.cs" (e.g., CodeDirectory) store cryptographic hashes and certificates, preventing tampering during execution or transfer.[12] This integration enhances security for executable content, as the system checks these attributes before allowing code to run, though they can be lost if files are copied without preserving extended attributes.[12] Journaling, when enabled, protects these metadata updates against corruption.[1]
Limitations and Criticisms
Performance and Reliability Issues
HFS Plus employs a bitmap-based allocation system for managing free space on volumes, which can lead to external fragmentation over time, particularly on large volumes subjected to intensive write operations. As files are repeatedly created, modified, and deleted, free space becomes scattered into smaller, non-contiguous blocks, increasing seek times and degrading access performance for subsequent reads and writes. This issue is exacerbated on volumes with many large files and limited free space, where the allocator struggles to find sufficiently contiguous blocks for new allocations. HFS+ includes mechanisms, such as online defragmentation for small files, to mitigate fragmentation. The journaling feature in HFS Plus, introduced in Mac OS X 10.2.2 in 2002 and optional in early versions, introduces a modest performance overhead during write operations to ensure data integrity. By logging metadata changes before committing them to the main file system structures, journaling adds latency to writes—typically a small but measurable increase due to the additional I/O required for journal updates—while enabling faster recovery after crashes or power failures. Without journaling enabled in early implementations, sudden power interruptions could result in inconsistent file system metadata, leading to potential data loss or corruption upon restart, as the system lacked mechanisms to replay uncommitted transactions.[1][13] Benchmark tests demonstrate that HFS Plus achieves respectable sequential read speeds, often reaching up to 149 MB/s on mechanical hard drives, making it suitable for large file transfers. However, its performance in random I/O scenarios lags behind contemporaries like NTFS, where fragmented access patterns amplify seek latencies on spinning disks, resulting in noticeably slower operations for workloads involving many small, scattered files. Additionally, HFS Plus lacked native support for TRIM commands—essential for maintaining SSD performance by informing the drive of unused blocks—until macOS 10.10.4 Yosemite in 2015, after which users could enable it via thetrimforce utility; prior to this, SSDs formatted with HFS Plus experienced gradual write amplification and reduced longevity without manual intervention.[14]
Early deployments of HFS Plus in Mac OS X, particularly before widespread journaling adoption around 2002, were prone to file system corruption from power failures, as unclean shutdowns could leave the volume in an inconsistent state requiring extensive repairs. Such incidents were common in real-world usage, often manifesting as unmountable volumes or lost files, and were addressed through the fsck_hfs utility, which scans and repairs inconsistencies in HFS Plus structures like B-trees and the extent file. This tool, integrated into macOS's boot process and Disk Utility, rebuilds damaged catalog entries and orphans files to a lost+found directory, mitigating but not eliminating the risks inherent to non-journaled volumes.[1][15]
Security and Compatibility Concerns
HFS Plus lacks built-in encryption capabilities, leaving unencrypted volumes in plaintext format and susceptible to offline attacks where physical access to the storage media allows unauthorized data extraction without needing system credentials.[1] To address this, Apple introduced FileVault in Mac OS X 10.3 Panther in 2003, which provides encryption for the user's home directory via a sparse disk image formatted with HFS Plus Journaled, using AES-128; however, this operates as an overlay rather than native file system encryption, requiring manual enablement and applying only to specific directories.[16] The permissions model in HFS Plus adopts a basic Unix-style (BSD-derived) structure, storing owner ID, group ID, and mode bits (such as read/write/execute for user, group, and others) in the catalog file's HFSPlusBSDInfo records to enforce access control.[1] For interoperability with non-Mac systems lacking native HFS Plus support, resource forks—used for additional metadata like application resources—are exported in the legacy AppleDouble format, creating sidecar files prefixed with "._"; improper handling of these files on foreign platforms, such as deletion during copies, can result in permanent loss of resource fork data.[1] A key compatibility challenge stems from HFS Plus's default case-insensitive file naming, where filenames differing only in case (e.g., "File.txt" and "file.txt") are treated as identical, potentially leading to collisions and data overwrites in environments expecting case-sensitive behavior, such as POSIX-compliant systems or cross-platform development.[1] Native support for POSIX Access Control Lists (ACLs) was added in Mac OS X 10.4 Tiger in 2005, using extended attributes for finer-grained permissions; the HFSX variant, introduced in 2003 with Mac OS X 10.3, supports case-sensitivity but is separate from ACL implementation.[1] HFS Plus volumes formatted under OS X are often unmountable on pre-OS X (Classic Mac OS) systems without conversion to the older HFS format, as native support began only with Mac OS 8.1 in 1998, and earlier versions like 8.0 or 7.x require third-party extensions or backports for readability. Journaled volumes require disabling journaling for compatibility with classic systems.[17]Cross-Platform Support
Linux Implementation
The Linux kernel provides support for HFS+ volumes through thehfsplus module, which enables mounting and basic file operations on these filesystems. As of 2025, the driver has been unmaintained since 2014, with a proposal for removal considered earlier in the year; recent security vulnerabilities highlight ongoing risks.[18] Initial read-only support for HFS+ was integrated into Linux 2.4 kernels around 2001, particularly in PowerPC configurations, allowing users to access Macintosh-formatted partitions without modification. Full read/write capabilities were added in Linux 2.6.4 (released in January 2004) via patches from developer Roman Zippel, building on an earlier out-of-tree read-only driver by Brad Boyer; this implementation includes awareness of HFS+ journaling, mounting journaled volumes as read-only by default to avoid risks, though a force mount option permits writes at the user's peril.[19][20][21]
User-space tools for managing HFS+ filesystems are available in the hfsprogs package, a port of Apple's Darwin utilities, which includes mkfs.hfsplus for formatting new volumes and fsck.hfsplus (also invoked as fsck.hfs) for checking and repairing filesystem integrity. These tools support the creation of HFS+ volumes with configurable block sizes and handle name encoding by converting between UTF-8 (used in Linux) and UTF-16 (native to HFS+), but they issue warnings about HFS+'s default case-insensitive and case-preserving behavior, which can lead to unexpected file conflicts on case-sensitive systems.[22][23]
Despite these features, Linux's HFS+ implementation has notable limitations. Extended attributes, used in HFS+ for metadata like resource forks and security descriptors, received improved support starting with kernel 3.9 in 2013 through reworked functions for getting, setting, and deleting them, though full compatibility with Apple-specific attributes remains partial; earlier kernels offered only basic or no xattr handling. Writes from Linux can risk filesystem corruption, particularly with resource forks (often stored as hidden files or xattrs) and journaled volumes, as the driver does not fully replicate Apple's proprietary handling of forks and metadata updates. Recent vulnerabilities, such as those reported in 2025 (e.g., heap overflows), further emphasize the risks of corruption and security issues.[24][23][25]
In practice, Linux HFS+ support facilitates dual-boot environments alongside macOS, where users share data across partitions, and enables reading Time Machine backups created on macOS without needing Apple hardware. Major distributions like Debian and Ubuntu have included the hfsplus kernel module and hfsprogs package by default since approximately 2006, making it readily available for such cross-platform workflows.[26]