Чому я можу змінити файл лише для читання?


42

Коротке запитання:

Чому ми можемо маніпулювати файлом, доступним лише для читання у 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+, Enterі я бачу це повідомлення про помилку:

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

Поки все має сенс. Але коли я натискаю: Esc+ :+ w+ q+ !+ Enter, Vim зберігає зміни.

Я використовую Ubuntu 16.04 і VIM 7.4.


1
@Zanna У вас є каталог, у якому знаходиться файл?
Роб

Так, це була б ВЕЛИЧЕЗНА проблема в іншому випадку :)
Роб

11
Змінення файлу та заміна файлу - це дві різні речі з різними вимогами дозволу.
Девід Шварц

1
Ви можете поглянути на це . Це в основному відповідає на ваше запитання і як правильно вказав @DavidSchwartz :Modifying a file and replacing a file are two different things
Panagiotis Tabakis

@PanagiotisTabakis Дуже приємно знайти це геніальне .. chmod, щоб файл читав-писав і повертався знову, якщо він у вас є. ЛЮБИТИ це :)
Роб

Відповіді:


58

Як вже було сказано @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\n", 11)). Якщо ви спробуєте це в домашніх умовах, ви побачите, що після редагування цього vimфайлу файл тепер буде належати вам, а не root.

Отже, строго кажучи, vimне редагування файлу, до якого ви не маєте права запису. Це видалення файлу з каталогу, до якого ви маєте доступ для запису, а потім створення нового файлу, до якого, знову ж таки, у вас є доступ для запису.



8
@CCJ - це операція запису в каталог, але не файл, ні. Операції запису над файлами - це ті, що змінюють вміст файлу. Таким же чином створення / видалення файлів - це операції запису в каталог, оскільки ви змінюєте його вміст.
terdon

2
Крім того, це небезпечний порядок операцій. Безпечніше було б записати заміну на нове ім’я файлу, а потім використовувати rename(2)для заміни старого файлу. Тоді немає жодного часового вікна, де ваших даних не існує на диску.
Пітер Кордес

5
@PeterCordes гм, гаразд. Можливо, ви хочете направити свої скарги на розробників vim. Я навіть не використовую річ, я в таборі emacs.
terdon

3
@CCJ Видалення файлу - це операція запису в каталог, що містить його, а не в сам файл. Цілком інтуїтивно зрозуміло, що якщо ви керуєте каталогом (тобто маєте доступ до нього для запису), ви повинні мати можливість контролювати те, що в ньому є, і власник окремого файлу не повинен дозволяти вам замінювати вас.
fkraiem

16

Поки ви маєте батьківський каталог, ви можете видалити або замінити файл незалежно від дозволу, оскільки ви можете змінити вміст каталогу :).

Спробуйте це з іншою командою, наприклад, rm, вона підкаже вам, але ви все одно можете це зробити. Зробіть каталог не доступним для запису, і це має зупинити його.

Доповнення:

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


7
Здається, що VIM вибирає з декількох стратегій, включаючи перезапис на місці або від’єднання + запис нового файлу.
Пітер Кордес

3
@PeterCordes Так, мабуть, буде дуже важко робити те, що ви йому скажете :) Дуже хитро. :)
Роб

16

Використовуючи, 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

10

Дивіться :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

2

Це попередження VIM для вас, що може бути відносно важливим, враховуючи, як працюють дозволи в UNIX. Очевидна неінтуїтивність цього полягає в тому, що файлові системи UNIX мають дозволи для файлу, що зберігається в i-вузлі файлу. Структура каталогів якимось чином відокремлена і пов'язує лише ці i-вузли. У каталогах також є свої дозволи, які говорять про те, чи можете ви зв’язати / від’єднати файли до неї, чи прочитати їх, або перейти до підкаталогів. Така конструкція дозволяє одному і тому ж файлу з’являтися в декількох різних місцях у структурі каталогу (через жорсткі посилання). Говорячи "add! To override", VIM намагається попередити вас, що оригінальний файл буде від’єднаний (тому він залишатиметься в усіх інших місцях недоторканим), а новий файл буде створений та пов'язаний з оригінальним місцем у структурі каталогу. У випадку, якщо кількість посилань початкового файлу зменшиться до нуля, вихідний файл буде звільнений, але якщо ні, ви ефективно клонуєте файл. Відкриття файлу також вважається посиланням, тому якщо якась програма відкрила файл, і ви погоджуєтесь "додати! Переосмислити", програма не побачить змін, внесених вами до файлу з VIM. Цей файл від’єднується від каталогу тільки VIM, і після закриття файлу іншою програмою файл буде звільнений, якщо тільки він не був пов’язаний де-небудь ще.

Зверніть увагу, що в Windows, дозволи для файлів зберігаються в каталозі, тому з точки зору парадигми дозволів Windows, ця поведінка vim дійсно може виглядати дивним. Для запису до файлу Windows логічно може також перевіряти деякі дозволи каталогів, навіть дозволи на супер-каталог. Як було сказано вище, в UNIX права доступу до каталогу не мають значення для маніпуляцій з файлом, наскільки ви змогли перерахувати його та відкрити (тобто було x для всіх супер-каталогів). Відкритий файл у UNIX може навіть більше не мати імені файлу, якщо після відкриття його було від’єднано з усіх каталогів.

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


2

Як ваш редактор vim, так і ваш файл несуть ваш

 getpwnam("navid")->pw_uid

право власності, щоб ви могли також розшифруватися

 :!chmod +w %

і ви можете здогадатися, що колись ще простіше

 :!rm %

(вимагаючи лише + w, дозвіл на відключення зв’язку.

Спробуйте переписати свої старші сестри

 /home/whoopi/.profile

так як прості навидки та ставки - це ваше враження, ви бажаєте відмовитись.


Дякую @Zanna за редагування коду, хоча це коштувало мені новачка крихітної репутації, хоча заслужено.
Роман Чиборра

1

Це не зовсім відповідь, але якщо ви дійсно хочете встановити файл, щоб ніхто не міг його змінити чи видалити, ви можете зробити його непорушним.

Зазвичай, навіть якщо файл належить root, ви все одно можете видалити файл, якщо у вас є дозволи на запис у папку. Але коли ви робите файл незмінним, навіть root не може його змінити або видалити.

Щоб зробити файл незмінним (вам потрібно sudo):

sudo chattr +i myFile.txt

Ви можете побачити це за допомогою lsattr(буква iв результаті):

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

Щоб файл знову став нормальним:

sudo chattr -i myFile.txt

Для уточнення: Коли файл незмінний, його неможливо видалити, перейменувати, змінити або навіть жорстко пов’язати.

Варто прочитати man chattr, адже файли можуть мати ряд корисних атрибутів.

Також вам може бути корисним "обмежене видалення". Якщо розміщено у папці (а не у файлі), це означає, що той, хто створює файл у папці, може змінювати або видаляти цей файл, але більше ніхто (крім кореня). У папці /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.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.