131 Stimmen

Abrufen des Dateinamens aus dem Dateideskriptor in C

Ist es möglich, den Dateinamen eines Dateideskriptors (Linux) in C zu ermitteln?

153voto

bdonlan Punkte 213545

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.

119voto

zneak Punkte 129366

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.

36voto

Martin v. Löwis Punkte 120025

Unter Windows, mit GetFileInformationByHandleEx , vorbei DateiNameInfo können Sie den Dateinamen abrufen.

17voto

Alex Martelli Punkte 805329

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;-).

11voto

Duck Punkte 25886

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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X