Page suivantePage précédenteTable des matières

10. Récupérer les blocs de données

Cette partie est soit très facile, soit nettement moins, selon que les fichiers que vous essayez de récupérer occupent moins ou plus de 12 blocs.

10.1 Les fichiers courts

Si le fichier n'occupait pas plus de 12 blocs, alors les numéros de blocs où sont situées toutes ses données sont écrits dans l'inode : vous pouvez les lire directement sur la sortie de stat correspondant à l'inode. De surcroît, debugfs a une commande qui automatise cette tâche. Pour reprendre l'exemple précédent :

debugfs:  stat <148003>
Inode: 148003   Type: regular    Mode:  0644   Flags: 0x0   Version: 1
User:   503   Group:   100   Size: 6065
File ACL: 0    Directory ACL: 0
Links: 0   Blockcount: 12
Fragment:  Address: 0    Number: 0    Size: 0
ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
mtime: 0x313bf4d7 -- Tue Mar  5 08:01:27 1996
dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
BLOCKS:
594810 594811 594814 594815 594816 594817
TOTAL: 6

Ce fichier a six blocs. Puisqu'il est en-dessous de la limite des 12, nous demandons à debugfs d'écrire le fichier dans un nouvel endroit, comme par exemple /mnt/recovered.000 :

debugfs:  dump <148003> /mnt/recovered.000

Bien sûr, on peut faire ça aussi avec fsgrab ; je le montre ici en guise d'exemple d'utilisation :

# fsgrab -c 2 -s 594810 /dev/hda5> /mnt/recovered.000
# fsgrab -c 4 -s 594814 /dev/hda5>> /mnt/recovered.000

Que ce soit avec debugfs ou avec fsgrab, il y aura un peu de déchet à la fin de /mnt/recovered.000, mais ce n'est pas très important. Si vous voulez vous en débarrasser, la méthode la plus simple est de prendre le champ Size de l'inode, et le brancher sur l'option bs d'une ligne de commande dd.

# dd count=1 if=/mnt/recovered.000 of=/mnt/resized.000 bs=6065

Bien sûr, il est possible qu'un ou plusieurs blocs où était écrit votre fichier aient été écrasés. Si c'est le cas, pas de chance : le bloc est mort et enterré (rendez-vous compte, si seulement vous aviez démonté plus tôt !).

10.2 Les fichiers plus longs

Les problèmes apparaissent lorsque le fichier tient sur plus de 12 blocs de données. Ici, il vaut mieux en savoir un peu sur la manière dont sont structurés les systèmes de fichiers Unix. Les données du fichier sont stockées dans des unités appelées « blocs ». Ces blocs peuvent être numérotés séquentiellement. Un fichier a également un « inode », où sont placées des informations telles que propriétaire, permissions ou type. Comme les blocs, les inodes sont numérotés séquentiellement, bien que la séquence soit différente. Une entrée de répertoire consiste en un nom de fichier associé à un numéro d'inode.

Mais, si on en restait là, le noyau ne saurait toujours pas trouver les données correspondant à une entrée de répertoire. Ainsi l'inode indique également l'endroit où se trouvent les blocs de données du fichier, comme suit :

Relisez bien tout ça : je sais que c'est compliqué, mais c'est important, aussi.

Maintenant, l'implantation du noyau pour toutes les versions actuelles (2.0.36 inclue) efface malheureusement tous les blocs indirects (et doublement indirects, etc.) lors de la suppression d'un fichier. Alors, si votre fichier occupait plus de 12 blocs, vous n'êtes pas garanti de pouvoir retrouver les numéros de tous les blocs dont vous avez besoin (sans parler de leur contenu).

La seule méthode que j'aie pu trouver jusqu'ici consiste à supposer que le fichier n'est pas fragmenté : s'il l'est, vous aurez des ennuis. En supposant que le fichier n'est pas fragmenté, il y a plusieurs dispositions de blocs de données, selon le nombre de blocs de données utilisés par le fichier :

0 à 12

les numéros de bloc sont indiqués dans l'inode, comme décrit précédemment ;

13 à 268

après les blocs directs, comptez un pour le bloc indirect, puis vous avez 256 blocs de données ;

269 à 65804

comme avant, il y a 12 blocs directs, un bloc indirect (inutile), et 256 blocs. Ils sont suivis d'un bloc doublement indirect (inutile), et 256 répétitions de : un bloc indirect (inutile) et 256 blocs de données ;

65805 ou plus

