Алгоритм восстановления данных APFS и структура файловой системы

«ApFS» предлагает возможность восстановления определенных состояний файловой системы, включая старые или удаленные версии файлов. Суперблок контейнера содержит ссылку на структуру контрольной точки. Контрольная точка ссылается на предыдущий суперблок контейнера, который содержит информацию в более старом состоянии файловой системы. Таким образом, можно восстановить несколько старых состояний путем анализа цепочки суперблока контейнера.

Алгоритм восстановления данных APFS и структура файловой системы

Перейти к просмотру
Топ программ для восстановления данных с APFS диска или как восстановить Apple MacOs диск в Windows

Топ программ для восстановления данных с APFS диска или как восстановить Apple MacOs диск в Windows

Контейнеры и Тома

Структура файловой системы APFS имеет вид b-дерева, где корневой каталог с данными — это листья этого дерева. Все ветви хранят лишь ссылки на следующий узел пока не дойдут до листьев. Файловая система использует контейнеры в качестве ячеек хранения. Эти контейнера могут содержать несколько томов. Также он является основным объектом для хранения данных. Для одного тома размер контейнера должен быть более 512 МБ, для двух томов – более 1024Мб и т.д.

На рисунке ниже представлена структура файловой системы «ApFS».

ApFS

Каждый элемент этой структуры (кроме файла распределения) начинается с 32-байтового заголовка блока, который содержит некоторую общую информацию о блоке. Далее следует тело файловой системы. Оно состоит из следующих элементов:

  • 0x01: Суперблок контейнера (Container Superblock)
  • 0x02: Узел (Node)
  • 0x05: Менеджер пространства (Space manager)
  • 0x07: Файл размещения (Allocation Info File)
  • 0x0C: Контрольная точка (Checkpoint)
  • 0x0D: Суперблок тома (Volume Superblock)

Контейнеры обычно точно такие же, как записи в таблице разделов GUID (GPT). У них есть собственная защита от сбоев и схема распределения дискового пространства. Каждый контейнер содержит один или несколько томов, каждый из которых имеет собственное пространство имен, набор файлов и каталогов.

Файловая система «ApFS» не поддерживает напрямую программный «RAID», но его можно использовать с томами Apple RAID для поддержки чередования (RAID 0), зеркалирования (RAID 1) и склейки (JBOD).

С 64-битным индексом тома «ApFS» поддерживают до 9 квинтиллионов (1018) файлов.

Новая файловая система от Apple использует наносекунды для установки меток времени. В HFS + метки времени были установлены с точностью до секунды. Это уменьшит количество сбоев при передаче данных и других файловых операциях.

«ApFS» имеет встроенную систему шифрования и использует системы AES-XTS или AES-CBC, в зависимости от устройства. Пользователь может использовать несколько ключей шифрования для обеспечения безопасности данных даже в случае «физического взлома» носителя.

Это далеко не полный список нововведений, которыми обладает «ApFS».

Разделы, отформатированные в «ApFS», не распознаются OS X 10.11 Yosemite и более ранними версиями операционной системы.

Block Header (Заголовок блока)

Каждая структура файловой системы в «ApFS» начинается с заголовка блока. А сам заголовок начинается с контрольной суммы. Другая информация в заголовке включает в себя версию блока с копией при записи, идентификатор блока и его тип.

Смещение Размер Тип ID
0 8 uint64 Контрольная сумма (checksum)
8 8 uint64 Идентификатор (block_id)
16 8 uint64 Версия (version)
24 2 uint16 Тип блока (block_type)
26 2 uint16 Флаги (flags)
28 4 uint32 Отступ (padding)

Из таблицы мы видим, что 1uint = 1 бит, 8 бит = 1 байту, из этого uint64 = 8, uint32 = 4, и uint16 = 2 байтам.

Container Superblock

Суперблок контейнера (Container Superblock) – это входная точка в файловую систему. Из-за структуры файловой системы с контейнерами и гибкими томами, распределение необходимо обрабатывать на уровне контейнера. Суперблок контейнера содержит информацию о размере блока, их количестве и указателях в менеджере пространства для этой задачи. Кроме того, в суперблоке хранятся идентификаторы (ID) блоков всех томов. Для сопоставления идентификаторов блоков блокам смещения, сохраняется указатель на карту блоков B-дерева. Это дерево содержит записи для каждого тома с его идентификатором и смещением. Суперблок контейнера – это самый высокий уровень файловой системы.

Он имеет следующий вид:

