Czy można uzyskać nazwę pliku deskryptora pliku (Linux) w C?
Czy można uzyskać nazwę pliku deskryptora pliku (Linux) w C?
Odpowiedzi:
Można używać readlink
na /proc/self/fd/NNN
gdzie NNN jest deskryptor pliku. W ten sposób otrzymasz nazwę pliku taką, jaka była w momencie otwarcia - jednak jeśli plik został przeniesiony lub usunięty od tego czasu, może już nie być dokładny (chociaż w niektórych przypadkach Linux może śledzić zmiany nazw). Aby zweryfikować, stat
nazwa pliku podana i fstat
FD masz, i upewnić się, st_dev
i st_ino
są takie same.
Oczywiście nie wszystkie deskryptory plików odnoszą się do plików, a dla nich zobaczysz dziwne ciągi tekstowe, takie jak pipe:[1538488]
. Ponieważ wszystkie prawdziwe nazwy plików będą ścieżkami bezwzględnymi, możesz łatwo określić, które z nich są wystarczające. Ponadto, jak zauważyli inni, pliki mogą mieć wiele twardych linków wskazujących na nie - spowoduje to tylko zgłoszenie tego, za pomocą którego zostały otwarte. Jeśli chcesz znaleźć wszystkie nazwy dla danego pliku, musisz po prostu przejść przez cały system plików.
fd
byłoby takim odniesieniem), numeru i-węzła nie można ponownie wykorzystać. Każde oprogramowanie korzystające z numeru i-węzła po zamknięciu pliku lub przed jego otwarciem podlega z natury warunkom wyścigu.
setuid()
sztuczki, /proc/self/fd
proces może nie być dostępny. Zobacz: permalink.gmane.org/gmane.linux.kernel/1302546
Miałem ten problem na Mac OS X. Nie mamy /proc
wirtualnego systemu plików, więc przyjęte rozwiązanie nie działa.
Zamiast tego mamy F_GETPATH
polecenie fcntl
:
F_GETPATH Get the path of the file descriptor Fildes. The argu-
ment must be a buffer of size MAXPATHLEN or greater.
Aby pobrać plik powiązany z deskryptorem pliku, możesz użyć tego fragmentu:
#include <sys/syslimits.h>
#include <fcntl.h>
char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
// do something with the file path
}
Ponieważ nigdy nie pamiętam, gdzie MAXPATHLEN
jest zdefiniowane, pomyślałem, że PATH_MAX
z syslimits będzie dobrze.
getsockname
.
W systemie Windows za pomocą GetFileInformationByHandleEx , przekazując FileNameInfo , możesz pobrać nazwę pliku.
Jak podkreśla Tyler, nie ma sposobu, aby zrobić to, czego potrzebujesz "bezpośrednio i niezawodnie", ponieważ dana FD może odpowiadać 0 nazwom plików (w różnych przypadkach) lub> 1 (wiele "twardych linków" jest ogólnie opisywana tą drugą sytuacją ). Jeśli nadal potrzebujesz funkcji ze wszystkimi ograniczeniami (dotyczącymi prędkości ORAZ możliwości uzyskania 0, 2, ... wyników zamiast 1), oto jak możesz to zrobić: po pierwsze, fstat FD - to ci mówi , w rezultacie struct stat
, na jakim urządzeniu znajduje się plik, ile ma twardych linków, czy jest to plik specjalny itp. To może już odpowiedzieć na twoje pytanie - np. jeśli 0 twardych linków WIESZ, że w rzeczywistości nie ma odpowiedniej nazwy pliku na dysku.
Jeśli statystyki dają ci nadzieję, musisz "chodzić po drzewie" katalogów na odpowiednim urządzeniu, aż znajdziesz wszystkie twarde linki (lub tylko pierwszy, jeśli nie potrzebujesz więcej niż jednego i każdy to zrobi ). W tym celu używasz readdir (i oczywiście opendir & c) rekurencyjnie otwierających podkatalogi, dopóki nie znajdziesz w struct dirent
otrzymanym w ten sposób tym samym numerze i-węzła, który miałeś w oryginale struct stat
(w tym czasie, jeśli chcesz całą ścieżkę, a nie tylko nazwę, aby odtworzyć łańcuch katalogów, musisz przejść wstecz).
Jeśli to ogólne podejście jest do zaakceptowania, ale potrzebujesz bardziej szczegółowego kodu w C, daj nam znać, nie będzie to trudne do napisania (chociaż wolałbym nie pisać, jeśli jest bezużyteczne, tj. Nie możesz wytrzymać nieuchronnie powolnej wydajności lub możliwość uzyskania! = 1 wyniku na potrzeby Twojej aplikacji ;-).
Zanim uznasz to za niemożliwe, proponuję przyjrzeć się kodowi źródłowemu polecenia lsof .
Mogą istnieć ograniczenia, ale wydaje się, że lsof jest w stanie określić deskryptor pliku i nazwę pliku. Ta informacja istnieje w systemie plików / proc, więc powinno być możliwe uzyskanie do niej dostępu z twojego programu.
Możesz użyć fstat (), aby uzyskać i-węzeł pliku przez statct stat. Następnie za pomocą readdir () możesz porównać znaleziony i-węzeł z tymi, które istnieją (struct dirent) w katalogu (zakładając, że znasz katalog, w przeciwnym razie będziesz musiał przeszukać cały system plików) i znaleźć odpowiadającą mu nazwę pliku. Paskudny?
Niemożliwy. Deskryptor pliku może mieć wiele nazw w systemie plików lub może nie mieć żadnej nazwy.
Edycja: Zakładając, że mówisz o zwykłym starym systemie POSIX, bez żadnych interfejsów API specyficznych dla systemu operacyjnego, ponieważ nie określiłeś systemu operacyjnego.