«ApFS» предлагает возможность восстановления определенных состояний файловой системы, включая старые или удаленные версии файлов. Суперблок контейнера содержит ссылку на структуру контрольной точки. Контрольная точка ссылается на предыдущий суперблок контейнера, который содержит информацию в более старом состоянии файловой системы. Таким образом, можно восстановить несколько старых состояний путем анализа цепочки суперблока контейнера.
Контейнеры и Тома
Структура файловой системы APFS имеет вид b-дерева, где корневой каталог с данными — это листья этого дерева. Все ветви хранят лишь ссылки на следующий узел пока не дойдут до листьев. Файловая система использует контейнеры в качестве ячеек хранения. Эти контейнера могут содержать несколько томов. Также он является основным объектом для хранения данных. Для одного тома размер контейнера должен быть более 512 МБ, для двух томов – более 1024Мб и т.д.
На рисунке ниже представлена структура файловой системы «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» начинается с заголовка блока. А сам заголовок начинается с контрольной суммы. Другая информация в заголовке включает в себя версию блока с копией при записи, идентификатор блока и его тип.
СмещениеРазмерТипID08uint64Контрольная сумма (checksum)88uint64Идентификатор (block_id)168uint64Версия (version)242uint16Тип блока (block_type)262uint16Флаги (flags)284uint32Отступ (padding)
Из таблицы мы видим, что 1uint = 1 бит, 8 бит = 1 байту, из этого uint64 = 8, uint32 = 4, и uint16 = 2 байтам.
Container Superblock
Суперблок контейнера (Container Superblock) – это входная точка в файловую систему. Из-за структуры файловой системы с контейнерами и гибкими томами, распределение необходимо обрабатывать на уровне контейнера. Суперблок контейнера содержит информацию о размере блока, их количестве и указателях в менеджере пространства для этой задачи. Кроме того, в суперблоке хранятся идентификаторы (ID) блоков всех томов. Для сопоставления идентификаторов блоков блокам смещения, сохраняется указатель на карту блоков B-дерева. Это дерево содержит записи для каждого тома с его идентификатором и смещением. Суперблок контейнера – это самый высокий уровень файловой системы.
Он имеет следующий вид:
Смещение (HEX)ТипIdОписание0tApFS_COHHeaderЗаголовок объекта-контейнера (Container Object Header)20uint32MagicNumber (NXSB)Значение для проверки чтения Суперблока контейнера.24uint32BlockSizeРазмер блока контейнера (в байтах)28uint64BlocksCountКоличество контейнерных блоков30uint64FeaturesКарта (bitmap) основных функций контейнера38uint64ReadOnlyFeaturesКарта (bitmap) базовых функций контейнера (только для чтения)40uint64IncompatibleFeaturesКарта (bitmap) основных несовместимых функций контейнера48tApFS_UuidUuidUUID контейнера58tApFS_IdentNextIdentСледующий идентификатор для нового логического или виртуального объекта60tApFS_TransactionNextTransactionНомер следующей транзакции68uint32DescriptorBlocksКоличество блоков, используемых дескриптором6Cuint32DataBlocksКоличество блоков, используемых данными70tApFS_AddressDescriptorBaseБазовый адрес дескриптора или идентификатор физического объекта с деревом адресо78int32DataBaseАдрес базы данных или идентификатор физического объекта с адресным деревом80uint32DescriptorNextИндекс следующего дескриптора84uint32DataNextСледующий индекс данных88uint32DescriptorIndexИндекс первого действительного элемента в сегменте дескриптора8Cuint32DescriptorLengthКоличество блоков в сегменте дескриптора, используемого суперблоком90uint32DataIndexИндекс первого действительного элемента в сегменте данных94uint32DataLengthКоличество блоков в сегменте данных, используемом суперблоком98tApFS_IdentSpaceManagerIdentИдентификатор логического объекта Space ManagerA0tApFS_IdentObjectsMapIdentИдентификатор физического объекта карты объекта контейнераA8tApFS_IdentReaperIdentИдентификатор логического объектаB0uint32ReservedForTestingB4uint32MaximumVolumesМаксимально возможное количество объемов в контейнереB8tApFS_IdentVolumesIdents[100]Объем масива идентификаторов виртуальных объектов3D8uint64Counters[32]Массив счетчиков, хранящих информацию о контейнере4D8tApFS_BlockRangeBlockedOutOfRangeФизический диапазон блоков, которые нельзя использовать4E8tApFS_IdentMappingTreeIdentИдентификатор физического объекта в дереве, используемый для отслеживания объектов, перемещаемых из заблокированного хранилища.4F0uint64OtherFlagsКарта других функций контейнера4F8tApFS_AddressJumpstartEFIId физического объекта с данными EFI-драйвера500tApFS_UuidFusionUuidUUID контейнера Fusion или ноль для контейнеров, отличных от Fusion510tApFS_BlockRangeKeyLockerРасположение ключевой метки контейнера520uint64EphemeralInfo[4]Массив полей, используемый для управления логическими данными540tApFS_IdentReservedForTesting548tApFS_IdentFusionMidleTreeIdentТолько для обьединенных устройств550tApFS_IdentFusionWriteBackIdentТолько для обьединенных устройств558tApFS_BlockRangeFusionWriteBackBlocksБлоки, используемые для области кэша
С определением типов:
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:
Volume Superblock (Суперблок тома)
Суперблок тома (Volume Superblock) – существует для каждого тома в файловой системе. Он содержит название тома, идентификатор и отметку времени. Подобно суперблоку контейнера (Container Superblock), он содержит указатель на карту блоков, которая отображает идентификаторы блоков на их смещения. Кроме того, в суперблоке тома хранится указатель на корневой каталог, который хранится как узел.
Смещение (HEX)ТипIdОписание0tApFS_COHHeaderЗаголовок объекта-контейнера (Container Object Header)20uint32MagicNumber (APSB)Значение, которое можно использовать для проверки того, что мы читаем экземпляр Volume Superblock24uint32IndexInSuperBlockИндекс идентификатора объекта этого тома в массиве тома контейнера28uint64FeaturesBitmap основных функций, используемых томом30uint64ReadOnlyFeaturesBitmap основных функций (только для чтения), используемых томом38uint64IncompatibleFeaturesБитовая карта (Bitmap) несовместимых функций объема40uint64LastUnmountTimeВремя последнего размонтирования тома (в наносекундах с полуночи 01.01.1970)48uint64ReservedBlocksCountКоличество блоков, зарезервированных для выделения тома50uint64QuotaBlocksCountМаксимальное количество блоков, которое этот том может выделить58uint64AllocatedCountКоличество блоков, выделенных в настоящее время файловой системе этого тома.60uint8MetaCryptoState[20]Информация о ключе, используемом для шифрования метаданных для этого тома (экземпляр wrapped_meta_crypto_state_t)74uint32RootTreeTypeТип дерева корневой папки (обычно: тип ( eApFS_ObjectFlag_Virtual << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип eApFS_ObjectType_0E_FileSystemTree )78uint32ExtentRefTreeTypeТип дерева привязки экстентов (обычно: тип ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип OBJECT_TYPE_BLOCKREF )7Cuint32SnapshotMetaTreeTypeТип дерева метаданных снимка (обычно: тип ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , подтип OBJECT_TYPE_BLOCKREF )80tApFS_IdentObjectsMapIdentИдентификатор физического объекта на карте объемного объекта88tApFS_IdentRootTreeIdentИдентификатор виртуального объекта дерева корневой папки90tApFS_IdentExtentRefTreeIdentИдентификатор физического объекта дерева связей экстентов98tApFS_IdentSnapshotMetaTreeIdentИдентификатор виртуального объекта дерева метаданных снимкаA0tApFS_TransactionRevertToXidНомер транзакции моментального снимка, в который будет возвращен томA8tApFS_IdentRevertToSuperBlockИдентификатор физического объекта VS, к которому вернется томB0uint64NextObjectIdentСледующий идентификатор, который будет назначен объекту файловой системы на томе.B8uint64NumberOfFilesКоличество обычных файлов в томеC0uint64NumberOfDirectoriesКоличество папок в томеC8uint64NumberOfSymbolicLinksКоличество символьных ссылок в томеD0uint64NumberOfOtherObjectsКоличество других объектов в томе (не включая x0B8_NumberOfFiles , x0C0_NumberOfDirectories и x0C8_NumberOfSymbolicLinks )D8uint64NumberOfSnapshotsКоличество снимков в этом томеE0uint64TotalBlocksAllocatedОбщее количество блоков, выделенных этим томомE8uint64TotalBlocksFreedОбщее количество блоков, освобожденных этим томомF0tApFS_UuidUuid100uint64LastModifiedTimeВремя последнего изменения этого объема (в наносекундах с полуночи 01.01.1970)108uint64Flags110tApFS_0D_FSMFormattedByИнформация о программном обеспечении, создавшем этот том140tApFS_0D_FSMModifiedBy[8]Информация о программном обеспечении, изменившем этот объем2C0uint8VolumeName[256]Имя нулевого тома строки UTF-83C0uint32NextDocumentIdentСледующий идентификатор документа, который будет назначен (хранится в расширенном поле APFS_0E_TYPE_DOCUMENT_ID документа)3C4uint16RoleРастровое изображение роли тома3C6uint16Reserved3C8tApFS_TransactionRootToXidНомер транзакции снэпшота для некорневых или ноль для корневых3D0tApFS_IdentEncryptStateIdentТекущее состояние шифрования или дешифрования, или ноль, если нет шифрования
Подробная иллюстрация «APFS»:
Checkpoint (Чекпоинт)
Чекпоинт – это временное состояние контейнера. Каждая контрольная точка инициализируется в Суперблоке контейнера, и текущее состояние обычно является последним. Чекпоинт включает метаданные как контейнера, так и тома. Точки восстановления и снимки похожи друг на друга. Основное различие между чекпоинтом и моментальным снимком заключается в возможности пользователя восстановить файловую систему из сохраненных моментальных снимков с помощью API файловой системы.
Checkpoint Superblock Descriptor (Дескриптор Чекпоинта Суперблока)
Этот блок содержит информацию о структурах метаданных в «ApFS» и является предшествующим блоком Дескриптора. Наиболее важной информацией в этом блоке является расположение Bitmap Structure (BMS), бывшего файла распределения в HFS +.
Дескриптор суперблока контрольной точки:
Bitmap Structures (Битовая карта или карта тома)
Записи об использованных и неиспользованных блоках. Существует только одна карта тома, которая покрывает весь контейнер и является общей для всех томов в файловой системе. «ApFS» использует набор блоков для хранения Карты тома (Bitmap Structures).
В «ApFS» карта являются общей для всех томов в контейнере. В каждом томе указаны котировки блока в контейнере, но сами блоки не находятся в выделенных областях. Ссылка на карту тома лежит в Дескрипторе чекпоинта суперблока (CSBD), в котором находиться информация о самом верхнем уровне структуры, дескрипторе битовой карты (BMD). На рисунке ниже показана базовая структура этой карты. Она разбита по уровням, где BMD находиться вверху и устанавливает границы. Внизу лежат «Bitmap Blocks» (BMB), которые отслеживают блоки в контейнере. Один байт в BMB отслеживает восемь блоков, каждый бит которых обеспечивает статус распределения. Каждый бит – это статус отдельного блока.
Таблицы (Tables)
Таблицы используются в каталоге и экстентах B-дерева, списке томов и карте идентификатора объекта.
Таблицы, используемые в «ApFS», представляют собой небольшие одноблочные «базы данных» с несколько иным назначением в структурах файловой системы. Поле типа таблицы состоит из 2 байтов, расположенных в блоке со смещением 0x20 непосредственно после заголовка узла. Существует восемь таблиц от 0 до 7. Последующие 2 байта обеспечивают уровень таблицы от 0 и выше. В таблице второго уровня будут записи, относящиеся к базовой таблице первого уровня. А таблицы нулевого уровня относятся к блокам, которые часто содержат метаданные файлов.
Типы таблиц различаются по структуре, но заголовок таблицы для всех типов имеет 24-байтовый вид.
На рисунке представлен образец структуры заголовка таблицы:
Описание значений полей в структуре заголовка:
Смещение (HEX)ПолеТип данныхОписание20tableTypeuint16Возможные значения 0-7. Это таблица 122tableLeveluint16Указывает уровень B-дерева.24tableRecordsuint16Количество записей в таблице26Unknown 1uint1628Unknown 2uint162AtableIndexSizeuint16Размер области индекса таблицы.2CtableKeyAreaSizeuint16Размер ключевой области таблицы.2EtableFreeSpaceSizeuint16Размер свободной площади. Область данных таблицы заканчивается со смещением
0x38+tableIndexSize+tableKeyAreaSize+tableFreeSpaceSize. 0x38 + 0x80 + 0x170 + 0xd58 .30Unknown 3uint1632Unknown 4uint1634Unknown 5uint1636Unknown 6uint16
Здесь показан общий макет различных таблиц:
Не все элементы на картинке используются во всех таблицах. На рисунке показан полный блок с заголовком блока верхнего узла. Остальная часть блока составляет таблицу.
Сразу после заголовка таблицы идет индекс записи. Их есть 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НЕТuint16uint16uint16uint16VariesPossible1ДАuint16uint16uint16uint16VariesPossible2НЕТuint16uint16uint16uint16VariesPossible3ДАuint16uint16uint16uint16VariesPossible4НЕТuint16uint1616 bytes8 bytes5ДАuint16uint1616 bytes8 bytes6НЕТuint16uint1616 bytes16 bytes7ДАuint16uint1616 bytes16 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-дерева или существовать сами по себе. Узлы могут содержать записи гибкого или фиксированного размера. Узел начинается со списка указателей на ключи входа и записи входа. Таким образом, для каждой записи узел содержит заголовок записи в начале узла, ключ входа в середине узла и запись входа в конце узла.
Структура заголовка узла (Node header):
СмещениеполеТип данныхКомментарии0ChecksumUint64Fletchers Checksum Algorithm8IDUint64Object-ID or Block#10CheckpointUint6418UnknownUint16Possible level in B-Tree1AUnknownUint16All observations shows value 0x40001CUnknownUint16Flag?1EUnknownUint16Often seen value 0x0b, 0x0e and 0x0f
Менеджер пространства (Space Manager)
«Space Manager» (Менеджер пространства) используется для управления выделенными блоками в контейнере «ApFS». Хранит количество свободных блоков и указатель на файлы информации о размещении.
позицияразмертипID04uint32размер блока168uint64totalblocks408uint64freeblocks1448uint64prev_allocationinfofile_block3528uint64allocationinfofile_block
Allocation info file (Информационный файл распределения)
Файл распределения работает как отсутствующий заголовок. Здесь хранятся длина файлов размещения, версия и его смещение.
позицияразмертипID44uint32alloc_file_length84uint32alloc_file_version244uint32TOTAL_BLOCKS284uint32free_blocks324uint32allocationfile_block
Файл и папка B-дерева
Записи всех файлов и папок на томе. Они выполняют ту же роль, что и файлы каталога в «HFS+».
Extents (Экстенты B-дерева)
Отдельное B-дерево всех экстентов тома. Экстенты – это ссылки на содержимое файла с информацией о том, где начинается содержимое данных, и о их длине в блоках. Файл с некоторым содержимым будет иметь как минимум один экстент. А фрагментированный файл будет иметь несколько экстентов. Дерево экстентов – это отдельная структура.
В каждой записи файла, экстенты, определяются для каждого из этих файлов в B-дереве. Эта отдельная структура экстентов является частью функции моментального снимка.
64-bit inodes (index descriptors) – индексные дескрипторы
64-битные inodes значительно увеличивают пространство имен по сравнению с 32-битными идентификаторами в «HFS+». 64-разрядная файловая система «ApFS» поддерживает более 9 квинтиллионов файлов на каждом томе. Как сказал Билл Гейтс, этого должно хватить на всех.
«ApFS» предлагает возможность восстановления определенных состояний файловой системы, включая старые или удаленные версии файлов. Суперблок контейнера содержит ссылку на структуру контрольной точки. Контрольная точка ссылается на предыдущий суперблок контейнера, который содержит информацию в более старом состоянии файловой системы. Таким образом, можно восстановить несколько старых состояний путем анализа цепочки суперблока контейнера.
Полную версию статьи со всеми дополнительными видео уроками смотрите в источнике: https://hetmanrecovery.com/ru/recovery_news/data-recovery-algorithmfile-system-apfs-and-its-structure.htm