Por que não posso editar links e diretórios diretamente?

4

Existem programas como hexedit que permitem editar cada bit de um arquivo, e como eu continuo ouvindo que no Unix "tudo é um arquivo", eu tentei editar algum diretório, esperando bytes referindo-se a inodes ou nomes de arquivos. Em vez disso, eu recebo:

hexedit: teste: not a file

No entanto, fiquei feliz em descobrir que ele funcionava com muitos arquivos dev (partições, discos rígidos inteiros, componentes falsos (como /dev/null ), o nome dele).

E para links, hexedit os segue, e o erro é o mesmo do destino, embora com o nome do link, no meu teste:

hexedit: testeln: not a file

Mesmo se o arquivo original for removido e o link inválido, o comportamento será o mesmo. Mas isso não é tudo.

Se alguém copia links simbólicos sem uma opção especial para preservar (ou usa as opções de rsync ), eles se tornam arquivos regulares e, felizmente, eu tinha um link antigo como esse:

00000000   49 6E 74 78  4C 4E 4B 01  2F 00 73 00  72 00 76 00  2F 00 73 00  61 00 6D 00  62 00 61 00  2F 00 73 00  IntxLNK./.s.r.v./.s.a.m.b.a./.s.
00000020   68 00 61 00  72 00 65 00                                                                                h.a.r.e.

No caso de /dev/initctl , loop-control , snapshot e tty2 (mesmo que esteja aberto e tenha privilégios de leitura / gravação), hexedit dá (depois de limpar a tela, na última linha ):

the long seek failed (-1 instead of 0), leaving :(

Para /dev/log :

hexedit: log: No such device or address

Posso ver diretórios de tal maneira? Por que os links são seguidos automaticamente? Como posso mudar esse comportamento? Por que o hexedit se comporta assim (AFAIK) para links simbólicos e diretórios? Eu suspeito que alguns arquivos estranhos que encontrei em /dev estão aparentemente vazios, mesmo se eu usar sudo .

    
por JMCF125 11.01.2014 / 16:08

3 respostas

3

POSIX requer esse comportamento para arquivos de determinados tipos no nível de chamada do sistema. A função open segue links simbólicos, exceto se o sinalizador O_NOFOLLOW estiver definido - o que hexedit provavelmente não faz.

Para diretórios, a função read deve retornar um código de erro e definir errno para EISDIR . De link :

The fildes argument refers to a directory and the implementation does not allow the directory to be read using read() or pread(). The readdir() function should be used instead.

Como @goldilocks sugeriu, existem pelo menos 7 tipos diferentes de arquivos, cada um com semântica diferente:

  • arquivos regulares
  • links simbólicos
  • diretórios
  • bloquear dispositivos
  • dispositivos de caracteres
  • FIFOs e
  • soquetes
por 11.01.2014 / 21:56
2

Você está parcialmente certo em suas expectativas. "Tudo é um arquivo" significa que mesmo coisas que não são arquivos, como telas, microfones, etc, ocupam um lugar na árvore do sistema de arquivos e podem ser acessadas usando alguns das mesmas chamadas de sistema como arquivos regulares ( open, write, etc.). Muitos de seus exemplos não são muito parecidos com arquivos. /dev/null não é um arquivo vazio, por exemplo, mas um "driver de dispositivo" muito especial, um pequeno código do kernel que aceita solicitações de leitura e gravação (retornando EOF para o primeiro e ignorando o segundo). Portanto, não é realmente um arquivo, mas se comporta como um. Pense também no ponto de montagem de um disco: ele não é um arquivo em nenhum sentido, é um gancho que dá acesso a toda a hierarquia de arquivos nesse disco.

Um diretório, por outro lado, é de fato um "bloco de bytes" como colocado por @goldilocks: Ele ocupa espaço no disco e contém a estrutura de dados que mapeia os nomes dos arquivos. para inodes. Mas, como você descobriu, ele não se comporta como arquivos simples. Você está recebendo mensagens de erro porque os diretórios são muito importantes para deixar vulneráveis a comandos comuns do usuário. Imagine se você acidentalmente escreveu

grep foo bar > subdir

onde você pretendia escrever

grep foo bar > subdir/newfile

... seu diretório subdir seria escolhido, e com ele a consistência do seu sistema de arquivos, porque todos os seus arquivos subitamente se tornariam órfãos inodes. Portanto, os diretórios são protegidos de várias maneiras. Você também não tem permissão para fazer um link físico para um diretório, porque vários links para diretórios significam que o sistema de arquivos não é mais uma árvore. Nos velhos tempos (décadas atrás), a raíz costumava ser capaz de fazer um pouco disso, e havia todo tipo de "editores de diretórios" por aí. Não tenho certeza até que ponto isso ainda é possível.

    
por 11.01.2014 / 21:29
1

Algumas variantes unix (incluindo o Unix original, mas não o Linux) permitem abrir um diretório como um arquivo regular e ler a partir dele. O conteúdo do diretório depende do formato do sistema de arquivos, o que torna a utilidade muito limitada.

Escrever em um diretório seria muito perigoso. Eu acho que o Unix original permitia que programas rodassem como root, mas os unices modernos não. Se você pudesse gravar em um diretório, poderia tornar o sistema de arquivos inválido, introduzir loops, referir-se a blocos que não existem, criar executáveis setuid alterando seus proprietários e permissões, e assim por diante. É por isso que apenas o código dentro do kernel tem permissão para criar diretórios.

Links simbólicos são um caso diferente. Abrir e ler os links simbólicos abre o arquivo de destino porque é para isso que os links simbólicos são projetados: eles são transparentes para qualquer coisa que opere no conteúdo do arquivo (como um editor). Seria possível ter uma interface em que a leitura do conteúdo de um link simbólico usasse open (com um sinalizador especial), read e close , mas isso forneceria pouco benefício sobre a única chamada readlink . Escrever um link simbólico com write seria mais problemático, já que eles teriam que fazer o armazenamento alocado para o alvo crescer; no lado da aplicação que perderia o benefício de symlink ser atômico.

    
por 12.01.2014 / 00:35