# Linux Ext2fs Undeletion mini-HOWTO

## Autor: Aaron Crane aaronc@poboc.com
v1.3, 2 lutego 1999
Wersja polska: Bartosz Sawicki sawickib@ee.pw.edu.pl
v1.0, 15 kwietnia 1999

Wyobraź sobie. Trzy ostatnie trzy dni spędziłeś bez snu, jedzenia, a nawet bez prysznica. Właśnie ukończyłeś program, który przyniesie Ci światową sławę i uznanie. Musisz go jeszcze tylko starować i umieścić na Metalab-ie. No, i skasować wszystkie kopie zapasowe tworzone przez Emacs-a. Piszesz więc `rm * ~`. Już za późno, zauważyłeś dodatkową spację w poleceniu. Właśnie skasowałeś całe swoje dzieło ! Nadchodzi pomoc. Dokument ten wyjaśnia jak odzyskiwać skasowane pliki w systemie plików Second Extended File System. Może uda Ci się jednak opublikować Twój genialny program. Dokument ten został napisany w standardzie ISO-8859-2. Oryginał tego dokumentu znajduje się pod adresem http://pobox.com/~aaronc/.

## 1. Wstęp

To mini-Howto stara się dostarczyć porad jak odzyskiwać skasowane pliki w systemie plików ext2. Zawiera ono również dyskusję, jak przede wszystkim, nie dopuścić do skasowania ważnych plików.

Chciałbym, aby było ono przydatne dla ludzi, którym zdarzył się mały wypadek z `rm`; jakkolwiek mam również nadzieję, że przeczytają je także inni. Nigdy nie wiadomo, pewnego dnia, któraś z zamieszczonych tu informacji z może uratować Ci tyłek.

Tekst ten zakłada ogólną podstawową wiedzę o systemie plików UNIX-a. Mam jednak nadzieję, że będzie dostępny dla większości użytkowników Linux-a. Jeśli jesteś całkowicie początkujący, obawiam się, że odzyskiwanie plików wymaga ilości wiedzy technicznej, której nie posiadasz.

Nie będziesz mógł odtwarzać skasowanych plików z systemu plików ext2 bez praw odczytu do urządzenia, na którym były one przechowywane. Ogólnie oznacza to, że musisz być administatorem (root). Niektóre dystrybucje (takie jak Debian GNU/Linux) tworzą grupę `disk`, której członkowie mają dostęp do takich urządzeń. Będziesz potrzebował także `debugfs` z pakietu `e2fsprogs`. Prawdopodobnie jest on już zainstalowany przez Twoją dystrybucję.

Dlaczego to napisałem? Wynikło to głównie z moich własnych doświadczeń ze zwykłą głupotą i katastrofą spowodowaną przez komendę `rm -r` wykonywaną z prawami administratora. Skasowałem 97 plików typu JPEG, których potrzebowałem i których prawie na pewno nie można było odzyskać z innych źrodeł. Z pomocą użytecznych wskazówek (patrz rozdział Wyrazy uznania i Bibliografia) i dużej wytrwałości, odzyskałem 91 nieuszkodzonych plików. Udało mi się odtworzyć częściowo następne pięć (wystarczająco, aby zobaczyć co było na tych obrazkach). Tylko jednego nie byłem w stanie obejrzeć, ale nawet w tym przypadku, jestem prawie pewien, ze stracone zostały nie wiecej niż 1024 bajty (niefortunnie z samego poczatku pliku; uwzględniając to, że nic nie wiem o formacie JPG, zrobiłem wszystko co mogłem).

W dalszych rozważaniach będę chciał przedstawić jakiej wielkości współczynnika odtworzenia skasowanych plików możesz się spodziewać.

## 1.1 Historia publikacji

Istnieją następujące upublicznione wersje tego dokumentu (i daty ich publikacji):

- v1.0, 18 stycznia 1997
- v1.1, 23 lipca 1997 (patrz rozdział Zmiany w wersji 1.1)
- v1.2, 4 sierpnia 1997 (patrz rozdział Zmiany w wersji 1.2)
- v1.3, 2 lutego 1999 (patrz rozdział Zmiany w wersji 1.3)

### Zmiany w wersji 1.1

Jakie zmiany zostały zrobione w tej wersji? Przede wszystkim, został poprawiony błąd w przykładowym odzyskiwaniu pliku. Dziękuję wszystkim, którzy napisali, żeby wskazać mi ten błąd. Mam nadzieję, że nauczyłem się być bardziej uważnym przy interakcyjnej pracy z programem.

Po drugie, rozważania o systemie plików w UNIX-ie zostały przerobione tak, aby uczynić je bardziej zrozumiałymi. Od początku nie byłem z tego zadowolony i dostałem komentarze, że nie było to napisane zbyt jasno.

Po trzecie, uuencode'owany gzip-owany tar-owany pakiet `fsgrab` ze środka pliku został usunięty. Teraz program dostępny jest na mojej stronie domowej i na Metalab-ie (i kopiach, w Polsce - Sunsite ).

