Почему я не могу напрямую редактировать ссылки и каталоги?

Существуют такие программы, как hexedit которые позволяют редактировать каждый бит файла, и, как я все время слышу, что в Unix «все есть файл», я попытался отредактировать какой-то каталог, ожидая байтов, ссылающихся на inodes или имена файлов. Вместо этого я получаю:

 hexedit: teste: not a file 

Тем не менее, я был счастлив, обнаружив, что он работает со многими файлами dev (разделы, целые жесткие диски, поддельные компоненты (например, /dev/null ), вы называете это).

И для мягких ссылок, hexedit следует за ними, и ошибка совпадает с ошибкой адресата, хотя с именем ссылки вместо этого в моем тесте:

 hexedit: testeln: not a file 

Даже если исходный файл удален и ссылка недействительна, поведение будет одинаковым. Но это еще не все.

Если вы копируете символические ссылки без специальной опции для сохранения (или использования опций rsync ), они становятся обычными файлами, и, к счастью, у меня была старая ссылка:

 00000000 49 6E 74 78 4C 4E 4B 01 2F 00 73 00 72 00 76 00 2F 00 73 00 61 00 6D 00 62 00 61 00 2F 00 73 00 IntxLNK./.srv/.samba/.s. 00000020 68 00 61 00 72 00 65 00 hare 

В случае /dev/initctl , loop-control , snapshot и tty2 (даже если он открыт и у меня есть права на чтение / запись), hexedit дает (после очистки экрана в последней строке):

 the long seek failed (-1 instead of 0), leaving :( 

Для /dev/log :

 hexedit: log: No such device or address 

Могу ли я увидеть каталоги таким образом? Почему автоматически следуют ссылки? Как я могу изменить это поведение? Почему hexedit ведет себя так же (AFAIK) для символических ссылок и каталогов? Я подозреваю, что некоторые странные файлы, которые я нашел в /dev , кажутся пустыми, даже если я использую sudo .

3 Solutions collect form web for “Почему я не могу напрямую редактировать ссылки и каталоги?”

POSIX требует такого поведения для файлов определенных типов на уровне системного вызова. open функция следует за символическими ссылками, за исключением случаев, когда O_NOFOLLOW флаг O_NOFOLLOW – который, скорее всего, не работает с hexedit .

Для каталогов функция read возвращает код ошибки и устанавливает errno в EISDIR . С http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html :

Аргумент fildes относится к каталогу, и реализация не позволяет чтение каталога с помощью read () или pread (). Вместо этого следует использовать функцию readdir ().

Как предположил @goldilocks, по крайней мере существует 7 разных типов файлов, каждый из которых имеет различную семантику:

  • регулярные файлы
  • символические ссылки
  • каталоги
  • блочные устройства
  • символьные устройства
  • FIFO и
  • Розетки

Вы отчасти правы в своих ожиданиях. «Все является файлом» на самом деле означает, что даже вещи, которые не являются файлами, такими как экраны, микрофоны и т. Д., Занимают место в дереве файловой системы и могут быть доступны с использованием некоторых из тех же системных вызовов, что и обычные файлы ( open, write, т. Д.). .). Многие из ваших примеров не очень похожи на файлы. /dev/null – это не пустой файл, например, но очень специальный «драйвер устройства», небольшой код ядра, который принимает запросы чтения и записи (возврат EOF для первого и игнорирование второго). Таким образом, это не файл, а ведет себя как один. Подумайте также о точке монтирования для диска: это не файл в каком-то смысле, это крючок, который дает вам доступ ко всей иерархии файлов на этом диске.

Справочник, с другой стороны, действительно является «блоком байтов», как ставит его @goldilocks: он занимает пробел на диске и содержит структуру данных, которая отображает имена файлов в inodes. Но, как вы обнаружили, он не ведет себя как обычные файлы. Вы получаете сообщения об ошибках, потому что каталоги слишком важны, чтобы оставить уязвимыми для обычных пользовательских команд. Представьте, если вы случайно написали

 grep foo bar > subdir 

где вы хотели написать

 grep foo bar > subdir/newfile 

… ваш каталог subdir будет закрыт, а вместе с ним и согласованность вашей файловой системы, потому что все его файлы внезапно станут сиротами inodes. Таким образом, каталоги защищены разными способами. Вам также не разрешается жестко ссылаться на каталог, поскольку несколько ссылок на каталоги означают, что файловая система больше не является деревом. В прежние времена (несколько десятилетий назад) корень имел обыкновение делать некоторые из них, и вокруг него были всевозможные «редакторы каталогов». Не уверен, насколько это все еще возможно.

Некоторые Unix-варианты (включая оригинальный Unix, но не Linux) позволяют открывать каталог, как обычный файл, и читать из него. Содержимое каталога зависит от формата файловой системы, что делает его весьма ограниченным.

Запись в каталог будет очень опасной. Я думаю, что исходный Unix разрешил его программам, запущенным как root, но современные устройства этого не делают. Если вы могли бы написать в каталог, вы могли бы сделать файловую систему недействительной, ввести циклы, указать блоки, которые не существуют, создать исполняемые файлы setuid, изменив их владельца и разрешения и т. Д. Вот почему только код, запущенный внутри ядра, может создавать каталоги.

Символические ссылки – это другой случай. Открытие и чтение символических ссылок открывает целевой файл, потому что для этого предназначены символические ссылки: они прозрачны для всего, что работает с содержимым файла (например, с редактором). Было бы возможно иметь интерфейс, в котором чтение содержимого символической ссылки будет использоваться open (со специальным флагом), read и close , но это не принесло бы никакой пользы по сравнению с единственным вызовом на readlink . Написание символической ссылки с вызовами write было бы более проблематичным, поскольку они должны были бы увеличить выделение памяти для целевой аудитории; на стороне приложения, которая потеряла бы выгоду от использования symlink .

Linux и Unix - лучшая ОС в мире.