Можно ли получить файл по его индоду?

27

Я выполнил следующие команды в указанном порядке:

$ln a b
$ls -i a b
523669 a 523669 b
$rm -f a
$ls -i b
523669 b

Из этого теста я пришел к выводу, что команда rmфактически удаляет только имя файла ( aв этом тесте), а не файл, так как индекс все еще существует и может быть получен через другое имя файла ( b).

Мой вопрос заключается в том, что если файл жестко связан только с одним именем файла, то, когда rmфайл исполняется, полностью ли удален реальный файл (т. Е. Индекс)? И если нет, можно ли получить файловый индекс без имени файла и только через этот индекс?

user43312
источник
Звучит для меня специфично для ОС.
Игнасио Васкес-Абрамс
@ Игнасио Васкес-Абрамс. Вы имеете в виду, это зависит от версии?
user43312
Нет, я имею в виду, это зависит от операционной системы. У каждого есть разные (если есть ) способы подключения к VFS.
Игнасио Васкес-Абрамс
@Ignacio Vazquez-Abrams Есть ли у вас какие-либо идеи о БРЗ или РЗП?
user43312
1
@BruceEdiger Os X вроде как делает это. Вы можете получить доступ к объекту файловой системы, используя «URL ссылки на файл», который, по сути, построен из номера файловой системы и номера узла. Однако официально не поддерживается их создание. Вместо этого вы получаете «URL ссылки на файл» для файла и затем используете его вместо имени пути для последующих обращений в том же сеансе времени выполнения, чтобы ваше приложение не обращало внимания на перемещение файла в другое место на том же томе.
Аналоговый файл

Ответы:

29

Если вы попытаетесь открыть файл через его inode, это обойдет любой обход каталога. Обратный путь в каталогах необходим для определения прав доступа к файлу и каталогам, ведущим к нему. Без обхода каталога ядро ​​не может определить, разрешено ли вызывающему процессу доступ к файлу.

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

В Linux (и, вероятно, в других вариантах Unix по той же причине) вы не можете создать ссылку на удаленный файл, поэтому, если у файла больше нет имени, вы не можете повторно добавить его. Вы можете открыть удаленный файл, открыв магические ссылки под /proc/$pid/fd/.

Если у файла больше нет ссылки и он больше не открыт, он больше не существует, и пространство, ранее использовавшееся его данными, может быть восстановлено в любое время.

May Вы можете сделать это, поворачивая байты непосредственно в файловой системе зависимым от файловой системы способом, например, с помощью debugfsдля ext2 / ext3 / ext4. Для этого требуется доступ к устройству, на котором смонтирована файловая система (т. Е., Как правило, это может сделать только root). Однако, хотя debugfs может обращаться к файлу по inode, это не поможет, если файл будет удален: файл будет действительно удален, если приложение закроет его, и запуск debugfs в режиме чтения-записи в смонтированной файловой системе является рецептом для стихийное бедствие.

Жиль "ТАК - перестань быть злым"
источник
11

В Linux debugfsинтерактивный отладчик файловой системы ext2 / ext3 / ext4 предоставляет lnкоманду, которая может взять номер индекса filespecи создать новую жесткую ссылку на соответствующий файл. Однако на практике это требует, чтобы несвязанный файл оставался открытым процессом , поддерживая дескриптор открытого файла в /proc/[pid]/fd/[n]. Попытка сделать это для удаленного файла, скорее всего, приведет к повреждению файловой системы.

Это связано с тем, что для того, чтобы ext3 (и в расширении ext4) могли безопасно возобновить отключение после сбоя, он фактически обнуляет указатели блоков в inode , тогда как ext2 просто помечает эти блоки как неиспользуемые в растровых изображениях блоков и отмечает inode как "удалено" и оставляет указатели блока в покое. Тем не менее, поскольку файловая система должна быть смонтирована для чтения-записи, чтобы создать жесткую ссылку, блоки, зарезервированные для удаленного файла, возможно, уже были перераспределены.

До версии ядра 2.6.39 раньше использовалась опция, представленная в GNU coreutils v8.0 , для восстановления несвязанного файла с помощью дескриптора открытого файла, если и несвязанный файл, и новый hardlink находились в файловой системе tmpfs . Эта возможность была с тех пор отключена , в связи, как и Жиль отметил, соображения безопасности , связанные с позволяя создавать жесткую ссылку непосредственно из файлового дескриптора.ln -L|--logical/proc/[pid]/fd/[n]

