Linux Ext2fs Mini- COMO FAZER de Não Deleção Aaron Crane, v1.2, 4 de agosto de 1997 Imagine o seguinte. Você passou os últimos três dias sem dormir, sem comer e sem mesmo tomar banho. Sua compulsão por programação finalmente valeu a pena: você terminou aquele programa que lhe trará fama e reconhecimento mundial. Tudo o que você ainda tem que fazer é compactá-lo e colocá-lo no Sunsite (N.T. : atual Metalab). Oh, e apagar todos aqueles arquivos de cópias de segurança Emacs. Aí você digita rm * ~. E tarde demais, você percebe o espaço extra naquele comando. Você acabou de apagar todo o seu _m_a_g_n_u_m _o_p_u_s! Mas alguma ajuda está à mão. Este documento apresenta uma discussão de como recuperar arquivos apagados de um Segundo Sistema de Arquivos Estendido. Talvez, você possa lançar aquele programa afinal... ______________________________________________________________________ Índice geral 1. Introdução 1.1 Histórico da revisão 1.1.1 Mudanças na versão 1.1 1.1.2 Mudanças na v1.2 1.2 Localizações canônicas deste documento 2. Como não apagar os arquivos 3. Que índice de recuperação posso esperar? 4. Então, como fazer para recuperar um arquivo apagado? 5. Desmontando o Sistema de Arquivos 6. Preparando para alterar os inodes diretamente 7. Preparar para escrever os dados em outra parte 8. Encontrando os inodes apagados 9. Obtendo os detalhes dos inodes 10. Recuperando os blocos de dados 10.1 Arquivos curtos 10.2 Arquivos maiores 11. Modificando inodes diretamente 12. Isto ficará mais fácil no futuro? 13. Existem algumas ferramentas para automatizar este processo? 14. Colophon 15. Créditos e Bibliografia 16. Aspectos Legais ______________________________________________________________________ 11.. IInnttrroodduuççããoo Este mini-COMO FAZER tenta fornecer dicas de como recuperar os arquivos apagados de um sistema de arquivos ext2. Também contém uma discussão limitada de como evitar que os arquivos sejam indevidamente apagados. Pretendo certamente ser útil às pessoas que acabaram, digamos, de ter um pequeno acidente com rm; porém, espero que as pessoas de alguma forma o leiam. Nunca se sabe, um dia quem sabe, as informações contidas aqui podem salvar sua vida. O texto presume um pequeno conhecimento anterior sobre os sistemas de arquivo UNIX em geral (N.T. sugerimos a leitura do Guia do Administrador de Sistemas Linux, disponível em www.conectiva.com.br). No entanto, eu espero que seja acessível à maioria dos usuários Linux. Se você é um completo iniciante, sinto muito, mas a não eliminação dos arquivos sob Linux _r_e_a_l_m_e_n_t_e exige uma certa quantia de conhecimento técnico e persistência, pelo menos por hora. Você será incapaz de recuperar arquivos apagados de sistemas de arquivos ext2 sem pelo menos ler o acesso ao dispositivo bruto no qual o arquivo está armazenado. Em geral, isto significa que deve-se ser superusuário. Será necessário o programa debugfs do pacote e2fsprogs. Isto deve ter sido instalado pelo sua distribuição. Por que eu escrevi isto? Em grande parte isto vem de minha própria experiência com um comando como superusuário rm -r tolo e desastroso. Eu apaguei cerca de 97 arquivos JPEG que eu precisava e não seria possível recuperá-los de outras fontes. Usando algumas dicas úteis (veja a seção ``Créditos e Bibliografia'') e muita persistência, recuperei 91 arquivos sem danos. Consegui salvar pelo menos partes de cinco dos demais (o suficiente para ver qual a gravura que estava em cada caso). Só um ficou sem condições de ser mostrado e mesmo este, eu tenho quase certeza absoluta que não mais que 1.024 bytes foram perdidos (embora infelizmente do início do arquivo; dado que eu não sei nada sobre o formato de arquivo JFIF fiz o máximo que podia). Discutirei mais adiante que tipo de índice de recuperação você pode esperar de arquivos apagados. 11..11.. HHiissttóórriiccoo ddaa rreevviissããoo As várias revisões lançadas publicamente deste documento (e suas datas de publicação) são as seguintes: · v1.0 em 18 de janeiro de 1997 · v1.1 em 23 de julho de 1997 (ver seção ``Mudanças na v1.1'') · v1.2 em 4 de agosto de 1997 (ver seção ``Mudanças na v1.2'') 11..11..11.. MMuuddaannççaass nnaa vveerrssããoo 11..11 Que mudanças foram feitas nesta versão? Antes de mais nada, o "thinko" no exemplo da recuperação do arquivo foi consertado. Graças a todos aqueles que salientaram meu erro, espero ter aprendido a ser mais cuidadoso ao fazer uma interação de programa. Em segundo lugar, a discussão do desenho do sistema de arquivo UNIX foi reescrito para ser, espero, mais compreensível. Eu não estava completamente feliz com ele em primeiro lugar e o comentário de algumas pessoas indicou que ele não era muito claro. Em terceiro lugar, o vasto código do arquivo tar (``tarball'') compactado do fsgrab no meio do arquivo foi removido. O programa agora está disponível em my webservidor e logo deve chegar a Sunsite (e seus espelhos). Em quarto lugar, o documento foi traduzido para o Projeto de Documentação Linux através de Ferramentas SGML que contém a linguagem de marcação. Esta linguagem pode ser facilmente convertida para um número de outras linguagens de marcação (inclusive HTML e LaTeX) para convenientes exposição e impressão. Um benefício disto é que edições no papel numa tipografia linda são objetivos muito mais realizáveis e uma outra coisa é que o documento tem referências cruzadas e ligações quando vistos na Rede. 11..11..22.. MMuuddaannççaass nnaa vv11..22 Esta revisão é uma mudança basicamente de acréscimos. Está aqui principalmente para incluir as mudanças sugeridas por leitores, uma das quais é particularmente importante. A primeira mudança foi sugerida por Egil Kvaleberg , que salientou o comando dump em debugfs. Obrigado, outra vez, Egil. A segunda mudança é para mencionar o uso de chattr para evitar a eliminação de arquivos importantes. Obrigado, Herman Suijs por mencionar este. O resumo foi revisado. Os URLs tem sido adicionados para organizações e software. Várias outras mudanças menores têm sido feitas (inclusive o conserto de erros de digitação e assim por diante). 11..22.. LLooccaalliizzaaççõõeess ccaannôônniiccaass ddeessttee ddooccuummeennttoo O lançamento mais recente deste documento deve sempre estar disponível no formato de texto simples em Linux Documentation Project Servidor (e espelhos). O lançamento mais recente é também mantido em my webservidor em vários formatos: · SGML source . Esta é a fonte como eu a escrevi, usando o pacote de Ferramentas SGML. · HTML . Este é HTML, automaticamente gerado da fonte SGML. · Plain text . Este é o texto simples, que é também automaticamente gerado da fonte SGML. Perceba que este arquivo é idêntico ao Metalan, assim se você quiser o texto simples, recomenda-se que se consiga a partir do seu espelho LDP favorito (pois será provavelmente muito mais rápido). 22.. CCoommoo nnããoo aappaaggaarr ooss aarrqquuiivvooss É vital lembrar que o Linux é diferente do MS-DOS quando se trata da não eliminação. Para MS-DOS (e sua descendência: o Windows 95), é geralmente bastante simples não apagar um arquivo - o 'sistema operacional' (eu uso o termo livremente) até mesmo vem com um utilitário que automatiza muito do processo. Para o Linux, este não é o caso. Assim, a regra número um (a primeira diretiva, caso se prefira) é: MMAANNTTEERR CCÓÓPPIIAASS DDEE SSEEGGUURRAANNÇÇAA não importa o que se possa fazer. Eu sei que eu sou uma pessoa agradável de se conversar. Eu deveria simplesmente alegrar empobrecimento (sendo estudante devo ter _a_l_g_u_n_s perks) e exortar todos usuários bem pensantes de Linux a sair e comprar um dispositivo de cópia de segurança útil, imaginar um esquema de cópia de segurança decente, e _u_s_á_-_l_a _a_t_i_v_a_m_e_n_t_e. Para maiores informações sobre isto, leia Frisch (1995) (ver seção ``Créditos e Bibliografia''). Na falta de cópias de segurança, o que se faz? (Ou mesmo na presença de cópias de segurança: cintos e fitas não são uma má política quando dados importantes estão em jogo). Tente estabelecer as permissões dos arquivos importantes para 440 (ou menos): negar-se o acesso de escrita a esses arquivos significa que rm requer uma confirmação explícita antes de apagar (eu acho, porém, que se estou recursivamente apagando um diretório com rm -r, interromperei o programa no primeiro ou segundo pedido de confirmação e relançarei o comando como rm -rf). Um bom truque para arquivos selecionados é criar uma ligação direta com eles num diretório escondido. Eu ouvi uma história sobre um administrador de sistema que repetidamente apagava /etc/passwd por acaso (e com isso a metade do sistema). Um dos ajustes para isto foi fazer algo como o que se segue (como superusuário): # mkdir /.backup # ln /etc/passwd /.backup Isto exige algum esforço para apagar os conteúdos dos arquivos completamente. Ao se digitar: # rm /etc/passwd então # ln /.backup/passwd /etc salvará o desatento administrador. Claro que isto não ajuda no caso de sobrescrita do arquivo, por isso de qualquer maneira as cópias de segurança serão necessárias. Num sistema de arquivos ext2 é possível usar os atributos ext2 para proteger as coisas. Estes atributos são manipulados através do comando chattr. Há um atributo `append-only': um arquivo com este atributo pode ser acrescido, mas não pode ser apagado, e os conteúdos existentes do arquivo não podem ser sobrescritos. Se um diretório tiver este atributo, qualquer arquivo ou diretórios dentro dele podem ser modificados, mas nenhum arquivo pode ser apagado. O atributo `append-only' é estabelecido com: $ chattr +a ARQUIVO... Há também um atributo 'imutável', que só pode ser estabelecido ou retirado pelo superusuário. Um arquivo ou diretório com este atributo não pode ser modificado, renomeado, ou receber conexões diretas (links). Pode ser estabelecido como se segue: # chattr +i ARQUIVO... O ext2fs também provê o atributo 'não removível' (+u no chattr). A intenção aqui é que se um arquivo com este atributo for apagado, ao invés de ser de fato reutilizado, ele é simplesmente movido para um 'local seguro' para a eliminação em uma data posterior. Infelizmente esta característica não foi ainda implementada na linha principal dos kernels. Porém, vários ajustes de kernel existem para promover a habilidade de tornar a eliminação reversível. Veja se estiver interessado em ajustar esta facilidade ao kernel. A atualização mais recente que conheço é a de Rogier Wolff , Darren J Moffat e Kurt Huwig . Salientaria que enquanto este ajuste implementa a característica, ele não é uma 'solução para não apagar' no momento. Os arquivos não elimináveis são simplesmente movidos para um outro diretório, devendo haver um servidor para limpá-los periodicamente. Algumas pessoas defendem a composição de um nome alternativo para o comando rm ou uma função distinta para rm -i (que pede confirmação para _t_o_d_o_s arquivos que você apaga). Realmente, as versões recentes da distribuição Red Hat fazem isso por padrão para todos os usuários, inclusive o superusuário. Pessoalmente, não suporto o software que não pode ser executado desatendido, por isso não o utilizo. E sempre há a possibilidade de mais cedo ou mais tarde, estar-se executando o sistema em modo monousuário, ou usando um ambiente de trabalho diferente, ou ainda uma máquina diferente, onde a função rm personalizada não existe. Caso se espere que a confirmação seja solicitada, pode ser fácil esquecer onde se está e especificar arquivos demais a serem apagados. Da mesma forma, os vários programas que substituem rm também são, em minha opinião, muito perigosos. Uma solução levemente melhor é começar usando um pacote que administre a eliminação 'reciclável' fornecendo um comando diferente do rm. Para detalhes sobre estes, veja Peek, et al (1993) (veja a seção ``Bibliografia e Créditos''). 33.. QQuuee íínnddiiccee ddee rreeccuuppeerraaççããoo ppoossssoo eessppeerraarr?? Isso depende. Entre os problemas com a recuperação de arquivos em sistemas operacionais com alta qualidade, multitarefa e multiusário como o Linux, o maior reside no fato de que nunca se sabe quando alguém irá escrever no disco. Por isso quando se solicita ao sistema operacional para apagar um arquivo, presume-se que os blocos usados por aquele arquivo sejam somente os alocados e necessários para a criação do arquivo (este é um exemplo específico de um princípio geral para o Linux: o kernel e as ferramentas associadas presumem que os usuários não sejam leigos). Em geral, quando mais uso tenha a máquina, é menor a probabilidade de recuperar arquivos com sucesso. Também, a fragmentação do disco pode afetar a facilidade da recuperação de arquivos. Se a partição contendo os arquivos apagados estiver fragmentada, é improvável que se possa ler todo o arquivo. Caso a máquina, assim como a minha, é usada efetivamente como uma estação de trabalho de um único usuário (a minha nem mesmo tem ainda uma conexão de rede, talvez ano que vem...), e não se estava executando nenhuma tarefa de uso intensivo de disco no momento fatal da eliminação indevida de alguns arquivos, pode-se esperar um índice de recuperação como o descrito acima. Pude recuperar quase 94% dos arquivos (e estes eram arquivos binários, e por favor, repare) sem danos. Ao se conseguir 80% ou mais, pode-se sentir satisfeito consigo mesmo, eu acho. 44.. EEnnttããoo,, ccoommoo ffaazzeerr ppaarraa rreeccuuppeerraarr uumm aarrqquuiivvoo aappaaggaaddoo?? O procedimento envolve principalmente a descoberta de dados num dispositivo de partição bruta e torná-los visíveis novamente para o sistema operacional. Há basicamente duas maneiras de se fazer isto: uma é modificar o sistema de arquivos existente de tal forma que os inodes apagados tenham os seus indicadores de 'apagados' removidos e espera-se que simplesmente num passe de mágica os dados voltem a seus respectivos lugares. O outro método, que é mais seguro, mas mais lento, é calcular onde os dados estão na partição e escrevê-los em um outro arquivo. Há alguns passos que são necessários antes de se começar a tentar uma recuperação de dados. Veja as seções ``Desmontando o Sistema de Arquivos'', ``Preparando mudanças diretas de inodes '' e ``Preparando a gravação de dados em qualquer local '' para maiores detalhes. Para descobrir como salvar realmente arquivos, veja as seções ``Encontrando e apagando inodes '', ``Obtendo os detalhes dos inodes'', ``Recuperando blocos de dados'' e ``Modificando inodes diretamente''. 55.. DDeessmmoonnttaannddoo oo SSiisstteemmaa ddee AArrqquuiivvooss Não importando qual método se escolha, o primeiro passo é desmontar o sistema de arquivo que contenha os arquivos apagados. Firmemente desencorajo qualquer impulso que se possa ter para lidar com um sistema de arquivos montado. Este passo deve ser dado _l_o_g_o _q_u_e _p_o_s_s_í_v_e_l depois o momento em que se perceba que arquivos tenham sido indevidamente apagados. O método mais simples é o que se segue: presumindo-se que os arquivos apagados estivessem por exemplo na partição /usr, deve-se executar o comando: # umount /usr Pode-se porém necessitar algumas coisas instaladas em /usr. Para utilizar os dados da partição pode-se remontá-la somente com permissões de leitura, no seguinte formato: # mount -o ro,remount /usr Caso os arquivos apagados estivessem na partição raiz, será necessário acrescentar a opção -n para prevenir a gravação pelo comando mount em /etc/mtab: # mount -n -o ro,remount / Apesar de tudo isso, é possível que haja um outro processo usando aquele sistema de arquivos (que fará com que o comando de desmontagem falhe, emitindo uma mensagem de erro similar a 'Recurso Ocupado'). Há um programa que enviará um sinal para qualquer processo usando um arquivo dado ou um ponto de montagem: fuser. Tente isto para a partição /usr: # fuser -v -m /usr Ele relacionará os processos envolvidos. Presumindo-se que nenhum deles seja vital, pode-se executar: # fuser -k -v -m /usr para enviar a cada processo um sinal SIGKILL (que certamente o finalizará), ou ainda, # fuser -k -TERM -v -m /usr para enviar a cada um SIGTERM (que normalmente fará com que o processo seja finalizado normalmente). 66.. PPrreeppaarraannddoo ppaarraa aalltteerraarr ooss iinnooddeess ddiirreettaammeennttee Meu conselho? Não faça deste jeito. Eu realmente não acho sensato brincar com um sistema de arquivos a um nível baixo o suficiente para que isso funcione. Há também problemas como a possibilidade de se recuperar com segurança somente os primeiros 12 blocos de cada arquivo. Por isso caso se tenha qualquer arquivo maior para recuperar, terá que se usar o outro método de qualquer maneira. (Porém veja a seção ``Isso será mais simples no futuro?'' para informações adicionais). Caso se entenda que se deva fazer desta maneira, meu conselho é copiar os dados da partição bruta para uma imagem em uma partição diferente, e então montar isto usando um sistema circular de recuperação: # cp /dev/hda5 /root/working # mount -t ext2 -o loop /root/working /mnt Isto, porém requer uma versão recente de mount (embora se deva ter a versão 2.6 ou mais nova, pois todas as versões anteriores tem um problema de segurança importante que permite usuários comuns terem acesso como superusuários. As distribuições importantes, isto é, Debian, RedHat e Slackware, e a Conectiva Linux foram todas atualizadas com a versão 2.6 de mount). Usar um sistema circular significa que quando se destruir completamente todo o sistema de arquivo (o que como é plenamente possível (e provável)), tudo o que se tem a fazer é copiar a partição bruta de volta e recomeçar. 77.. PPrreeppaarraarr ppaarraa eessccrreevveerr ooss ddaaddooss eemm oouuttrraa ppaarrttee É necessário certificar-se de se ter uma partição de resgate em algum lugar. Com sorte o sistema utilizado tem várias partições, talvez uma raiz, uma /usr e uma /home. Com todos estas para escolher, não se deve ter nenhum problema: apenas crie um novo diretório em alguma delas. Caso se tenha somente a partição raiz e tudo esteja armazenado nela (como eu, até se reparticionar o disco), as coisas ficam um pouco mais complexas. Talvez se tenha uma partição MS-DOS ou Windows que se possa usar. Ou se tem um programa de discos virtuais em memória no kernel, talvez como um módulo? Para usar o disco em memória (supondo que se tenha um kernel mais recente que o 1.3.48), pode-se executar o seguinte: # dd if=/dev/zero of=/dev/ram0 bs=1k count=2048 # mke2fs -v -m 0 /dev/ram0 2048 # mount -t ext2 /dev/ram0 /mnt Este procedimento criará um volume de disco em memória de 2MB, montando-o em seguida como /mnt. Um pequeno aviso: ao se usar kerneld para carregar e descarregar automaticamente os módulos, não desmonte o disco em memória até que qualquer arquivo que esteja nele seja copiado para um meio de armazenagem não volátil. Uma vez desmontado, o kerneld assume que pode descarregar o módulo (depois do período de espera usual) e uma vez que isto aconteça, a memória é reutilizada por outras partes do kernel, perdendo-se todos os dados e as horas de trabalho que se passaram recuperando seus dados. Caso se tenha um dos novos dispositivos removíveis de 'super unidades de disquetes', eles provavelmente são uma boa escolha para a localização da partição de salvamento. Caso contrário, será necessário utilizar as unidades de disquete. A outra coisa que se pode precisar é um programa que possa ler os dados necessários a partir do meio do dispositivo. Num instante o dd fará o trabalho, mas para ler de uma partição de 600 MB para uma partição de 800MB, o dd insiste em ler, ignorando os primeiros 600 MB. Isto pode levar muito tempo. Minha saída para isto foi escrever um programa que irá diretamente para o meio da partição. É chamado fsgrab, e os fontes podem ser encontrados em meu servidor web e ele deve logo estar em metalab (e seus espelhos). Caso se queira usar este método, o resto deste Como Fazer supõe que se tenha fsgrab à disposição. Se nenhum dos arquivos que se estiver tentando recuperar tiver mais que 12 blocos de comprimento (onde um bloco tem um tamanho normal de um kilobyte), então não se precisará do fsgrab. Caso se necessite usar fsgrab, mas não se queira fazê-lo, é bastante simples traduzir uma linha de comando fsgrab para uma para dd. Se tivermos: fsgrab -c _c_o_n_t_a_d_o_r -s _i_g_n_o_r_a_r _d_i_s_p_o_s_i_t_i_v_o então o comando dd correspondente é: dd bs=1k if=_d_i_s_p_o_s_i_t_i_v_o count=_c_o_n_t_a_d_o_r skip=_i_g_n_o_r_a_r Devo adverti-lo que embora o fsgrab tenha funcionado perfeitamente para mim, eu não assumo nenhuma responsabilidade sobre seu desempenho. Foi realmente uma saída muita rápida para conseguir que as coisas funcionassem. Para maiores detalhes sobre a falta de garantia, veja a seção "Sem Garantia" no arquivo COPYING incluído com ele (o GNU Licença Geral Pública). 88.. EEnnccoonnttrraannddoo ooss iinnooddeess aappaaggaaddooss O próximo passo é perguntar ao sistema de arquivos quais inodes foram liberados recentemente. Esta é uma tarefa que pode ser realizada com o utilitário debugfs. Inicie debugfs com o nome do dispositivo no qual o sistema de arquivos estiver armazenado: # debugfs /dev/hda5 Caso se queira modificar os inodes diretamente, deve ser acrescentada uma opção -w para habilitar a gravação no sistema de arquivos: # debugfs -w /dev/hda5 O parâmetro do debugfs para encontrar os inodes apagados é 0 lsdel. Deve-se então digitar o seguinte comando: debugfs: lsdel Após muita lamentação e trabalho duro do disco, uma longa lista é canalizada para seu paginador favorito (o valor de$PAGER). Agora deve-se salvar uma cópia do resultado. Caso se tenha o comando less, pode-se digitar -o seguido do nome do arquivo de saída. Caso contrário, deve-se enviar a saída para algum outro lugar. Por exemplo: debugfs: quit # echo lsdel | debugfs /dev/hda5 > lsdel.out Agora, baseado somente no horário desta eliminação, o tamanho, o tipo e as permissões numéricas e proprietário, tem-se que elaborar quais destes inodes apagados são aqueles que se quer. Com sorte, será possível vê-los porque eles são a grande quantidade de inodes que foram apagados há cerca de 5 minutos atrás. Caso contrário, analise cuidadosamente através da lista. Eu sugiro se possível, que se imprima a lista dos inodes que se queira recuperar. Isso tornará a vida bem mais fácil. 99.. OObbtteennddoo ooss ddeettaallhheess ddooss iinnooddeess debugfs tem um comando stat que imprime os detalhes sobre um inode. Execute o comando para cada inode em sua lista de recuperação. Por exemplo, caso se esteja interessado no inode número 148003, deve-se executar o seguinte: 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 Caso se tenha muitos arquivos para recuperar, pode-se querer automatizar isto. Supondo-se que a lista de inodes lsdel para recuperar esteja em lsdel.out, tente o seguinte: # cut -c1-6 lsdel.out | grep "[0-9]" | tr -d " " > inodes Este novo arquivo inodes contém apenas os números dos inodes a serem recuperados, um por linha. Salvamos em um arquivo porque é muito provável que ele venha a se tornar necessário mais tarde. Então deve- se executar: # sed 's/^.*$/stat <\0>/' inodes | debugfs /dev/hda5 > stats e stats contém a saída de todos os comandos stat. 1100.. RReeccuuppeerraannddoo ooss bbllooccooss ddee ddaaddooss Esta parte pode ser tanto mais fácil quanto mais difícil. Depende se o arquivo que se está tentando recuperar tenha ou não mais de 12 blocos de tamanho. 1100..11.. AArrqquuiivvooss ccuurrttooss Se o arquivo não tinha mais que 12 blocos de tamanho, então os números dos blocos de todos os seus dados estão armazenados no inode: pode-se lê-los diretamente da saída stat do inode. Além disso, debugfs tem um comando que desempenha esta tarefa automaticamente. Para exemplificar o que tivemos antes, repetimos aqui: 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 Este arquivo tem seis blocos (veja o campo BLOCKS). Uma vez que ele é menor que o limite de 12, usaremos debugfs para escrever o arquivo em um novo local, chamando-o de /mnt/recuperado.000: debugfs: dump <148003> /mnt/recuperado.000 Naturalmente que isto também pode ser feito com fsgrab, no seguinte formato: # fsgrab -c 2 -s 594810 /dev/hda5 > /mnt/recuperado.000 # fsgrab -c 4 -s 594814 /dev/hda5 >> /mnt/recuperado.000 Tanto com debugfs ou fsgrab, haverá algum lixo no final de /mnt/recuperado.000, porém isso não é importante. Caso se queira livrar-se dele, o método mais simples é verificar o campo Size do inode e utilizá-lo na opção bs em uma linha de comando dd: # dd count=1 if=/mnt/recuperado.000 of=/mnt/resized.000 bs=6065 Claro que é possível que um ou mais dos blocos que compunham o arquivo tenham sido sobrescritos. Se isso aconteceu, então você está sem sorte pois o bloco se foi para sempre (mas só pense se você tivesse desmontado mais cedo!). 1100..22.. AArrqquuiivvooss mmaaiioorreess Os problemas crescem quando o arquivo tem mais de 12 blocos de dados. Vale a pena saber um pouco sobre a estruturação do sistema de arquivos UNIX. Os dados do arquivo são armazenados em unidades chamadas 'blocos'. Estes blocos podem ser numerados seqüencialmente. Um arquivo também tem um 'inode', que é o lugar onde são guardadas informações como quem é o proprietário, quais as permissões, e qual o tipo do arquivo. Como os blocos, os inodes são numerados seqüencialmente, embora tenham uma seqüência diferente. Uma entrada de diretório consiste do nome do arquivo e um número de inode. Mas com este estado de coisas, é ainda impossível para o kernel encontrar os dados correspondentes a uma entrada de diretório. Por isso o inode também armazena o local dos blocos de dados, como se segue: · Os números dos blocos dos primeiros 12 blocos de dados estão armazenados diretamente no inode. Estes às vezes são chamados de _b_l_o_c_o_s _d_i_r_e_t_o_s . · O inode contém o número do bloco de um _b_l_o_c_o _i_n_d_i_r_e_t_o. Um bloco indireto contém os números de blocos de 256 blocos de dados adicionais. · O inode contém o número do bloco de um _b_l_o_c_o _d_u_p_l_a_m_e_n_t_e _i_n_d_i_r_e_t_o. Um bloco duplamente indireto contém os números de blocos de 256 blocos indiretos adicionais. · O inode contém o número do bloco de um bloco três vezes indireto. _U_m _b_l_o_c_o _t_r_ê_s _v_e_z_e_s _i_n_d_i_r_e_t_o _c_o_n_t_é_m _o_s _n_ú_m_e_r_o_s _d_e _b_l_o_c_o_s _d_e _2_5_6 _b_l_o_c_o_s _d_u_p_l_a_m_e_n_t_e _i_n_d_i_r_e_t_o_s _a_d_i_c_i_o_n_a_i_s. Leia novamente: sei que é complexo, mas também é importante. Agora, a implementação do kernel atual (certamente para todas as versões acima de 2.0.30) infelizmente zera todos os blocos indiretos (e os blocos duplamente indiretos, e assim por diante) quando apaga um arquivo. Assim se seu arquivo for maior que 12 blocos, não se tem garantia de poder encontrar até mesmo os números de todos os blocos que se precisa, isso sem mencionar os seus conteúdos. O único método que eu pude encontrar até aqui é presumir que o arquivo não foi fragmentado: se foi, temos problemas. Supondo que o arquivo não foi fragmentado, há vários planos de blocos de dados de acordo com quantos blocos de dados o arquivo usou: 00 ttoo 1122 Os números dos blocos estão guardados no inode como descrito acima. 1133 ttoo 226688 Depois dos blocos diretos, conte um para o bloco indireto, e então existem 256 blocos de dados. 226699 ttoo 6655880044 Como antes, há 12 blocos diretos, um (inútil) bloco indireto, e 256 blocos. Estes são seguidos por um duplamente (inútil) bloco indireto, e 256 repetições de um (inútil) bloco indireto e 256 blocos de dados. 6655880055 oouu mmaaiiss O plano dos primeiros 65804 blocos é como acima. Então segue três vezes um bloco indireto e 256 repetições de uma `seqüência duplamente indireta'. Cada seqüência duplamente indireta consiste de um bloco duplamente indireto, seguido por 256 repetições de um (inútil) bloco indireto e 256 blocos de dados. Claro, mesmo se estes números de blocos de dados presumidos estiverem corretos, não há garantia de que seus dados estejam intactos. Além disso, quanto mais longo for arquivo, menor a chance de que tenha sido escrito no sistema de arquivos sem a fragmentação apreciável (exceto em circunstâncias especiais). Note que presumo do começo ao fim que o tamanho de bloco é de 1024 bytes, por ser este o valor padrão. Caso os blocos sejam maiores, alguns dos números acima mudarão. Especificamente: uma vez que cada número de bloco tem 4 bytes de comprimento, um tamanho de bloco/4 é o valor do número de blocos que podem ser armazenados em cada bloco indireto. Assim todas as vezes que o número 256 aparecer na discussão acima, substitua-o pelo tamanho de bloco/4. Os limites de 'números de blocos necessários' também terão que ser mudados. Vamos dar uma olhada num exemplo de recuperação de um arquivo mais longo. debugfs: stat <1387> Inode: 148004 Type: regular Mode: 0644 Flags: 0x0 Version: 1 Usuário: 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 Parece haver um chance razoável de que este arquivo não seja fragmentado: certamente os primeiros 12 blocos listados no inode (que são todos blocos de dados) são adjacentes. Portanto podemos começar salvando aqueles blocos. # fsgrab -c 12 -s 8314 /dev/hda5 > /mnt/recuperado.001 Agora, o próximo bloco listado no inode, o 8326, é um bloco indireto que podemos ignorar. Mas confiamos que ele será seguido por 256 blocos de dados (dos números 8327 até 8582). # fsgrab -c 256 -s 8327 /dev/hda5 >> /mnt/recuperado.001 O bloco final listado no inode é 8583. Note que vamos bem em termos do arquivo ser adjacente: os últimos dados que escrevemos foram do bloco número 8582, que é 8327 + 255. Este bloco 8583 é duplamente indireto, o qual pode ser ignorado. É seguido por até 256 repetições de um bloco indireto (que é ignorado) seguido por 256 blocos de dados. Usando a aritmética rapidamente, nós emitimos os seguintes comandos. Note que pulamos o bloco duplamente indireto número 8583, e o bloco indireto 8584 imediatamente (esperamos) a seguir, e começamos no bloco 8585 para dados. # fsgrab -c 256 -s 8585 /dev/hda5 >> /mnt/recuperado.001 # fsgrab -c 256 -s 8842 /dev/hda5 >> /mnt/recuperado.001 # fsgrab -c 256 -s 9099 /dev/hda5 >> /mnt/recuperado.001 # fsgrab -c 256 -s 9356 /dev/hda5 >> /mnt/recuperado.001 # fsgrab -c 256 -s 9613 /dev/hda5 >> /mnt/recuperado.001 # fsgrab -c 256 -s 9870 /dev/hda5 >> /mnt/recuperado.001 Somando, nós vemos que até aqui escrevemos 12 + (7 * 256) blocos, o que são 1804. O resultado do `stat' para o inode nos deu um 'contador de blocos' de 3616; infelizmente estes blocos tem 512 bytes de comprimento (como uma ressaca do UNIX), assim nós realmente queremos 3616/2 = 1808 blocos de 1024 bytes. Isto significa que precisamos só de mais quatro blocos. O último bloco de dados escrito foi o número 10125. Como estivemos fazendo até aqui, omitimos um bloco indireto (número 10126) e podemos escrever então aqueles últimos quatro blocos. # fsgrab -c 4 -s 10127 /dev/hda5 >> /mnt/recuperado.001 Agora, com um pouco de sorte, todo o arquivo foi recuperado com sucesso. Ufa!! 1111.. MMooddiiffiiccaannddoo iinnooddeess ddiirreettaammeennttee Este método é, aparentemente, muito mais simples. No entanto como mencionado acima ele não pode suportar arquivos maiores que 12 blocos. Para cada inode que se quiser recuperar, deve-se estabelecer a contagem de um e alterar o horário de eliminação para zero. Isto é realizado através do comando mi (modificar inode) do debugfs. Algumas amostras de saída, que modificam o inode 148003 acima: 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] Isto é, estabelecemos a data de eliminação para 0 e a ligação em 1, bastando pressionar Enter para cada um dos outros campos. Admito que isto é um pouco trabalhoso caso se tenha muitos arquivos para recuperar, mas me parece algo suportável. Se você queria brilho, você deveria ter usado um 'sistema operacional' gráfico com uma bonita 'Lata de Reciclar'. A propósito, a saída mi se refere ao campo de 'Data e Criação' no inode. Isto é mentira! (ou enganoso, de qualquer maneira). O fato é que não se pode dizer num sistema de arquivos UNIX quando um arquivo foi criado. O item st_ctime de um struct stat se refere à `data de mudança do inode ', isto é, a última vez que qualquer um dos detalhes do inode foram alterados. Termina a lição de hoje. Note-se que as versões mais recentes de debugfs que aquela que estou usando provavelmente não incluem alguns dos campos listados acima (especificamente, Reservad1 e (alguns) campos de fragmento). Uma vez que se tenha modificado os inodes, pode-se sair de debugfs e executar: # e2fsck -f /dev/hda5 A idéia é que cada um dos arquivos apagados foi literalmente recuperado, mas nenhum deles aparece em qualquer entrada de diretório. O programa e2fsck pode detectar isto e acrescentará uma entrada de diretório para cada arquivo no diretório /lost+found do sistema de arquivos (assim, se a partição estiver normalmente montada no /usr, os arquivos aparecerão agora no /usr/lost+found). Tudo o que se tem a fazer é definir o nome de cada arquivo a partir de seu conteúdo, e fazê-los voltar a seu lugar correto na árvore de sistema de arquivos. Ao se executar e2fsck, será definida uma saída informativa e algumas perguntas sobre os danos a serem reparados. Responda 'sim' a tudo que se referir a 'resumo de 0' ou aos inodes que se tenha modificado. Qualquer coisa além fica a seu critério, embora seja uma boa idéia responder 'sim' a todas as perguntas. Quando e2fsck terminar, pode-se remontar o sistema de arquivos. Na verdade, há uma alternativa ao e2fsck: deixe os arquivos em /lost+found, use o debugfs para criar uma ligação no sistema de arquivos para o inode, através do comando link após a modificação do inode: debugfs: link <148003> teste.txt Isto cria um arquivo chamado teste.txt, naquele que debugfs ache que seja o diretório atual. E foo.txt será o seu arquivo. É preciso ainda executar e2fsck para corrigir os resumos das informações, contagens de blocos, etc.. 1122.. IIssttoo ffiiccaarráá mmaaiiss ffáácciill nnoo ffuuttuurroo?? Sim. Na verdade, eu acredito que já está. O kernel em desenvolvimento da série 2.1.x não zera os blocos indiretos há mais de seis meses. No início de dezembro de 1996, houve um boato na lista de correio do linux-kernel sobre a produção de um outro kernel que também deixaria intactos os blocos indiretos na eliminação de arquivos. Embora como nas versões pré-lançadas do kernel 2.0.31 isto não aconteceu, mas desconfio que seja viável. Uma vez que o Linux e os outros programadores de kernel superem esta limitação na produção de kernels, muitas das minhas objeções à técnica de modificação de inodes à mão desaparecerão. No mais tardar isto deve acontecer no lançamento da série kernel 2.2.x, a qual (de acordo com as escalas de tempo do desenvolvimento histórico do kernel) deve acontecer a qualquer momento no primeiro semestre de 1999. Quando esta demanda for implementada, será possível também usar o comando dump no debugfs para arquivos longos. 1133.. EExxiisstteemm aallgguummaass ffeerrrraammeennttaass ppaarraa aauuttoommaattiizzaarr eessttee pprroocceessssoo?? Sim. Infelizmente, eu acho que elas sofrem do mesmo problema que a técnica de modificação de inode manual: os blocos indiretos são irrecuperáveis. No entanto, dada a probabilidade que isto não seja mais um problema em breve, vale a pena olhar estes programas. Alguém na rede mencionou lde de Scott Heavner. Para ser honesto eu não o recomendaria como ferramenta para a recuperação automática de arquivos. É mais como um debugfs em tela cheia do que qualquer outra coisa, embora realmente tenha algumas características como a habilidade para investigar certos tipos ou certos conteúdos de arquivos. Também funciona com o xia (alguém realmente usa isto ainda?) e minix, sistemas de arquivos antigos. A versão 2.3.4 está disponível em Metalab e espelhos (embora haja a possibilidade de haver uma versão mais recente que esta). O lde _r_e_a_l_m_e_n_t_e tem alguma documentação bastante útil sobre os conceitos básicos de sistemas de arquivos, bem como um documento sobre como usá-la na recuperação de arquivos apagados. Embora eu não a tenha usado, suspeito que o método acima é mais prático. Parece que o programa que _r_e_a_l_m_e_n_t_e funciona é o GNU Midnight Commander, mc mc. Esta é uma ferramenta de gerenciamento de arquivos de tela cheia, baseada, até onde eu sei, num certo programa do MS-DOS conhecido comumente como `NC'. mc suporta o mouse na console e num xterm Linux e provê sistemas de arquivo virtuais que permitem truques como cd em um arquivo compactado (tarfile). Entre seus sistemas de arquivos virtuais está um para a não eliminação de arquivos em sistemas ext2. Tudo parece muito acessível, no entanto eu devo admitir que eu mesmo nunca usei o programa - prefiro um bom ambiente de linha de comandos. Aparentemente deve-se configurar o programa com a opção --with-ext2undel. Serão necessárias ainda as bibliotecas de desenvolvimento e arquivos que vem com o pacote e2fsprogs. Acredito que uma vez que o programa seja construído, pode-se executar algo como cd undel:dev/hda5/, e conseguir uma lista dos arquivos apagados. A versão estável mais recente é provavelmente a 4.0. Assim como com o kernel, as versões de desenvolvimento _n_ã_o estão recomendadas a não programadores. A lista de servidores (acima de 70) está disponível em the Midnight Commander 4 Webservidor , ou tente servidor FTP oficial (o qual é bastante lento). 1144.. CCoolloopphhoonn Pretendo produzir atualizações regulares deste documento contanto que eu tenha tempo para fazê-lo e tenha algo interessante a dizer. Isto significa que estou ansioso para ouvir comentários dos leitores. A minha maneira de escrever poderia ser mais clara? Você poderia pensar em alguma coisa que faria as questões mais fáceis? Existe alguma ferramenta nova que o faz automaticamente? Quem _m_a_t_o_u _J_F_K_? Não importa. Se você tiver alguma coisa a dizer sobre este documento ou qualquer outro assunto, escreva para mim em . 1155.. CCrrééddiittooss ee BBiibblliiooggrraaffiiaa Se eu tiver enxergado mais longe que os outros, é porque eu estava em cima dos ombros de um gigante. (Isaac Newton) Muito deste mini-COMO FAZER proveio de uma postagem na comp.os.linux.misc grupo de notícias de Robin Glover . Eu gostaria de agradecer ao Robin por gentilmente me permitir retrabalhar suas idéias neste mini-COMO FAZER. Algumas referências bibliográficas · FFrriisscchh, Æleen (1995), _E_s_s_e_n_t_i_a_l _S_y_s_t_e_m _A_d_m_i_n_i_s_t_r_a_t_i_o_n, segunda edição, O'Reilly and Associates, Inc., ISBN: 1-56592-127-5. · GGlloovveerr, Robin (31 Jan 1996), _H_O_W_-_T_O _: _u_n_d_e_l_e_t_e _l_i_n_u_x _f_i_l_e_s _(_e_x_t_2_f_s_/_d_e_b_u_g_f_s_), comp.os.linux.misc Usenet. · PPeeeekk, Jerry, Tim OO''RReeiillllyy, Mike LLoouukkiiddeess et al (1993), _U_N_I_X _P_o_w_e_r _T_o_o_l_s, O'Reilly and Associates, Inc./Random House, Inc., ISBN: 0-679-79073-X. 1166.. AAssppeeccttooss LLeeggaaiiss Todas as marcas registradas são propriedade de seus respectivos donos. Especificamente: · _M_S_-_D_O_S e _W_i_n_d_o_w_s são marcas registradas de Microsoft . · _U_N_I_X é marca registrada de the Open Group . · Maiores informações sobre o assunto de marca registrada Linuxin estão disponíveis em the Linux Mall . Este documento tem os direitos autorais (c) 1997 de Aaron Crane . Ele pode ser distribuído gratuitamente no seu todo, inclusive aviso de direitos autorais, mas não pode ser mudado sem permissão de qualquer dos autores ou do Coordenador de Documentação Linux. Há permissão para cópias textuais de pequenas partes com finalidade de revisão ou citação; nestas circunstâncias, as seções podem ser reproduzidas com uma intimação apropriada, mas sem o aviso de direitos autorais. O Coordenador do COMO FAZER Linux é Tim Bynum .