Смещение (HEX) Тип Id Описание
0 tApFS_COH Header Заголовок объекта-контейнера (Container Object Header)
20 uint32 MagicNumber (NXSB) Значение для проверки чтения Суперблока контейнера.
24 uint32 BlockSize Размер блока контейнера (в байтах)
28 uint64 BlocksCount Количество контейнерных блоков
30 uint64 Features Карта (bitmap) основных функций контейнера
38 uint64 ReadOnlyFeatures Карта (bitmap) базовых функций контейнера (только для чтения)
40 uint64 IncompatibleFeatures Карта (bitmap) основных несовместимых функций контейнера
48 tApFS_Uuid Uuid UUID контейнера
58 tApFS_Ident NextIdent Следующий идентификатор для нового логического или виртуального объекта
60 tApFS_Transaction NextTransaction Номер следующей транзакции
68 uint32 DescriptorBlocks Количество блоков, используемых дескриптором
6C uint32 DataBlocks Количество блоков, используемых данными
70 tApFS_Address DescriptorBase Базовый адрес дескриптора или идентификатор физического объекта с деревом адресо
78 int32 DataBase Адрес базы данных или идентификатор физического объекта с адресным деревом
80 uint32 DescriptorNext Индекс следующего дескриптора
84 uint32 DataNext Следующий индекс данных
88 uint32 DescriptorIndex Индекс первого действительного элемента в сегменте дескриптора
8C uint32 DescriptorLength Количество блоков в сегменте дескриптора, используемого суперблоком
90 uint32 DataIndex Индекс первого действительного элемента в сегменте данных
94 uint32 DataLength Количество блоков в сегменте данных, используемом суперблоком
98 tApFS_Ident SpaceManagerIdent Идентификатор логического объекта Space Manager
A0 tApFS_Ident ObjectsMapIdent Идентификатор физического объекта карты объекта контейнера
A8 tApFS_Ident ReaperIdent Идентификатор логического объекта
B0 uint32 ReservedForTesting
B4 uint32 MaximumVolumes Максимально возможное количество объемов в контейнере
B8 tApFS_Ident VolumesIdents[100] Объем масива идентификаторов виртуальных объектов
3D8 uint64 Counters[32] Массив счетчиков, хранящих информацию о контейнере
4D8 tApFS_BlockRange BlockedOutOfRange Физический диапазон блоков, которые нельзя использовать
4E8 tApFS_Ident MappingTreeIdent Идентификатор физического объекта в дереве, используемый для отслеживания объектов, перемещаемых из заблокированного хранилища.
4F0 uint64 OtherFlags Карта других функций контейнера
4F8 tApFS_Address JumpstartEFI Id физического объекта с данными EFI-драйвера
500 tApFS_Uuid FusionUuid UUID контейнера Fusion или ноль для контейнеров, отличных от Fusion
510 tApFS_BlockRange KeyLocker Расположение ключевой метки контейнера
520 uint64 EphemeralInfo[4] Массив полей, используемый для управления логическими данными
540 tApFS_Ident ReservedForTesting
548 tApFS_Ident FusionMidleTreeIdent Только для обьединенных устройств
550 tApFS_Ident FusionWriteBackIdent Только для обьединенных устройств
558 tApFS_BlockRange FusionWriteBackBlocks Блоки, используемые для области кэша

С определением типов:

uint8  tApFS_Uuid;
uint64 tApFS_Ident;
uint64 tApFS_Transaction;
int64  tApFS_Address;
uint64 tApFS_BTreeKey;

и

struct tApFS_BlockRange
{
    tApFS_Address       First;          // Первый блок
    uint64              Count;          // Количество блоков
}
struct tApFS_COH
{
    uint64              CheckSum;       // Контрольная сумма блока
    tApFS_Ident         Ident;          // Идентификатор
    tApFS_Transaction   Transaction;    // Object change transaction number
    uint16              Type;           // Тип объекта
    uint16              Flags;          // Флаги объекта
    uint32              SubType;        // Подтип объекта
};

с перечнем типов объектов:

