Может ли Vim нарушить права доступа к файлам?

Может ли Vim нарушить права доступа к файлам?

На днях я, как обычно, пользовался Vim, когда заметил нечто странное. Вот что я сделал:

~$ touch testfile
~$ ls -l | grep testfile
-rw-r--r-- 1 username groupname 0 Jul 23 10:00 testfile
~$ vim testfile

Затем я сделал изменение, сохранил и вышел с помощью :wq. Довольно нормально. Затем, однако:

~$ sudo chown root:root testfile
~$ sudo chmod 644 testfile
~$ sudo -k
~$ ls -l | grep testfile
-rw-r--r-- root root 0 Jul 23 10:02 testfile
~$ vim testfile

Итак, root должен иметь права на чтение и запись, а все остальные должны иметь только право на чтение. Отредактируйте файл, попробуйте сохранить — не получится. Отлично, работает так, как и задумано. Однако, если вы сохраните с помощью :w!, vim каким-то образом изменит владельца файла обратно на имя_пользователя:группа_пользователей, и файл будет сохранен. Даже если вы сделаете это:

~$ sudo chmod 444 testfile
~$ sudo -k
~$ ls -l | grep testfile
-r--r--r-- 1 root root 0 Jul 23 10:06 testfile
~$ vim testfile

Ты можешьвсе ещеперезаписать с помощью :w!! Что происходит? Как vim может нарушать законы владения файлами и разрешения таким образом? Я посмотрел на страницу справки в vim, сказав :help :wи нашел это:

:w[rite]! [++opt]    Like ":write", but forcefully write when 'readonly' is set or there is another reason why writing was refused.
                     Note: This may change the permission and ownership of the file and break (symbolic) links. Add the 'W' flage to 'cpoptions' to avoid this.

Раньше мне не удавалось записать файл в vim, хотя это было невозможно, поэтому, полагаю, суть моего вопроса в том, как сделать файл нередактируемым в vim, и почему это не основано на правах доступа файловой системы, как я ожидал, и какой механизм использует vim для редактирования файла, который другие редакторы (gedit, nano) использовать не могут?

EDIT: Компьютер, на котором я это пробовал, использует ядро ​​Linux 3.15.5-2-ARCH. Номер версии Vim - 7.4.373-1, и это тот, который установлен pacman- я не компилировал его с нуля с какими-либо специальными опциями.

решение1

Я вижу, что ваш текущий путь — ~, домашний каталог вашего пользователя. У вас должны быть права на запись в этот каталог.

Подумайте об этом по-другому: если у вас есть права на чтение и запись в каталог, что мешает вам скопировать файл, удалить старый и переименовать новый с другими правами доступа?

Именно это и делает vim!


Если вы запустите vim под strace, например:

open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = -1 EACCES (Permission denied)
lstat("testfile", {st_mode=S_IFREG|0644, st_size=10, ...}) = 0
getuid()                                = 1000
unlink("testfile")                      = 0
open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 3
write(3, "ffjidfjds\n", 10)             = 10
fsync(3)                                = 0
close(3)                                = 0
chmod("testfile", 0644)                 = 0

На основании этого журнала я могу предположить следующий процесс:

Некоторые более ранние проверки разрешений (и chownпопытки и т. д.) опущены для краткости.

  1. openПопытка открыть файл для записи (неудача: отказано в доступе)
  2. lstatПроверьте владельца файла
  3. getuuidПроверьте текущий идентификатор пользователя, чтобы увидеть, совпадает ли он с владельцем файла.
  4. unlinkУдалить файл (это разрешено, так как есть разрешение на запись в каталог)
  5. openСоздайте новый файл с тем же именем.
  6. writeСодержимое файла (читал ранее, я набрал какую-то тарабарщину)
  7. fsyncСбросить файл на диск (не так уж и важно)
  8. close
  9. chmodИзмените права доступа нового файла так, чтобы они были похожи на права доступа старого файла — просто теперь у него новый владелец.

Связанный контент