Montage d'une partition HFS+
Linux est parfaitement capable de gérer, en lecture et en écriture, une partition HFS+ (MacOS). Le montage d'une telle partition nécessite diverses opérations sans grande complexité, sauf dans quelques cas pathologiques.
Montage de la partition
Module noyau nécessaire
Le module noyau se nomme hfsplus. Lors de la configuration d'un noyau, il est accessible par
File Systems -->
Miscellaneous filesystems -->
Apple Macintosh file system support
Apple Extended HFS file system support
Le premier module (Apple Macintosh file system support) correspond aux systèmes de fichiers HFS, qui ne sont pratiquement plus utilisés. Ce module permet de lire, mais pas d'écrire, sur un tel système de fichiers. Le second module (Apple Extended HFS file system support) est celui qui nous intéresse pour HFS+.
Le module peut être inclus dans le noyau ou compilé en tant que module chargeable.
Commande de montage
Dans le cas qui nous intéresse, nous avons fait une copie du disque dur sous la forme d'un fichier (format brut, copie réalisée à l'aide de dd ou similaire; voir par exemple l'article sur rEFIND). Il convient donc de passer par losetup pour transformer virtuellement ce fichier en un descripteur de périphérique (/dev/loopX).
En théorie, mount accepte les principaux paramètres de losetup, et tout peut être exécuté en une seule commande. Dans la pratique, nous avons souvent rencontré des situations où mount ne prenait pas correctement en compte certains paramètres de losetup. Il suffit alors de décomposer la commande en deux temps, d'abord losetup, puis mount.
Nous commençons par déterminer l'organisation du support et des partitions, à l'aide de fdisk, parted ou, ici, mmls :
$ mmls disque-128G.dd
GUID Partition Table (EFI)
Offset Sector: 0
Units are in 512-byte sectors
Slot Start End Length Description
00: Meta 0000000000 0000000000 0000000001 Safety Table
01: ----- 0000000000 0000000039 0000000040 Unallocated
02: Meta 0000000001 0000000001 0000000001 GPT Header
03: Meta 0000000002 0000000033 0000000032 Partition Table
04: 00 0000000040 0000409639 0000409600 EFI System Partition
05: 01 0000409640 0235708599 0235298960 Customer
06: 02 0235708600 0236978135 0001269536 Recovery HD
07: ----- 0236978136 0236978175 0000000040 Unallocated
La partition qui nous intéresse porte ici le nom Customer. Elle commence au bloc 409640 et se termine au bloc 235708599, pour une taille totale de 235298960 blocs. La commande normale de montage est donc
$ mount -o ro,loop,offset=$((512*409640)), sizelimit=$((512*235298960)) disque-128G.dd point-de-montage
Les options transmises à mount sont :
- ro : montage en lecture uniquement
- loop : passer par losetup (montage d'un système de fichier présent dans un fichier)
- offset : déplacement (en octets) pour atteindre le début de la partition
- sizelimit : taille (en octets) de la partition. Ce paramètre est indispensable pour HFS+, du fait de la présence d'un second superbloc en fin de partition
Si tout se passe correctement, la partition demandée est montée et peut être examinée. En cas de difficulté, la première chose à faire est de séparer losetup et mount :
$ losetup --read-only -f --offset=$((512*409640)) --sizelimit=$((512*235298960)) disque-128G.dd
$ losetup -a
/dev/loop0: [64780]:145096713 (disque-128G.dd), offset 209735680, sizelimit 120473067520
$ mount -o ro /dev/loop0 point-de-montage
Dans la plupart des cas, la partition est montée correctement.
Un cas difficile
Erreur de montage
Il peut arriver que, malgré toutes les tentatives et vérifications, la commande de montage échoue en affichant (via syslog) les messages suivants :
Dec 9 10:20:09 kernel: hfsplus: unable to find HFS+ superblock
Dec 9 10:23:53 kernel: hfsplus: invalid secondary volume header
Le second message est très important, et explique la situation :
- le pilote HFS+ trouve bien le premier superbloc, situé 1Ko après le début de la partition, mais
- il ne trouve pas le second superbloc, placé à la fin de la dite partition.
Une telle situation paraît de prime abord surprenante. En effet, la partition a été formattée sous MacOS et peut y être utilisée. Cela signifie qu'elle est correcte et que toutes les méta-informations nécessaires sont présentes. Mais Linux ne veut rien savoir.
En réalité, il y a un détail qui est souvent oublié :
- le second superbloc est situé à la fin du système de fichiers, moins deux blocs (il commence sur le pénultième bloc du système de fichiers)
- le système de fichiers n'occupe pas toujours toute la surface de la partition.
Lorsque le système de fichiers occupe l'intégralité de la partition, les commandes précédentes fonctionnent bien. Si le système de fichiers n'occupe pas toute la partition, il faut trouver où il se termine exactement.
Recherche du second superbloc
Le second superbloc étant une copie du premier, nous examinons celui-ci pour savoir quoi chercher. Comme il peut être difficile de charger toute la partition dans un éditeur hexadécimal, nous extrayons seulement le premier demi-Go :
$ dd if=disque-128G.dd skip=409640 bs=512 count=1024 of=/tmp/debut
1024+0 records in
1024+0 records out
524288 bytes (524 kB) copied, 0.0430321 s, 12.2 MB/s
Et nous examinons le contenu situé à 1 Ko à l'intérieur de ces données :
Le superbloc commence par H+ suivi de six octets suivi de HFSJ suivi de quatre octets. Le disque étant de taille modeste, nous pouvons rechercher la chaine HFSJ dans toute la partition, en ne retenant que la dernière occurrence :
$ dd if=disque-128G.dd bs=512 skip=409640 count=235298960 | strings -t d | grep HFSJ
1032 HFSJ
[autres occurrences]
111386692246 jHfSj
120154295304 HFSJ
$
Pour un gros disque, il faudrait extraire les quelques derniers Go de la partition pour ne faire la recherche que sur ceux-ci.
Dans les résultats, nous constatons la présence de la chaîne HFSJ au 1032ème octet de la zone examinée. L'examen du superbloc montrant que cette chaîne apparaît au huitième octet du superbloc, cela place le dit superbloc au 1024ème octet de la zone examinée -- l'emplacement normal du premier superbloc d'une partition HFS+.
La dernière ligne de résultats indique que la chaîne HFSJ se trouve au 120154295304ème octet de la zone, ce qui met le second superbloc à l'emplacement 120154295296 (huit octets avant l'occurrence de la chaîne), soit au bloc numéro 234676358. En ajoutant 2 au numéro de bloc, ou 1024 à l'emplacement de début du second superbloc, nous obtenons la taille réelle du système de fichiers. Il suffit alors d'utiliser cette valeur pour le paramètre sizelimit de losetup/mount :
$ losetup -f --read-only --offset $((512*409640)) --sizelimit=$((512*234676360)) fichier-128Go.dd
$ mount -o ro /dev/loop0 point-de-montage
$
La partition est (enfin !) montée et peut être examinée.
Conclusion
Dans la plupart des cas, le système de fichiers HFS+ occupe l'intégralité de la partition sur laquelle il est présent. Dès lors que l'on indique à mount/losetup la taille de la partition , à l'aide du paramètre sizelimit, celle-ci peut être montée sans difficulté.
Si le système de fichiers HFS+ n'occupe pas toute la partition, il est nécessaire de déterminer la taille réelle du système de fichiers. Cela peut se faire en recherchant la dernière occurrence de la chaine HFSJ, qui est présente dans le superbloc du système de fichiers. Cette dernière occurrence permet de connaître l'emplacement du second superbloc du système de fichiers et, de là, la taille réelle du système de fichiers dans la partition. Il suffit ensuite de transmettre cette information à mount/losetup pour monter la partition.