enum eApFS_ObjectType
{
    eApFS_ObjectType_01_SuperBlock            = 0x0001, //Суперблок контейнера
    eApFS_ObjectType_02_BTreeRoot             = 0x0002, // Би-дерево: узловой элемент
    eApFS_ObjectType_03_BTreeNode             = 0x0003, // Би-дерево: лист
    eApFS_ObjectType_05_SpaceManager          = 0x0005, // Менеджер пространства
    eApFS_ObjectType_06_SpaceManagerCAB       = 0x0006, // Менеджер пространства: адреса сегментов
    eApFS_ObjectType_07_SpaceManagerCIB       = 0x0007, // Менеджер пространства: информация сегментов
    eApFS_ObjectType_08_SpaceManagerBitmap    = 0x0008, // Карта свободного пространства используемая Менеджером пространства
    eApFS_ObjectType_09_SpaceManagerFreeQueue = 0x0009, // Свободное место используемое менеджером пространства_ (ключи - _tApFS_09_SpaceManagerFreeQueue_Key_, значения - _tApFS_09_SpaceManagerFreeQueue_Value_)
    eApFS_ObjectType_0A_ExtentListTree        = 0x000A, // Дерево списка экстентов (ключи – смещение начального экстента_tApFS_Address_, значение – физическое расположение данных _tApFS_BlockRange_)
    eApFS_ObjectType_0B_ObjectsMap            = 0x000B, // Тип – Карта обьектов; subType – Дерево записей карты обьектов (ключи - _tApFS_0B_ObjectsMap_Key_, значения - _tApFS_0B_ObjectsMap_Value_)
    eApFS_ObjectType_0C_CheckPointMap         = 0x000C, // Карта контрольных точек (чекпоинтов)
    eApFS_ObjectType_0D_FileSystem            = 0x000D, // Файловая система тома
    eApFS_ObjectType_0E_FileSystemTree        = 0x000E, // Дерево файловой системы (ключи начинаются с _tApFS_BTreeKey_, описывает тип и значение ключа)
    eApFS_ObjectType_0F_BlockReferenceTree    = 0x000F, // Дерево ссылок на блоки (ключи - _tApFS_BTreeKey_, значения - _tApFS_0F_BlockReferenceTree_Value_)
    eApFS_ObjectType_10_SnapshotMetaTree      = 0x0010, // Дерево снимков (ключи - _tApFS_BTreeKey_, значения - _tApFS_10_SnapshotMetaTree_Value_)
    eApFS_ObjectType_11_Reaper                = 0x0011, // Reaper
    eApFS_ObjectType_12_ReaperList            = 0x0012, // Reaper List
    eApFS_ObjectType_13_ObjectsMapSnapshot    = 0x0013, // Дерево снимков карты обьектов (ключи - _tApFS_Transaction_, значения - _tApFS_13_ObjectsMapSnapshot_Value_)
    eApFS_ObjectType_14_JumpStartEFI          = 0x0014, // EFI Загрузчик
    eApFS_ObjectType_15_FusionMiddleTree      = 0x0015, // Дерево объединённых устройств для отслеживания блоков жестких дисков, кэшированных SSD (ключи - _tApFS_Address_, значения - _tApFS_15_FusionMiddleTree_Value_)
    eApFS_ObjectType_16_FusionWriteBack       = 0x0016, // Состояние кэша обратной записи объединённых устройств
    eApFS_ObjectType_17_FusionWriteBackList   = 0x0017, // Список кэша обратной записи объединённых устройств
    eApFS_ObjectType_18_EncryptionState       = 0x0018, // Шифрование
    eApFS_ObjectType_19_GeneralBitmap         = 0x0019, // General Bitmap
    eApFS_ObjectType_1A_GeneralBitmapTree     = 0x001A, // Дерево General Bitmap (keys - uint64, keys - uint64)
    eApFS_ObjectType_1B_GeneralBitmapBlock    = 0x001B, // Блок General Bitmap
    eApFS_ObjectType_00_Invalid               = 0x0000, // Недействителен как тип или отсутствует как подтип
    eApFS_ObjectType_FF_Test                  = 0x00FF  // Зарезервировано для тестирования (никогда не сохраняется на носителе)
    eApFS_ObjectType_FF_Test                  = 0x00FF  // Зарезервировано для тестирования (никогда не сохраняется на носителе)
};

enum eApFS_ObjectFlag
{
    eApFS_ObjectFlag_Virtual         = 0x0000, // Виртуальный объект
    eApFS_ObjectFlag_Ephemeral       = 0x8000, // Логический объект
    eApFS_ObjectFlag_Physical        = 0x4000, // Физический объект
    eApFS_ObjectFlag_NoHeader        = 0x2000, // Объект без заголовка _tApFS_ContainerObjectHeader_ (например, Карта (bitmap) менеджера пространства)
    eApFS_ObjectFlag_Encrypted       = 0x1000, // Зашифрованный объект
    eApFS_ObjectFlag_NonPersistent   = 0x0800, // Объект из этим флагом никогда не сохраняется на носителе
    eApFS_ObjectFlag_StorageTypeMask = 0xC000, // Битовая (bitmask) маска для доступа к флагам категорий обьектов
    eApFS_ObjectFlag_ValidMask       = 0xF800  // Действительный флаг битовой маски
};

struct tApFS_0B_ObjectsMap_Key
{
    tApFS_Ident       ObjectIdent; // Идентификатор объекта
    tApFS_Transaction Transaction; // Номер транзакции
};

struct tApFS_0B_ObjectsMap_Value
{
    uint32       Flags;    // Флаги
    uint32       Size;     // Размер объекта в байтах (кратный размеру блока контейнера)
    tApFS_Address Address; // Адрес объекта
};

struct tApFS_09_SpaceManagerFreeQueue_Key
{
    tApFS_Transaction sfqk_xid;
    tApFS_Address     sfqk_paddr;
};

struct tApFS_09_SpaceManagerFreeQueue_Value
{
    uint64            sfq_count;
    tApFS_Ident       sfq_tree_oid;
    tApFS_Transaction sfq_oldest_xid;
    uint16            sfq_tree_node_limit;
    uint16            sfq_pad16;
    uint32            sfq_pad32;
    uint64            sfq_reserved;
};