Po czwarte, dokument ten został przetłumaczony na język składu SGML używany w Linux Documention Project. Ten język może być łatwo konwertowany do innych języków składu (np. HTML-a i LaTeX-a) w celu dogodnego sposobu wyświetlania i drukowania. Jedną z korzyści z tego jest to, że ładny wygląd wersji papierowej jest łatwiejszy do osiągniecia. Inną jest to, że dokument zawiera wewnętrzne i zewnętrzne odnośniki, gdy oglądany jest przez WWW.

egil@kvaleberg.no, który wskazał na polecenie `dump` w `debugfs`. Jeszcze raz, dzięki Egil. Druga zmiana polegała na zaznaczeniu, że użycie `chattr` pomaga uniknąć skasowania ważnych plików. Dziekuję Hermanowi Suijs `H.P.M.Suijs@kub.nl` za zauważenie tego. Streszczenie zostało uaktualnione. Zostały dodane URL-e do organizacji i oprogramowania. Wprowadzono wiele innych mniejszych zmian (literówki i tym podobne).

###

### Zmiany w wersji 1.3

Pomimo, że jest to pierwsza wersja od 17 miesięcy, jest tutaj mało nowego. W wersji tej poprawione są drobniejsze błędy (literówki, puste URL-e, tego typu rzeczy -- szczególnie nie związane z Open Group), uaktualniono kilka części tekstu, które uległy przeterminowaniu, takich jak partie dotyczące wersji jądra i `lde`. No i zmieniłem `Sunsite' na `Metalab'.

To wydanie jest przewidywane jako ostatnie przed wersją 2.0, która, mam nadzieję, będzie pełnym Howto. Pracuję nad istotnymi zmianami, które spowodują zwiększenie głównego numeru wersji.

## 1.2 Inne lokalizacje tego dokumentu

Najnowsza publiczna wersja tego dokumentu powinna być zawsze dostępna na Linux Documentation Project site (i kopiach, w Polsce - Sunsite ).

Najbardziej aktualna wersja jest również przechowywana na mojej stronie domowej w kilku formatach:

- źródło SGML. To jest format źródłowy, tak jak to napisałem używając pakietu SGML Tools.
- HTML. To jest HTML, automatycznie wygenerowany ze źródła SGML.
- czysty tekst. To jest czysty tekst, który również został automatycznie wygenerowany ze źródła SGML.

## 2. Jak nie skasować plików

Trzeba pamiętać, że Linux różni się od MS-DOS jeśli chodzi o kasowanie plików. W MS-DOS (jak i w Windows 95), dosyć łatwo jest odzyskać skasowane pliki - `system operacyjny' (używam tego terminu dosyć swobodnie) dostarcza nawet narzędzi, które automatyzują ten proces. W Linux-ie jest inaczej.

Reguła numer jeden (podstawowa wskazówka) brzmi:

> RÓB KOPIE ZAPASOWE

bez względu na wszystko. Pomyśl o wszystkich swoich danych. Być może, jak ja, trzymasz kilkuletni zbiór listów, kontaktów, programów, dokumentów na swoim komputerze. Pomyśl co by się stało z Twoim życiem, gdyby Twój dysk uległ katastrofalnemu uszkodzeniu, lub gdyby -- o wielkie nieba ! -- złośliwy craker wyczyścił Twój dysk. To nie jest niemożliwe; korespondowałem z wieloma ludźmi w takiej sytuacji. Myślę, że teraz wszyscy rozsądnie myślący użytkownicy Linux-a wyjdą, kupią urządzenie do robienia kopii zapasowych, opracują kalendarz archiwizacji i będą się jego trzymać. Ja używam wolnego dysku twardego w innym komputerze i okresowo kopiuję tam przez sieć ethernet mój katalog domowy. Więcej informacji o planowaniu kalendarza archiwizacji znajdziesz u Frischa (1995) (patrz rozdział Bibliografia i Wyrazy Uznania).

Co wtedy, gdy nie ma kopii zapasowej? (lub nawet przy istnieniu kopii zapasowej: żadne środki bezpieczeństwa nie są złym rozwiązaniem w miejscu gdzie przechowywane są ważne dane).

Spróbuj ustawić prawa dostępu do ważnych plików na 440 (lub mniej): odebranie sobie samemu praw zapisu oznacza, że `rm` będzie wymagał potwierdzenia przed skasowaniem. (Zauważyłem, że jeśli rekursywnie kasuję katalog `rm -r`, prośba potwierdzenia pojawi się przy pierwszym i drugim pliku, potem program zachowuje się jak `rm -rf`).

Niezłą sztuczką dla wybranych plików jest utworzenie w ukrytym katalogu twardych dowiązań do nich. Kiedyś usłyszałem historię o administatorze, który przez pomyłkę skasował `/etc/passwd` (nieomal w ten sposób niszcząc system). Jednym z rozwiązań takiego kłopotu jest zrobienie czegoś następującego (jako root):

> `

