Como desassociar (remover) o hardlink especial “.” criado para uma pasta?

29

No Linux, quando você cria uma pasta, ele cria automaticamente dois hard links no inode correspondente. Uma que é a pasta que você pediu para criar, a outra é a pasta . special desta pasta.

Exemplo:

$ mkdir folder
$ ls -li
total 0
124596048 drwxr-xr-x    2 fantattitude  staff    68 18 oct 16:52 folder
$ ls -lai folder
total 0
124596048 drwxr-xr-x  2 fantattitude  staff   68 18 oct 16:52 .
124593716 drwxr-xr-x  3 fantattitude  staff  102 18 oct 16:52 ..

Como você pode ver, tanto folder quanto . estão dentro de folder e têm o mesmo número de inode (mostrado com a opção -i ).

Existe alguma maneira de excluir este hardlink especial . ?

É apenas para experimentação e curiosidade. Também acho que a resposta também se aplica ao arquivo .. especial.

Eu tentei pesquisar rm man, mas não consegui encontrar uma maneira de fazer isso. Quando tento remover . , tudo que consigo é:

rm: "." and ".." may not be removed

Estou muito curioso sobre o modo como essas coisas funcionam, por isso não se abstenha de ser muito detalhado sobre o assunto.

EDIT: Talvez eu não tenha sido claro com o meu post, mas quero entender o mecanismo subjacente que é responsável por . arquivos e as razões pelas quais eles não podem ser excluídos.

Eu sei que o padrão POSIX não permite uma pasta com menos de 2 hardlinks, mas não entendi bem o motivo. Quero saber se é possível fazer isso de qualquer maneira.

    
por Fantattitude 18.10.2016 / 17:01

4 respostas

46

É tecnicamente possível excluir . , pelo menos em sistemas de arquivos EXT4. Se você criar uma imagem do sistema de arquivos em test.img , montá-la e criar uma pasta test , desmonte-a novamente, edite-a usando debugfs :

debugfs -w test.img
cd test
unlink .

debugfs não recusa e elimina obedientemente a entrada de diretório . no sistema de arquivos. O diretório test ainda é utilizável, com uma surpresa:

sudo mount test.img /mnt/temp
cd /mnt/temp/test
ls

mostra apenas

..

então . realmente desapareceu. Ainda cd . , ls . , pwd ainda se comporta como de costume!

Eu já fiz esse teste usando rmdir . , mas isso exclui o inode do diretório ( enorme graças a BowlOfRed para apontando isto ), o que deixa test uma entrada de diretório pendente e é a verdadeira razão para os problemas encontrados. Nesse cenário, a pasta test se torna inutilizável; depois de montar a imagem, executando ls produz

ls: cannot access '/mnt/test': Structure needs cleaning

e o log do kernel mostra

EXT4-fs error (device loop2): ext4_lookup:1606: inode #2: comm ls: deleted inode referenced: 38913

A execução de e2fsck nessa situação na imagem exclui completamente o diretório test (o inode do diretório desapareceu, por isso não há nada para restaurar).

Tudo isso mostra que . existe como uma entidade específica no sistema de arquivos EXT4. Eu tenho a impressão de que o código do sistema de arquivos no kernel espera que . e .. existam, e avisa se eles não o fizerem (veja namei.c ), mas com o teste unlink . -based eu não vi esse aviso. e2fsck não gosta da entrada de diretório . ausente e oferece a correção:

$ /sbin/e2fsck -f test.img
e2fsck 1.43.3 (04-Sep-2016)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Missing '.' in directory inode 30721.
Fix<y>?

Isso recria a entrada de diretório . .

    
por 18.10.2016 / 17:47
5

Não há como remover essa entrada de diretório. A entrada . significa "este diretório", a entrada .. significa "diretório pai deste diretório". Eles não são realmente hard links, é assim que a estrutura de diretórios é criada / representada.

    
por 18.10.2016 / 17:04
3

Como descrito em Notas do Leão no Unix 6 Source Code , o Unix inicial tinha um arquivo em disco onde os arquivos e diretórios eram representados no disco por estruturas de inode. Houve um bit especial que indicava que o conteúdo do arquivo era um diretório. Cada inode tinha um link para seu próprio inode que permitia a um arquivo saber em qual diretório estava. A exceção era o diretório '/' que possuía ele mesmo. Houve também um link para o conteúdo. Se um inode não tivesse conteúdo, ele poderia ser retornado à lista livre. Como um diretório era apenas um arquivo abençoado, até mesmo um diretório vazio precisava ter conteúdo para evitar que ele fosse coletado como lixo. Assim, o .. era o link do inode para o inode pai e o. estava lá para indicar que o diretório ainda era utilizável. rmdir (chamando unlink) poderia remover o arquivo. diretório se não houvesse outro conteúdo e o inode passaria então para a lista livre quando não houvesse mais referências a ele.

    
por 18.10.2016 / 23:28
0

Como o 'possível duplicata de' resposta 's pós diz, o padrão POSIX especifica que se rmdir tenta remover o diretório atual, deve falhar.

Com qualquer coisa que você construa, você precisa ter uma base. É difícil definir caminhos relativos sem uma maneira de dizer "aqui". Então o '.' é definido como 'aqui'.

Além disso, você pode remover 'dot' e 'dot dot'. Escreva seu próprio sistema operacional que não os define. Embora Unix (e, por extensão, Mac OSX), Linux, e até mesmo MS DOS e Windows todo o uso de ponto e dotdot.

TL; DR - 'ponto' está na definição do SO.

    
por 18.10.2016 / 17:43