Each APFS file system entry has both an inode and directory record. The inode record stores metadata such as the entry’s timestamps, ownership, type, and permissions (among others). Directory records store information about where the entry is stored within the file system’s hierarchy. A single inode may be referenced by more than one directory record, meaning the same file or folder may be present at multiple paths in the file system, as is the case with hard links.
Each APFS volume has a logical file system stored on disk as a collection of File System Objects. Unlike other APFS Objects, File System Objects consist of one or more File System Records, which are stored in the volume’s File System Tree (FS-Tree). Each record stores specific information about a file or directory. Analyzing each record and associating them with other records with the same identifier gives a complete picture of the file system entry. This post will discuss how these records are organized in the volume’s FS-Tree.
In this blog post, we will explore the Volume Superblock in APFS, a critical data structure containing important information about an individual APFS volume. We will discuss locating the Volume Superblock on disk and describe some fields in the on-disk format. By the end of this post, you should better understand the volume Superblock’s role in the APFS file system and how to parse its on-disk structure.
Earlier in this series, we discussed APFS Containers and how they address physical objects via a fixed block size. This was followed up with a discussion on enumerating Checkpoint Maps to locate ephemeral objects. The last remaining kind of objects that we need to know how to find are virtual objects. Today, we will discuss an essential specialization of B-Trees, the Object Map (OMAP), and their critical role in managing these virtual objects in APFS.
Mastering the skill of B-Tree traversal is essential in parsing information from APFS. Our last post gave an overview of APFS B-Trees, their layout, and on-disk node structures. Today, we will discuss applying that knowledge to perform enumeration and fast lookups of referenced objects.