Почему я могу изменить файл только для чтения?

Короткий вопрос:

Почему может мы управлять файлом только для чтения в использовании Vim: + w + q +! даже, не будучи администратором?

Долгий вопрос:

У меня есть текстовый файл (myFile.txt), который только для чтения для всех:

navid@navid-ThinkPad-T530:~/ubuntuTest$ ls -l myFile.txt 
-r--r--r-- 1 navid navid 26 Aug 22 21:21 myFile.txt

Я могу открыть его с Vim, не имея административных привилегий:

navid@navid-ThinkPad-T530:~/ubuntuTest$ vi myFile.txt 

Я изменяю его и нажатие: Esc +: + w + q + Входят, и я вижу это сообщение об ошибке:

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

До сих пор все имеет смысл. Но когда я нажимаю: Esc +: + w + q +! + Входят, Vim сохраняет изменения.

Я использую Ubuntu 16.04 и VIM 7.4.

42
задан 14 August 2018 в 05:53

7 ответов

Как уже упоминал @Rob , вы можете сделать это, только если у вас есть доступ на запись к каталог, содержащий файл. Попытка сделать то же самое с файлом в, например, / etc не удастся.

Что касается того, как vim это делает, он удаляет файл и воссоздает его. Чтобы проверить это, я создал файл, принадлежащий пользователю root:

echo foo | sudo tee fff

, а затем приступил к редактированию файла с помощью vim описанным вами способом, но присоединил процесс к strace к посмотрите, что происходит:

strace vim fff 2> strace.out

Затем я проверил strace.out и обнаружил:

unlink("fff")                           = 0
open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "foasdasdao\n", 11)            = 11

Итак, файл был сначала удален ( unlink ("fff") ), затем был создан новый был создан файл с тем же именем ( open ("fff", O_WRONLY | O_CREAT | O_TRUNC, 0644) ), и в него были записаны внесенные мной изменения ( write (4, "foasdasdao \ п ", 11) ). Если вы попробуете это дома, то увидите, что после редактирования с помощью vim файл теперь будет принадлежать вам, а не root.

Итак, строго говоря, vim не редактирует файл, к которому у вас нет доступа на запись. Он удаляет файл из каталога, к которому у вас есть доступ на запись, а затем создает новый файл, к которому, опять же, у вас есть доступ на запись.

58
ответ дан 23 November 2019 в 00:02

Используя w! , вы удаляете исходный файл (, что вам разрешено ) и вместо этого записываете свою версию.

Когда вы Имея права записи в каталог, вы можете: создавать, перемещать или удалять файлы в этом каталоге.

$ mkdir foo
$ echo hi > foo/file
$ chmod 777 foo
$ chmod 700 foo/file
$ ls -l foo/file 
-rwx------ 1 ravexina ravexina 7 Aug 31 03:19 foo/file

Теперь позвольте мне переключить моего пользователя и изменить файл

$ sudo -u user2 -s
$ vi foo/a # save using w! (I wrote into the file bye)
$ ls -l foo/a
-rwx------ 1 user2 user2 7 Aug 31 03:20 foo/file

Теперь посмотрим, что там:

$ cat foo/file
bye
16
ответ дан 23 November 2019 в 00:02

Пока вы владеете родительским каталогом, вы можете удалить или заменить файл независимо от разрешения, поскольку вы можете изменить содержимое каталога :).

Попробуйте это с помощью другой команды как и rm, он предложит вам, но вы все равно можете это сделать. Сделайте каталог недоступным для записи, и это должно остановить его.

Дополнение:

Только что попробовал, но пока у меня есть файл, я все еще могу изменять его, даже если папка только для чтения. Однако, когда я меняю владельца на root:root не может открыть файл для записи. Таким образом решаются изменения файлов, принадлежащих root (или кому-то еще)

16
ответ дан 23 November 2019 в 00:02

См. : help 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).

Поскольку у вас есть права на запись в каталог (то есть вы можете создавать, удалять или переименовывать файлы в нем), система позволяет это .


Значение по умолчанию cpoptions не содержит W :

                                                'cpoptions' 'cpo' cpo
'cpoptions' 'cpo'       string  (Vim default: "aABceFs",
                                 Vi default:  all flags)
                        global
10
ответ дан 23 November 2019 в 00:02