>     # mkdir /.backup
>     # ln /etc/passwd /.backup

> `

Teraz skasowanie pliku wymaga większego wysiłku: gdy napiszesz tylko

> `

>     # rm /etc/passwd

> `

wtedy

> `

>     # ln /.backup/passwd /etc

> `

odtworzy Twój plik. Oczywiście, to rozwiązanie nie pomoże jeśli nadpiszesz plik, więc nie zapomninaj o kopii zapasowej.

W systemie plików ext2 jest możliwe użycie atrybutów ext2, aby ochraniać pliki. Atrybuty te mogą być zmieniane za pomocą komendy `chattr`. Istnieje atrybut `append-only`: plik z tym atrybutem może być tylko powiększany, nie może być skasowany i istniejąca zawartość nie może być nadpisana. Jeśli atrybut ten ma katalog, każdy plik czy katalog w nim leżący może być normalnie modyfikowany, ale żaden z plików nie może zostać skasowany. Atrybut `append-only' ustawia się poleceniem

> `

>     $ chattr +a FILE...

> `

Istnieje również atrybut `immutable', który może być zapalany lub gaszony tylko przez administratora. Pliku lub katalogu z tym atrybutem nie można zmienienić, skasować, zmienić jego nazwy, czy utworzyć do niego twardego dowiązania. Można go ustawić w następujący sposób:

> `

>     # chattr +i FILE...

> `

Ext2fs dostarcza również atrybutu `undeletable' (`+u` in `chattr`). Założenie było takie, że plik z tym atrybutem po skasowaniu zostaje przeniesiony w bezpieczne miejsce `safe location', aby rzeczywiste skasowanie przesunąć w czasie. Niestety funkcja ta nie jest jeszcze zaimplementowana w jądrze. Myślałem, że będzie większe zainteresowanie nią i stanie się to szybko, ale nie jest ona dostępna (według mojej wiedzy) w żadnej aktualnej wersji jądra.

Niektórzy radzą, aby zrobić alias lub funkcję w powłoce `rm`, która wykonywałaby `rm -i` (będziesz musiał potwierdzić skasowanie każdego pliku). Dystrubucja Red Hat robi to domyślnie dla wszystkich użytkowników, w tym i dla root-a. Ja osobiście nie lubię oprogramowania, które nie może działać bez mojej pomocy, dlatego nie używam tego sposobu. Wcześniej, czy później może pojawić się kolejny problem: kiedy będziesz pracował w trybie singe-user, lub będziesz używał innej powłoki lub nawet innej maszyny, gdzie Twoja funkcja `rm` nie istnieje. Jeśli będziesz spodziewał się, że każde skasowanie wymaga potwierdzenia, dosyć łatwo jest nie przewidzieć tego, że kazałeś skasować zbyt wiele plików. Również skrypty i programy, które podmieniają `rm` mogą być bardzo niebezpieczne.

Trochę lepszym rozwiązaniem jest użycie pakietu, który umożliwia `odtwarzalne' kasowanie poprzez specjalną komendę zastępująca `rm`. Szczegóły znajdziesz u Peeka (1993) (patrz rozdział Bibliografia i Wyrazy Uznania). Jednak w ten sposób przyzwyczajamy użytkownika do pewniej nonszalancji przy kasowaniu plików. Nie jest to najlepsze, bowiem system typu Unix wymaga jednak uważnego działania.

## 3. Jakiego współczynnika odzyskania skasowanych plików mogę się spodziewać ?

To zależy. Problem wynika z tego, że w systemie operacyjnym wysokiej jakości, wielozadaniowym, wieloużytkownikowym, takim jak Linux, nie możesz przewidzieć kiedy ktoś zechce zapisać coś na dysk. Po chwili, w której kazałeś systemowi skasować jakiś plik, bloki przez niego zajęte mogą zostać użyte, gdy system będzie chciał zapisać coś nowego. (Jest to jeden przykład ogólnej zasady systemów typu Unix: jądro i związane z nim programy zakładają, że użytkownicy nie są idiotami). Ogólnie rzecz biorąc, im bardziej obciążona jest Twoja maszyna, tym mniej prawdopodobne jest odzyskanie plików.

Znaczenie może mieć również fragmentacja dysku. Jeśli partycja, na której był skasowany plik jest bardzo pofragmentowana, masz małe szanse na odczytanie całej jego treści.

Jeśli Twój komputer, tak jak mój, realnie jest maszyną jednoużytkownikową i nie robiłeś niczego co intensywnie korzystało z dysku w tragicznej chwili skasowania pliku, możesz się spodziewać współczynnika odzysku zbliżonego do tego wymienionego niżej. Ja odzyskałem prawie 94% plików (były to pliki binarne) w stanie nieuszkodzonym. Jeżeli otrzymasz 80% lub więcej, myślę, że będziesz z siebie zadowolony.

## 4. Jak odzyskać skasowane pliki ?

Operacja ta polega głównie na znalezieniu danych na urządzeniu partycji i uczynieniu ich ponownie widocznymi dla systemu operacyjnego. Są dwa sposoby, żeby to zrobić: pierwszy polega na takiej zmianie systemu plików, żeby usunąć znacznik `deleted' ze skasowanych iwęzłów z nadzieją, że pliki nagle pojawią się na swoim miejscu. Inną metodą, bezpieczniejszą, ale wolniejszą jest znalezienie położenia interesujących danych na partycji i zapisaniu ich jako nowy plik w innym systemie plików.

