Ist es möglich, den Dateinamen eines Dateideskriptors (Linux) in C abzurufen?
Ist es möglich, den Dateinamen eines Dateideskriptors (Linux) in C abzurufen?
Antworten:
Sie können mit readlink
auf /proc/self/fd/NNN
dem NNN ist der Dateideskriptor. Dadurch erhalten Sie den Namen der Datei wie beim Öffnen. Wenn die Datei jedoch seitdem verschoben oder gelöscht wurde, ist sie möglicherweise nicht mehr korrekt (obwohl Linux in einigen Fällen Umbenennungen verfolgen kann). Um zu überprüfen, stat
der Dateiname angegeben und fstat
die fd Sie haben, und stellen Sie sicher , st_dev
und st_ino
sind gleich.
Natürlich beziehen sich nicht alle Dateideskriptoren auf Dateien, und für diese werden einige seltsame Textzeichenfolgen angezeigt, z pipe:[1538488]
. Da alle realen Dateinamen absolute Pfade sind, können Sie leicht bestimmen, welche diese Pfade sind. Wie andere angemerkt haben, können Dateien mehrere Hardlinks haben, die auf sie verweisen - dies meldet nur den, mit dem sie geöffnet wurden. Wenn Sie alle Namen für eine bestimmte Datei finden möchten, müssen Sie nur das gesamte Dateisystem durchlaufen.
fd
wäre ein solcher Verweis), kann die Inode-Nummer nicht wiederverwendet werden. Jede Software, die nach dem Schließen der Datei oder vor dem Öffnen eine Inode-Nummer verwendet, unterliegt von Natur aus den Rennbedingungen.
setuid()
Tricks ausführen, kann es sein /proc/self/fd
, dass Ihr Prozess nicht auf Sie zugreift. Siehe: permalink.gmane.org/gmane.linux.kernel/1302546
Ich hatte dieses Problem unter Mac OS X. Wir haben kein /proc
virtuelles Dateisystem, daher kann die akzeptierte Lösung nicht funktionieren.
Wir haben stattdessen einen 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 einem Dateideskriptor zugeordnete Datei abzurufen, 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 daran erinnere, wo MAXPATHLEN
definiert ist, dachte ich, dass PATH_MAX
Syslimits in Ordnung wären.
getsockname
.
In Windows können Sie mit GetFileInformationByHandleEx , indem Sie FileNameInfo übergeben , den Dateinamen abrufen.
Wie Tyler betont, gibt es keine Möglichkeit, "direkt und zuverlässig" das zu tun, was Sie benötigen, da eine bestimmte FD 0 Dateinamen (in verschiedenen Fällen) oder> 1 (mehrere "harte Links") entsprechen kann, wie die letztere Situation allgemein beschrieben wird ). Wenn Sie die Funktionalität mit allen Einschränkungen (Geschwindigkeit UND Möglichkeit, 0, 2, ... Ergebnisse anstelle von 1 zu erhalten) weiterhin benötigen, können Sie dies folgendermaßen tun: Zuerst fstat the FD - dies sagt Ihnen In der Folge struct stat
, auf welchem Gerät die Datei lebt, wie viele Hardlinks sie hat, ob es sich um eine spezielle Datei handelt usw. Dies kann Ihre Frage bereits beantworten - z. B. wenn Sie 0 Hardlinks kennen, wissen Sie, dass es tatsächlich keinen entsprechenden Dateinamen gibt auf der Festplatte.
Wenn die Statistiken Ihnen Hoffnung geben, müssen Sie den Baum der Verzeichnisse auf dem entsprechenden Gerät "durchgehen", bis Sie alle festen Links gefunden haben (oder nur den ersten, wenn Sie nicht mehr als einen benötigen und jeder dies tun wird ). Zu diesem Zweck verwenden Sie readdir (und natürlich opendir & c), um Unterverzeichnisse rekursiv zu öffnen, bis Sie in einem struct dirent
so empfangenen die gleiche Inode-Nummer finden, die Sie im Original hatten struct stat
(zu diesem Zeitpunkt, wenn Sie den gesamten Pfad und nicht nur den Namen möchten). Sie müssen die Verzeichniskette rückwärts durchlaufen, um sie zu rekonstruieren.
Wenn dieser allgemeine Ansatz akzeptabel ist, Sie jedoch detaillierteren C-Code benötigen, lassen Sie es uns wissen, es wird nicht schwer zu schreiben sein (obwohl ich ihn lieber nicht schreiben würde, wenn er nutzlos ist, dh Sie können der unvermeidlich langsamen Leistung oder der Leistung nicht standhalten Möglichkeit zu bekommen! = 1 Ergebnis für die Zwecke Ihrer Bewerbung ;-).
Bevor Sie dies als unmöglich abschreiben, sollten Sie sich den Quellcode des Befehls lsof ansehen .
Es kann Einschränkungen geben, aber lsof scheint in der Lage zu sein, den Dateideskriptor und den Dateinamen zu bestimmen. Diese Informationen sind im Dateisystem / proc vorhanden, sodass es möglich sein sollte, von Ihrem Programm aus darauf zuzugreifen.
Sie können fstat () verwenden, um den Inode der Datei nach struct stat abzurufen. Mit readdir () können Sie dann den gefundenen Inode mit dem in einem Verzeichnis vorhandenen (struct dirent) vergleichen (vorausgesetzt, Sie kennen das Verzeichnis, andernfalls müssen Sie das gesamte Dateisystem durchsuchen) und den entsprechenden Dateinamen finden. Böse?
Unmöglich. Ein Dateideskriptor kann mehrere Namen im Dateisystem haben oder überhaupt keinen Namen.
Bearbeiten: Angenommen, Sie sprechen von einem einfachen alten POSIX-System ohne betriebssystemspezifische APIs, da Sie kein Betriebssystem angegeben haben.