O que o '!' realmente faz quando é adicionado a um comando ex (: wq! |: w! |: q!)?

5

Eu entendo que isso significa força para fazer algo.

Ao fazer $ vim -R file , eu entro no modo read-only , mas isso funciona apenas como modo preventivo

-R  Radonly mode.  The 'readonly' option will be set for all the
    files being edited.  You can still edit the buffer, but will
    be prevented from accidentally overwriting a file.  If you
    forgot that you are in View mode and did make some changes,
    you can overwrite a file by adding an exclamation mark to
    the Ex command, as in ":w!".  The 'readonly' option can be
    reset with ":set noro" (see the options chapter, |options|).
    Subsequent edits will not be done in readonly mode.  Calling
    the executable "view" has the same effect as the -R argument.
    The 'updatecount' option will be set to 10000, meaning that
    the swap file will not be updated automatically very often.

Mas o que eu ainda não consigo entender é por que ele faz a instrução de pular as permissões mesmo que o proprietário do arquivo seja root user, além de também alterar owner & grupo.

    
por tachomi 09.09.2015 / 20:31

2 respostas

6

! geralmente significa o que você esperaria de "força", mas o que isso significa para um comando específico depende do comando. No caso de w! , se o Vim não puder gravar no arquivo por algum motivo, ele tentará excluir e criar um novo com o conteúdo do buffer atual.

Considere o seguinte exemplo (observe os números de inode):

$ touch foo
$ chmod -w foo
$ stat foo
  File: ‘foo’
  Size: 0           Blocks: 0          IO Block: 4096   regular empty file
Device: 22h/34d Inode: 10396141    Links: 1
Access: (0444/-r--r--r--)  Uid: ( 1000/ muru)   Gid: ( 1000/ muru)
Access: 2015-09-10 00:24:28.259290486 +0530
Modify: 2015-09-10 00:24:28.259290486 +0530
Change: 2015-09-10 00:24:30.771263735 +0530
 Birth: -
$ vim -c 'r!date' -c 'wq!' foo
$ stat foo                    
  File: ‘foo’
  Size: 30          Blocks: 8          IO Block: 4096   regular file
Device: 22h/34d Inode: 10396151    Links: 1
Access: (0444/-r--r--r--)  Uid: ( 1000/ muru)   Gid: ( 1000/ muru)
Access: 2015-09-10 00:24:37.727189657 +0530
Modify: 2015-09-10 00:24:37.731189614 +0530
Change: 2015-09-10 00:24:37.763189273 +0530
 Birth: -
$ cat foo
Thu Sep 10 00:24:37 IST 2015

É por isso que o proprietário e o grupo mudam. As permissões são preservadas - :h write-permissions :

                                                    write-permissions
When writing a new file the permissions are read-write.  For unix the mask is
0666 with additionally umask applied.  When writing a file that was read Vim
will preserve the permissions, but clear the s-bit.

Se você quiser fazer o Vim recusar gravações, consulte :h write-readonly :

                                                    write-readonly
When the 'cpoptions' option contains 'W', Vim will refuse to overwrite a
readonly file.  When 'W' is not present, ":w!" will overwrite a readonly file,
if the system allows it (the directory must be writable).

Observe que "o diretório deve ser gravável" - porque sem um diretório gravável, o Vim não pode excluir nem criar um novo arquivo.

    
por 09.09.2015 / 21:01
2

Como afirmado no vim (1), -R garante que o arquivo não será acidentalmente substituído quando o usuário cegamente diz :w , mas não desabilita a gravação com :w! .

Mas é apenas um aplicativo e, quando está prestes a fazer algo com arquivos, o kernel do sistema operacional verificará as permissões de qualquer maneira. Uma experiência: eu corri

strace vim /etc/hostname 2>vim.out

sob um usuário. Mesmo sem -R explícito, ele começou em readonly, porque ele olhou para as permissões. Depois de mudar o buffer

W10: Warning: Changing a readonly file

apareceu.

Agora :w e eu obtive

E45: 'readonly' option is set (add ! to override)

Eu apliquei a sugestão e

"/etc/hostname" E212: Can't open file for writing

Previsivelmente, em vim.out , vemos:

open("/etc/hostname", O_WRONLY|O_CREAT|O_TRUNC, 0644) = -1 EACCES (Permission denied)
    
por 09.09.2015 / 21:08

Tags