APFS: Algorithme de récupération de données et structure du système de fichiers

ApFS offre la possibilité pour restaurer certains états du système de fichiers, y compris la restauration des versions anciennes ou supprimées des fichiers. Le superblock conteneur contient un lien vers l’élément appelé point de contrôle. Un tel point de contrôle fait référence au superblock conteneur précédent qui stocke les informations sur un état plus ancien du système de fichiers.De cette façon, plusieurs états plus anciens peuvent être restaurés en analysant la chaîne du superblock conteneur.

APFS: Algorithme de récupération de données et structure du système de fichiers

Visualisation
🔝 Top Tools to Recover Data from APFS drives or how to recover Apple MacOs disk in Windows (2021)🍏

🔝 Top Tools to Recover Data from APFS drives or how to recover Apple MacOs disk in Windows (2021)🍏

Conteneurs et volumes

La structure du système de fichiers ApFS est celle d’un arbre B, où le répertoire racine contenant les données correspond aux feuilles de cet arbre. Tous les nœuds de branche contiennent uniquement des liens vers le nœud suivant jusqu’à ce qu’ils atteignent les nœuds feuilles. Ce système de fichiers utilise des conteneurs comme cellules de stockage, et ces cellules peuvent contenir plusieurs volumes ApFS. En outre, un conteneur est l’objet principal pour stocker des données. Pour contenir un volume, il doit être > 512 Mo, au moins > 1024 Mo est nécessaire pour contenir plus de 2 volumes et ainsi de suite.

L’image ci-dessous montre un aperçu de la structure ApFS.

ApFS

Chaque élément de cette structure (à l’exception du fichier d’allocation) commence par un en-tête de bloc de 32 octets, qui contient des informations générales sur le bloc. L’élément qui le suit est le corps du système de fichiers. Il est composé des parties suivantes:

  • 0x01: Superblock de conteneurs
  • 0x02: Nœud
  • 0x05: Responsable d’espace
  • 0x07: Fichier d’informations sur l’allocation
  • 0x0C: Point de contrôle
  • 0x0D: Superblock de volume

Les conteneurs sont généralement exactement les mêmes que les entrées de la table de partition GUID (GPT). Ils ont leur propre système de protection contre les pannes et d’allocation d’espace disque. Chaque conteneur contient un ou plusieurs volumes ou systèmes de fichiers, chacun ayant son propre espace de noms, et un ensemble de fichiers et de répertoires.

Bien que ApFS ne supporte pas directement le logiciel RAID, mais il peut être utilisé avec des volumes Apple RAID pour prendre en charge la répartition (RAID 0), la mise en miroir (RAID 1) et la concaténation (JBOD).

Avec un index 64 bits, les volumes ApFS prendront en charge jusqu’à 9 quintillions (1018) de fichiers.

Le nouveau système de fichiers utilise des nanosecondes pour définir les horodatages. Dans HFS +, les horodatages étaient définis à la seconde la plus proche. Cela réduira le nombre d’échecs de transfert de données et d’autres opérations sur les fichiers.

ApFS possède un système de cryptage intégré et utilise les systèmes AES-XTS ou AES-CBC, selon l’appareil. Vous pouvez utiliser plusieurs clés de cryptage pour assurer la sécurité des données même en cas de ”compromis physique” du support.

C’est loin d’être une liste complète des innovations dont ApFS peut se vanter.

Les partitions formatées en ApFS ne sont pas reconnues par OS X 10.11 Yosemite et les versions antérieures du système d’exploitation.

En-tête de bloc

Chaque élément de la structure du système de fichiers dans ApFS commence par un en-tête de bloc. Cet en-tête commence par une somme de contrôle. D’autres informations dans l’en-tête incluent la version de copie sur écriture du bloc, l’identifiant de bloc (id) et le type de bloc.

Position Taille Type 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

Dans le tableau, nous pouvons voir que 1uint = 1 bit, 8 bits = 1 octet, donc uint64 = 8, uint32 = 4 et uint16 = 2 octets.

Superblock de conteneurs

The CS (Superblock de conteneurs) est le point d’entrée du système de fichiers. En raison de la structure du système de fichiers avec des conteneurs et des volumes flexibles, l’allocation doit être traitée au niveau du conteneur. Le Superblock de conteneurs contient des informations sur la taille du bloc, le nombre de blocs et des pointeurs pour cette tâche dans le gestionnaire d’espace. De plus, les identificateurs de bloc (ID) de tous les volumes sont stockés dans le superblock. Pour mapper les ID de bloc aux décalages de bloc, un pointeur vers une carte de bloc B-tree est enregistré. Cette arborescence B contient des entrées pour chaque volume avec son ID et son décalage. Le Superblock de conteneurs est le niveau le plus élevé du système de fichiers.

Voici à quoi ça ressemble:

