Très souvent, nous constatons que le fichier que nous essayons d'enregistrer dans vim après modification est signalé en lecture seule. La solution consiste à ajouter !wq
, j'essaie de comprendre ce qui se passe en interne qui permet au programme vim d'obtenir suffisamment d'autorisations pour écrire le fichier en lecture seule?
Y a-t-il un drapeau interne qui est commuté ou le vim gagne temporairement les privilèges pendant un certain temps?
Lorsque vous faites w!
Dans Vim, ce qui se passe réellement dépend de la personne qui possède le fichier.
Si vous (l'utilisateur actuel) êtes le propriétaire du fichier, Vim modifiera les autorisations en écriture avant de réécrire le fichier. Il supprime ensuite les autorisations d'écriture pour restaurer les bits d'autorisation à ce qu'ils étaient depuis le début.
Si vous n'êtes pas le propriétaire du fichier, mais si vous disposez d'autorisations d'écriture dans le répertoire en cours, Vim supprimera le fichier d'origine et écrit le document dans un nouveau fichier du même nom. Le nouveau fichier se verra alors attribuer les mêmes autorisations que le fichier d'origine, mais vous appartiendra.
À aucun moment, Vim ne bénéficie de privilèges élevés pour pouvoir écrire dans le fichier.
Les mécanismes décrits ci-dessus sont les options disponibles que tout programme qui doit écrire dans un fichier en lecture seule doit choisir (c'est-à-dire modifier temporairement l'autorisation pendant l'écriture dans le fichier, ou supprimer le fichier et en créer un nouveau), et ce que Vim finit par choisir de faire peut en fin de compte dépendre d'un certain nombre de paramètres configurables.
Comme on le voit dans les commentaires ci-dessous, il y a une certaine confusion à propos de ce qui précède. Si vous voulez voir par vous-même ce qui se passe réellement avec votre configuration de Vim sur votre marque particulière d'Unix, je vous recommande de suivre les appels système que Vim fait lors de l'écriture dans un fichier en lecture seule. La façon dont cela est fait dépend de l'Unix que vous utilisez. Sous Linux, cela se fait probablement par ex. strace vim file
(Puis modifiez le fichier, enregistrez-le avec w!
Et quittez).
C'est le premier cas (sortie de ktrace
+ kdump
sur OpenBSD):
13228 vim CALL chmod(0x19b1d94b4b10,0100644<S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH|S_IFREG>)
13228 vim NAMI "file"
13228 vim RET chmod 0
13228 vim CALL lseek(3,0x1000,SEEK_SET)
13228 vim RET lseek 4096/0x1000
13228 vim CALL write(3,0x19b1e0aa9000,0x1000)
Cela modifie les autorisations sur le fichier afin qu'il soit accessible en écriture (l'indicateur S_IWUSR
Utilisé avec chmod()
) et y écrit le tampon.
Il définit ensuite les autorisations d'origine:
13228 vim CALL fchmod(4,0100444<S_IRUSR|S_IRGRP|S_IROTH|S_IFREG>)
13228 vim RET fchmod 0
13228 vim CALL close(4)
13228 vim RET close 0
Pour l'autre cas:
Il dissocie (supprime) d'abord le fichier, puis le recrée (avant d'écrire dans le fichier et de modifier les autorisations ultérieurement):
44487 vim CALL unlink(0x79fdbc1f000)
44487 vim NAMI "file"
44487 vim RET unlink 0
44487 vim CALL open(0x79fdbc1f000,0x201<O_WRONLY|O_CREAT>,0644<S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH>)
44487 vim NAMI "file"
44487 vim RET open 4
Vim ne peut pas obtenir d'autorisations supplémentaires. L'option :w!
Remplace simplement l'option interne 'readonly'
, Qui peut avoir été définie car:
-R
ou avec :view
au lieu de :edit
, ou :setlocal readonly
Dans ce dernier cas, une écriture de fichier peut toujours être possible car Vim (par défaut) crée un nouveau fichier puis remplace le fichier d'origine par celui-ci. Cela dépend toujours des autorisations définies de manière à permettre cela.
Pour vraiment gagner des autorisations d'écriture là où l'utilisateur qui a ouvert Vim n'en a pas, l'astuce :w !Sudo tee >/dev/null file
Doit être utilisée, soit directement, soit via un plugin comme SudoEdit .
Vous ne pouvez jamais écrire dans un fichier sur lequel vous ne disposez pas d'autorisations d'écriture. Cependant, vous pouvez supprimer ce fichier si vous avez des autorisations d'écriture sur le répertoire.
L'astuce que VIM utilise est de supprimer le fichier et d'en écrire un nouveau.
Il est possible de montrer que c'est la méthode VIM utilise sans lire le code source en vérifiant numéro d'inode avant et après:
$ touch foo
$ chmod u-w foo
$ ls -li foo
60818465 -r--r----- 1 philip philip 0 Feb 25 10:24 foo
$ vi foo
$ # edit the file and save with :w!
$ ls -li foo
60818467 -r--r----- 1 philip philip 8 Feb 25 10:25 foo
Notez que le numéro d'inode a changé, indiquant que le nouveau fichier n'est PAS le même fichier que celui que vous avez modifié.
FYI Ma configuration actuelle est vraiment courte:
runtime! debian.vim
if has("syntax")
syntax on
endif
set tabstop=4
set autoindent
Et les paquets Debian installés sont:
vim 2:8.1.0875-1
vim-common 2:8.1.0875-1
vim-runtime 2:8.1.0875-1
vim-tiny 2:8.1.0875-1
Lorsque vim est en mode compatible vi,: w! ne remplacera que le mode en lecture seule du tampon, mais n'essaiera pas de modifier les autorisations de fichier dans les deux sens, contournera les autorisations en renommant un fichier différent au nom de l'original ou fera d'autres trucs d'heure amateur.
C'est le seul comportement correct à mon humble avis - le drapeau qui contrôle cela est W
de cpoptions
/cpo
. De :help cpo
:
*'cpoptions'* *'cpo'* *cpo* 'cpoptions' 'cpo' string (Vim default: "aABceFs", Vi default: all flags) ... *cpo-W* W Don't overwrite a readonly file. When omitted, ":w!" overwrites a readonly file, if possible.
:set compatible
activera tous les drapeaux cpo
. Vous pouvez modifier uniquement le drapeau W
avec :set cpo+=W
ou set cpo-=W
.