Format de fichier FSEvents : pages 1SLD, 2SLD et 3SLD
La structure sur disque des journaux .fseventsd de macOS : fichiers gzip, en-têtes de page DLS, champs par version et données tronquées ou corrompues.
En bref. Chaque journal .fseventsd est un fichier gzip. Une fois décompressé, c'est une suite de pages ; chaque page commence par un en-tête de 12 octets (1SLD, 2SLD ou 3SLD, quatre octets inconnus, une taille de page en little-endian) suivi d'enregistrements : un chemin terminé par un NUL puis 12, 20 ou 24 octets de champs fixes. Cette structure correspond à ce qu'implémentent FSEventsParser (Nicole Ibrahim, Apache-2.0) et mac_apt (ydkhatri, MIT) ; Apple ne la documente pas.
Le dossier
.fseventsd/
0000000012a44181 gzip log file; name = an event ID in hex
0000000012a4439d
fseventsd-uuid text: the stream UUID
no_log optional, empty: logging disabled
Les noms des journaux comportent 16 chiffres hexadécimaux. FSEventsParser interprète le nom comme le dernier identifiant d'événement du fichier ; le FSEvents Parser de ce site compare le nom aux identifiants contenus dans le fichier et signale ceux dont le nom sort de leur propre plage (fichiers renommés ou mal placés).
La couche gzip
Chaque journal est un flux gzip ordinaire (RFC 1952). Certains fichiers contiennent plusieurs membres gzip, et la copie d'un journal encore en cours d'écriture se termine prématurément. Un lecteur robuste :
- décompresse les membres les uns après les autres ;
- conserve chaque octet qu'il a pu décompresser lorsque le flux est tronqué ou endommagé, au lieu de rejeter le fichier ;
- vérifie le CRC-32 et la taille en fin de flux, et signale une incohérence sans écarter de données ;
- accepte des données déjà décompressées par un autre outil (elles commencent directement par une signature de page).
En-tête de page
| Offset | Taille | Champ |
|---|---|---|
| 0 | 4 | Signature, stockée sous forme des octets ASCII 1SLD, 2SLD ou 3SLD |
| 4 | 4 | Inconnu |
| 8 | 4 | Taille de la page, u32 little-endian, comptée depuis le début de l'en-tête |
Les pages se succèdent jusqu'à la fin des données décompressées. Certaines publications les appellent « DLS1/DLS2 », car c'est ce qu'on lit en interprétant la signature comme un entier little-endian ; les octets sur disque sont bien 1SLD. Voir page DLS.
Enregistrements
Après l'en-tête, les enregistrements sont accolés les uns aux autres jusqu'à la taille de la page :
| Champ | 1SLD | 2SLD | 3SLD |
|---|---|---|---|
| Chemin, UTF-8, terminé par NUL | oui | oui | oui |
| Identifiant d'événement, u64 LE | +0 | +0 | +0 |
| Flags, u32 LE | +8 | +8 | +8 |
| Node ID, u64 LE | +12 | +12 | |
| Champ supplémentaire, 4 octets | +20 | ||
| Partie fixe après le chemin | 12 octets | 20 octets | 24 octets |
- 2SLD est apparu avec macOS 10.13 High Sierra, 3SLD avec macOS 14 Sonoma (d'après les notes d'implémentation de FSEventsParser). Un volume utilisé au fil des mises à jour peut contenir plusieurs versions.
- Le chemin est relatif à la racine du volume, tel qu'il était au moment de la journalisation :
Users/dana/Library/LaunchAgents/com.example.updater.plist, et non/System/Volumes/Data/Users/…. Des chemins vides existent. - Le champ supplémentaire 3SLD est décodé par FSEventsParser comme un identifiant d'utilisateur signé sur 32 bits (
fs_uid) et laissé sans nom par mac_apt. Apple ne l'a pas documenté ; considérez toute interprétation comme une hypothèse et testez-la sur des données connues. - Les flags sont traités dans la référence des flags.
Parser de façon défensive
Les collectes réelles contiennent des journaux tronqués, carvés ou endommagés. Voici les règles que suit le parseur de ce site :
- Une page dont la taille déclarée dépasse les données est parsée jusqu'à la fin des données, et l'anomalie est signalée.
- Un enregistrement dont le chemin n'a pas de NUL, ou dont les champs fixes ne tiennent pas, est écarté et signalé ; les enregistrements qui le précèdent sont conservés.
- Des octets nuls après le dernier enregistrement ou la dernière page constituent du slack, pas une erreur.
- Les octets qui ne sont pas une signature de page sont ignorés jusqu'au prochain
1SLD/2SLD/3SLD, et le nombre d'octets ignorés est signalé. - Les enregistrements aux combinaisons de flags impossibles (à la fois File et Folder, à la fois Symlink et Hard link) sont comptés comme un signe d'endommagement, comme le fait FSEventsParser pour les données carvées.
- Les chemins qui ne sont pas de l'UTF-8 valide sont affichés avec des caractères de remplacement et comptabilisés.
Horodatages
Le format n'en contient aucun. La manière de dater les enregistrements à partir des dates de modification des fichiers journaux est traitée dans dater les enregistrements FSEvents.
FAQ
Quelle est la différence entre 1SLD, 2SLD et 3SLD ?
La taille des enregistrements. Un enregistrement 1SLD contient un chemin, un identifiant d'événement sur 8 octets et des flags sur 4 octets ; 2SLD ajoute un node ID sur 8 octets (macOS 10.13 et versions ultérieures) ; 3SLD ajoute 4 octets de plus (macOS 14 et versions ultérieures).
Les journaux FSEvents sont-ils en little-endian ?
Oui. La taille de page, l'identifiant d'événement, les flags, le node ID et le champ supplémentaire sont tous stockés en little-endian. Certains outils lisent les flags en big-endian avec des constantes aux octets inversés, ce qui donne les mêmes noms.