it-swarm.com.de

Wie überschreibt vim den schreibgeschützten Modus?

Sehr oft stellen wir fest, dass die Datei, die wir nach der Bearbeitung in vim speichern möchten, schreibgeschützt ist. Der Weg, dies zu umgehen, besteht darin, !wq, ich versuche herauszufinden, was intern funktioniert, damit das vim-Programm genügend Berechtigungen zum Schreiben der schreibgeschützten Datei erhält.

Gibt es ein internes Flag, das gewechselt wird oder das vim vorübergehend für einige Zeit die Berechtigungen erhält?

24
Atul

Wenn Sie in Vim w! Ausführen, hängt das, was tatsächlich passiert, davon ab, wem die Datei gehört.

  • Wenn Sie (der aktuelle Benutzer) der Eigentümer der Datei sind, ändert Vim die Berechtigungen so, dass sie beschreibbar sind, bevor die Datei neu geschrieben wird. Anschließend werden die Schreibberechtigungen entfernt, um die Berechtigungsbits von Anfang an wiederherzustellen.

  • Wenn Sie nicht der Eigentümer der Datei sind, aber über Schreibberechtigungen im aktuellen Verzeichnis verfügen, löscht Vim die Originaldatei und schreibt das Dokument in eine neue Datei mit demselben Namen. Die neue Datei erhält dann die gleichen Berechtigungen wie die Originaldatei, gehört jedoch Ihnen.

Vim erhält zu keinem Zeitpunkt erhöhte Berechtigungen, um in die Datei schreiben zu können.

Die oben beschriebenen Mechanismen sind die verfügbaren Optionen, aus denen jedes Programm, das in eine schreibgeschützte Datei schreiben muss, auswählen muss (dh entweder die Berechtigung beim Schreiben in die Datei vorübergehend ändern oder die Datei löschen und eine neue erstellen) Was Vim letztendlich tun möchte, hängt möglicherweise von einer Reihe konfigurierbarer Einstellungen ab.

Wie in den Kommentaren unten zu sehen ist, gibt es einige Verwirrung über das Obige. Wenn Sie selbst sehen möchten, was mit Ihrer Einrichtung von Vim unter Ihrer bestimmten Unix-Marke tatsächlich passiert, würde ich empfehlen, die Systemaufrufe zu verfolgen, die Vim beim Schreiben in eine schreibgeschützte Datei ausführt. Wie dies gemacht wird, hängt davon ab, welches Unix Sie verwenden. Unter Linux erfolgt dies wahrscheinlich z. strace vim file (Bearbeiten Sie dann die Datei, speichern Sie sie mit w! Und beenden Sie sie).


Dies ist der erste Fall (Ausgabe von ktrace + kdump unter 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)

Dadurch werden die Berechtigungen für die Datei so geändert, dass sie beschreibbar ist (das mit chmod() verwendete Flag S_IWUSR) Und der Puffer in sie geschrieben.

Anschließend werden die ursprünglichen Berechtigungen festgelegt:

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

Für den anderen Fall:

Die Verbindung wird zuerst aufgehoben (gelöscht) und dann neu erstellt (bevor in die Datei geschrieben und die Berechtigungen später geändert werden):

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
26
Kusalananda

Vim kann keine zusätzlichen Berechtigungen erhalten. Das :w! überschreibt nur das interne 'readonly' Option, die möglicherweise gesetzt wurde, weil:

  • sie haben die Datei über das -R Befehlszeilenoption oder mit :view Anstatt von :edit, oder :setlocal readonly
  • Vim erkennt, dass die Datei derzeit keine Schreibberechtigungen hat

Im letzteren Fall ist ein Dateischreiben möglicherweise weiterhin möglich, da Vim (standardmäßig) eine neue Datei erstellt und dann die Originaldatei durch diese ersetzt. Dies hängt immer noch davon ab, welche Berechtigungen so festgelegt wurden, dass dies möglich ist.


Um wirklich Schreibberechtigungen zu erhalten, bei denen der Benutzer, der Vim geöffnet hat, keine hat, muss :w !Sudo tee >/dev/null file Trick muss entweder direkt oder über ein Plugin wie SudoEdit verwendet werden.

4
Ingo Karkat

Sie können niemals in eine Datei schreiben, für die Sie keine Schreibberechtigung haben. Sie können diese Datei jedoch löschen, wenn Sie über Schreibberechtigungen für das Verzeichnis verfügen.

Der Trick, den VIM] verwendet, besteht darin, die Datei zu löschen und eine neue zu schreiben.

Es ist möglich zu zeigen, dass dies die Methode ist, die VIM verwendet, ohne den Quellcode zu lesen, indem Sie die Inode-Nummer vorher und nachher überprüfen:

$ 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

Beachten Sie, dass sich die Inode-Nummer geändert hat, um anzuzeigen, dass die neue Datei NICHT mit der von Ihnen bearbeiteten übereinstimmt.


Zu Ihrer Information Meine aktuelle Konfiguration ist wirklich kurz:

runtime! debian.vim
if has("syntax")
  syntax on
endif
set tabstop=4
set autoindent

Und Debian-Pakete installiert sind:

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
2
Philip Couling

Wenn sich vim im vi-kompatiblen Modus befindet, gilt Folgendes: w! überschreibt nur den schreibgeschützten Modus des Puffers, versucht jedoch nicht, die Dateiberechtigungen hin und her zu ändern, Berechtigungen zu umgehen, indem eine andere Datei in den Namen des Originals umbenannt wird, oder andere Amateurstunden zu erledigen.

Dies ist meiner Meinung nach das einzig richtige Verhalten - das Flag, das dies steuert, ist W von cpoptions/cpo. Von :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 Schaltet alle cpo Flags ein. Sie können nur das Flag W mit :set cpo+=W Oder set cpo-=W Ändern.

2
mosvy