Décalage (HEX) Type Id Description
0 tApFS_COH Entête En-tête d’objet conteneur
20 uint32 MagicNumber (NXSB) Valeur à vérifier lors de la lecture d’un Superblock de conteneur.
24 uint32 BlockSize Taille du bloc de conteneur (octets)
28 uint64 BlocksCount Nombre de blocs conteneurs
30 uint64 Features Nombre de blocs conteneurs
38 uint64 ReadOnlyFeatures Bitmap pour les principales fonctionnalités du conteneur (lecture seule)
40 uint64 IncompatibleFeatures Bitmap pour les fonctionnalités incompatibles du conteneur
48 tApFS_Uuid Uuid UUID du conteneur
58 tApFS_Ident NextIdent L’identifiant suivant du nouvel objet logique ou virtuel
60 tApFS_Transaction NextTransaction Prochain numéro de transaction
68 uint32 DescriptorBlocks Nombre de blocs utilisés par descripteur
6C uint32 DataBlocks Nombre de blocs utilisés par les données
70 tApFS_Address DescriptorBase Adresse de base du descripteur ou identifiant d’objet physique avec arborescence d’adresses
78 int32 DataBase Adresse de base de données ou identifiant d’objet physique avec arborescence d’adresses
80 uint32 DescriptorNext Index des descripteurs suivants
84 uint32 DataNext Index de données suivant
88 uint32 DescriptorIndex Index du premier élément valide dans le segment de descripteur
8C uint32 DescriptorLength Nombre de blocs dans le segment descripteur utilisé par superblock
90 uint32 DataIndex Index du premier élément valide dans le segment de données
94 uint32 DataLength Nombre de blocs dans le segment de données utilisé par superblock
98 tApFS_Ident SpaceManagerIdent Identifiant de l’objet logique Space Manager
A0 tApFS_Ident ObjectsMapIdent Identificateur de l’objet physique de mappage d’objet conteneur
A8 tApFS_Ident ReaperIdent Identificateur d’objet logique
B0 uint32 ReservedForTesting
B4 uint32 MaximumVolumes Nombre maximum possible de volumes du stockage dans le conteneur
8 tApFS_Ident VolumesIdents[100] Tableau de volumes d’identificateurs d’objets virtuels
3D8 uint64 Counters[32] Tableau de compteurs stockant les informations concernant les conteneurs
4D8 tApFS_BlockRange BlockedOutOfRange Plage physique des blocs non utilisables
4E8 tApFS_Ident MappingTreeIdent Identificateur d’objet physique de l’arborescence utilisée pour suivre les objets déplacés du stockage verrouillé.
4F0 uint64 OtherFlags Bitmap des fonctions d’autres conteneurs
4F8 tApFS_Address JumpstartEFI ID d’objet physique avec les données du pilote EFI
500 tApFS_Uuid FusionUuid UUID du conteneur Fusion ou zéro pour les conteneurs non Fusion
510 tApFS_BlockRange KeyLocker Emplacement de l’étiquette de clé du conteneur
50 uint64 EphemeralInfo[4] Tableau de champ utilisé pour gérer les données éphémères
540 tApFS_Ident ReservedForTesting
548 tApFS_Ident FusionMidleTreeIdent Appareils Fusion uniquement
550 tApFS_Ident FusionWriteBackIdent Appareils Fusion uniquement
558 tApFS_BlockRange FusionWriteBackBlocks Blocs utilisés pour la zone de cache

Avec les types définis:

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

et

struct tApFS_BlockRange
{
    tApFS_Address       First;          // Premier bloc
    uint64              Count;          // Nombre de blocs
}
struct tApFS_COH
{
    uint64              CheckSum;       // Somme de contrôle du bloc
    tApFS_Ident         Ident;          // Identifiant
    tApFS_Transaction   Transaction;    // Numéro de transaction de modification d'objet
    uint16              Type;           // Type d'objet
    uint16              Flags;          // Indicateurs d'objet
    uint32              SubType;        // Sous-type d'objet
};

avec la liste des types d'objet:

