Est-il possible d'obtenir le nom de fichier d'un descripteur de fichier (Linux) en C?
Est-il possible d'obtenir le nom de fichier d'un descripteur de fichier (Linux) en C?
Réponses:
Vous pouvez utiliser readlink
le /proc/self/fd/NNN
NNN est le descripteur de fichier. Cela vous donnera le nom du fichier tel qu'il était quand il a été ouvert - cependant, si le fichier a été déplacé ou supprimé depuis, il peut ne plus être exact (bien que Linux puisse suivre les renommés dans certains cas). Pour vérifier, stat
le nom du fichier donné et fstat
la vous avez fd, et assurez - vous st_dev
et st_ino
sont les mêmes.
Bien sûr, tous les descripteurs de fichiers ne font pas référence à des fichiers, et pour ceux-ci, vous verrez des chaînes de texte étranges, telles que pipe:[1538488]
. Puisque tous les noms de fichiers réels seront des chemins absolus, vous pouvez déterminer lesquels sont assez facilement. De plus, comme d'autres l'ont noté, les fichiers peuvent avoir plusieurs liens physiques pointant vers eux - cela ne rapportera que celui avec lequel ils ont été ouverts. Si vous voulez trouver tous les noms d'un fichier donné, il vous suffira de parcourir tout le système de fichiers.
fd
serait une telle référence), le numéro d'inode ne peut pas être réutilisé. Tout logiciel utilisant un numéro d'inode après avoir fermé le fichier ou avant de l'ouvrir est intrinsèquement soumis à des conditions de concurrence.
setuid()
astuces, il est possible que /proc/self/fd
votre processus ne soit pas accessible. Voir: permalink.gmane.org/gmane.linux.kernel/1302546
J'ai eu ce problème sur Mac OS X. Nous n'avons pas de /proc
système de fichiers virtuel, donc la solution acceptée ne peut pas fonctionner.
Nous avons, à la place, une F_GETPATH
commande pour fcntl
:
F_GETPATH Get the path of the file descriptor Fildes. The argu-
ment must be a buffer of size MAXPATHLEN or greater.
Donc, pour obtenir le fichier associé à un descripteur de fichier, vous pouvez utiliser cet extrait de code:
#include <sys/syslimits.h>
#include <fcntl.h>
char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
// do something with the file path
}
Comme je ne me souviens jamais où MAXPATHLEN
est défini, j'ai pensé que les PATH_MAX
limites système seraient bien.
getsockname
.
Dans Windows, avec GetFileInformationByHandleEx , en passant FileNameInfo , vous pouvez récupérer le nom du fichier.
Comme le souligne Tyler, il n'y a aucun moyen de faire ce dont vous avez besoin "directement et de manière fiable", car un FD donné peut correspondre à 0 noms de fichiers (dans divers cas) ou> 1 (plusieurs "liens durs" est la façon dont cette dernière situation est généralement décrite ). Si vous avez encore besoin de la fonctionnalité avec toutes les limitations (sur la vitesse ET sur la possibilité d'obtenir 0, 2, ... résultats plutôt que 1), voici comment vous pouvez le faire: d'abord, fstat le FD - cela vous dit , dans le résultat struct stat
, sur quel périphérique le fichier vit, combien de liens durs il a, s'il s'agit d'un fichier spécial, etc. Cela peut déjà répondre à votre question - par exemple, si 0 lien dur, vous SAVEZ qu'il n'y a en fait pas de nom de fichier correspondant sur disque.
Si les statistiques vous donnent de l'espoir, alors vous devez «parcourir l'arborescence» des répertoires sur l'appareil concerné jusqu'à ce que vous trouviez tous les liens en dur (ou juste le premier, si vous n'en avez pas besoin de plus d'un et n'importe lequel le fera. ). Pour cela, vous utilisez readdir (et opendir & c bien sûr) en ouvrant récursivement les sous-répertoires jusqu'à ce que vous trouviez dans un struct dirent
ainsi reçu le même numéro d'inode que vous aviez dans l'original struct stat
(à quel moment si vous voulez le chemin complet, plutôt que juste le nom, vous devrez parcourir la chaîne de répertoires en arrière pour la reconstruire).
Si cette approche générale est acceptable, mais que vous avez besoin d'un code C plus détaillé, faites-le nous savoir, ce ne sera pas difficile à écrire (bien que je préfère ne pas l'écrire si c'est inutile, c'est-à-dire que vous ne pouvez pas supporter les performances inévitablement lentes ou le possibilité d'obtenir! = 1 résultat pour les besoins de votre candidature ;-).
Avant d'écrire cela comme impossible, je vous suggère de regarder le code source de la commande lsof .
Il peut y avoir des restrictions mais lsof semble capable de déterminer le descripteur et le nom du fichier. Ces informations existent dans le système de fichiers / proc, il devrait donc être possible d'accéder à partir de votre programme.
Vous pouvez utiliser fstat () pour obtenir l'inode du fichier par struct stat. Ensuite, en utilisant readdir (), vous pouvez comparer l'inode que vous avez trouvé avec ceux qui existent (struct dirent) dans un répertoire (en supposant que vous connaissez le répertoire, sinon vous devrez rechercher tout le système de fichiers) et trouver le nom de fichier correspondant. Méchant?
Impossible. Un descripteur de fichier peut avoir plusieurs noms dans le système de fichiers ou ne pas avoir de nom du tout.
Edit: En supposant que vous parlez d'un ancien système POSIX, sans API spécifiques au système d'exploitation, puisque vous n'avez pas spécifié de système d'exploitation.