struct tApFS_10_SnapshotMetaTree_Value
{
    tApFS_Ident ExtentRefIdent;    // Идентификатор физического объекта Би-дерева, в котором хранится информация об экстенте
    tApFS_Ident SuperBlockIdent;   // Идентификатор суперблока
    uint64      CreatedTime;       // Время создания снимка (в наносекундах с полуночи 01/01/1970)
    uint64      LastModifiedTime;  // Время изменения снимка (в наносекундах с полуночи 01/01/1970)
    uint64      iNum;
    uint32      ExtentRefTreeType; // Тип Би-дерева, в котором хранится информация об экстентах
    uint16      NameLength;        // Длинна имени снимка (включая символ конца строки)
    uint8       Name[];            // Имя снимка (заканчивается на 0)
};

struct tApFS_13_ObjectsMapSnapshot_Value
{
    uint32      Flags;    // Флаги снимков
    uint32      Padding;  // Зарезервировано (для корректировки)
    tApFS_Ident Reserved; // Зарезервировано
};

struct tApFS_15_FusionMiddleTree_Value
{
    tApFS_Address fmv_lba;
    uint32        fmv_length;
    uint32        fmv_flags;
};

Пример структуры файловой системы ApFS:

Пример структуры файловой системы ApFS

Volume Superblock (Суперблок тома)

Суперблок тома (Volume Superblock) - существует для каждого тома в файловой системе. Он содержит название тома, идентификатор и отметку времени. Подобно суперблоку контейнера (Container Superblock), он содержит указатель на карту блоков, которая отображает идентификаторы блоков на их смещения. Кроме того, в суперблоке тома хранится указатель на корневой каталог, который хранится как узел.

