SysFailure

Imprimer

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 :

Début du superbloc HFS+

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.