Muitas vezes vemos que o arquivo que estamos tentando salvar no vim após a edição é relatado como somente leitura. A maneira de contornar isso é adicionar !wq
, estou tentando descobrir o que acontece internamente que permite que o programa vim obtenha permissão suficiente para gravar o arquivo somente leitura?
Existe um sinalizador interno que é comutado ou o vim ganha temporariamente os privilégios por algum tempo?
Quando você faz isso
w!
no Vim, o que realmente acontece depende de quem é o dono do arquivo.Se você (o usuário atual) for o proprietário do arquivo, o Vim alterará as permissões para serem graváveis antes de reescrever o arquivo. Em seguida, ele remove as permissões de gravação para restaurar os bits de permissão ao que eram desde o início.
Se você não for o proprietário do arquivo, mas tiver permissões de gravação no diretório atual, o Vim excluirá o arquivo original e gravará o documento em um novo arquivo com o mesmo nome. O novo arquivo receberá as mesmas permissões do arquivo original, mas será de sua propriedade.
Em nenhum momento o Vim ganha privilégios elevados para poder gravar no arquivo.
A mecânica descrita acima são as opções disponíveis que qualquer programa que precise gravar em um arquivo somente leitura deve escolher (ou seja, alterar temporariamente a permissão enquanto grava no arquivo ou excluir o arquivo e criar um novo) e o que o Vim acaba escolhendo fazer pode, no final, depender de uma série de configurações configuráveis.
Como visto nos comentários abaixo, há alguma confusão sobre o acima. Se você quiser ver por si mesmo o que realmente acontece com a configuração do Vim em sua marca específica de Unix, recomendo rastrear as chamadas de sistema que o Vim faz enquanto grava em um arquivo somente leitura. Como isso é feito depende de qual Unix você está usando. No Linux, isso provavelmente é feito por exemplo
strace vim file
(editar o arquivo, salvá-low!
e sair).Este é o primeiro caso (saída de
ktrace
+kdump
no OpenBSD):Isso altera as permissões no arquivo para que ele seja gravável (o
S_IWUSR
sinalizador usado comchmod()
) e grava o buffer nele.Em seguida, ele define as permissões originais:
Para o outro caso:
Ele primeiro desvincula (exclui) o arquivo e depois o recria (antes de gravar no arquivo e alterar as permissões posteriormente):
O Vim não pode obter permissões adicionais. O
:w!
apenas substitui a'readonly'
opção interna, que pode ter sido definida porque:-R
opção de linha de comando ou com:view
em vez de:edit
, ou:setlocal readonly
Para o último caso, uma gravação de arquivo ainda pode ser possível porque o Vim (por padrão) cria um novo arquivo e substitui o arquivo original por ele. Isso ainda depende das permissões serem definidas de forma a permitir isso.
Para realmente ganhar permissões de escrita onde o usuário que abriu o Vim não tem nenhuma, o
:w !sudo tee >/dev/null file
truque tem que ser usado, seja diretamente, ou através de um plugin como SudoEdit .Você nunca pode gravar em um arquivo no qual não tem permissões de gravação. No entanto, você pode excluir esse arquivo se tiver permissões de gravação no diretório.
O truque que o VIM está usando é excluir o arquivo e escrever um novo.
É possível mostrar que este é o método que o VIM usa sem ler o código-fonte verificando o número do inode antes e depois:
Observe que o número do inode mudou mostrando que o novo arquivo NÃO é o mesmo arquivo que você editou.
FYI Minha configuração atual é muito curta:
E os pacotes debian instalados são:
Quando o vim está no modo compatível com vi, :w! apenas substituirá o modo somente leitura do buffer, mas não tentará alterar as permissões do arquivo para frente e para trás, ignorar as permissões renomeando um arquivo diferente para o nome do original ou fazer outras coisas amadoras.
Este é o único comportamento correto IMHO -- o sinalizador que controla isso é
W
decpoptions
/cpo
. De:help cpo
::set compatible
acenderá todas ascpo
bandeiras. Você pode alterar apenas oW
sinalizador com:set cpo+=W
ouset cpo-=W
.