la disposition des 65804 premiers blocs est identique à ce qui est décrit di-dessus. Suivent un bloc triplement indirect (inutile) et 256 répétitions d'une séquence « doublement indirect ». Chaque séquence doublement indirecte consiste en un bloc doublement indirect (inutile), suivi de 256 répétitions de : un bloc indirect (inutile) et 256 blocs de données.

Bien entendu, même si ces blocs sont supposés corrects, rien ne garantit que les données qu'ils contiennent sont intactes. De plus, plus le fichier est long, moins vous avez de chances qu'il ait pu être écrit dans le système de fichiers sans fragmentation raisonnable (sauf dans certaines circonstances particulières).

Notez que j'ai supposé depuis le début que vos blocs occupaient la taille de 1024 octets, c'est-à-dire la valeur standard. Si vos blocs sont plus grands, une partie des nombres écrits plus haut doivent être changés. Typiquement, puisque chaque numéro de bloc occupe 4 octets, le nombre de numéros de bloc pouvant être placés dans chaque bloc indirect est taille_du_bloc/4. Donc, chaque fois que le nombre 256 apparaît dans la dicussion qui précède, remplacez-le par taille_du_bloc/4. Les limitations « nombre de blocs requis » devront également être modifiées.

Examinons un exemple de récupération de fichier plus long.

debugfs:  stat <1387>
Inode: 148004   Type: regular    Mode:  0644   Flags: 0x0   Version: 1
User:   503   Group:   100   Size: 1851347
File ACL: 0    Directory ACL: 0
Links: 0   Blockcount: 3616
Fragment:  Address: 0    Number: 0    Size: 0
ctime: 0x31a9a574 -- Mon May 27 13:52:04 1996
atime: 0x31a21dd1 -- Tue May 21 20:47:29 1996
mtime: 0x313bf4d7 -- Tue Mar  5 08:01:27 1996
dtime: 0x31a9a574 -- Mon May 27 13:52:04 1996
BLOCKS:
8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8583
TOTAL: 14

Il semble y avoir de bonnes chances pour que ce fichier ne soit pas fragmenté : de façon évidente, les 12 premiers blocs listés dans l'inode (qui sont tous des blocs de données) sont contigus. Nous pouvons donc commencer par récupérer ces blocs :

# fsgrab -c 12 -s 8314 /dev/hda5> /mnt/recovered.001

Maintenant, le bloc suivant listé dans l'inode, 8326, est un bloc indirect, que nous pouvons ignorer. Mais nous nous fions à notre intuition qu'il sera suivi de 256 blocs de données (du numéro 8327 au numéro 8582).

# fsgrab -c 256 -s 8327 /dev/hda5>> /mnt/recovered.001

Le dernier bloc listé dans l'inode est le 8583. Notez que ça ressemble toujours bien à un fichier contigu : le numéro du dernier bloc que nous ayons écrit était le 8582, donc 8327 + 255. Ce bloc 8583 est un bloc doublement indirect, que nous pouvons ignorer. Il est suivi par jusqu'à 256 répétitions d'un bloc indirect (ignoré) suivi de 256 blocs de données. Après un petit calcul mental, on en déduit les commandes suivantes. Remarquez qu'on saute le bloc doublement indirect 8583 et le bloc indirect 8584, qui suivent immédiatement (espérons-le) et qu'on commence directement à lire les données depuis le bloc 8585.

# fsgrab -c 256 -s 8585 /dev/hda5>> /mnt/recovered.001
# fsgrab -c 256 -s 8842 /dev/hda5>> /mnt/recovered.001
# fsgrab -c 256 -s 9099 /dev/hda5>> /mnt/recovered.001
# fsgrab -c 256 -s 9356 /dev/hda5>> /mnt/recovered.001
# fsgrab -c 256 -s 9613 /dev/hda5>> /mnt/recovered.001
# fsgrab -c 256 -s 9870 /dev/hda5>> /mnt/recovered.001

En rassemblant tout, on voit qu'on a écrit depuis le début 12 + (7 * 256) blocs, c'est-à-dire 1804. La commande « stat » nous a indiqué pour l'inode un « blockcount » de 3616 ; mais ces blocs occupaient malheureusement 512 octets (un reliquat d'Unix), ce que nous voulons réellement est alors 3616/2 = 1808 blocs de 1024 octets. Cela signifie que nous avons seulement besoin de quatre blocs de plus. Le dernier bloc de données écrit portait le numéro 10125. De la même façon que depuis le début, on saute un bloc indirect (numéro 10126) ; on peut alors écrire ces quatre derniers blocs.

# fsgrab -c 4 -s 10127 /dev/hda5>> /mnt/recovered.001

Et maintenant, avec un peu de chance, le fichier complet a été récupéré avec succès.


Page suivantePage précédenteTable des matières