Смещение (HEX) Тип Id Описание
0 tApFS_COH Header Заголовок объекта-контейнера (Container Object Header)
20 uint32 MagicNumber (APSB) Значение, которое можно использовать для проверки того, что мы читаем экземпляр Volume Superblock
24 uint32 IndexInSuperBlock Индекс идентификатора объекта этого тома в массиве тома контейнера
28 uint64 Features Bitmap основных функций, используемых томом
30 uint64 ReadOnlyFeatures Bitmap основных функций (только для чтения), используемых томом
38 uint64 IncompatibleFeatures Битовая карта (Bitmap) несовместимых функций объема
40 uint64 LastUnmountTime Время последнего размонтирования тома (в наносекундах с полуночи 01.01.1970)
48 uint64 ReservedBlocksCount Количество блоков, зарезервированных для выделения тома
50 uint64 QuotaBlocksCount Максимальное количество блоков, которое этот том может выделить
58 uint64 AllocatedCount Количество блоков, выделенных в настоящее время файловой системе этого тома.
60 uint8 MetaCryptoState[20] Информация о ключе, используемом для шифрования метаданных для этого тома (экземпляр wrapped_meta_crypto_state_t)
74 uint32 RootTreeType Тип дерева корневой папки (обычно: тип ( eApFS_ObjectFlag_Virtual << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип eApFS_ObjectType_0E_FileSystemTree )
78 uint32 ExtentRefTreeType Тип дерева привязки экстентов (обычно: тип ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип OBJECT_TYPE_BLOCKREF )
7C uint32 SnapshotMetaTreeType Тип дерева метаданных снимка (обычно: тип ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип OBJECT_TYPE_BLOCKREF )
80 tApFS_Ident ObjectsMapIdent Идентификатор физического объекта на карте объемного объекта
88 tApFS_Ident RootTreeIdent Идентификатор виртуального объекта дерева корневой папки
90 tApFS_Ident ExtentRefTreeIdent Идентификатор физического объекта дерева связей экстентов
98 tApFS_Ident SnapshotMetaTreeIdent Идентификатор виртуального объекта дерева метаданных снимка
A0 tApFS_Transaction RevertToXid Номер транзакции моментального снимка, в который будет возвращен том
A8 tApFS_Ident RevertToSuperBlock Идентификатор физического объекта VS, к которому вернется том
B0 uint64 NextObjectIdent Следующий идентификатор, который будет назначен объекту файловой системы на томе.
B8 uint64 NumberOfFiles Количество обычных файлов в томе
C0 uint64 NumberOfDirectories Количество папок в томе
C8 uint64 NumberOfSymbolicLinks Количество символьных ссылок в томе
D0 uint64 NumberOfOtherObjects Количество других объектов в томе (не включая x0B8_NumberOfFiles , x0C0_NumberOfDirectories и x0C8_NumberOfSymbolicLinks )
D8 uint64 NumberOfSnapshots Количество снимков в этом томе
E0 uint64 TotalBlocksAllocated Общее количество блоков, выделенных этим томом
E8 uint64 TotalBlocksFreed Общее количество блоков, освобожденных этим томом
F0 tApFS_Uuid Uuid
100 uint64 LastModifiedTime Время последнего изменения этого объема (в наносекундах с полуночи 01.01.1970)
108 uint64 Flags
110 tApFS_0D_FSM FormattedBy Информация о программном обеспечении, создавшем этот том
140 tApFS_0D_FSM ModifiedBy[8] Информация о программном обеспечении, изменившем этот объем
2C0 uint8 VolumeName[256] Имя нулевого тома строки UTF-8
3C0 uint32 NextDocumentIdent Следующий идентификатор документа, который будет назначен (хранится в расширенном поле APFS_0E_TYPE_DOCUMENT_ID документа)
3C4 uint16 Role Растровое изображение роли тома
3C6 uint16 Reserved
3C8 tApFS_Transaction RootToXid Номер транзакции снэпшота для некорневых или ноль для корневых
3D0 tApFS_Ident EncryptStateIdent Текущее состояние шифрования или дешифрования, или ноль, если нет шифрования

Подробная иллюстрация «APFS»:

Подробная иллюстрация APFS

Checkpoint (Чекпоинт)

Чекпоинт - это временное состояние контейнера. Каждая контрольная точка инициализируется в Суперблоке контейнера, и текущее состояние обычно является последним. Чекпоинт включает метаданные как контейнера, так и тома. Точки восстановления и снимки похожи друг на друга. Основное различие между чекпоинтом и моментальным снимком заключается в возможности пользователя восстановить файловую систему из сохраненных моментальных снимков с помощью API файловой системы.

Checkpoint Superblock Descriptor (Дескриптор Чекпоинта Суперблока)

Этот блок содержит информацию о структурах метаданных в «ApFS» и является предшествующим блоком Дескриптора. Наиболее важной информацией в этом блоке является расположение Bitmap Structure (BMS), бывшего файла распределения в HFS +.

Дескриптор суперблока контрольной точки:

Дескриптор суперблока контрольной точки

Bitmap Structures (Битовая карта или карта тома)

Записи об использованных и неиспользованных блоках. Существует только одна карта тома, которая покрывает весь контейнер и является общей для всех томов в файловой системе. «ApFS» использует набор блоков для хранения Карты тома (Bitmap Structures).

В «ApFS» карта являются общей для всех томов в контейнере. В каждом томе указаны котировки блока в контейнере, но сами блоки не находятся в выделенных областях. Ссылка на карту тома лежит в Дескрипторе чекпоинта суперблока (CSBD), в котором находиться информация о самом верхнем уровне структуры, дескрипторе битовой карты (BMD). На рисунке ниже показана базовая структура этой карты. Она разбита по уровням, где BMD находиться вверху и устанавливает границы. Внизу лежат «Bitmap Blocks» (BMB), которые отслеживают блоки в контейнере. Один байт в BMB отслеживает восемь блоков, каждый бит которых обеспечивает статус распределения. Каждый бит - это статус отдельного блока.

Bitmap Blocks

Таблицы (Tables)

Таблицы используются в каталоге и экстентах B-дерева, списке томов и карте идентификатора объекта.

Таблицы, используемые в «ApFS», представляют собой небольшие одноблочные «базы данных» с несколько иным назначением в структурах файловой системы. Поле типа таблицы состоит из 2 байтов, расположенных в блоке со смещением 0x20 непосредственно после заголовка узла. Существует восемь таблиц от 0 до 7. Последующие 2 байта обеспечивают уровень таблицы от 0 и выше. В таблице второго уровня будут записи, относящиеся к базовой таблице первого уровня. А таблицы нулевого уровня относятся к блокам, которые часто содержат метаданные файлов.

Типы таблиц различаются по структуре, но заголовок таблицы для всех типов имеет 24-байтовый вид.

На рисунке представлен образец структуры заголовка таблицы:

На рисунке представлен образец структуры заголовка таблицы

Описание значений полей в структуре заголовка:

Смещение (HEX) Поле Тип данных Описание
20 tableType uint16 Возможные значения 0-7. Это таблица 1
22 tableLevel uint16 Указывает уровень B-дерева.
24 tableRecords uint16 Количество записей в таблице
26 Unknown 1 uint16
28 Unknown 2 uint16
2A tableIndexSize uint16 Размер области индекса таблицы.
2C tableKeyAreaSize uint16 Размер ключевой области таблицы.
2E tableFreeSpaceSize uint16 Размер свободной площади. Область данных таблицы заканчивается со смещением
0x38+tableIndexSize+tableKeyAreaSize+tableFreeSpaceSize. 0x38 + 0x80 + 0x170 + 0xd58 .
30 Unknown 3 uint16
32 Unknown 4 uint16
34 Unknown 5 uint16
36 Unknown 6 uint16

Здесь показан общий макет различных таблиц:

Здесь показан общий макет различных таблиц

Не все элементы на картинке используются во всех таблицах. На рисунке показан полный блок с заголовком блока верхнего узла. Остальная часть блока составляет таблицу.

Сразу после заголовка таблицы идет индекс записи. Их есть 2 типа. Один с двумя значениями: смещением в ключах, и смещением в разделе данных для каждого из Uint16. Второй использует 4 значения Uint16 со смещением и длиной как для ключа, так и для разделов данных. Индекс записи таблицы содержит информацию о ключах и записях данных в таблице. Еще одно различие между типами таблиц - использование нижних колонтитулов.

В таблицах 1, 3, 5 и 7 в конце блока используется нижний колонтитул размером 0x28 байтов. В этих таблицах все смещения данных относятся к смещению 0xFD8, а нижний колонтитул содержит различные значения, специфичные для типа таблицы. Другие типы таблиц не имеют нижнего колонтитула, и все ссылки на содержимое раздела данных относятся к концу блока.

В B-деревьях с несколькими уровнями, - таблицы 1, 3, 5 и 7-я находятся на самом верхнем уровне, поскольку они имеют нижний колонтитул. Нижний колонтитул, используется для хранения информации о полном B-дереве. Одно из значений в нижнем колонтитуле - это общее количество записей в структуре этого дерева.

Определение таблицы начинается со смещения 0x20 в блоке. Здесь указан тип таблицы, количество строк, размер ключевого раздела и промежуток между ключом и разделом данных. После свойств таблицы, определения строк и столбцов описываются смещение 0x38. Таблица содержит заголовок, определения записей, разделы ключей и данных. У некоторых типов таблиц также есть нижний колонтитул. Заголовок начинается со смещения 0x20 и имеет длину 0x18 байт. Заголовок этого типа таблицы начинается с 16-битового значения, которое представляет тип таблицы. Затем следуют два байта, представляющие уровень в B-дереве, на котором используется таблица. Два последующих байта представляют количество строк в таблице. Длина записи определения сканирования находится в 0x2A, за которым следует Uint16, который записывает длину ключевого раздела. Далее следует разрыв между ключом и разделом данных. Нижний колонтитул таблицы всегда равен 0x28 байтам и всегда занимает конец блока. А индексы таблицы имеют 4 или 8 байтов каждый. На 8-байтовых индексах два первых «Uint16» - это смещение и длина ключевой записи. Следующие два «Uint16» - это смещение и длина записи данных в таблице. Таблицы с 4-байтовыми индексами имеют два значения Uint16, которые содержат смещение ключа и записей данных. Длина данных в двух записях предопределена. В таблицах с нижним колонтитулом смещение записи данных относительно начала нижнего колонтитула (0x28 байт). А для других типов таблиц это смещение относится к концу блока.

Большинство значений, касающихся заголовка и нижнего колонтитула таблицы, ясны, по крайней мере, для чтения типа таблицы. Смещение 0x18 в нижнем колонтитуле (смещение 0xFF в блоке 4 Кб) - это количество записей в таблице и во всех базовых таблицах (если это таблица с уровнем выше 0, по смещению 0x22). Смещение 0x20 в нижнем колонтитуле - это номер следующей записи в таблице.

Таблица 0

Таблица 0 типа лежит в структуре каталога B-дерева между узлами листьев и корневым узлом. Значения Неизвестно (Unknown) c 3 по 6 представлены в виде смещения и длины ключа. Смещения данных и длины следующей доступной записи. Если свободных индексных записей нет, смещения устанавливаются на «0xFFFF» и длину «0x00».

Записи в таблице представляют собой четыре значения «Uint16». Первые 2 - это смещение и длина значения в ключевом разделе, а следующие - это смещение и значение содержимого в разделе данных.

Примером таблицы 0 типа может быть идентификатор узла каталога, именной ключ в разделе ключей и идентификатор объекта в разделе данных. У этой таблицы нет нижнего колонтитула.

Таблица 1

Первая таблица имеет нижний колонтитул, а индекс таблицы содержит четыре 16-битных значений, где первые 2 значения представляют собой смещение записи в ключевом разделе и длину записи. Следующие 2 значения обеспечивают смещение записи в разделе данных и ее длину. Эта таблица часто встречается как в структуре каталога B-дерева, так и в дереве экстентов для узла верхнего уровня. Примером являются значения: «Parent ID» и имя ключа (имя файла или папки в структуре каталога, и начальный номер блока в B-дереве экстентов), идентификатор объекта при использовании в качестве корневого узла в структуре каталога или номер блока, когда используется в дереве экстентов.

Примеры этой таблицы приведены ниже:

Примеры этой таблицы приведены ниже

Таблица 2

Вторая таблица. Первоначально эта таблица идентична предыдущей, но не имеет нижнего колонтитула. Этот тип таблицы очень часто встречается в конечных узлах в структуре каталога B-дерева, где ключевой раздел представлен с «Parent ID» и именем ключа.

Таблица 3

Третья таблица идентична предыдущей. Индекс таблицы такой же, как у первой таблицы. Типичные значения зависят от структуры, в которой они используются. В структуре каталога B-дерева и дереве экстентов эта таблица часто используется как узел верхнего уровня в небольших объемах, где корневым узлом одновременно является корневой и листовой узел. В таком примере использования, ключевой записью может быть «Parent ID». Именной ключ, и запись данных могут быть файлом метаданных с большим варьированием размера.

Другие записи таблицы — это идентификатор объекта «Object ID» и его тип в ключевой записи, с экстентами информации о файлах и записями данных. 3 таблица имеет нижний колонтитул.

Пример таблицы:

Пример таблицы

Таблица 4

4 таблица несколько отличается от предыдущих. В таблице нет нижнего колонтитула, а индекс таблицы имеет только 2 значения: смещение записи в ключевом разделе и 1 значение для раздела данных. Длина содержимого фиксирована и составляет 16 байтов в ключевом разделе и 8 байт в разделе данных. Смещения в разделе данных относятся к концу блока.

Таблица 5

5 таблица похожа на 4. Единственное отличие состоит в том, что у этого типа есть нижний колонтитул, и все смещения данных начинаются с «offset-0x28» (начало нижнего колонтитула). Записи в ключевом разделе составляют 16 байтов и 8 байт в разделе данных. Этот тип таблицы чаще всего наблюдается на узлах верхнего уровня в структуре каталога B-дерева и в больших контейнерах с многоуровневыми деревьями.

Таблица 6

6 таблица тоже похожа на 4. Индекс таблицы имеет только смещение к содержимому в разделе ключей и данных, но не ее длину. Длинна определена предварительно. Каждая запись составляет 16 байтов. Для этого типа таблицы нет нижнего колонтитула. Эта таблица часто встречается в конечных узлах структуры каталога B-дерева. Типичное содержимое раздела ключа включает в себя идентификатор объекта и ID Тома Чекпоинта Суперблока «Volume Checkpoint Superblock ID», в то время как в разделе данных обычно записывается их размер и номер блока.

Таблица 7

7 Таблица похожа на 6-ю. Единственным отличием является нижний колонтитул, который содержит информацию, аналогичную описанной для 1 таблицы. Этот тип таблицы наблюдается в широком диапазоне структур и часто встречается на самых верхних уровнях многослойной структуры или в однослойных структурах, таких как описание тома.

Пример

Пример

Сводка таблиц

В данной таблице показаны основные свойства различных типов таблиц:

Тип Нижний колонтитул Смещение ключевого раздела Длина ключевого раздела Смещение раздел данных Длина раздел данных Длина Ключа Длина данныех
0 НЕТ uint16 uint16 uint16 uint16 Varies Possible
1 ДА uint16 uint16 uint16 uint16 Varies Possible
2 НЕТ uint16 uint16 uint16 uint16 Varies Possible
3 ДА uint16 uint16 uint16 uint16 Varies Possible
4 НЕТ uint16 uint16 16 bytes 8 bytes
5 ДА uint16 uint16 16 bytes 8 bytes
6 НЕТ uint16 uint16 16 bytes 16 bytes
7 ДА uint16 uint16 16 bytes 16 bytes

Одним из наиболее важных блоков в структуре каталога B-дерева является корневой узел, который является наивысшим уровнем в структуре папок. Этот узел использует ключи поиска переменной длины. Одной из улучшенных функций «ApFS» является быстрый поиск в каталогах. Одно из значений, которое тесно связано с этой функцией, - это количество всех записей в древовидной структуре, расположенной в нижнем колонтитуле таблицы.

У корневого узла структуры B-дерева есть 2 варианта выбора таблицы, поскольку у обоих есть нижние колонтитулы. 3 Таблица – как корневой узел, наблюдается только в небольших контейнерах с небольшим количеством файлов, где корневой узел также является индексным и листовым узлами.

В карте объектов для корневого узла используется только 5 таблица, за исключением очень маленьких структур, где может встречаться 7-я.

Интерпретация таблиц показывает, что таблицы 0 и 2 имеют одинаковые значения. То же самое наблюдается между таблицами 1 и 3. Эти таблицы, по-видимому, имеют разное назначение в зависимости от того, в какой структуре они находятся.

Моментальные снимки (Snapshots)

Моментальные снимки – это снимки файловой системы тома только для чтения. Операционная система может использовать эти снимки для более эффективной процедуры резервного копирования. Благодаря им Time Machine будет работать быстрее. И благодаря поддержке мгновенных образов «Time Machine», больше не нужно сохранять несколько полных копий файла на диск - она может просто отслеживать определенные изменения. Например, если вы редактируете файл, изменение с использованием HFS +, он сохраняет две копии файла, в первом записаны новые изменения, и второй на случай, если вы захотите вернуться к прежнему виду. В «APFS» сохраняется только исходный файл и записываются различия между исходным файлом и любыми обновленными версиями, занимая меньше места на диске. Как и в случае с улучшениями в Fusion Drive, информация занимает меньше места на диске.

Хотя «ApFS» и значительно уступает по своим возможностям 128-битной ZFS, которая поддерживается Linux, FreeBSD и другими бесплатными ОС, но со стороны Apple это шаг в правильном направлении.

Как упоминалось выше, Apple долгое время пыталась перенести ZFS на OS X. Позже OpenZFS был реализован для OS X (O3X) и MacZFX.

Nodes (узлы)

Узлы - это гибкие контейнеры, которые используются для хранения различных видов записей. Они могут быть частью B-дерева или существовать сами по себе. Узлы могут содержать записи гибкого или фиксированного размера. Узел начинается со списка указателей на ключи входа и записи входа. Таким образом, для каждой записи узел содержит заголовок записи в начале узла, ключ входа в середине узла и запись входа в конце узла.

Nodes (узлы)
позиция размер тип ID
0 4 uint32 alignment
4 4 uint32 ENTRY_COUNT
10 2 uint16 HEAD_SIZE
16 8 entry meta_entry
24 ... entry entries (repeat entry_count times)

Структура заголовка узла (Node header):

Смещение поле Тип данных Комментарии
0 Checksum Uint64 Fletchers Checksum Algorithm
8 ID Uint64 Object-ID or Block#
10 Checkpoint Uint64
18 Unknown Uint16 Possible level in B-Tree
1A Unknown Uint16 All observations shows value 0x4000
1C Unknown Uint16 Flag?
1E Unknown Uint16 Often seen value 0x0b, 0x0e and 0x0f

Менеджер пространства (Space Manager)

«Space Manager» (Менеджер пространства) используется для управления выделенными блоками в контейнере «ApFS». Хранит количество свободных блоков и указатель на файлы информации о размещении.

позиция размер тип ID
0 4 uint32 размер блока
16 8 uint64 totalblocks
40 8 uint64 freeblocks
144 8 uint64 prev_allocationinfofile_block
352 8 uint64 allocationinfofile_block

Allocation info file (Информационный файл распределения)

Файл распределения работает как отсутствующий заголовок. Здесь хранятся длина файлов размещения, версия и его смещение.

позиция размер тип ID
4 4 uint32 alloc_file_length
8 4 uint32 alloc_file_version
24 4 uint32 TOTAL_BLOCKS
28 4 uint32 free_blocks
32 4 uint32 allocationfile_block

Файл и папка B-дерева

Записи всех файлов и папок на томе. Они выполняют ту же роль, что и файлы каталога в «HFS+».

Extents (Экстенты B-дерева)

Отдельное B-дерево всех экстентов тома. Экстенты - это ссылки на содержимое файла с информацией о том, где начинается содержимое данных, и о их длине в блоках. Файл с некоторым содержимым будет иметь как минимум один экстент. А фрагментированный файл будет иметь несколько экстентов. Дерево экстентов - это отдельная структура.

В каждой записи файла, экстенты, определяются для каждого из этих файлов в B-дереве. Эта отдельная структура экстентов является частью функции моментального снимка.

64-bit inodes (index descriptors) - индексные дескрипторы

64-битные inodes значительно увеличивают пространство имен по сравнению с 32-битными идентификаторами в «HFS+». 64-разрядная файловая система «ApFS» поддерживает более 9 квинтиллионов файлов на каждом томе. Как сказал Билл Гейтс, этого должно хватить на всех.

«ApFS» предлагает возможность восстановления определенных состояний файловой системы, включая старые или удаленные версии файлов. Суперблок контейнера содержит ссылку на структуру контрольной точки. Контрольная точка ссылается на предыдущий суперблок контейнера, который содержит информацию в более старом состоянии файловой системы. Таким образом, можно восстановить несколько старых состояний путем анализа цепочки суперблока контейнера.

Dmytriy Zhura

Автор: , Технический писатель

Дмитрий Жура – автор и один из IT-инженеров компании Hetman Software. Имеет почти 10 летний опыт работы в IT-сфере: администрирование и настройка серверов, установка операционных систем и различного программного обеспечения, настройка сети, информационная безопасность, внедрения и консультация по использованию специализированного ПО. Является экспертом в области восстановления данных, файловых систем, устройств хранения данных и RAID массивов.

Andrey Mareev

Редактор: , Технический писатель

В далеком 2005 году, я получил диплом по специальности «Прикладная математика» в Восточноукраинском национальном университете. А уже в 2006 году, я создал свой первый проект по восстановлению данных. С 2012 года, начал работать в компании «Hetman Software», отвечая за раскрутку сайта, продвижение программного обеспечения компании, и как специалист по работе с клиентами.

Рекомендуем для вас

Вас приветствует ассистент Hetman Software, созданный на основе искусственного интеллекта.
Начать Чат