Это предупреждение VIM, которое может быть относительно важным, учитывая, как работают разрешения в UNIX. Очевидная неинтуитивность этого заключается в том, что файловые системы UNIX имеют разрешения для файла, хранящегося в i-узле файла. Структура каталогов как-то отделена и связывает только эти i-узлы. Каталоги также имеют свои разрешения, которые говорят, можете ли вы связывать / отключать файлы в нем, читать его или переходить к подкаталогам. Такой дизайн позволяет, чтобы один и тот же файл мог появляться в нескольких разных местах в структуре каталогов (через жесткие ссылки). Сказав «добавить! Для переопределения», VIM пытается предупредить вас, что исходный файл будет отключен (поэтому он останется нетронутым во всех других местах), а новый файл будет создан и связан с исходным местом в структуре каталогов. В случае, если счетчик ссылок исходного файла уменьшается до нуля, исходный файл будет освобожден, но если нет, вы фактически клонируете файл. Открытие файла также считается ссылкой, поэтому, если какая-то программа открыла файл и вы согласны «добавить! Для отмены», программа не увидит изменений, внесенных вами в файл с помощью VIM. Файл отключается от каталога только VIM, и после закрытия файла другой программой файл будет освобожден, если он не был связан где-то еще.

Обратите внимание, что в Windows,разрешения для файлов хранятся в каталоге, поэтому с точки зрения парадигмы разрешений Windows такое поведение vim может действительно выглядеть странно. Для записи в файл Windows по логике может также проверять права доступа к некоторым каталогам, даже к суперкаталогам. Как было сказано выше, в UNIX права доступа к каталогам не имеют отношения к манипуляциям с файлом, поскольку вы могли их перечислить и открыть (т.е. было x для всех суперкаталогов). Открытый файл в UNIX может даже не иметь имени файла, если он был отключен от всех каталогов после открытия.

Например, у вас есть файл / home / user1 / foo, и это тот же файл, что и (т.е. жестко привязанный к) / home / user2 / foo, и файл не доступен для записи никому и в настоящее время открыт программой P (открыт для чтения и записи программой, запущенной пользователем root). Если user1 открывает его с помощью vim и перезаписывает, он делает свою копию и больше не видит исходный файл. Если впоследствии user2 откроет свою ссылку с помощью vim и напишет в нее, ссылка снова будет отключена, и он создаст еще одну копию. Программа P по-прежнему будет видеть исходный файл и может свободно читать или писать в него. Как только программа закроет файл, файл исчезнет (будет освобожден файловой системой).

2
ответ дан 23 November 2019 в 00:02

И ваш процесс редактора vim, и ваш файл принадлежат вам

 getpwnam("navid")->pw_uid

, так что вы также можете выложить

 :!chmod +w %

, и вы могли догадаться, что когда-то давным-давно был еще проще

 :!rm %

( требуется только + w, но разрешение на отключение. и даже не право владения) стало слишком частым для того, чтобы кто-то мог вводить, так что vim был перепрограммирован так, чтобы автоматически предлагать и по запросу автоматически выполнять такую ​​операцию.

Попробуйте перезаписать

 /home/whoopi/.profile

своей старшей сестры как простой навид, и держите пари, что ваш vim даст вам желаемый отказ.

2
ответ дан 23 November 2019 в 00:02

Это не совсем ответ, но если вы действительно хотите установить файл так, чтобы никто не мог измените или удалите его, вы можете сделать его неизменным.

Обычно, даже если файл принадлежит пользователю root, вы все равно можете удалить файл, если у вас есть права на запись в папку. Но когда вы делаете файл неизменяемым, даже root не может его изменить или удалить.

Чтобы сделать файл неизменяемым (вам нужно sudo ):

sudo chattr +i myFile.txt

Вы можете увидеть это с помощью lsattr ] (буква i в результате):

$ lsattr myFile.txt
----i--------e-- myFile.txt

Чтобы снова сделать файл нормальным:

sudo chattr -i myFile.txt

Уточнение: когда файл неизменяемый, его нельзя удалить, переименовать, изменить или даже жестко -linked.

Стоит прочитать man chattr , потому что файлы могут иметь ряд полезных атрибутов.

Вы также можете найти полезным "ограниченное удаление". Если он помещен в папку (а не в файл), это означает, что любому, кто создает файл в папке, разрешено изменять или удалять этот файл, но никто другой (кроме root). В папке / tmp установлен этот флаг. Вы можете увидеть это с помощью флага t на / tmp :

$ ls -l --directory /tmp
drwxrwxrwt 10 root root 4096 Sep  6 09:00 /tmp

Чтобы установить или снять флаг ограниченного удаления в папке:

chmod +t myFolder      # Add the restricted deletion flag.
chmod -t myFolder      # Remove the restricted deletion flag.
1
ответ дан 23 November 2019 в 00:02

Другие вопросы по тегам:

Похожие вопросы: