Rastreando barras em links simbólicos para diretórios

8

Estou tentando emular o processo de resolução do caminho (consulte a página de manual path_resolution) em sistemas como o Unix.

Meu sistema operacional é Linux com GNU coreutils 8.7.

Para esclarecer o significado de '/' à direita na resolução, fiz as seguintes coisas em um shell:

mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link

Tudo estava bem, porque this_is_link é um link simbólico e eu apenas o removi. Mas enquanto tenta:

mkdir this_is_dir
ln -s this_is_dir this_is_link
rm this_is_link/

Ecoou rm: cannot remove 'this_is_link/': Is a directory

Bem, o '/' à direita causou o seguinte link simbólico, pensei. Então, eu tentei outro comando:rmdir this_is_link/

E um resultado engraçado saiu: rmdir: failed to remove 'this_is_link/': Not a directory

Não o que eu esperava. Então, pedi ao meu amigo para confirmar se o mesmo resultado poderia ser obtido em seu sistema. Ele tinha uma versão inferior do coreutils do que eu. E o resultado foi incrível, não importa rmou rmdir 'this_is_link/', Not a directoryocorre o mesmo erro .

E outro amigo acabou de experimentar no Mac OS, o resultado é: rm=> 'É um diretório', rmdir=> o diretório foi excluído com sucesso, o link permaneceu .

Há alguma especificação sobre o comportamento exato da resolução do caminho?

ymfoi
fonte

Respostas:

7

A especificação POSIX / Single Unix especifica que um nome de caminho com uma barra final deve se referir a um diretório (consulte as definições de base §4.11 resolução do nome de caminho ). foo/é de fato definido como equivalente a foo/.(para propósitos de resolução de caminho, não ao manipular nomes de arquivos; basenamee dirnameignora barras finais). A maioria das implementações respeita isso, mas existem algumas exceções.

Isso explica o comportamento de rm this_is_link/: é equivalente a rm this_is_link/., onde o argumento é claramente um diretório.

rmdir this_is_link/da mesma forma, consulte o diretório O fato de isso não acontecer na sua máquina é um bug no GNU coreutils. O OSX está se comportando corretamente aqui.

Gilles 'SO- parar de ser mau'
fonte
Isto é exatamente o que eu precisava, obrigado cara!
Ymfoi
-1

Minha vez:

  • '' rm link / '' falha porque rm olha o último caractere, vê que é uma barra, dá o diagnóstico (não realmente correto) que você viu;
  • '' link rmdir / '' falha corretamente: o link não é um diretório, é um link simbólico
  • '' link rm '' terá êxito corretamente

Aliás, a resolução do caminho tem muito pouco a ver com isso, apenas parece '' rm '' cortando uma esquina em vez de (corretamente) invocar "stat" em um argumento (que é o que rmdir está fazendo).

Felicidades.

Forma de vida alienígena
fonte
1
Na verdade, o inverso parece verdadeiro: rmchama stat (bem, newfstatat, na verdade, com a AT_SYMLINK_NOFOLLOWopção) e se recusa a continuar, enquanto rmdir realmente chama rmdir (2), mas recebe ENOTDIR.
Ansgar Esztermann
O @AnsgarEsztermann AT_SYMLINK_NOFOLLOWimpedirá que ele siga o link simbólico, portanto, a rm deve excluir o próprio link em vez de imprimir "Não é um diretório" que não corresponde à circunstância.
ymfoi 23/01
De uma breve verificação com stat (1), a barra final substituirá a opção. A saída de state stat -Ldifere apenas se o argumento for fornecido sem uma barra final.
Ansgar Esztermann
@AnsgarEsztermann Oh, entendo ... Thx. E os diferentes efeitos em diferentes ambientes? Alguma ideia?
ymfoi 23/01/12
1
É o contrário: na máquina do ymfoi, rmestá se comportando corretamente e rmdirnão está. O final /deve forçá-los a tratar seus argumentos como um diretório, de acordo com o padrão POSIX. Veja minha resposta para referências .
Gilles 'SO- stop be evil'