Можно ли получить имя файла дескриптора файла (Linux) на C?
Можно ли получить имя файла дескриптора файла (Linux) на C?
Ответы:
Вы можете использовать readlink
на /proc/self/fd/NNN
где NNN является дескриптор файла. Это даст вам имя файла, которое было при его открытии - однако, если файл был перемещен или удален с тех пор, он может быть неточным (хотя Linux может отслеживать переименования в некоторых случаях). Чтобы проверить, stat
укажите имя файла и fstat
имеющийся у вас fd и убедитесь, что st_dev
и st_ino
совпадают.
Конечно, не все файловые дескрипторы относятся к файлам, и для них вы увидите некоторые странные текстовые строки, например pipe:[1538488]
. Поскольку все настоящие имена файлов будут абсолютными путями, вы можете легко определить, какие из них. Кроме того, как отмечали другие, файлы могут иметь несколько жестких ссылок, указывающих на них - это будет сообщать только о той, с которой он был открыт. Если вы хотите найти все имена для данного файла, вам просто нужно пройти через всю файловую систему.
fd
такой ссылкой будет открытый файл ), номер inode не может быть использован повторно. Любое программное обеспечение, использующее номер inode после закрытия файла или перед его открытием, по своей сути подвержено условиям гонки.
setuid()
трюки, это /proc/self/fd
может быть недоступно для вашего процесса. См .: permalink.gmane.org/gmane.linux.kernel/1302546
У меня была эта проблема в Mac OS X. У нас нет /proc
виртуальной файловой системы, поэтому принятое решение не сработает.
Вместо этого у нас есть F_GETPATH
команда для fcntl
:
F_GETPATH Get the path of the file descriptor Fildes. The argu-
ment must be a buffer of size MAXPATHLEN or greater.
Итак, чтобы связать файл с файловым дескриптором, вы можете использовать этот фрагмент:
#include <sys/syslimits.h>
#include <fcntl.h>
char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
// do something with the file path
}
Так как я никогда не помню, где MAXPATHLEN
определено, я подумал, что PATH_MAX
от syslimits будет хорошо.
getsockname
.
В Windows с GetFileInformationByHandleEx , передавая FileNameInfo , вы можете получить имя файла.
Как указывает Тайлер, невозможно сделать то, что вам нужно, «прямо и надежно», поскольку данный FD может соответствовать 0 имен файлов (в различных случаях) или> 1 (несколько «жестких ссылок» - это то, как обычно описывается последняя ситуация. ). Если вам все еще нужна функциональность со всеми ограничениями (по скорости И по возможности получения результатов 0, 2, ..., а не 1), вот как вы можете это сделать: во-первых, fstat FD - это говорит вам , в результате struct stat
, на каком устройстве находится файл, сколько жестких ссылок у него есть, является ли он специальным файлом и т. д. Это может уже ответить на ваш вопрос - например, если 0 жестких ссылок, вы ЗНАЕТЕ, что на самом деле нет соответствующего имени файла на диске.
Если статистика вселяет надежду, то вам нужно «пройтись по дереву» каталогов на соответствующем устройстве, пока вы не найдете все жесткие ссылки (или только первую, если вам не нужно больше одной, и подойдет любая ). Для этой цели вы используете readdir (и, конечно, opendir & c), рекурсивно открывая подкаталоги до тех пор, пока вы не найдете в struct dirent
полученном таким образом том же индексном узле, который был у вас в оригинале struct stat
(в этот момент, если вам нужен весь путь, а не только имя, вам нужно будет пройти по цепочке каталогов назад, чтобы восстановить ее).
Если этот общий подход приемлем, но вам нужен более подробный код на C, сообщите нам, его будет нетрудно написать (хотя я бы предпочел не писать его, если он бесполезен, т.е. вы не можете противостоять неизбежно низкой производительности или возможность получения! = 1 результата для вашего приложения ;-).
Прежде чем списать это на невозможное, предлагаю вам взглянуть на исходный код команды lsof .
Могут быть ограничения, но lsof, похоже, способен определять дескриптор файла и имя файла. Эта информация существует в файловой системе / proc, поэтому ее можно будет получить из вашей программы.
Вы можете использовать fstat (), чтобы получить индексный дескриптор файла с помощью struct stat. Затем, используя readdir (), вы можете сравнить найденный inode с теми, которые существуют (struct dirent) в каталоге (при условии, что вы знаете каталог, иначе вам придется искать по всей файловой системе) и найти соответствующее имя файла. Противно?
Невозможно. Файловый дескриптор может иметь несколько имен в файловой системе или вообще не иметь имени.
Изменить: предполагая, что вы говорите о простой старой системе POSIX без каких-либо API-интерфейсов, специфичных для ОС, поскольку вы не указали ОС.