Recuperación de Datos en APFS: Algoritmo y Estructura del Sistema de Archivos
ApFS ofrece la capacidad de restaurar estados específicos del sistema de archivos, incluidas versiones antiguas o eliminadas de archivos. El superbloque de contenedores contiene un enlace a la estructura del punto de control. El punto de control se refiere al superbloque anterior del contenedor, que contiene información en el estado anterior del sistema de archivos. Por lo tanto, es posible restaurar varios estados antiguos analizando la cadena del superbloque de contenedores.
- Contenedores y Volumen
- Block Header (Encabezado de bloque)
- Container Superblock
- Volume Superblock (Superbloque de Volumen)
- Checkpoint (Punto de Control)
- Checkpoint Superblock Descriptor (Descriptor de punto de control de superbloque)
- Bitmap Structures (Mapa de bits o mapa de volumen)
- Tablas (Tables)
- Resumen de tablas
- Instantáneas (Snapshots)
- Nodes (nodos)
- Administrador de Espacio (Space Manager)
- Allocation info file (Archivo de información de distribución)
- Archivo y carpeta de árbol B
- Extents (Extensiones de árbol B)
- 64-bit inodes (index descriptors) - descriptores de índices
- Preguntas y respuestas
- Comentarios
Contenedores y Volumen
La estructura del sistema de archivos APFS tiene la forma de un árbol b, donde el directorio de datos raíz son las hojas de este árbol. Todas las ramas almacenan solo enlaces al siguiente nodo hasta que llegan a las hojas. El sistema de archivos utiliza contenedores como ubicaciones de almacenamiento. Estos contenedores pueden contener varios volúmenes. También es el objeto principal para almacenar datos. Para un volumen, el tamaño del contenedor debe ser superior a 512 MB, para dos volúmenes, más de 1024 MB, etc.
La siguiente figura muestra la estructura del sistema de archivos “ApFS”.
Cada elemento de esta estructura (excepto el archivo de asignación) comienza con un encabezado de bloque de 32 bytes que contiene información general sobre el bloque. El siguiente es el cuerpo del sistema de archivos. Consta de los siguientes elementos:
- 0x01: Superbloque del contenedor (Container Superblock)
- 0x02: Nodo (Node)
- 0x05: Administrador de Espacio (Space manager)
- 0x07: Ubicación de Archivo (Allocation Info File)
- 0x0C: Punto de Control (Checkpoint)
- 0x0D: Superbloque de volumen (Volume Superblock)
Los contenedores suelen ser exactamente iguales a las entradas de una tabla de particiones GUID (GPT). Tienen su propio esquema de asignación de disco y protección contra fallas. Cada contenedor contiene uno o más volúmenes, cada uno con su propio espacio de nombres, conjunto de archivos y directorios.
El sistema de archivos «ApFS» no es compatible directamente con el programa «RAID», pero se puede utilizar con volúmenes RAID de Apple para admitir la creación de bandas (RAID 0), duplicación (RAID 1) y empalme (JBOD).
Con un índice de 64 bits los volúmenes «ApFS» admite hasta 9 quintillones (1018) de archivos.
El nuevo sistema de archivos de Apple usa nanosegundos para establecer marcas de tiempo. En HFS +, las marcas de tiempo se han establecido en el segundo más cercano. Esto reducirá la cantidad de fallas durante las transferencias de datos y otras operaciones de archivos.
«ApFS» tiene un cifrado incorporado y utiliza AES-XTS o AES-CBC, según el dispositivo. El usuario puede utilizar varias claves de cifrado para mantener la seguridad de los datos incluso en caso de «Ataque cibernético físico» de los medios.
Esta no es una lista completa de las innovaciones que posee «ApFS».
Las secciones formateadas en «ApFS», no son reconocidas por OS X 10.11 Yosemite o sistemas operativos anteriores.
Block Header (Encabezado de bloque)
Cada estructura del sistema de archivos en «ApFS» comienza con un encabezado de bloque. Y el encabezado en sí comienza con una suma de comprobación. Otra información en el encabezado incluye la versión de copia en escritura del bloque, el ID del bloque y su tipo.
Parcialidad | Tamaño | Tipo | ID |
---|---|---|---|
0 | 8 | uint64 | Suma de control (checksum) |
8 | 8 | uint64 | Identificador (block_id) |
16 | 8 | uint64 | Versión (version) |
24 | 2 | uint16 | Tipo de bloque (block_type) |
26 | 2 | uint16 | Banderas (flags) |
28 | 4 | uint32 | Relleno (padding) |
De la tabla podemos ver que 1uint = 1 bit, 8 bits = 1 byte, de eso uint64 = 8, uint32 = 4 y uint16 = 2 bytes.
Container Superblock
Superbloque del contenedor (Container Superblock) – es el punto de entrada al sistema de archivos. Debido a la estructura del sistema de archivos con contenedores y volúmenes de disquete, la distribución debe manejarse a nivel de contenedor. El superbloque contenedor contiene información sobre el tamaño del bloque, su número y punteros en el administrador de espacio para esta tarea. Además, el superbloque almacena ID de bloque para todos los volúmenes. Para asignar identificadores de bloque a bloques de desplazamiento, se almacena un puntero al mapa de bloques del árbol B. Este árbol contiene entradas para cada volumen con su ID y compensación. El superbloque de contenedores es el nivel más alto en el sistema de archivos.
Tiene el siguiente tipo:
Parcialidad (HEX) | Tipo | Id | Descripción |
---|---|---|---|
0 | tApFS_COH | Header | Encabezado del objeto contenedor (Container Object Header) |
20 | uint32 | MagicNumber (NXSB) | El valor a verificar para leer el Superbloque del contenedor. |
24 | uint32 | BlockSize | Tamaño del bloque de contenedor (en bytes) |
28 | uint64 | BlocksCount | Número de bloques de contenedores |
30 | uint64 | Features | Mapa de bits de las principales funciones del contenedor |
38 | uint64 | ReadOnlyFeatures | Mapa de bits de las funciones básicas del contenedor (solo de lectura) |
40 | uint64 | IncompatibleFeatures | Mapa de bits de las principales funciones incompatibles del contenedor |
48 | tApFS_Uuid | Uuid | UUID del contenedor |
58 | tApFS_Ident | NextIdent | Siguiente identificador para nuevo objeto lógico o virtual |
60 | tApFS_Transaction | NextTransaction | Siguiente número de transacción |
68 | uint32 | DescriptorBlocks | Número de bloques utilizados por el descriptor |
6C | uint32 | DataBlocks | Número de bloques usados por datos |
70 | tApFS_Address | DescriptorBase | Dirección base de un descriptor o identificador de un objeto físico con un árbol de direcciones |
78 | int32 | DataBase | Dirección de base de datos o identificador de un objeto físico con un árbol de direcciones |
80 | uint32 | DescriptorNext | Siguiente índice de descriptor |
84 | uint32 | DataNext | Siguiente índice de datos |
88 | uint32 | DescriptorIndex | El índice del primer elemento válido en el segmento descriptor. |
8C | uint32 | DescriptorLength | El número de bloques en el segmento descriptor utilizado por el superbloque |
90 | uint32 | DataIndex | El índice del primer elemento válido en el segmento de datos |
94 | uint32 | DataLength | Número de bloques en el segmento de datos utilizados por el superbloque |
98 | tApFS_Ident | SpaceManagerIdent | Administrador de espacio de ID de entidad |
A0 | tApFS_Ident | ObjectsMapIdent | El identificador de objeto físico del mapa de objetos del contenedor |
A8 | tApFS_Ident | ReaperIdent | Identificador de entidad |
B0 | uint32 | ReservedForTesting | |
B4 | uint32 | MaximumVolumes | El número máximo posible de volúmenes en un contenedor |
B8 | tApFS_Ident | VolumesIdents[100] | Volumen de matriz de identificadores de objetos virtuales |
3D8 | uint64 | Counters[32] | Matriz de contadores que almacenan información sobre el contenedor |
4D8 | tApFS_BlockRange | BlockedOutOfRange | Rango físico de bloques que no se pueden usar |
4E8 | tApFS_Ident | MappingTreeIdent | El identificador de un objeto físico en el árbol que se usa para rastrear los objetos que se mueven desde el almacenamiento bloqueado. |
4F0 | uint64 | OtherFlags | Mapa de otras funciones de contenedor |
4F8 | tApFS_Address | JumpstartEFI | Identificación de un objeto físico con datos del controlador EFI |
500 | tApFS_Uuid | FusionUuid | UUID de contenedor de Fusion, o cero para contenedores que no son de Fusion |
510 | tApFS_BlockRange | KeyLocker | Ubicación de la marca clave del contenedor |
520 | uint64 | EphemeralInfo[4] | Matriz de campos utilizados para manipular datos lógicos |
540 | tApFS_Ident | ReservedForTesting | |
548 | tApFS_Ident | FusionMidleTreeIdent | Solo para dispositivos vinculados |
550 | tApFS_Ident | FusionWriteBackIdent | Solo para dispositivos vinculados |
558 | tApFS_BlockRange | FusionWriteBackBlocks | Bloques utilizados para el área de caché |
Con definición de tipo:
uint8 tApFS_Uuid;
uint64 tApFS_Ident;
uint64 tApFS_Transaction;
int64 tApFS_Address;
uint64 tApFS_BTreeKey;
и
struct tApFS_BlockRange
{
tApFS_Address First; // Primer bloque
uint64 Count; // Cantidad de bloques
}
struct tApFS_COH
{
uint64 CheckSum; // Suma de control del bloque
tApFS_Ident Ident; // Identificador
tApFS_Transaction Transaction; // Object change transaction number
uint16 Type; // Tipo de objeto
uint16 Flags; // Bandera de objeto
uint32 SubType; // Subtipo de objeto
};
con una lista de tipos de objetos:
enum eApFS_ObjectType
{
eApFS_ObjectType_01_SuperBlock = 0x0001, //Superbloque del contenedor
eApFS_ObjectType_02_BTreeRoot = 0x0002, // Árbol-B: nodal elemento
eApFS_ObjectType_03_BTreeNode = 0x0003, // Árbol-B: lista
eApFS_ObjectType_05_SpaceManager = 0x0005, // Administrador de espacio
eApFS_ObjectType_06_SpaceManagerCAB = 0x0006, // Administrador de espacio: dirección de segmentos
eApFS_ObjectType_07_SpaceManagerCIB = 0x0007, // Administrador de espacio: información de segmentos
eApFS_ObjectType_08_SpaceManagerBitmap = 0x0008, // Mapa de espacio libre utilizado por el Administrador de espacio
eApFS_ObjectType_09_SpaceManagerFreeQueue = 0x0009, // Espacio libre utilizado por el administrador de espacio_ (llaves - _tApFS_09_SpaceManagerFreeQueue_Key_, significado - _tApFS_09_SpaceManagerFreeQueue_Value_)
eApFS_ObjectType_0A_ExtentListTree = 0x000A, // Árbol lista extensiones (llaves – Parcialidad del principio экстента_tApFS_Address_, significado – ubicación física de datos _tApFS_BlockRange_)
eApFS_ObjectType_0B_ObjectsMap = 0x000B, // Tipo – Mapa de objetos; subType – Árbol registros mapas de objetos (llaves - _tApFS_0B_ObjectsMap_Key_, significado - _tApFS_0B_ObjectsMap_Value_)
eApFS_ObjectType_0C_CheckPointMap = 0x000C, // Mapa de puntos de control (puntos de control)
eApFS_ObjectType_0D_FileSystem = 0x000D, // Sistema de archivos volumen
eApFS_ObjectType_0E_FileSystemTree = 0x000E, // Árbol sistema de archivos (llaves comienzan с _tApFS_BTreeKey_, describe Tipo и valor de la llave)
eApFS_ObjectType_0F_BlockReferenceTree = 0x000F, // Árbol enlace a bloques (llaves - _tApFS_BTreeKey_, valor - _tApFS_0F_BlockReferenceTree_Value_)
eApFS_ObjectType_10_SnapshotMetaTree = 0x0010, // Árbol instantáneas (llaves - _tApFS_BTreeKey_, valor - _tApFS_10_SnapshotMetaTree_Value_)
eApFS_ObjectType_11_Reaper = 0x0011, // Reaper
eApFS_ObjectType_12_ReaperList = 0x0012, // Reaper List
eApFS_ObjectType_13_ObjectsMapSnapshot = 0x0013, // Árbol instantáneas mapas objetos (llaves - _tApFS_Transaction_, valor - _tApFS_13_ObjectsMapSnapshot_Value_)
eApFS_ObjectType_14_JumpStartEFI = 0x0014, // EFI Cargador
eApFS_ObjectType_15_FusionMiddleTree = 0x0015, // Árbol dispositivos conectados para el seguimiento de bloques de discos duros, SSD en caché (llave - _tApFS_Address_, valor - _tApFS_15_FusionMiddleTree_Value_)
eApFS_ObjectType_16_FusionWriteBack = 0x0016, // Estado de caché respuesta de dispositivos conectados
eApFS_ObjectType_17_FusionWriteBackList = 0x0017, // Lista de caché respuesta de dispositivos conectados
eApFS_ObjectType_18_EncryptionState = 0x0018, // Cifrado
eApFS_ObjectType_19_GeneralBitmap = 0x0019, // General Bitmap
eApFS_ObjectType_1A_GeneralBitmapTree = 0x001A, // Árbol General Bitmap (keys - uint64, keys - uint64)
eApFS_ObjectType_1B_GeneralBitmapBlock = 0x001B, // Bloque General Bitmap
eApFS_ObjectType_00_Invalid = 0x0000, // No es válido como tipo o no está como subtipo
eApFS_ObjectType_FF_Test = 0x00FF // Reservado para pruebas (nunca se guarda en dispositivo)
eApFS_ObjectType_FF_Test = 0x00FF // Reservado para pruebas (nunca se guarda en dispositivo)
};
enum eApFS_ObjectFlag
{
eApFS_ObjectFlag_Virtual = 0x0000, // Objeto virtual
eApFS_ObjectFlag_Ephemeral = 0x8000, // Objeto lógico
eApFS_ObjectFlag_Physical = 0x4000, // Objeto físico
eApFS_ObjectFlag_NoHeader = 0x2000, // Objeto sin título _tApFS_ContainerObjectHeader_ (por ejemplo, mapa (bitmap) administrador de espacio)
eApFS_ObjectFlag_Encrypted = 0x1000, // Objeto cifrado
eApFS_ObjectFlag_NonPersistent = 0x0800, // Objeto con estas banderas nunca se guardaran en dispositivo
eApFS_ObjectFlag_StorageTypeMask = 0xC000, // Битовая (bitmask) máscara para permiso a banderas de objetos de categoría
eApFS_ObjectFlag_ValidMask = 0xF800 // Bandera real de máscara de bits
};
struct tApFS_0B_ObjectsMap_Key
{
tApFS_Ident ObjectIdent; // Identificador de Objeto
tApFS_Transaction Transaction; // Número de transacción
};
struct tApFS_0B_ObjectsMap_Value
{
uint32 Flags; // Bandera
uint32 Size; // tamaño objeto en bites (tamaño corto de bloque del contenedor)
tApFS_Address Address; // Dirección del objeto
};
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; // Identificador de objeto físico árbol-B, en el que se guarda la información sobre la extención
tApFS_Ident SuperBlockIdent; // Identificador del superbloque
uint64 CreatedTime; // Hora de instantánea (en nanosegundos desde medianoche de 01/01/1970)
uint64 LastModifiedTime; // Hora de instantánea (en nanosegundos desde medianoche de 01/01/1970)
uint64 iNum;
uint32 ExtentRefTreeType; // Tipo árbol-B, en el que se guarda la información sobre la extención
uint16 NameLength; // Largo de nombre de la instantánea incluye símbolos al final de la fila)
uint8 Name; // Nombre instantánea (termina en 0)
};
struct tApFS_13_ObjectsMapSnapshot_Value
{
uint32 Flags; // Banderas de instantaneas
uint32 Padding; // Reservado (para correcciones)
tApFS_Ident Reserved; // Reservado
};
struct tApFS_15_FusionMiddleTree_Value
{
tApFS_Address fmv_lba;
uint32 fmv_length;
uint32 fmv_flags;
};
Ejemplo de la estructura de un sistema de archivos ApFS:
Volume Superblock (Superbloque de Volumen)
Superbloque de volumen (Volume Superblock) - existe para cada volumen del sistema de archivos. Contiene el nombre del volumen, el ID y la marca de tiempo. Como superbloque de contenedores (Container Superblock), contiene un puntero a un mapa de bloques que asigna un ID de bloque a sus compensaciones. Además, el superbloque de volumen almacena un puntero al directorio raíz, que se almacena como un nodo.
Parcialidad (HEX) | Tipo | Id | Descripción |
---|---|---|---|
0 | tApFS_COH | Header | Encabezado del objeto contenedor (Container Object Header) |
20 | uint32 | MagicNumber (APSB) | Un valor que se puede utilizar para comprobar que estamos leyendo una instancia. Volume Superblock |
24 | uint32 | IndexInSuperBlock | El índice del ID de objeto de este volumen en la matriz de volúmenes del contenedor. |
28 | uint64 | Features | Mapa de bits de las principales funciones utilizadas por volumen |
30 | uint64 | ReadOnlyFeatures | Mapa de bits de funciones básicas (solo lectura) utilizadas por volumen |
38 | uint64 | IncompatibleFeatures | Mapa de bits de funciones de volumen incompatibles |
40 | uint64 | LastUnmountTime | La hora en que se desmontó el volumen por última vez (en nanosegundos desde la medianoche del 01/01/1970) |
48 | uint64 | ReservedBlocksCount | Número de bloques reservados para asignación de volumen |
50 | uint64 | QuotaBlocksCount | El número máximo de bloques que puede asignar este volumen |
58 | uint64 | AllocatedCount | El número de bloques asignados actualmente al sistema de archivos de este volumen. |
60 | uint8 | MetaCryptoState[20] | nformación sobre la clave utilizada para cifrar los metadatos de este volumen (ejemplar wrapped_meta_crypto_state_t) |
74 | uint32 | RootTreeType | Tipo de raíz del árbol de carpeta (generalmente: Tipo ( eApFS_ObjectFlag_Virtual << 16) \ eApFS_ObjectType_02_BTreeRoot , subtipo eApFS_ObjectType_0E_FileSystemTree ) |
78 | uint32 | ExtentRefTreeType | Tipo de árbol de mapeo de extensión (generalmente: Tipo ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , subtipo OBJECT_TYPE_BLOCKREF ) |
7C | uint32 | SnapshotMetaTreeType | Tipo de árbol de metadatos de instantáneas (generalmente: Tipo ( eApFS_ObjectFlag_Physical << 16) \ eApFS_ObjectType_02_BTreeRoot , subtipo OBJECT_TYPE_BLOCKREF ) |
80 | tApFS_Ident | ObjectsMapIdent | Identificador de objeto físico en el mapa de objeto volumétrico |
88 | tApFS_Ident | RootTreeIdent | Identificador de objeto virtual del árbol de carpetas raíz |
90 | tApFS_Ident | ExtentRefTreeIdent | Identificador de objeto físico del árbol de vínculos de extensión |
98 | tApFS_Ident | SnapshotMetaTreeIdent | Identificador de objeto virtual de árbol de metadatos de instantánea |
A0 | tApFS_Transaction | RevertToXid | El número de transacción de la instantánea a la que se devolverá el volumen. |
A8 | tApFS_Ident | RevertToSuperBlock | Identificador del objeto VS físico al que se revertirá el volumen |
B0 | uint64 | NextObjectIdent | El siguiente identificador que se asignará al objeto del sistema de archivos en volumen. |
B8 | uint64 | NumberOfFiles | Cantidad de archivos regulares en volumen |
C0 | uint64 | NumberOfDirectories | Cantidad de carpetas en volumen |
C8 | uint64 | NumberOfSymbolicLinks | Cantidad de enlaces simbólicos en volumen |
D0 | uint64 | NumberOfOtherObjects | Cantidad de otros objetos en el volumen (no de la llave x0B8_NumberOfFiles , x0C0_NumberOfDirectories и x0C8_NumberOfSymbolicLinks ) |
D8 | uint64 | NumberOfSnapshots | Cantidad de instantáneas en este volumen |
E0 | uint64 | TotalBlocksAllocated | Cantidad total de bloques asignados por este volumen |
E8 | uint64 | TotalBlocksFreed | Cantidad total de bloques liberados por este volumen |
F0 | tApFS_Uuid | Uuid | |
100 | uint64 | LastModifiedTime | Hora del último cambio de este volumen (en nanosegundos desde la medianoche del 01/01/1970) |
108 | uint64 | Flags | |
110 | tApFS_0D_FSM | FormattedBy | Información sobre el software que creó este volumen |
140 | tApFS_0D_FSM | ModifiedBy[8] | Información sobre el software que cambió este volumen |
2C0 | uint8 | VolumeName[256] | Nombre del volumen cero de la fila UTF-8 |
3C0 | uint32 | NextDocumentIdent | Siguiente identificador de documento que se asignará (almacenado en el campo extendido APFS_0E_TYPE_DOCUMENT_ID del documento) |
3C4 | uint16 | Role | Mapa de bits de rol de volumen |
3C6 | uint16 | Reserved | |
3C8 | tApFS_Transaction | RootToXid | Número de transacción de instantánea para no root o cero para root |
3D0 | tApFS_Ident | EncryptStateIdent | El estado actual de cifrado o descifrado, o cero si no hay cifrado |
Ilustración detallada de «APFS»:
Checkpoint (Punto de Control)
Punto de control - este es el estado temporal del contenedor. Cada punto de control se inicializa en el Superbloque del contenedor, y el estado actual suele ser el último. El punto de control contiene metadatos tanto para el contenedor como para el volumen. Los puntos de recuperación y las instantáneas son similares entre sí. La principal diferencia entre un punto de control y una instantánea es la capacidad del usuario para restaurar el sistema de archivos a partir de instantáneas guardadas mediante la API del sistema de archivos.
Checkpoint Superblock Descriptor (Descriptor de punto de control de superbloque)
Este bloque contiene información sobre las estructuras de metadatos en «ApFS» y es el bloque Descriptor precedente. La información más importante de este bloque es la ubicación de la estructura de mapa de bits (BMS), el archivo de distribución anterior en HFS+.
Descriptor del superbloque del punto de control:
Bitmap Structures (Mapa de bits o mapa de volumen)
Registros de bloques usados y no usados. Solo hay un mapa de volumen que cubre todo el contenedor y es común a todos los volúmenes del sistema de archivos. «ApFS» utiliza un conjunto de bloques para almacenar el mapa de volumen (Bitmap Structures).
En «ApFS» el mapa es común a todos los volúmenes del contenedor. Cada volumen contiene cotizaciones para el bloque en el contenedor, pero los bloques en sí no están en las áreas asignadas. El enlace al mapa de volumen se encuentra en el Descriptor de punto de control de superbloque (CSBD), que contiene información sobre el nivel superior de la estructura, el descriptor de mapa de bits (BMD). La siguiente figura muestra la estructura básica de este mapa. Se divide en niveles, con BMD en la parte superior y estableciendo límites. Debajo se encuentran «Bitmap Blocks» (BMB), que realizan un seguimiento de los bloques en el contenedor. Un byte en el BMB realiza un seguimiento de ocho bloques, cada bit de los cuales proporciona un estado de asignación. Cada bit es el estado de un bloque independiente.
Tablas (Tables)
Las tablas se utilizan en el catálogo y las extensiones del árbol B, la lista de volúmenes y el mapa de ID de objeto.
Las tablas utilizadas en «ApFS», son pequeñas «bases de datos» de un bloque con un propósito ligeramente diferente en las estructuras del sistema de archivos. El campo de tipo de tabla consta de 2 bytes ubicados en el bloque con parcialidad 0x20 inmediatamente después del encabezado del nodo. Hay ocho tablas del 0 al 7. Los siguientes 2 bytes proporcionan el nivel de tabla 0 y superior. La tabla del segundo nivel contendrá registros relacionados con la tabla base del primer nivel. Y las tablas de nivel cero se refieren a bloques que a menudo contienen metadatos de archivos.
Los tipos de tablas varían en estructura, pero el encabezado de la tabla para todos los tipos es de 24 bytes.
La figura muestra una estructura de encabezado de tabla de muestra:
Descripción de valores de campo en la estructura del encabezado:
Parcialidad (HEX) | Campo | Tipo de datos | Descripción |
---|---|---|---|
20 | tableType | uint16 | Los valores posibles son 0-7. Esta es la tabla 1 |
22 | tableLevel | uint16 | Indica el nivel del árbol B. |
24 | tableRecords | uint16 | Número de registros en la tabla |
26 | Unknown 1 | uint16 | |
28 | Unknown 2 | uint16 | |
2A | tableIndexSize | uint16 | tamaño de áreas de índice de tabla. |
2C | tableKeyAreaSize | uint16 | tamaño de área clave de la mesa. |
2E | tableFreeSpaceSize | uint16 | tamaño de área libre. El área de datos de la mesa termina con parcialidad 0x38+tableIndexSize+tableKeyAreaSize+tableFreeSpaceSize. 0x38 + 0x80 + 0x170 + 0xd58 . |
30 | Unknown 3 | uint16 | |
32 | Unknown 4 | uint16 | |
34 | Unknown 5 | uint16 | |
36 | Unknown 6 | uint16 |
Aquí hay un diseño general de las distintas tablas:
No todos los elementos de la imagen se utilizan en todas las tablas. La figura muestra un bloque completo con el encabezado del bloque de nodo superior. El resto del bloque es una tabla.
El índice del registro sigue inmediatamente después del encabezado de la tabla. Hay 2 tipos de ellos. Uno con dos valores: Parcialidad en la llave, y Parcialidad en la sección de datos para cada uno de Uint16. El segundo usa 4 valores Uint16 con Parcialidad y longitud para las particiones de la llave y de datos. El índice de registros de la tabla contiene información sobre los registros de la llave y de datos en la tabla. Otra diferencia entre tipos de tablas es el uso de pies de página.
Las tablas 1, 3, 5 y 7 usan Pie de página tamaño 0x28 bytes al final del bloque. En estas tablas, todos los offsets de datos se refieren al offset 0xFD8 y el pie de página contiene varios valores específicos del tipo de tabla. Otros tipos de tablas no tienen pie de página, y todas las referencias al contenido de la sección de datos se refieren al final del bloque.
En los árboles B con múltiples niveles, - тLas tablas 1, 3, 5 y 7 están al más alto nivel, ya que tienen pie de página. El pie de página, utilizado para almacenar información sobre el árbol B completo. Uno de los valores en el pie de página es el número total de entradas en la estructura de este árbol.
La definición de la tabla comienza en el desplazamiento 0x20 en el bloque. Muestra el Tipo de la tabla, el número de filas, el tamaño de la sección clave y el espacio entre la clave y la sección de datos. Después de las propiedades de la tabla, la parcialidad 0x38 describe las definiciones de filas y columnas. La tabla contiene el título, las definiciones de registros, las secciones clave y los datos. Algunos tipos de tablas también tienen un pie de página. El encabezado comienza en el desplazamiento 0x20 y tiene una longitud de 0x18 bytes. El encabezado de este tipo de tabla comienza con un valor de 16 bits que representa el tipo de la tabla. Luego siguen dos bytes, que representan el nivel en el árbol B en el que se usa la tabla. Los siguientes dos bytes representan el número de filas de la tabla. La longitud del registro de definición de escaneo es 0x2A, seguida de Uint16, que registra la longitud de la clave de sección. Luego viene la brecha entre la clave y la sección de datos. El pie de página de la tabla es siempre 0x28 bytes y siempre ocupa el final del bloque. Y los índices de la tabla son de 4 u 8 bytes cada uno. En índices de 8 bytes, los dos primeros "Uint16" son la parcialidad y longitud del registro de claves. Los siguientes dos "Uint16" son registros de parcialidad y longitud de datos en la tabla. Las tablas con índices de 4 bytes tienen dos valores Uint16 que contienen registros de parcialidad de la llave y de datos. La longitud de datos en dos entradas está predeterminada. En las tablas de pie de página de parcialidad, los registros de datos son relativos al inicio del pie de página (0x28 bytes). Y para otros tipos de tablas, esta parcialidad se refiere al final del bloque.
La mayoría de los significados relacionados con el encabezado y pie de página de una tabla son claros, al menos a partir de un tipo de lectura de la tabla. La parcialidad es 0x18 en el pie de página (parcialidad 0xFF en un bloque de 4 KB) es el número de registros en la tabla y en todas las tablas base (si es una tabla con un nivel superior a 0, en el offset 0x22). La parcialidad 0x20 en el pie de página es el número de la siguiente entrada en la tabla.
Tabla 0
Una tabla de tipo 0 se encuentra en la estructura de directorios del árbol B entre los nodos hoja y el nodo raíz. Los valores desconocidos del 3 al 6 se presentan como desplazamiento y longitud de la llave. Compensaciones de datos y longitud del siguiente registro disponible. Si no hay entradas de índice libres, las compensaciones se establecen en «0xFFFF» y la longitud «0x00».
Los registros de la tabla son cuatro valores «Uint16». Los primeros 2 - estos son los valores de parcialidad y longitud en la sección clave, y los siguientes son la parcialidad y el valor de contenido en la sección de datos.
Un ejemplo de tabla tipo 0 sería un identificador de nodo de catálogo, una clave de nombre en la sección de claves y un identificador de objeto en la sección de datos. Esta tabla no tiene pie de página.
Tabla 1
La primera tabla tiene un pie de página y el índice de la tabla contiene cuatro valores de 16 bits, donde los primeros 2 valores son la parcialidad del registro de la sección de clave y la longitud del registro. Los siguientes 2 valores proporcionan la entrada de parcialidad en la sección de datos y su longitud. Esta tabla se encuentra a menudo tanto en la estructura de directorios del árbol B como en el árbol de extensión del nodo de nivel superior. Un ejemplo son los valores: «Parent ID» y nombre de la llave (el nombre de un archivo o carpeta en la estructura del directorio y el número de bloque inicial en el árbol B de extensión), el identificador de objeto cuando se usa como nodo raíz en la estructura de directorio o el número de bloque cuando se usa en el árbol de extensión.
A continuación se muestran ejemplos de esta tabla:
Tabla 2
La segunda tabla. Inicialmente, esta tabla es idéntica a la anterior, pero no tiene pie de página. Este tipo de tabla es muy común en los nodos hoja en la estructura de directorios del árbol B donde se representa la sección clave con «Parent ID» y el nombre de la llave.
Tabla 3
La tercera tabla es idéntica a la anterior. El índice de la tabla es el mismo que el de la primera tabla. Los valores típicos dependen de la estructura en la que se utilizan. En la estructura de directorio del árbol B y el árbol de extensión, esta tabla se usa a menudo como un nodo de nivel superior en volúmenes pequeños, donde el nodo raíz son los nodos raíz y hoja. En tal caso de uso, la entrada clave podría ser «Parent ID». La clave de nombre y la entrada de datos pueden ser un archivo de datos de metado con gran variación de tamaño.
Otras entradas de la tabla son identificadores de objeto «Object ID» y su tipo en el registro de claves, con extensión de información de archivo y registros de datos. La tercera mesa tiene un зie de página.
Ejemplo de tabla:
Tabla 4
La tabla 4 es ligeramente diferente a los anteriores. No hay pie de página en la tabla y el índice de la tabla tiene solo 2 valores: Parcialidad de la entrada en la sección clave y 1 valor para la sección de datos. La longitud del contenido se fija en 16 bytes en la sección clave y 8 bytes en la sección de datos. Las compensaciones en la sección de datos se refieren al final del bloque.
Tabla 5
La tabla 5 es parecida a la 4. La única diferencia es que este tipo tiene un pie de página y todas las compensaciones de datos comienzan con «offset-0x28» (inicio de pie de página). Las entradas en la sección clave son 16 bytes y 8 bytes en la sección de datos. Este tipo de tabla se ve más comúnmente en los nodos de nivel superior en la estructura de directorios del árbol B y en contenedores grandes con árboles en niveles.
Tabla 6
La tabla 6 también se parece a la 4. El índice de la tabla solo tiene parcialidad a los contenidos en la sección de claves y de datos, pero no a su longitud. La longitud está predefinida. Cada entrada tiene 16 bytes. No hay pie de página para este tipo de tabla. Esta tabla se encuentra a menudo en los nodos hoja de la estructura de directorios del árbol B. Уl contenido típico de la sección de la llave de la incluye el identificador de objeto y el ID de volumen del Superblock Checkpoint «Volume Checkpoint Superblock ID», mientras que la sección de datos suele registrar su tamaño y número de bloque.
Tabla 7
La tabla 7 se parece a la sexta. La única diferencia es el pie de página, que contiene información similar a la descrita para la Tabla 1. Este tipo de tabla se ve en una amplia gama de estructuras y a menudo se encuentra en los niveles más altos de una estructura de múltiples capas o en estructuras de una sola capa como la descripción del volumen.
Ejemplo
Resumen de tablas
Esta tabla muestra las propiedades principales de varios tipos de tablas:
Tipo | Pie de página | Parcialidad de sección clave | Longitud de sección clave | Parcialidad de sección de datos | Longitud de sección de datos | Longitud de la llave | Longitud de datos |
---|---|---|---|---|---|---|---|
0 | NO | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
1 | SÍ | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
2 | NO | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
3 | SÍ | uint16 | uint16 | uint16 | uint16 | Varies | Possible |
4 | NO | uint16 | uint16 | 16 bytes | 8 bytes | ||
5 | SÍ | uint16 | uint16 | 16 bytes | 8 bytes | ||
6 | NO | uint16 | uint16 | 16 bytes | 16 bytes | ||
7 | SÍ | uint16 | uint16 | 16 bytes | 16 bytes |
Uno de los bloques más importantes en la estructura de directorios del árbol B es el nodo raíz, que es el nivel más alto en la estructura de carpetas. Este nodo utiliza claves de búsqueda de longitud variable. Una de las características mejoradas de «ApFS» es una búsqueda rápida en directorios. Un valor que está estrechamente relacionado con esta característica es el número de todos los registros en la estructura de árbol ubicada en el pie de la tabla.
El nodo raíz de la estructura del árbol B tiene 2 opciones de selección de tabla ya que ambas tienen pies de página. La tabla 3: como un nodo raíz, visto solo en contenedores pequeños con una pequeña cantidad de archivos, donde el nodo raíz también es un índice y nodos hoja.
En el mapa de características para el nodo raíz, solo se usa la quinta tabla, excepto para estructuras muy pequeñas donde puede encontrar la séptima.
La interpretación de las tablas muestra que las tablas 0 y 2 tienen el mismo significado. Lo mismo se observa entre las tablas 1 y 3. Estas tablas parecen tener diferentes propósitos según la estructura en la que se encuentren.
Instantáneas (Snapshots)
Las instantáneas son instantáneas del sistema de archivos de solo lectura de un volumen. El sistema operativo puede utilizar estas instantáneas para realizar copias de seguridad más eficientes. Gracias a la «Time Machine» correrá más rápido. Y gracias al soporte de imágenes instantáneas «Time Machine», ya no es necesario guardar varias copias completas de un archivo en el disco, simplemente puede realizar un seguimiento de cambios específicos. Por ejemplo, si edita un archivo modificado usando HFS+, conserva dos copias del archivo, la primera registra los nuevos cambios y la segunda en caso de que quiera volver a la vista anterior. En «APFS» sólo se conserva el archivo original y se registran las diferencias entre el archivo original y las versiones actualizadas, ocupando menos espacio en disco. Al igual que con las mejoras en «Fusion Drive», la información ocupa menos espacio en disco.
Aunque «ApFS» es significativamente inferior en sus capacidades a ZFS de 128 bits, que es compatible con Linux, FreeBSD y otros sistemas operativos gratuitos, este es un paso en la dirección correcta de Apple.
Como se mencionó anteriormente, Apple ha intentado cambiar ZFS a OS X durante mucho tiempo. Más tarde, OpenZFS se implementó para OS X (O3X) y MacZFX.
Nodes (nodos)
Los nodos son contenedores flexibles que se utilizan para almacenar varios tipos de registros. Pueden ser parte del árbol B o pueden existir por sí mismos. Los nodos pueden contener entradas de tamaño fijo o flexible. El nodo comienza con una lista de punteros a claves de entrada y entradas de entrada. Por lo tanto, para cada registro, el nodo contiene el encabezado de entrada al principio del nodo, la clave de entrada en el medio del nodo y la grabación de entrada al final del nodo.
Posición | tamaño | Tipo | ID |
---|---|---|---|
0 | 4 | uint32 | alignment |
4 | 4 | uint32 | ENTRY_COUNT |
10 | 2 | uint16 | HEAD_SIZE |
16 | 8 | entry | meta_entry |
24 | ... | entry | entries (repeat entry_count times) |
Estructura de encabezado de nodo (Node header):
Parcialidad | Campo | Tipo de datos | Comentario |
---|---|---|---|
0 | Checksum | Uint64 | Fletchers Checksum Algorithm |
8 | ID | Uint64 | Object-ID or Block# |
10 | Checkpoint | Uint64 | |
18 | Unknown | Uint16 | Possible level in B-Tree |
1A | Unknown | Uint16 | All observations shows value 0x4000 |
1C | Unknown | Uint16 | Flag? |
1E | Unknown | Uint16 | Often seen value 0x0b, 0x0e and 0x0f |
Administrador de Espacio (Space Manager)
«Space Manager» (Administrador de Espacio) se utiliza para gestionar bloques asignados en un contenedor «ApFS». Almacena el número de bloques libres y un puntero a archivos de información de ubicación.
Posición | tamaño | Tipo | ID |
---|---|---|---|
0 | 4 | uint32 | tamaño de bloque |
16 | 8 | uint64 | totalblocks |
40 | 8 | uint64 | freeblocks |
144 | 8 | uint64 | prev_allocationinfofile_block |
352 | 8 | uint64 | allocationinfofile_block |
Allocation info file (Archivo de información de distribución)
El archivo de distribución actúa como un encabezado faltante. Aquí es donde se almacena la Longitud de los archivos, la versión y su parcialidad.
Posición | tamaño | Tipo | 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 |
Archivo y carpeta de árbol B
Registros de todos los archivos y carpetas del volumen. Tienen la misma función que los archivos de directorio en «HFS+».
Extents (Extensiones de árbol B)
Un árbol B dividido de todas las extensiones del volumen. Las extensiones son enlaces al contenido de un archivo con información sobre dónde comienzan los contenidos de datos y su longitud en bloques. Un archivo con algún contenido tendrá al menos una extensión. Un archivo fragmentado tendrá varias extensiones. El árbol de extensiones es una estructura separada.
En cada entrada de archivo, se definen extensiones para cada uno de estos archivos en el árbol B. Esta estructura de extensión separada es parte de la funcionalidad de instantánea.
64-bit inodes (index descriptors) - descriptores de índices
Los inodos de 64 bits aumentan significativamente el espacio de nombres sobre los identificadores de 32 bits en «HFS+». Sistema de archivos de 64 bits en «ApFS» admite más de 9 quintillones de archivos por volumen. Como dijo Bill Gates, esto debería ser suficiente para todos.
«ApFS» ofrece la capacidad de restaurar ciertos estados del sistema de archivos, incluidas versiones antiguas o eliminadas de archivos. El superbloque de contenedores contiene un enlace a la estructura del punto de control. El punto de control se refiere al superbloque anterior del contenedor, que contiene información en el estado anterior del sistema de archivos. Por tanto, es posible restaurar varios estados antiguos analizando la cadena del superbloque de contenedores.