Przed odtwarzeniem danych musisz zrobić kilka rzeczy; patrz rozdziały Odmontowanie systemu plików, Przygotowanie do bezpośrednich zmian w iwęzłach i Przygotowanie do zapisania danych w innym miejscu. Informację jak odzyskiwać pliki znajdziesz w rozdziałach Szukanie skasowanych iwęzłów, Uzyskiwanie szczegółowych informacji o iwęzłach, Odzyskiwanie bloków danych i Bezpośrednie modyfikacje iwęzłów.

## 5. Odmontowanie systemu plików

Niezależnie od metody jaką wybrałeś, pierwszym krokiem jest odmontowanie systemu plików zawierającego skasowane pliki. Zdecydowanie nie polecam żadnych działań na zamontowanym systemie plików. Krok ten powinien być wykonany najszybciej jak to będzie możliwe od momentu, gdy zauważyłeś, że pomyłkowo skasowałeś pliki. Im szybciej odmontujesz system plików, tym większa będzie szansa, że Twoje dane nie zostaną nadpisane (zamazane).

Najprostszą metodą, aby to zrobić jest: zakładając, że skasowane pliki były systemie plików `/usr`,

> `

>     # umount /usr

> `

Jeśli chcesz możesz również utrzymać widoczność katalogu `/usr`. Zamontuj go w trybie tylko-do-odczytu:

> `

>     # mount -o ro,remount /usr

> `

W przypadku, gdy skasowane pliki były na głównej partycji musisz dodać opcję `-n`, aby zabronić programowi `mount` na próby zapisu do `/etc/mtab`:

> `

>     # mount -n -o ro,remount /

> `

