Подтвердить что ты не робот

Получить имя файла из файлового дескриптора в C

Можно ли получить имя файла дескриптора файла (Linux) в C?

4b9b3361

Ответ 1

Вы можете использовать readlink в /proc/self/fd/NNN, где NNN - файловый дескриптор. Это даст вам имя файла, как оно было, когда оно было открыто - однако, если файл был перемещен или удален с тех пор, он может быть не более точным (хотя Linux может отслеживать переименование в некоторых случаях). Чтобы проверить, stat имя файла и fstat значение fd у вас есть, и убедитесь, что st_dev и st_ino совпадают.

Конечно, не все дескрипторы файлов относятся к файлам, и для них вы увидите некоторые нечетные текстовые строки, например pipe:[1538488]. Поскольку все настоящие имена файлов будут абсолютными путями, вы можете определить, какие из них достаточно просты. Кроме того, как отмечали другие, файлы могут иметь несколько жестких ссылок, указывающих на них - это будет сообщать только тот, с которым он был открыт. Если вы хотите найти все имена для данного файла, вам просто нужно пройти всю файловую систему.

Ответ 2

У меня была эта проблема в 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 будет в порядке.

Ответ 4

Как указывает Тайлер, нет никакого способа сделать то, что вам нужно "прямо и надежно", поскольку данный FD может соответствовать 0 именам файлов (в разных случаях) или > 1 (несколько "жестких ссылок" - это то, как последняя ситуация как правило, описывается). Если вам все еще нужна функциональность со всеми ограничениями (по скорости И по возможности получать 0, 2,... результаты, а не 1), вот как вы можете это сделать: во-первых, fstat FD - это сообщает вам, в результате struct stat, какое устройство живет в файле, сколько жестких ссылок он имеет, будь то специальный файл и т.д. Это может уже ответить на ваш вопрос - например если 0 жестких ссылок вы будете ЗНАТЬ, на самом деле нет соответствующего имени файла на диске.

Если статистика дает вам надежду, тогда вам нужно "ходить по дереву" каталогов на соответствующем устройстве, пока не найдете все жесткие ссылки (или только первые, если вам не нужно больше одного и любого другого один сделаю). Для этой цели вы используете readdir (и, конечно, opendir и c), рекурсивно открывая подкаталоги, пока не найдете в полученном таким образом struct dirent тот же номер inode, который у вас был в исходном struct stat (когда вам нужен весь путь, а не просто имя, вам нужно будет пройти цепочку каталогов назад, чтобы восстановить его).

Если этот общий подход является приемлемым, но вам нужен более подробный код C, сообщите нам, что его будет сложно написать (хотя я бы предпочел написать его, если он бесполезен, т.е. вы не можете противостоять неизбежно медленному производительность или возможность получения!= 1 результат для вашей заявки; -).

Ответ 5

Прежде чем записать это как невозможное, я предлагаю вам посмотреть исходный код команды lsof.

Могут быть ограничения, но lsof кажется способным определять дескриптор файла и имя файла. Эта информация существует в файловой системе /proc, поэтому она должна быть доступна из вашей программы.

Ответ 6

Вы можете использовать fstat(), чтобы получить файл inode с помощью struct stat. Затем, используя readdir(), вы можете сравнить найденный inode с существующими (struct dirent) в каталоге (при условии, что вы знаете каталог, иначе вам придется искать всю файловую систему) и найти соответствующее имя файла. Противный?

Ответ 7

невыполнима. Файловый дескриптор может иметь несколько имен в файловой системе или вообще не иметь имени.

Изменить: Предполагая, что вы говорите о простой старой системе POSIX, без каких-либо специфических для ОС API, поскольку вы не указали ОС.