Чи можливо отримати назву дескриптора файлу (Linux) в C?
Чи можливо отримати назву дескриптора файлу (Linux) в C?
Відповіді:
Ви можете використовувати readlink
на /proc/self/fd/NNN
де NNN є дескриптор файлу. Це дасть вам ім'я файлу таким, яким воно було, коли він був відкритий - однак, якщо файл був переміщений чи видалений з того часу, він більше не може бути точним (хоча Linux може відстежувати перейменування в деяких випадках). Щоб перевірити, stat
ім'я файлу , задане і fstat
ФД у вас є, і переконайтеся , що st_dev
і st_ino
ті ж.
Звичайно, не всі дескриптори файлів посилаються на файли, і для тих, хто побачить деякі незвичайні текстові рядки, такі як pipe:[1538488]
. Оскільки всі справжні імена файлів будуть абсолютними шляхами, ви можете визначити, які з них досить легко. Далі, як зазначають інші, файли можуть мати декілька жорстких посилань, що вказують на них - про це повідомлятиметься лише той, з яким він був відкритий. Якщо ви хочете знайти всі імена для даного файлу, вам просто доведеться пройти всю файлову систему.
fd
буде така посилання), номер введення не може бути використаний повторно. Будь-яке програмне забезпечення, яке використовує номер 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
таким чином такий самий номер inode, який ви мали в оригіналі struct stat
(в цей час, якщо ви хочете весь шлях, а не лише ім'я, вам потрібно буде пройти ланцюжок каталогів назад, щоб відновити його).
Якщо цей загальний підхід прийнятний, але вам потрібен більш детальний код C, повідомте нас, це буде важко написати (хоча я краще не напишу його, якщо він марний, тобто ви не зможете протистояти неминуче повільній продуктивності або можливість отримати! = 1 результат для вашої заявки ;-).
Ви можете використовувати fstat (), щоб отримати inode файлу за допомогою stat stat. Потім, використовуючи readdir (), ви можете порівняти знайдений інод з тими, які існують (struct dirent) у каталозі (якщо припустити, що ви знаєте каталог, інакше вам доведеться шукати всю файлову систему) і знайти відповідне ім'я файлу. Неприємний?
Неможливо. Дескриптор файлу може мати декілька імен у файловій системі або взагалі не мати імені.
Редагувати: якщо припустити, що ви говорите про звичайну стару систему POSIX, без будь-яких API для ОС, оскільки ви не вказали ОС.