enum eApFS_ObjectType
{
    eApFS_ObjectType_01_SuperBlock            = 0x0001, //Container superblockа
    eApFS_ObjectType_02_BTreeRoot             = 0x0002, // B-Tree: root node
    eApFS_ObjectType_03_BTreeNode             = 0x0003, // B-Tree: non-root node
    eApFS_ObjectType_05_SpaceManager          = 0x0005, // Space manager
    eApFS_ObjectType_06_SpaceManagerCAB       = 0x0006, // Space manager: segments’ addresses
    eApFS_ObjectType_07_SpaceManagerCIB       = 0x0007, // Space manager: segments’ information
    eApFS_ObjectType_08_SpaceManagerBitmap    = 0x0008, // Free сspace bitmap used by Space manager
    eApFS_ObjectType_09_SpaceManagerFreeQueue = 0x0009, // Free space used by Space manager_ (keys - _tApFS_09_SpaceManagerFreeQueue_Key_, values - _tApFS_09_SpaceManagerFreeQueue_Value_)
    eApFS_ObjectType_0A_ExtentListTree        = 0x000A, // Extents’ list tree (keys – offset beginning extent_tApFS_Address_, value – physical data location _tApFS_BlockRange_)
    eApFS_ObjectType_0B_ObjectsMap            = 0x000B, // Type – Objects map; subType – Object map record tree (keys - _tApFS_0B_ObjectsMap_Key_, values - _tApFS_0B_ObjectsMap_Value_)
    eApFS_ObjectType_0C_CheckPointMap         = 0x000C, // Check point map 
    eApFS_ObjectType_0D_FileSystem            = 0x000D, // Volume file system
    eApFS_ObjectType_0E_FileSystemTree        = 0x000E, // File system tree (keys start from с _tApFS_BTreeKey_, describes key type and value)
    eApFS_ObjectType_0F_BlockReferenceTree    = 0x000F, // Block reference tree (keys - _tApFS_BTreeKey_, values - _tApFS_0F_BlockReferenceTree_Value_)
    eApFS_ObjectType_10_SnapshotMetaTree      = 0x0010, // Snapshot meta tree (keys - _tApFS_BTreeKey_, values - _tApFS_10_SnapshotMetaTree_Value_)
    eApFS_ObjectType_11_Reaper                = 0x0011, // Reaper
    eApFS_ObjectType_12_ReaperList            = 0x0012, // Reaper List
    eApFS_ObjectType_13_ObjectsMapSnapshot    = 0x0013, // Objects map snapshot tree (keys - _tApFS_Transaction_, values - _tApFS_13_ObjectsMapSnapshot_Value_)
    eApFS_ObjectType_14_JumpStartEFI          = 0x0014, // EFI Loader
    eApFS_ObjectType_15_FusionMiddleTree      = 0x0015, // Fusion devices tree to track SSD cached HDD, blocks (keys - _tApFS_Address_, values - _tApFS_15_FusionMiddleTree_Value_)
    eApFS_ObjectType_16_FusionWriteBack       = 0x0016, // Fusion devices writeback cache status
    eApFS_ObjectType_17_FusionWriteBackList   = 0x0017, // Fusion devices writeback cache list
    eApFS_ObjectType_18_EncryptionState       = 0x0018, // Encryption
    eApFS_ObjectType_19_GeneralBitmap         = 0x0019, // General Bitmap
    eApFS_ObjectType_1A_GeneralBitmapTree     = 0x001A, // General Bitmap Tree (keys - uint64, keys - uint64)
    eApFS_ObjectType_1B_GeneralBitmapBlock    = 0x001B, // General Bitmap Block
    eApFS_ObjectType_00_Invalid               = 0x0000, // Non-valid as a type or absent subtype
    eApFS_ObjectType_FF_Test                  = 0x00FF  // Reserved for testing (never stored on media)
    eApFS_ObjectType_FF_Test                  = 0x00FF  // Reserved for testing (never stored on media)
};

enum eApFS_ObjectFlag
{
    eApFS_ObjectFlag_Virtual         = 0x0000, // Virtual object
    eApFS_ObjectFlag_Ephemeral       = 0x8000, // Ephemeral object
    eApFS_ObjectFlag_Physical        = 0x4000, // Physical object
    eApFS_ObjectFlag_NoHeader        = 0x2000, // Object with no header _tApFS_ContainerObjectHeader_ (for example, Space (bitmap) manager bitmap)
    eApFS_ObjectFlag_Encrypted       = 0x1000, // Encrypted object
    eApFS_ObjectFlag_NonPersistent   = 0x0800, // Object with this flag is never saved on media
    eApFS_ObjectFlag_StorageTypeMask = 0xC000, // Bitmask (bitmask) for для accessing к object category flags
    eApFS_ObjectFlag_ValidMask       = 0xF800  // Valid flag bit mask
};

struct tApFS_0B_ObjectsMap_Key
{
    tApFS_Ident       ObjectIdent; // Object identifier
    tApFS_Transaction Transaction; // Transaction number
};

struct tApFS_0B_ObjectsMap_Value
{
    uint32       Flags;    // Flags
    uint32       Size;     // Object size in bytes (multiple of containerру block size)
    tApFS_Address Address; // Object 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;    // Identifier  of B-Tree physical object, that stores the extent information
    tApFS_Ident SuperBlockIdent;   // Superblock identifier
    uint64      CreatedTime;       // Snapshot creation time (in nanoseconds from midnight 01/01/1970)
    uint64      LastModifiedTime;  // Snapshot last modified  time (in nanoseconds from midnight 01/01/1970)
    uint64      iNum;
    uint32      ExtentRefTreeType; // Type of B-tree, that stores extent information
    uint16      NameLength;        // Snapshot name length (including end of line character)
    uint8       Name[];            // Snapshot name (ending with 0)
};

struct tApFS_13_ObjectsMapSnapshot_Value
{
    uint32      Flags;    // Snapshot flags
    uint32      Padding;  // Reserved (for adjustment)
    tApFS_Ident Reserved; // Reserved
};

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

Un exemple de structure ApFS:

Un exemple de structure ApFS

Superblock de volume

