
На днях я, как обычно, пользовался 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 под 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
попытки и т. д.) опущены для краткости.
open
Попытка открыть файл для записи (неудача: отказано в доступе)lstat
Проверьте владельца файлаgetuuid
Проверьте текущий идентификатор пользователя, чтобы увидеть, совпадает ли он с владельцем файла.unlink
Удалить файл (это разрешено, так как есть разрешение на запись в каталог)open
Создайте новый файл с тем же именем.write
Содержимое файла (читал ранее, я набрал какую-то тарабарщину)fsync
Сбросить файл на диск (не так уж и важно)close
chmod
Измените права доступа нового файла так, чтобы они были похожи на права доступа старого файла — просто теперь у него новый владелец.