Poza tym wszystkim, możliwe jest również, że jakiś inny proces używa interesującego nas systemu plików (spowoduje to błąd typu `Resource busy' przy próbie odmontowania). `fuser` jest programem, który wyśle sygnał do każdego procesu używającego wskazanego pliku lub punktu montowania. Spróbuj tego dla partycji `/usr`:

> `

>     # fuser -v -m /usr

> `

W ten sposób uzyskasz listę przeszkadzających Ci procesów. Zakładając, że żaden z nich nie jest niezbędny, możesz napisać

> `

>     # fuser -k -v -m /usr

> `

aby wysłać sygnał `SIGKILL` do każdego z nich ( gwarantuje to ich zabicie), albo

> `

>     # fuser -k -TERM -v -m /usr

> `

aby przekazać każdemu sygnał `SIGTERM` (spowoduje to normalne zakończenie pracy procesów).

## 6. Przygotowanie do bezpośrednich zmian iwęzłów

Moja rada? Nie używaj tej metody. Nie uważam, żeby dobrym pomysłem była zabawa na niskim poziomie w systemie plików. Metoda ta stwarza również problemy jeśli chcesz odtworzyć pliki większe niż 12 bloków. W celu odzyskania dużych plików, tak czy owak, będziesz musiał użyć innej metody. (Chociaż patrz rozdział Czy będzie to kiedyś łatwiejsze? w celu dodatkowych informacji.)

Jeżeli jednak chcesz koniecznie użyć tego sposobu, lepiej skopiuj bezpośrednio obraz partycji na inną partycję, a później zamontuj ją używając pętli zwrotnej (loopback):

> `

>     # cp /dev/hda5 /root/working
>     # mount -t ext2 -o loop /root/working /mnt

> `

(Niektóre wersje `mount` nie potrafią tego zrobić. Jeśli Twój `mount` nie działa poprawnie, zalecam użycie najnowszej wersji, conajmniej 2.7. Dużo starsze wersje mają problemy z utrzymaniem bezpieczeństwa danych.)

Używając pętli zwrotnej, nawet jeśli całkowicie zniszczysz system plików, możesz ponownie skopiować partycję i zacząć próby od nowa.

## 7. Przygotowanie do zapisu danych w innym miejscu

Jeżeli wybierzesz tę drogę działania, musisz znaleźć partycję ratunkową -- miejsce, gdzie zapiszesz nowe kopie odzyskanych plików. Na całe szczęście, twój system zawiera kilka partycji: prawdopodobnie partycję główną, `/usr` i `/home`. Wybierz jedną z nich i utwórz na niej nowy katalog.

Jeśli masz tylko partycję główną i wszystko przechowujesz na niej, rozwiązanie troszkę się skomplikuje. Może masz partycje MS-DOS lub Windows, której bedziesz mógł użyć ? Albo masz sterownik do ramdisk-u w swoim jądrze, albo w module ? W celu użycia ramdisk-u (zakładając, że jądro jest nowsze od 1.3.48), napisz:

> `

>     # dd if=/dev/zero of=/dev/ram0 bs=1k count=2048
>     # mke2fs -v -m 0 /dev/ram0 2048
>     # mount -t ext2 /dev/ram0 /mnt

> `

W ten sposób stworzyłeś 2MB wolumen ramdisk-u i zamontowałeś do w `/mnt`.

Krótkie ostrzeżenie: jeżeli używasz `kerneld` (lub zastępującego go `kmod` w jądrach 2.2.x i późnych 2.1.x) w celu automatycznego ładowania i odładowywania modułów, nie odmontowuj ramdisk-u dopóki nie skopiujesz wszystkich plików na bardziej trwały nośnik. W chwili, gdy go odmontujesz, `kerneld` zakłada, że może odładować moduł (zwykle jednak czeka pewien okres). Gdy to już się stanie, pamięć zostanie użyta przez inne części jądra i stracisz wszystkie godziny spędzone na odzyskiwaniu danych.

Jeżeli masz napęd Zip, Jaz, LS-120 lub coś podobnego, może on spełniać z powodzeniem rolę partycji ratunkowej. W pozostałych przypadkach, użyj po prostu napędu stacji dyskietek.

Będziesz jeszcze potrzebował programu, który potrafi czytać dane ze środka partycji. Właściwie może to zrobić `dd`, ale aby przeczytać dane leżące od 600 MB do 800 MB, `dd` musi przeczytać i zignorować pierwsze 600 MB. Zajmuje to dosyć dużo czasu, nawet na szybkich dyskach. Moim sposobem na obejście tego problemu było napisanie programu, który przeskakuje w środek partycji. Nazywa się on `fsgrab`; pakiet ze źródłem możesz znaleźć na mojej stronie domowej lub na Metalab-ie (i kopiach, w Polsce - Sunsite ). Jeśli będziesz chciał stosować tę metodę, w dalszej części tego mini-JTZ zakładam, że masz `fsgrab`.

Nie potrzebujesz `fsgrab-a`, jeżeli żaden z plików, które starasz się odzyskać, nie zajmuje więcej niż 12 bloków (przeważnie blok ma rozmiar jednego kilobajta).

Jeżeli musisz użyć `fsgrab-a`, ale nie chce Ci się go ściągać i kompilować, jest też prosta droga na przetłumaczenie polecenia dla `fsgrab` na polecenie dla `dd`. Mając

> `fsgrab -c count -s skip device`

możesz użyć komendy `dd` (przeważnie jest to dużo wolniejsze)

> `dd bs=1k if=device count=count skip=skip`

Muszę Cię ostrzec, że chociaż dla mnie `fsgrab` działa doskonale, nie mogę brać odpowiedzialności za jego funkcjonowanie. Pisałem go dosyś szybko i niestarannie, po prostu, aby działał poprawnie. Więcej szczegółów o gwarancji znajdziesz w rozdziale `No Warranty' w pliku `COPYING` dołaczonym do pakietu (the GNU General Public Licence).

## 8. Szukanie skasowanych iwęzłów

Następnym krokiem jest odnalezienie w systemie plików tych iwęzłów, które zostały ostanio uwolnione. Do tego zadania użyjemy programu `debugfs`. Uruchom `debugfs` z nazwą urządzenia, na którym przechowywany jest system plików:

> `

>     # debugfs /dev/hda5

> `

Jeżeli chcesz bezpośrednio wprowadzać zmiany do iwęzłów, dodaj opcję `-w`, aby umożliwić zapisywanie do systemu plików:

> `

>     # debugfs -w /dev/hda5

> `

`lsdel` jest poleceniem `debugfs`, które wyszukuje skasowane iwęzły. Po zachęcie programu, napisz więc:

> `

>     debugfs:  lsdel

> `

Po chwili świergotania dysku, długa lista zostanie przekierowana do Twojego ulubionego łamacza na strony (ang. pager) (wartość zmiennej `$PAGER`). Powinienneś zachować gdzieś kopię tej listy. Jeżeli używasz `less`, możesz po prostu napisać `-o` i nazwę pliku wyjściowego. W innym razie, będziesz musiał przesłać wyniki do pliku w inny sposób. Spróbuj czegoś takiego:

> `

>     debugfs:  quit
>     # echo lsdel | debugfs /dev/hda5 > lsdel.out

> `

Teraz, tylko na podstawie czasu skasowania, rozmiaru, praw własności i właściciela musisz określić, które iwęzły należały do skasowanych plików. Będzie to prawdopodobnie proste zadanie jeśli wypadek przydarzył się 5 minut temu, jeśli nie, przeszukaj listę bardzo uważnie.

Polecam wydrukowanie sobie listy iwęzłów, które chcesz odzyskać. Ułatwi Ci to dalszą pracę.

## 9. Uzyskiwanie szczegółowych informacji o iwęzłach

`debugfs` dysponuje poleceniem `stat`, które wyświetla szczegółowe informacje o iwęźle. Wykonaj tę komendę dla wszystkich iwęzłów, które chcesz odzyskać. Na przykład, jeżeli interesuje Cię iwęzeł o numerze 148003, napisz tak:

> `

>     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

> `

Gdy chcesz odzyskać wiele plików, dobrze będzie jak zautomatyzujesz ten proces. Przy założeniu, że Twoja `lsdel` lista interesujących iwęzłów znajduje się w pliku `lsdel.out`, napisz coś takiego:

> `

>     # cut -c1-6 lsdel.out | grep "[0-9]" | tr -d " " > inodes

> `

Nowy plik `inodes` zawiera tylko numery iwęzłówm, które chcesz odzyskać, po jednym w jednej linii. Zapisaliśmy to, bowiem później bardzo nam się przyda. Potem piszesz po prostu:

> `

>     # sed 's/^.*$/stat <\0>/' inodes | debugfs /dev/hda5 > stats

> `

i plik `stats` zawiera wyniki wszystkich poleceń `stat`.

## 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:

- Numery pierwszych 12 bloków danych przechowywane są bezpośrednio w iwęźle; czasami nazywa się je blokami bezpośrednimi.
- Iwęzeł zawiera numer pośredniego bloku. Blok pośredni zawiera numery następnych 256 bloków z danymi.
- Iwęzeł zawiera numer podwójnie pośredniego bloku. Blok podwójnie pośredni zawiera numery dodatkowych 256 bloków pośrednich.
- Iwęzeł zawiera numer potrójnie pośredniego bloku. Blok potrójnie pośredni zawiera numery dodatkowych 256 bloków podwójnie pośrednich.

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.

## 11. Bezpośrednie modyfikacje iwęzłów

Metoda ta jest dużo prostsza. Jednak, tak jak wspomniałem wcześniej, nie może być jeszcze stosowana do plików większych niż 12 bloków.

W każdym iwęźle, który chcesz odzyskać musisz ustawić licznik podłączeń (linkcount) na jeden i czas skasowania (deletion time) na zero. Robi się to za pomocą polecenia `mi` (modify inode) w `debugfs`. Przykładowe wywołanie, modyfikacja iwęzła 148003 (tego co wcześniej):

> `

>     debugfs:  mi <148003>
>                               Mode    [0100644]
>                            User ID    [503]
>                           Group ID    [100]
>                               Size    [6065]
>                      Creation time    [833201524]
>                  Modification time    [832708049]
>                        Access time    [826012887]
>                      Deletion time    [833201524] 0
>                         Link count    [0] 1
>                        Block count    [12]
>                         File flags    [0x0]
>                          Reserved1    [0]
>                           File acl    [0]
>                      Directory acl    [0]
>                   Fragment address    [0]
>                    Fragment number    [0]
>                      Fragment size    [0]
>                    Direct Block #0    [594810]
>                    Direct Block #1    [594811]
>                    Direct Block #2    [594814]
>                    Direct Block #3    [594815]
>                    Direct Block #4    [594816]
>                    Direct Block #5    [594817]
>                    Direct Block #6    [0]
>                    Direct Block #7    [0]
>                    Direct Block #8    [0]
>                    Direct Block #9    [0]
>                   Direct Block #10    [0]
>                   Direct Block #11    [0]
>                     Indirect Block    [0]
>              Double Indirect Block    [0]
>              Triple Indirect Block    [0]

> `

Ustawiłem czas skasowania na 0, licznik podłączeń na 1 i nacisnąłem Enter dla wszystkich innych pól. Jest to pewną niedogodnością, jeżeli masz wiele plików do odzyskania. Myślę jednak, że można z tym żyć. Jeśli oczekujesz wygody, lepiej zacznij używać graficznego `systemu operacyjnego' ze ślicznym `Koszem na śmieci'.

Przy okazji: polecenie `mi` pokazuje `Czas stworzenia' (Creation time) w iwęźle. To kłamstwo ! (lub, jak kto woli, pomyłka.) Prawda jest taka, że nie można w systemie plików UNIX-a stwierdzić kiedy dany plik został utworzony. Pole `st_ctime` w `struct stat` zawiera `czas zmiany iwęzła', czyli czas ostaniej zmiany, któregoś z parametrów iwęzła. To tyle z dzisiejszej lekcji.

Nowsze wersje `debugfs` niż moja, prawdopodobnie nie wyświetalają niektórych pól w iwęźle (szczególnie, `Reserved1` i `Fragment`).

Po zmianie w iwęzłach, możesz wyjść z `debugfs` i napisać:

> `

>     # e2fsck -f /dev/hda5

> `

Pomysł polega na tym, że każdy ze skasowanych plików został odkasowany, ale nie pojawił się w żadnym katalogu. Program `e2fsck` umie to wykryć i doda pozycję dla każdego z nich w katalogu `/lost+found` systemu plików. (Jeżeli partycja była zamontowana w `/usr`, pliki pojawią się w `/usr/lost+found`, gdy ją zamontujesz.) Pracą, którą musisz jeszcze zrobić, to nadanie plikom nazw i umieszczenie ich we właściwym miejscu drzewa plików.

Po uruchomieniu `e2fsck`, wyświetli Ci on trochę informacji, ale zada również pytania, które zniszczenia naprawiać. Odpowiadaj `yes' (tak) na wszystko co dotyczy `summary information' lub iwęzłów, które zmieniałeś. Resztę pozostawiam do Twojej decyzji, pamiętaj, że nie jest najlepszą metodą odpowiadanie `tak' na wszystkie pytania. Po skończeniu pracy przez `e2fsck`, możesz ponownie zamontować system plików.

Istnieje alternatywne rozwiązanie do pozwolenia, aby `e2fsck` utworzył pliki w `/lost+found`. Możesz użyć `debugfs` i stworzyć w systemie plików dołączenie (link) do iwęzła. Służy do tego polecenie `link` w `debugfs`, po zmianach w samym iwęźle:

> `

>     debugfs:  link <148003> foo.txt

> `

W ten sposób powstanie w bieżącym katalogu plik o nazwie `foo.txt`; `foo.txt` będzie Twoim odzyskanym plikiem. Nadal musisz jednak uruchomić `e2fsck`, aby uaktualnić informacje ogólne, liczniki bloków itp. itd.

## 12. Czy będzie to kiedyś łatwiejsze?

Tak. Właściwie, mam nadzieję, że tak. Chociaż, gdy to piszę, aktualna, stabilna wersja jądra (seria 2.0.x) zeruje bloki pośrednie. Wersje serii rozwojowej 2.1.x i stabilnej 2.2.x nie mają tej wady. Dzisiaj, 2 lutego 1999 minęło dopiero kilka dni od wydania jądra 2.2.1; prawdopodobnie pojawi się ono w dystrybucjach za jeden, dwa miesiące.

Kiedy wersje jądra rozwiążą problem zerowania bloków pośrednich, wiele moich ręcznych technik modyfikacji iwęzłów nie będzie już potrzebnych. W tym samym czasie stanie się możliwe użycie polecenia `dump` w `debugfs` dla dużych plików i innych programów narzędziowych do odzyskiwania plików.

## 13. Czy są jakieś programy automatyzujące ten proces?

Pewnie, że są. Niestety cierpią one na te same problemy co ręczna technika zmian w iwęzłach: bloki pośrednie są nieodzyskiwalne. Warto im się przyjrzeć, bowiem wydaje się, że ograniczenie to wkrótce zniknie.

Napisałem program `e2recover`, który jest właściwie tylko Perl-ową otoczką dookoła `fsgrab`. Stara się on poradzić sobie z wyzerowanymi blokami pośrednimi i wydaje sie, że działa całkiem nieźle dla dużych plików, które nie uległy fragmentacji. Ustawia poprawne prawa dostępu (i właściciela, gdy to jest możliwe). Upewnia się również, że odzyskiwany plik ma poprawny rozmiar.

Program `e2recover` był planowany jako część poważnych zmian w tym Howto; oznacza to niestety, że więcej użytecznej dokumentacji do `e2recover` będzie zamieszczone dopiero w nowej wersji tego dokumentu. Jednak i teraz może on się komuś przydać; można go ściągnąć z mojej strony domowej, i wkrótce z Metalab-a (jest już w Polsce - Sunsite).

Scott D. Heavner jest autorem programu `lde`, the Linux Disk Editor. Może on być używany zarówno jako binarny edytor dysku i jako odpowiednik `debugfs` dla systemów plików ext2 i minix, a nawet dla systemu plików xia (chociaż wsparcie dla xia przestało być dostępne w jądrach 2.1.x i 2.2.x). Zawarto w nim kilka pomysłów wspomagających odzyskiwanie skasowanych plików: śledzenie listy bloków tworzących plik i wyszukiwanie danych na dysku. Zawiera on także całkiem użyteczną dokumentację o podstawach systemu plików oraz jak go używać do odzyskiwania plików skasowanych. Wersja 2.4 `lde` jest dostępna na Metalab-ie (i kopiach, w Polsce - Sunsite), lub na stronie domowej autora.

Inne możliwości oferowane są przez GNU Midnight Commander, `mc`. Jest to pełnoekranowe narzędzie do zarządzania plikami, oparte na znanym w środowisku MS-DOS programie o nazwie `NC'. `mc` obsługuje mysz zarówno na konsoli, jak i w oknie xterm-a, dostarcza mechanizm wirtualnych systemów plików, co umożliwia triki takie jak `cd` do archiwum tar. Odzyskiwanie plików obsługiwane jest przez jeden z takich wirtualnych systemów plików. Wszystko to brzmi bardzo zachęcająco, ale muszę przyznać, że nie używam tego programu -- wolę staromodne polecenia powłoki.

Aby używać możliwości odzyskiwania skasowanych plików, musisz skonfigurować program z opcją `-``-with-ext2undel`; będziesz również potrzebował bibliotek w wersji rozwojowej i niektórych plików zawartych w pakiecie `e2fsprogs`. W ten sposób zbudowana jest wersja dostarczana w Debian GNU/Linux; tak samo może być w innych dystrybucjach. Teraz możesz po prostu kazać mu `cd undel:/dev/hda5`, i otrzymasz `zawartość katalogu' ze skasowanymi plikami. Jak wiele innych i ten program bardzo źle radzi sobie z zerowaniem bloków pośrednich -- przeważnie odtwarza tylko pierwsze 12k większych plików.

Aktualną wersję można ściągnąć z serwera ftp the Midnight Commander.

## 14. Kolofon

Mam zamiar regularnie uaktualniać ten dokument tak długo jak będę miał wystarczająco dużo czasu i coś ciekawego do powiedzenia. Oznacza to, że bardzo mi zależy na komentarzach od czytelników. Czy moje pisanie może być bardziej zrozumiałe? Czy myślicie o czymś, co uczyniłoby problem prostszym? Jest jakiś program, który robi to wszystko automatycznie? Jeżeli masz coś do powiedzenia o tym dokumencie, albo o `fsgrab`, albo o `e2recover`, napisz do mnie `aaronc@pobox.com`.

## 15. Wyrazy uznania i bibliografia

> `Jeżeli widzę dalej od innych, to dlatego, że stoję na ramionach olbrzymów.' (Isaac Newton)

To mini-Howto wywodzi się z listu zamieszczonego w grupie `comp.os.linux.misc` przez Robina Glovera `swrglovr@met.rdg.ac.uk`. Chciałbym podziekować Robinowi za wspaniałomyślne pozwolenie na przetworzenie jego pomysłów w to mini-Howto.

Korzystając z okazji, chciałbym jeszcze raz podziękować wszystkim, którzy napisali do mnie o tym Howto. Otrzymywanie wyrazów wdzieczności czyni pracę wartą wysiłku.

Niektóre odnośniki bibliograficzne:

- Frisch, Ćleen (1995), Essential System Administration, second e O'Reilly and Associates, Inc., ISBN: 1-56592-127-5.
- Garfinkel, Simson, Daniel Weise and Steven Strassmann (1994), The Unix-Haters Handbook, IDG Books, ISBN: 1-56884-203-1. Większość tej książki wypełniają jednynie młodociane jęki ludzi, którzy myślą że ich system operacyjny był o wiele lepszy od Unix-a; a reszta książki nie dotyczy Cię, jeżeli używasz dobrego otoczenia użytkownika jakim jest GNU. Są tam jednak pewne ciekawe rzeczy; na przykład, dyskusja o tym jak łatwo jest skasować plik pod Unix-em warta jest przeczytania.
- Glover, Robin (31 Jan 1996), HOW-TO : undelete linux files (ext2fs/debugfs), comp.os.linux.misc Usenet posting.
- Peek, Jerry, Tim O'Reilly, Mike Loukides et al (1993), UNIX Power Tools, O'Reilly and Associates, Inc./Random House, Inc., ISBN: 0-679-79073-X. Second edition, 1998.

## 16. Formalności

Wszystkie znaki towarowe są własnością ich prawowitych właścicieli. Konkretnie:

- MS-DOS i Windows są znakami towarowymi Microsoftu.
- UNIX jest znakiem towarowym the Open Group.
- Linux jest znakiem towarowym zarejestrowanym w USA i kilku innych państwach dla Linusa Torvalds.

Prawa autorskie do tego dokumentu 1997, 1999 posiada Aaron Crane `aaronc@pobox.com`. Może on być darmowo rozpowszechniany w całości, łącznie z tą notą autorską. Nie może być zmieniany bez zgody autora lub koordynatora Linux Documentation Project HOWTO. Nie dotyczy to tylko kopiowania jego części w celu przeglądania lub cytowania; w takim przypadku, części te muszą być poprawnymi cytatami i nie muszą zawierać noty o prawach autorskich.

Autor oczekuje, ale nie wymaga, że ten kto będzie chciał sprzedawać kopie tego dokumentu, niezależnie od tego, czy na nośniku elektronicznym, czy papierowym, poinformuje jego lub koordynatora projektu Linux HOWTO o swoich zamiarach.

Koordynatorem projektu Linux HOWTO jest aktulanie Tim Bynum `linux-howto@sunsite.unc.edu`.

## 17. Od tłumacza

Starałem się, aby tłumaczenie było najwierniejsze z możliwych. Dlatego nie ma żadnych zmian w stosunku do orginału, za wyjątkiem odnośników do polskiej kopii serwera Metalab na Sunsite.icm.edu.pl.

Czekam na komentarze pod adresem: Bartosz Sawicki `sawickib@ee.pw.edu.pl`.