Le superblock de volume existe pour chaque volume du système de fichiers. Il contient le nom du volume, l'identifiant (ID) et un horodatage. De la même manière que le superblock conteneur, il contient un pointeur vers une carte de bloc qui représente les ID de bloc pour bloquer les décalages. De plus, le Volume Superblock contient un pointeur vers le répertoire racine qui est stocké en tant que nœud.

Décalage (HEX) Type Id Description
0 tApFS_COH Header Container Object Header
20 uint32 MagicNumber (APSB) Une valeur qui peut être utilisée pour vérifier la lecture d'une instance de Volume Superblock
24 uint32 IndexInSuperBlock Index d'identifiant d'objet de ce volume dans le tableau de volume du conteneur
28 uint64 Features Bitmap des principales fonctionnalités utilisées par le volume
30 uint64 ReadOnlyFeatures Bitmap des principales fonctionnalités (lecture seule) utilisées par le volume
38 uint64 IncompatibleFeatures Bitmap des fonctionnalités de volume incompatibles
40 uint64 LastUnmountTime Heure du dernier démontage du volume (en nanosecondes à partir de minuit du 01/01/1970)
48 uint64 ReservedBlocksCount Le nombre de blocs réservés pour allouer le volume
50 uint64 QuotaBlocksCount Le nombre maximum de blocs que ce volume peut allouer
58 uint64 AllocatedCount Le nombre de blocs actuellement alloués au système de fichiers de ce volume
60 uint8 MetaCryptoState[20] Informations sur la clé utilisée pour chiffrer les métadonnées de ce volume (wrapped_meta_crypto_state_t instance)
74 uint32 RootTreeType Type d'arborescence de dossiers racine (typiquement: type de(eApFS_ObjectFlag_Virtual << 16) \ eApFS_ObjectType_02_BTreeRoot, subtype of eApFS_ObjectType_0E_FileSystemTree)
78 uint32 ExtentRefTreeType Type d'arborescence de liaison d'étendue (typiquement: type de (eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot, subtype of OBJECT_TYPE_BLOCKREF)
7C uint32 SnapshotMetaTreeType Type d'arborescence de métadonnées d'instantané (typiquement: type de (eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot, subtype of OBJECT_TYPE_BLOCKREF)
80 tApFS_Ident ObjectsMapIdent Identifiant de l'objet physique de la carte d'objets de volume
88 tApFS_Ident RootTreeIdent Identifiant de l'objet virtuel de l'arborescence des dossiers racine
90 tApFS_Ident ExtentRefTreeIdent Identifiant de l'objet physique de l'arborescence des liens d'extension
98 tApFS_Ident SnapshotMetaTreeIdent Identificateur de l'objet virtuel de l'arborescence des métadonnées de l'instantané
A0 tApFS_Transaction RevertToXid Numéro de transaction de l'instantané auquel le volume sera renvoyé
A8 tApFS_Ident RevertToSuperBlock Identifiant de l'objet physique du VS vers lequel retournera le volume
B0 uint64 NextObjectIdent Prochain identifiant à attribuer à l'objet du système de fichiers dans le volume.
8 uint64 NumberOfFiles Le nombre de fichiers normaux dans le volume
C0 uint64 NumberOfDirectories Le nombre de dossiers dans le volume
C8 uint64 NumberOfSymbolicLinks Nombre de liens symboliques dans le volume
D0 uint64 NumberOfOtherObjects Nombre d'autres objets dans le volume (hors x0B8_NumberOfFiles, x0C0_NumberOfDirectories and x0C8_NumberOfSymbolicLinks)
D8 uint64 NumberOfSnapshots Nombre de clichés dans ce volume
E0 uint64 TotalBlocksAllocated Nombre total de blocs alloués par ce volume
E8 uint64 TotalBlocksFreed Nombre total de blocs libérés par ce volume
F0 tApFS_Uuid Uuid
100 uint64 LastModifiedTime Heure du dernier changement de ce volume (en nanosecondes à partir de minuit le 01/01/1970)
108 uint64 Flags
110 tApFS_0D_FSM FormattedBy Informations sur le logiciel qui a créé ce volume
140 tApFS_0D_FSM ModifiedBy[8] Informations sur le logiciel qui a modifié ce volume
2C0 uint8 VolumeName[256] UTF-8 String Zero Volume Name
3C0 uint32 NextDocumentIdent Identifiant suivant du document à affecter (stocké dans le champ étendu APFS_0E_TYPE_DOCUMENT_ID du document)
3C4 uint16 Role Bitmap de rôle de volume
3C6 uint16 Reserved
3C8 tApFS_Transaction RootToXid Numéro de transaction de cliché pour non-racine ou zéro pour racine
3D0 tApFS_Ident EncryptStateIdent État actuel du chiffrement ou du déchiffrement, ou zéro si aucun chiffrement

Une vue détaillée de APFS:

Une image APFS détaillée

Point de contrôle

Un point de contrôle est un état temporaire du conteneur. Chaque point de contrôle est initialisé avec Container Superblock et l'état actuel est généralement le dernier. Un point de contrôle inclut à la fois les métadonnées du conteneur et du volume. Les points de restauration et les instantanés sont similaires les uns aux autres. La principale différence entre un point de contrôle et un instantané est la capacité de l'utilisateur à restaurer le système de fichiers à partir d'instantanés stockés à l'aide de l'API du système de fichiers.

Descripteur de superblock de point de contrôle

Ce bloc contient des informations sur les structures de métadonnées dans ApFS et il est le bloc précédant le descripteur. L'information la plus importante dans ce bloc est l'emplacement de la structure Bitmap (BMS), l'ancien fichier d'allocation dans HFS+.

Descripteur de superblock de point de contrôle:

Descripteur de superblock de point de contrôle

Structures bitmap (bitmap ou volume map)

Enregistrements des blocs utilisés et inutilisés. Il n'y a qu'un seul système bitmap de volume qui couvre l'ensemble du conteneur et qui est commun à tous les volumes du système de fichiers. ApFS utilise une collection de blocs pour stocker les structures Bitmap (BMS).

Dans ApFS, le bitmap est commun à tous les volumes du conteneur. Chaque volume a une citation des blocs dans le conteneur mais les blocs ne sont pas dans des zones allouées. Le lien vers la carte de volume est stocké dans Container Superblock Bitmap Descriptor, qui contient les informations sur le niveau le plus élevé de la structure, le Bitmap Descriptor (BMD). L'image ci-dessous montre sa structure de base. Il est divisé en niveaux où le BMD est au sommet et définit les limites. En bas, vous pouvez voir des Blocs Bitmap qui gardent une trace des blocs dans le conteneur. Un octet dans le BMB garde la trace de huit blocs, où chaque bit fournit l'état d'allocation. Chaque bit est l'état d'un seul bloc.

Blocs bitmap

Tables

Les tables sont utilisées dans les catalogues et extensions B-tree, les listes de volumes et la carte d'ID d'objet.

Les tableaux utilisés dans ApFS sont de petites bases de données à bloc unique avec des objectifs légèrement différents dans les structures du système de fichiers. Le champ de type de tableau est composé de 2 octets situés dans le bloc avec le décalage 0x20 directement après l'en-tête du nœud. Il existe huit types de tableaux différents, de 0 à 7. Les 2 octets suivants fournissent le niveau de tableaux à partir de 0 et vers le haut. Un tableau de niveau deux contiendra des enregistrements faisant référence à la table de base de niveau 1. Les tableaux de niveau 0 font référence à des blocs qui contiennent souvent des métadonnées de fichier.

Les types de tableaux sont de structure différente mais l'en-tête de table de 24 octets est le même pour tous les types de tableaux.

L'image ci-dessous montre un exemple de structure d'en-tête de tableau:

L'image ci-dessous montre un exemple de structure d'en-tête de tableau

Description des significations des champs dans la structure d'en-tête:

Décalage (HEX) Champ Type de données Description
20 tableType uint16 Valeurs possibles 0-7. C'est un tableau de type 1
22 tableLevel uint16 Indique un niveau d'un B-Tree.
24 tableRecords uint16 Nombre d'enregistrements dans le tableau
26 Unknown 1 uint16
28 Unknown 2 uint16
2A tableIndexSize uint16 Taille de la zone d'index du tableau.
2C tableKeyAreaSize uint16 Taille de la zone clé du tableau.
2E tableFreeSpaceSize uint16 Taille de la zone libre. La zone de données du tableau se termine au décalage
0x38+tableIndexSize+tableKeyAreaSize+tableFreeSpaceSize. 0x38 + 0x80 + 0x170 + 0xd58.
30 Unknown 3 uint16
32 Unknown 4 uint16
34 Unknown 5 uint16
36 Unknown 6 uint16

Une disposition typique de différents tableaux est illustrée ici :

Une disposition typique pour différents tableaux

Tous les éléments de cette image ne sont pas utilisés dans tous les tableaux. Il montre un bloc complet avec l'en-tête de bloc/nœud en haut. Le reste du bloc constitue le tableau.

L'en-tête du tableau est suivi de l'index de l'enregistrement. Il en existe deux types. Le premier est à 2 valeurs seulement: décalage dans les clés et décalage dans la section des données pour chaque élément de Uint16. L'autre utilise 4 valeurs Uint16 avec décalage et longueur pour les sections de clé et de données. L'index d'enregistrement de tableau contient des informations sur les clés et les enregistrements de données du tableau. Une autre distinction entre les types de tableaux est leur utilisation de pieds de page.

Les types de tableau 1, 3, 5 et 7 utilisent un pied de page de 0x28 octets à la fin du bloc. Dans ces tableaux, tous les décalages de données sont liés au décalage 0xFD8, et le pied de page contient différentes valeurs spécifiques au type de tableau. D'autres types de tableaux n'ont pas de pied de page et toutes les références au contenu de la section de données sont liées à la fin du bloc.

Dans les arbres B à plusieurs couches, les types de tableau 1, 3, 5 ou 7 sont au niveau le plus élevé car ils ont un pied de page. Le pied de page est utilisé pour stocker des informations sur l'arbre B complet. L'une des valeurs du pied de page est le nombre total d'enregistrements dans l'ensemble de la structure B-tree.

La définition de table commence au décalage 0x20 dans le bloc avec le type de table, le nombre de lignes, la taille de la section clé et l'espace entre la section clé et la section de données. Après la configuration du tableau, les définitions de ligne et de colonne du tableau sont décrites à partir du décalage 0x38. Le tableau contient un en-tête, des définitions d'enregistrement, des sections de clé et de données. Certains types de tableaux ont également un pied de page. L'en-tête commence au décalage 0x20 dans le bloc et a une longueur de 0x18 octets. Cet en-tête de type de table commence par une valeur de 16 bits qui représente le type de tableau. Il est suivi de deux octets représentant le niveau dans l'arbre B auquel le tableau est utilisé. Les deux octets suivants représentent le nombre de lignes sur le tableau. La longueur de l'enregistrement pour la définition de balayage se trouve à 0x2A suivi d'un Uint16 qui enregistre la longueur de la section clé. Ceci est suivi par l'écart entre la clé et la section des données. Le pied de table est toujours de 0x28 octets et occupe toujours la fin du bloc. Les indices de tableau sont de 4 ou 8 octets chacun. Sur les index de 8 octets, les deux premiers Uint16 sont le décalage et la longueur de l'enregistrement de clé. Les deux Uint16 suivants sont le décalage et la longueur de l'enregistrement de données dans le tableau. Les tableaux avec des indices de 4 octets ont deux valeurs Uint16 qui sont le décalage de la clé et de l'enregistrement de données. La longueur des données dans les deux enregistrements est prédéfinie. Dans les tableaux avec un pied de page, le décalage par rapport à l'enregistrement de données est relatif au début du pied de page (0x28), et pour les autres types de tableaux, il est relatif à la fin du bloc.

Le décalage 0x18 dans le pied de page (décalage 0xFF dans un bloc de 4 Ko) est le nombre d'enregistrements dans le tableau et tous les tableaux sous-jacents (s'il s'agit d'une table avec un niveau supérieur à 0 dans le décalage 0x22). Le décalage 0x20 dans le pied de page correspond au numéro d'enregistrement suivant dans le tableau.

Tableau 0

Le type de table 0 est situé dans la structure du catalogue B-tree entre les nœuds feuilles et le nœud racine. Les valeurs Unknown 3-6 semblent être le décalage et la longueur de la clé, le décalage des données et la longueur du prochain enregistrement disponible. S'il n'y a pas d'enregistrements d'index libres, les décalages sont définis sur 0xFFFF et la longueur 0x00.

Les enregistrements du tableau sont quatre valeurs Uint16. Les 2 premiers sont le décalage et la longueur de la valeur dans la section clé et les suivants sont le décalage et la valeur du contenu dans la section données.

Un exemple de type de tableau 0 pourrait être l'ID de nœud de catalogue et la clé nommée dans la section clé et l'ID d'objet dans la section données. Ce tableau n'a pas de pied de page.

Tableau 1

Le type de tableau 1 a un pied de page et l'index de table contient 4 valeurs de 16 bits où les 2 premières valeurs sont le décalage vers l'enregistrement dans la section clé et la longueur de l'enregistrement. Les 2 valeurs suivantes fournissent le décalage de l'enregistrement dans la section des données et la longueur de cet enregistrement. Ce tableau est fréquemment observé à la fois dans la structure du catalogue B-tree et dans le B-tree Extents pour le nœud de niveau supérieur. Les exemples de valeurs sont ID parent et un nom de clé (nom de fichier/dossier dans la structure du catalogue et numéro de début de bloc dans l'arborescence B d'étendue) dans la section clé et un ID d'objet lorsqu'il est utilisé comme nœud racine dans la structure du catalogue ou un numéro de bloc lorsqu'il est utilisé dans l'arborescence B d'étendue.

Examples of this table are provided below:

Des exemples de ce tableau sont fournis ci-dessous

Table 2

Tableau de type 2. Initialement ce tableau est identique au précédent mais n'a pas de pied de page. Ce type de tableau est très fréquemment rencontré dans les nœuds feuilles de la structure du catalogue où la section clé est représentée par un ID parent et un nom de clé.

Table type 3

Ce type de tableau est similaire au précédent. L'index de tableau est le même que dans le type de tableau 1. Les valeurs typiques dépendent de la structure dans laquelle elles sont utilisées. Dans la structure du catalogue et l'arborescence B des étendues, ce tableau est souvent utilisé comme nœud de niveau supérieur dans de petits volumes où le nœud racine sert à la fois de nœud racine et de nœud feuille. Dans un tel exemple d'utilisation, l'enregistrement de clé peut être ID parent. La clé de nom et l'enregistrement de données peuvent être un fichier de métadonnées avec de grandes variations de taille.

D'autres enregistrements typiques peuvent être l'ID d'objet et le type d'objet dans l'enregistrement de clé, avec des étendues d'informations sur les fichiers et les enregistrements de données. Le type de tableau 3 a un pied de page.

Exemple de tableau:

Exemple de tableau

Tableau 4

Le type de tableau 4 est quelque peu différent des précédents. Le tableau n'a pas de pied de page et l'index du tableau n'a que 2 valeurs par enregistrement, le décalage de l'enregistrement dans la section clé, puis 1 pour la section données. La longueur du contenu est fixée avec 16 octets dans la section clé et 8 octets dans la section données. Les décalages dans la section des données sont relatifs à la fin du bloc.

Type de tableau 5

Le type de tableau 5 est très similaire au type 4. La seule différence est que ce type a un pied de page et que tous les décalages vers les données proviennent de offset-0x28 Les enregistrements dans la section clé sont de 16 octets et de 8 octets dans la section données. Ce type de table est principalement observé aux nœuds de niveau supérieur dans la structure du catalogue et dans les conteneurs plus grands avec des arbres B à plusieurs niveaux.

Type de tableau 6

Le type de tableau 6 est également très similaire au type 4. L'index de tableau n'a que le décalage par rapport au contenu dans la section clé et données et non la longueur. Les longueurs sont prédéfinies. Chaque enregistrement fait 16 octets. Il n'y a pas de pied de page pour ce type de tableau. Ce type de table est souvent observé dans les nœuds feuilles de la structure du catalogue. Le contenu typique de la section clé comprend l'ID d'objet et l'ID de superblock de point de contrôle de volume, tandis que la section de données enregistre généralement la taille des données et un numéro de bloc.

Type de tableau 7

Le type de tableau 7 est très similaire au type 6. La seule différence est le pied de page qui contient des informations similaires à celles décrites pour le type de tableau 1. Ce type de tableau est observé dans un large éventail de structures et est souvent rencontré dans les niveaux les plus élevés des structures multicouches ou dans les structures à une seule couche telles que les déclarations de volume.

Exemple

Exemple

Résumé du tableau

Le tableau suivant montre les propriétés de base des différents types de tableau:

Type Pied de page Décalage de la section clé Longueur de la section clé Décalage de la section de données Longueur de la section de données Longueur de clé Longueur des données
0 NO uint16 uint16 uint16 uint16 Varies Possible
1 YES uint16 uint16 uint16 uint16 variables Possible
2 NO uint16 uint16 uint16 uint16 Varies Possible
3 YES uint16 uint16 uint16 uint16 Varies Possible
4 NO uint16 uint16 16 bytes 8 bytes
5 YES uint16 uint16 16 bytes 8 bytes
6 NO uint16 uint16 16 bytes 16 bytes
7 YES uint16 uint16 16 bytes 16 bytes

L'un des blocs les plus importants de la structure du catalogue B-tree est le nœud racine qui est le niveau le plus élevé dans la structure des dossiers. Ce nœud utilise des clés de recherche de longueur variable. L'une des fonctionnalités améliorées d'ApFS est la recherche rapide dans les répertoires (FDS). L'une des valeurs qui est étroitement liée à cette fonctionnalité est le nombre de tous les enregistrements dans l'arborescence située dans le pied de tableau.

Dans la structure du catalogue B-tree, le nœud racine n'a que 2 options dans la sélection du tableau à utiliser puisque les deux ont des pieds de page. Le type de table 3 agissant en tant que nœud racine n'est observé que dans de petits conteneurs avec peu de fichiers où le nœud racine est également un index et un nœud feuille.

Dans la carte d'objets B-tree, seul le type de tableau 5 est utilisé pour le nœud racine, sauf dans le cas de très petites structures où le TYPE 7 peut être rencontré.

L'interprétation des tableaux montre que les tableaux TYPE 0 et 2 ont les mêmes artefacts. Il en est de même entre les tableaux TYPE 1 et 3. Ces tableaux semblent avoir un objectif différent selon la structure dans laquelle elles se trouvent.

Clichés

Snapshots -Clichés sont des "images" en lecture seule du système de fichiers dans le volume. Le système d'exploitation peut utiliser ces instantanés pour rendre les sauvegardes plus efficaces, et grâce à leur utilisation, Time Machine fonctionnera plus rapidement. Grâce à la prise en charge par ApFS des images instantanées Time Machine, vous n'avez plus besoin d'enregistrer plusieurs copies complètes du fichier sur votre disque - il peut simplement suivre des modifications spécifiques. Par exemple, si vous modifiez un fichier, modifier une seule diapositive à l'aide de HFS+ signifie enregistrer deux copies du fichier, une dans laquelle vos nouvelles modifications sont enregistrées et une au cas où vous voudriez revenir. Dans APFS, il enregistre simplement le fichier source et enregistre les différences entre le fichier source et toutes les versions mises à jour, effectuant ainsi la même tâche dans beaucoup moins d'espace. Tout comme dans le cas des améliorations de Fusion Drive, les informations occupent moins d'espace sur le disque.

Bien que ApFS soit considérablement inférieur dans ses capacités au ZFS 128 bits, qui est pris en charge par Linux, FreeBSD et d'autres systèmes d'exploitation libres, mais de la part d'Apple, c'est un pas dans la bonne direction.

Comme mentionné ci-dessus, Apple a longtemps essayé de porter ZFS sur OS X. Plus tard, OpenZFS a été implémenté pour OS X (O3X) et MacZFX.

Nœuds

Les nœuds sont des conteneurs flexibles utilisés pour stocker différents types d'entrées. Ils peuvent faire partie d'un arbre B-tree ou exister seuls. Les nœuds peuvent contenir des entrées flexibles ou de taille fixe. Un nœud commence par une liste de pointeurs vers les clés d'entrée et les enregistrements d'entrée. Ainsi, pour chaque entrée, le nœud contient un en-tête d'entrée au début du nœud, une clé d'entrée au milieu du nœud et un enregistrement d'entrée à la fin du nœud.

Nœuds
position Taille type ID
0 4 uint32 alignement
4 4 uint32 ENTRY_COUNT
10 2 uint16 HEAD_SIZE
16 8 entry meta_entry
24 ... entry entrées (repeat entry_count times)

En-tête de nœud:

Décalage Champ Type de données Commentaires
0 Checksum Uint64 Fletchers Checksum Algorithm
8 ID Uint64 Object-ID or Block#
10 Checkpoint Uint64
18 Unknown Uint16 Niveau possible en B-Tree
1A Unknown Uint16 Toutes les observations montrent la valeur 0x4000
1C Unknown Uint16 Flag?
1E Unknown Uint16 Valeur souvent vue 0x0b, 0x0e et 0x0f

Gestionnaire d'espace

Space Manager - Gestionnaire d'espace est utilisé pour gérer les blocs alloués dans le conteneur ApFS. Il stocke le nombre de blocs libres et un pointeur vers les fichiers d'informations d'allocation.

position Taille type ID
0 4 uint32 taille de bloc
16 8 uint64 totalblocks
40 8 uint64 freeblocks
144 8 uint64 prev_allocationinfofile_block
352 8 uint64 allocationinfofile_block

Fichier d'informations concernant l'allocation

Le fichier d'informations d'allocation fonctionne comme un en-tête manquant pour le fichier d'allocation. Il stocke la longueur, la version et le décalage du fichier d'allocation des fichiers d'allocation.

position Taille type 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

Fichier et dossier B-tree

Il enregistre tous les fichiers et dossiers du volume. Il joue le même rôle que le fichier catalogue dans HFS+.

Étendues (B-tree extents)

Un B-Tree séparé de toutes les étendues par volume. Les étendues sont des références au contenu du fichier avec des informations sur l'endroit où le contenu des données commence et la longueur des données dans les blocs. Un fichier avec un certain contenu aura au moins une extension. Un fichier fragmenté aura plusieurs extensions. L'étendue B-Tree est une structure distincte.

Dans chaque enregistrement de fichier, les étendues sont définies pour chacun des fichiers dans le B-Tree. Cette structure d'étendue distincte fait partie de la fonctionnalité d'instantané.

inodes 64 bits (descripteurs d'index)

Les inodes 64 bits augmentent considérablement l'espace de noms par rapport aux identifiants 32 bits dans HFS+. Le système de fichiers ApFS 64 bits prend en charge plus de 9 quintillions de fichiers sur chaque volume. Cela devrait suffire à tout le monde, comme l'a dit Bill Gates.

ApFS offre la possibilité de restaurer certains états du système de fichiers, y compris la restauration d'anciennes versions ou de versions supprimées de fichiers. Le superblock conteneur contient un lien vers l'élément appelé point de contrôle. Un tel point de contrôle fait référence au superblock conteneur précédent qui stocke les informations sur un état plus ancien du système de fichiers. De cette façon, nous pouvons essayer de restaurer plusieurs états plus anciens du système de fichiers en analysant cette chaîne de superblocks à l'intérieur du conteneur.

Abdelhamid Balti

Auteur: , Rédacteur technique

AbdelHamid Balti est un rédacteur technique chez Hetman Software. Il gère les tutoriels, les procédures et les revues détaillées concernant le fonctionnement des outils de l'entreprise avec toutes sortes de périphériques de stockage de données.

Mykhailo Miroshnychenko

Éditeur: , Rédacteur technique

Mykhailo Miroshnychenko est l'un des principaux programmeurs de la société Hetman Software. S'appuyant sur quinze années d'expérience en développement logiciel, il partage ses connaissances avec les lecteurs de notre blog. En plus de la programmation, Mykhailo est un expert dans le domaine de la récupération de données, des systèmes de fichiers, des périphériques de stockage de données et des matrices RAID.

Recommandé pour vous

Vous êtes accueilli par l'assistant Hetman Software, créé sur la base de l'intelligence artificielle.
Démarrer la discussion