Ist es möglich, den Dateinamen eines Dateideskriptors (Linux) in C zu ermitteln?
Antworten
Zu viele Anzeigen?Sie können verwenden readlink
en /proc/self/fd/NNN
wobei NNN der Dateideskriptor ist. Dadurch erhalten Sie den Namen der Datei, wie er beim Öffnen lautete - wenn die Datei jedoch seitdem verschoben oder gelöscht wurde, ist er möglicherweise nicht mehr korrekt (obwohl Linux in einigen Fällen Umbenennungen verfolgen kann). Zum Überprüfen, stat
den angegebenen Dateinamen und fstat
die fd, die Sie haben, und stellen Sie sicher st_dev
y st_ino
sind identisch.
Natürlich beziehen sich nicht alle Dateideskriptoren auf Dateien, und für diese werden Sie einige seltsame Textzeichenfolgen sehen, wie zum Beispiel pipe:[1538488]
. Da alle echten Dateinamen absolute Pfade sind, können Sie leicht feststellen, welche das sind. Wie bereits erwähnt, können Dateien mehrere Hardlinks haben, die auf sie verweisen - es wird nur derjenige angezeigt, mit dem sie geöffnet wurde. Wenn Sie alle Namen für eine bestimmte Datei finden wollen, müssen Sie einfach das gesamte Dateisystem durchforsten.
Ich hatte dieses Problem unter Mac OS X. Wir haben keine /proc
virtuellen Dateisystem, so dass die akzeptierte Lösung nicht funktionieren kann.
Wir haben stattdessen eine F_GETPATH
Befehl für fcntl
:
F_GETPATH Get the path of the file descriptor Fildes. The argu-
ment must be a buffer of size MAXPATHLEN or greater.
Um die mit einem Dateideskriptor verknüpfte Datei zu erhalten, können Sie dieses Snippet verwenden:
#include <sys/syslimits.h>
#include <fcntl.h>
char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
// do something with the file path
}
Da ich mich nie erinnern kann, wo MAXPATHLEN
definiert ist, dachte ich PATH_MAX
von syslimits wäre in Ordnung.
Unter Windows, mit GetFileInformationByHandleEx , vorbei DateiNameInfo können Sie den Dateinamen abrufen.
Wie Tyler betont, gibt es keine Möglichkeit, das, was Sie benötigen, "direkt und zuverlässig" zu tun, da ein gegebener FD 0 Dateinamen (in verschiedenen Fällen) oder > 1 entsprechen kann (mehrere "harte Links" ist die allgemeine Beschreibung der letzteren Situation). Wenn Sie die Funktionalität mit all den Einschränkungen (in Bezug auf die Geschwindigkeit UND die Möglichkeit, 0, 2, ... Ergebnisse statt 1 zu erhalten) dennoch benötigen, können Sie Folgendes tun: Erstens, fstat der FD - dies sagt Ihnen, in der resultierenden struct stat
Auf welchem Gerät sich die Datei befindet, wie viele Hardlinks sie hat, ob es sich um eine spezielle Datei handelt usw. Damit ist Ihre Frage vielleicht schon beantwortet - wenn z. B. 0 Hardlinks vorhanden sind, wissen Sie, dass es tatsächlich keinen entsprechenden Dateinamen auf der Festplatte gibt.
Wenn die Statistik Ihnen Hoffnung macht, müssen Sie den Baum der Verzeichnisse auf dem betreffenden Gerät "abwandern", bis Sie alle harten Links gefunden haben (oder nur den ersten, wenn Sie nicht mehr als einen brauchen und ein beliebiger genügt). Zu diesem Zweck verwenden Sie readdir (und opendir &c natürlich) rekursiv Unterverzeichnisse öffnen, bis Sie in einem struct dirent
erhielt somit dieselbe Inode-Nummer, die Sie in der ursprünglichen struct stat
(wenn Sie dann den gesamten Pfad und nicht nur den Namen wollen, müssen Sie die Verzeichnungskette rückwärts durchlaufen, um ihn zu rekonstruieren).
Wenn dieser allgemeine Ansatz akzeptabel ist, Sie aber detaillierteren C-Code benötigen, lassen Sie es uns wissen, es wird nicht schwer sein, ihn zu schreiben (obwohl ich ihn lieber nicht schreiben würde, wenn er nutzlos ist, d.h. wenn Sie die unvermeidlich langsame Leistung oder die Möglichkeit, != 1 Ergebnis zu erhalten, für die Zwecke Ihrer Anwendung nicht ertragen können;-).
Bevor Sie dies als unmöglich abtun, schlage ich vor, dass Sie einen Blick auf den Quellcode der lsof Befehl.
Es kann Einschränkungen geben, aber lsof scheint in der Lage zu sein, den Dateideskriptor und den Dateinamen zu ermitteln. Diese Informationen sind im Dateisystem /proc vorhanden, so dass es möglich sein sollte, sie von Ihrem Programm aus abzurufen.
- See previous answers
- Weitere Antworten anzeigen