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.
- Conteneurs et volumes
- En-tête de bloc
- Superblock de conteneurs
- Superblock de volume
- Point de contrôle
- Descripteur de superblock de point de contrôle
- Structures bitmap (bitmap ou volume map)
- Tables
- Résumé du tableau
- Clichés
- Nœuds
- Gestionnaire d'espace
- Fichier d'informations concernant l'allocation
- Fichier et dossier B-tree
- Étendues (B-tree extents)
- inodes 64 bits (descripteurs d'index)
- Questions et réponses
- Commentaires
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.
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:
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:
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:
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.
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:
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 :
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:
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:
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
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.
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.
1. Utilisez le chiffrement de fichier pour crypter les données sensibles.
2. Créez des copies de sauvegarde régulières et vérifiez-les pour vous assurer qu'elles sont valides.
3. Utilisez des outils de journalisation et de surveillance pour surveiller les activités sur le système de fichiers.
4. Mettez à jour le système d'exploitation et les logiciels régulièrement pour corriger les vulnérabilités et les failles de sécurité.
5. Configurez un pare-feu et des stratégies de contrôle d'accès pour limiter l'accès non autorisé à vos données.
6. Désactivez les services inutiles qui peuvent être utilisés pour accéder à vos données.
La récupération de données sur un système de fichiers APFS peut échouer dans les cas suivants :
- Les fichiers sont corrompus ou endommagés.
- Le système de fichiers a subi des changements structurels importants.
- Le volume a été reformaté ou partitionné.
- Les données ont été supprimées ou perdues.
- Les données sont cryptées ou protégées par un mot de passe.
1. Utilisez un mot de passe fort et unique pour protéger votre système de fichiers APFS.
2. Activez le cryptage des fichiers pour protéger vos données sensibles.
3. Utilisez des outils de sauvegarde réguliers pour vous assurer que vos données sont en sécurité en cas de problème.
4. Utilisez des outils de contrôle d'accès pour empêcher les utilisateurs non autorisés d'accéder aux fichiers.
5. Installez des mises à jour régulières pour vous assurer que votre système est à jour et protégé contre les dernières menaces.
1. Utilisez des sauvegardes automatiques régulières et des sauvegardes incrémentielles. Utilisez des outils de sauvegarde tels que Time Machine pour créer des sauvegardes régulières et complètes de vos données sur un disque externe.
2. Utilisez des outils de vérification de l’intégrité des données, tels que fsck_apfs, pour vérifier l’intégrité des fichiers et des systèmes de fichiers sur votre système APFS.
3. Utilisez des outils de cryptage pour crypter vos données sensibles afin de les protéger contre la perte et le vol.
4. Utilisez des outils de protection contre la corruption des données, tels que le journaling et le contrôle des erreurs, pour empêcher la corruption des données sur votre système APFS.
5. Utilisez des outils de restauration pour restaurer vos données à partir d’une sauvegarde si nécessaire.