Następna strona Poprzednia strona Spis treści

10. Odzyskiwanie bloków danych

Ta część jest albo bardzo łatwa, albo trudna, w zależności od tego, czy plik który chcesz odzyskać zajmował więcej niż 12 bloków.

10.1 Małe pliki

Jeżeli plik ma mniej niż 12 bloków, numery wszystkich bloków, które on zajmuje zapisane są w jednym iwęźle. Możesz odczytać je po wykonaniu polecenie stat dla tego iwęzła. Ponadto, w debugfs jest polecenie, które automatycznie odzyskuje taki plik. Weźmy ten sam przykład co poprzednio:

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

Plik ten zajmuje sześć bloków. Ponieważ jest to mniej niż 12, możemy użyć debugfs, aby zapisać plik w nowym miejscu, na przykład /mnt/recovered.000:

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

Oczywiście można to zrobić również, posługując się fsgrab. Pokażę jak wygląda takie przykładowe wywołanie:

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

Zarówno przy korzystaniu z debugfs jak i fsgrab, na końcu pliku /mnt/recovered.000 pozostaną śmieci. Nie ma to większego znaczenia. Łatwo można się ich pozbyć. Najprostszą metodą jest odczytanie pola Size w iwęźle i wpisanie tej wartości za opcją bs komendy dd:

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

Może się okazać, że jeden lub więcej z bloków zostało straconych, bowiem zostały już nadpisane. Jeżeli tak będzie, po prostu nie miałeś szczęścia: bloki te odeszły już na zawsze. (Wybraź sobie, że odmontowałeś je wcześniej!)

10.2 Większe pliki

Problem pojawia się, gdy plik zajmuje więcej niż 12 bloków danych. Przypadek ten wymaga pewnej wiedzy o tym jak zbudowany jest system plików UNIX-a. Dane pliku przechowywane są w jednostkach zwanych `blokami'. Bloki te są numerowane sekwencyjnie. Każdy plik ma również `iwęzeł', w którym przechowywane są informacje typu: właściciel, prawa dostępu i typ. Podobnie jak bloki, iwęzły są numerowane sekwencyjnie, chociaż mają one różne numeracje. Pozycja w katalogu odpowiadająca plikowi składa się z jego nazwy i numeru iwęzła.

Jednak na postawie tych informacji jądro nie jest jeszcze w stanie odnaleźć na partycji danych odpowiadających jednej z pozycji w katalogu. Żeby to umożliwić, iwęzeł przechowuje położenia bloków danych zajmowanych przez plik. Zorganizowane jest to w następujący sposób:

Przeczytaj to jeszcze raz: wiem, że to jest skomplikowane, ale bardzo ważne.

Niestety wszystkie implementacje jądra, aż do wersji 2.0.36 podczas kasowania pliku zerują bloki pośrednie (podwójnie pośrednie, itd.). Jeśli Twój plik jest większy niż 12 bloków, nie masz gawarancji, że będzie możliwe odnalezienie numerów wszystkich jego bloków, nie mówiąc już nic o ich zawartości.

Jedyną metodą jaką udało mi się znaleźć, jest oparcie się na założeniu, że plik nie był pofragmentowany. Jeżeli był, masz poważny problem. Zakładając, że plik nie był pofragmentowany, istnieje kilka sekcji bloków danych, w zależności od tego ile bloków danych zajmuje plik:

0 do 12

Numery bloków przechowywane są w iwęźle, jak to było opisane wcześniej.

13 to 268

Po blokach bezpośrednich, odlicz jeden na blok pośredni, dalej znajduje się 256 bloków danych.

269 do 65804

Tak jak poprzednio jest: 12 bezpośrednich bloków, (nieprzydatny) blok pośredni i 256 bloków. Po tym wszystkim następuje (nieprzydatny) podwójnie pośredni blok oraz 256 powtórzeń jednego (nieprzydatnego) bloku pośredniego i 256 bloków danych.

65805 lub więcej

Położenie piewszych 65804 bloków jak wyżej. Potem potrójnie pośredni blok i 256 powtórzeń `sekwecji podwójnie pośredniej'. Każda podwójnie pośrednia sekwencja zawiera (nieprzydatny) podwójnie pośredni blok, po którym następuje 256 powtórzeń jednego (nieprzydatnego) bloku pośredniego i 256 bloków danych.

Oczywiście, nawet jeśli numery bloków, które przyjęliśmy, są poprawne, nie ma żadnych gwarancji, że dane są w nich są nienaruszone. Dodatkowo, im dłuższy był plik, tym mniejsze szanse, że system operacyjny zapisał go bez żadnej fragmentacji (za wyjątkiem wyjątkowych sytuacji).

Założyłem, że rozmiar Twoich bloków wynosi 1024 bajty, tyle ile wartość standardowa. Jeśli Twój blok jest większy, niektóre z liczb podanych wyżej zmienią się. Sprecyzujmy: dopóki numer każdego bloku ma długość 4 bajtów, rozmiarbloku/4 jest liczbą numerów bloków, które mogą być przechowane w każdym bloku pośrednim. Każde wystąpienie liczby 256 we wcześniejszym opisie, zastąp na rozmiarbloku/4. Zmianie ulegną również ograniczenia na ilość wymaganych bloków.

Popatrz na przykładowe odzyskiwanie dużego pliku.

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

Wydaje się, że mamy pewne szanse, że plik nie jest pofragmentowany. Pewne jest tylko, że pierwsze 12 bloków, których numery są zawarte w iwęźle, jest `po kolei'. Możemy więc odtworzyć te bloki:

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

Następny blok, wymieniony w iwęźle, 8326, jest blokiem pośrednim, który ignorujemy. Mamy jednak nadzieję, że nastepne 256 bloków jest naszymi blokami danych (numery 8327 do 8582).

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

Ostatnim blokiem wymienionym w iwęźle jest 8583. Nadal zakładamy, że istnieje ciągłość w blokach. Jest to jednak uzasadnione bowiem: ostatnim blokiem danych był blok o numerze 8582 (8327 + 255). Blok 8583 jest podwójnie pośredni i może być zignorowany. Teraz może nastąpić do 256 powtórzeń bloku pośredniego (który można pominąć) i 256 bloków danych. Trochę arytmetyki i już można pisać kolejne polecenie. Zauważ, że pominęliśmy podwójnie pośredni blok 8583 oraz pośredni blok 8584 i rozpoczęliśmy czytać dane od bloku numer 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

Dodajmy to wszystko, zapisaliśmy do tej pory 12 + (7 * 256) bloków, co daje 1804. Wyniki polecenia `stat' dla iwęzła dały nam `blockcount' (liczba bloków) równe 3616. Niestety są to bloki o rozmiarze 512 bajtów (zaszłość z UNIX-a), na prawdę potrzebujemy więc 3616/2 = 1808 bloków o rozmiarze 1024 bajty. Oznacza to, że musimy jeszcze odnaleźć cztery bloki. Ostatni przeczytany blok danych miał numer 10125. Tak jak to robiliśmy do tej pory, pomijamy blok pośredni (numer 10126) i możemy już zapisać ostatnie cztery bloki.

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

Przy pewnym szczęściu udało nam się odzyskać cały plik.


Następna strona Poprzednia strona Spis treści