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.
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!)
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:
Numery bloków przechowywane są w iwêźle, jak to było opisane wcześniej.
Po blokach bezpośrednich, odlicz jeden na blok pośredni, dalej znajduje siê 256 bloków danych.
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.
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.