Томас Найман
источник
Я просто попытался использовать ln -Lдля восстановления удаленного файла из / proc и получил ошибку: «Нет такого файла или каталога», так что я не думаю, что на самом деле это поддерживает. У меня есть coreutils 8.21.
wingedsubmariner
1
ln -Lне делает то, что вы говорите, это делает. Это говорит lnо том, что если источник является символической ссылкой, он должен жестко связать цель. Символические ссылки внутри /proc/$pid/fdявляются специальными, и жесткая (deleted)ссылка не работает.
Жиль "ТАК - перестань быть злым"
Также debugfsне поможет, если файл был удален - если только вы не рискуете запустить его в режиме чтения-записи на смонтированной файловой системе, которая, вероятно, полностью искажает всю файловую систему.
Жиль "ТАК - перестань быть злым"
Обновлен ответ в отношении ln -L. Раньше было возможно создать жесткие ссылки, /proc/[pid]/fd/[n]используя его в определенных особых обстоятельствах, но с тех пор это было исправлено.
Томас Найман
1
debugfs«s lnдействительно низкий уровень и создает только имя, не обновляет счетчик и не снимает выделение блоков как неиспользуемые , так что это очень опасно . Предпочитаю debugfs, undelчто все это. Внимание: debugfsэто не будет работать на смонтированной файловой системе , если вы не хотите , чтобы принять шанс на обжечь FS в пепел.
Lloeki
9

Команды 'ln' и 'rm' работали точно так же в каждой файловой системе UNIX с начала 1970-х годов. Mac OSX, BSD и Linux все наследуют этот оригинальный дизайн.

Сам по себе файл UNIX не имеет имени, только номер инода или inum. Но вы можете получить к нему доступ только через запись в специальном файле «directory», который связывает имя с рассматриваемым inum; Вы не можете указать Inum напрямую.

Каталог сам по себе является файлом, поэтому вы также должны обращаться к нему через (другой) каталог и т. Д. Через серию имен каталогов, разделенных прямой косой чертой (/), известной как «имя пути». Путь начинается в «текущем рабочем каталоге» процесса, если только имя не начинается с «/», в этом случае он начинается с корневого каталога файловой системы. Например, если имя пути не содержит символов "/", то ожидается, что это будет запись в текущем каталоге.

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

Хотя каталоги имеют номера инодов, большинство файловых систем не допускают жестких ссылок на них; они могут появляться только в одном другом каталоге. (Одним необычным исключением является файловая система Mac OSX HFS +; это позволяет работать резервным копиям Time Machine.) Вы по-прежнему можете создавать «мягкие ссылки» на каталоги (или любой другой файл). Мягкая ссылка напоминает запись каталога, за исключением того, что она содержит другое имя пути, а не inum.

Каждый файл UNIX имеет владельца, группу и права доступа. Необходимо, но не достаточно, чтобы они позволили вам открыть файл; Вы также должны иметь как минимум разрешение на выполнение для каждого каталога в пути, который вы используете для ссылки на него. Вот почему нет стандартного способа открыть файл UNIX по номеру его индекса; это обойдёт важный, широко используемый механизм безопасности.

Но это не объясняет, почему не может быть стандартного способа для корневого (привилегированного) пользователя открыть файл по номеру инода, так как проверка разрешений в любом случае обходится. Это было бы очень полезно для определенных функций управления системой, таких как резервное копирование. Насколько мне известно, такие механизмы существуют, но все они зависят от файловой системы; не существует общего способа сделать это для любой файловой системы UNIX.

Фил Карн
источник
1
Нападающий в /молчит, поэтому он произносится как слэш.
Ctrl-Alt-Delor
4

Вопрос может быть взят теоретически (что может быть достигнуто debugfs) или прагматично (чрезвычайная ситуация). В последнем случае я предполагаю, что целью является сохранение дня и восстановление содержимого файла, возможно, в срочном порядке (именно так я и попал в этот вопрос, поэтому я думаю, что он все еще актуален и полезен).

Поскольку нет API ядра, debugfsего не следует запускать в действующей файловой системе, поскольку он напрямую управляет структурой FS. Поэтому, чтобы сделать это вживую, вы должны получить другое имя файла. Предполагая, что файл все еще открыт каким-либо процессом (любым процессом), можно найти все удобные файловые дескрипторы в /proc:

$ lsof -F pf "$PWD/a" | sed 's/^p//' # find pid and file descriptor number of any process having the file open
$ pid=1234
$ ls -l /proc/$pid/fd/* | grep "$PWD/a" # find file descriptor number
$ fd=42
$ cat /proc/$pid/fd/$fd > "$PWD/a.restored" # read contents to a new filename

Подсказки:

  • если у вас есть сомнения по поводу правильного FD, вы можете запустить такие команды, как fileна нем
  • если процесс записывает данные в файл, обязательно остановите этот процесс как можно скорее, иначе вы не получите последние данные. Уловка (непроверенная) может состоять в том, чтобы открыть файл, доступный только для чтения через fd, с помощью какого-либо другого процесса (попробуйте tail -f < /proc/$pid/fd/$fd > /dev/nullвыйти из процесса записи, чтобы он завершился корректно, и использовать fd нового процесса.
Lloeki
источник
2
Это должно быть tail -f < /proc/...во второй подсказке.
Мюррей Дженсен
Или используйте tail -c +0 -f для копирования в первую очередь вместо cat, если процесс записи только добавляется (без поиска назад и переписывания). Прежде чем выйти из другого процесса tail, дождитесь tailокончания файла.
Питер Кордес