Est-il possible d’obtenir le nom de fichier d’un descripteur de fichier (Linux) en C?
Vous pouvez utiliser readlink
sur /proc/self/fd/NNN
où NNN est le descripteur de fichier. Cela vous donnera le nom du fichier tel qu'il était à l'ouverture du dossier. Toutefois, si le fichier a été déplacé ou supprimé depuis, il risque de ne plus être précis (bien que Linux puisse suivre les renommements dans certains cas). Pour vérifier, stat
le nom de fichier donné et fstat
le fd que vous avez, et assurez-vous que st_dev
et st_ino
sont identiques.
Bien sûr, tous les descripteurs de fichiers ne font pas référence à des fichiers, et pour ceux-ci, certaines chaînes de texte étranges, telles que pipe:[1538488]
. Étant donné que tous les noms de fichiers réels seront des chemins absolus, vous pouvez facilement les identifier. En outre, comme d’autres l’ont déjà noté, plusieurs fichiers peuvent contenir des liens fixes dans les fichiers - cela ne signalera que celui avec lequel il a été ouvert. Si vous voulez trouver tous les noms pour un fichier donné, il vous suffira de parcourir tout le système de fichiers.
J'ai eu ce problème sur Mac OS X. Nous n'avons pas de /proc
système de fichiers virtuel, la solution acceptée ne peut donc pas fonctionner.
Nous avons plutôt un 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:
#include <sys/syslimits.h>
#include <fcntl.h>
char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
// do something with the file path
}
Puisque je ne me souviens jamais où MAXPATHLEN
est défini, je pensais que PATH_MAX
de syslimits serait bien.
Sous 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 une FD donnée peut correspondre à 0 nom de fichier (dans différents cas) ou à> 1 (plusieurs "liens durs" décrivent généralement cette dernière situation. ). Si vous avez toujours 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 procéder: en premier lieu, fstat le FD - cela vous dit, dans le résultat struct stat
, sur quel périphérique se trouve le fichier, combien de liens physiques il contient, qu’il s’agisse d’un fichier spécial, etc. Cela peut déjà répondre à votre question - par exemple. si 0 lien dur vous saurez qu'il n'existe en fait aucun nom de fichier correspondant sur le disque.
Si les statistiques vous donnent de l'espoir, vous devez alors "parcourir l'arborescence" des répertoires sur le périphérique concerné jusqu'à ce que vous trouviez tous les liens physiques (ou le premier, si vous n'avez pas besoin de plus d'un et que n'importe qui le fera. ). Pour cela, vous utilisez readdir (et opendir & c of course) en ouvrant récursivement les sous-répertoires jusqu’à ce que vous trouviez dans un struct dirent
_ a donc reçu le même numéro d’inode que vous aviez dans l’original struct stat
_ (à ce moment-là, si vous voulez tout le chemin plutôt que le nom, vous devez parcourir la chaîne de répertoires à l’arrière pour le reconstruire).
Si cette approche générale est acceptable, mais que vous avez besoin de code C plus détaillé, dites-le-nous, il ne sera pas difficile de l'é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 la possibilité d'obtenir! = 1 résultat pour les besoins de votre candidature ;-).
Avant d'écrire ceci 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 de fichier et le nom du fichier. Ces informations existent dans le système de fichiers/proc, il devrait donc être possible de les obtenir à 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 trouvé avec ceux qui existent (struct dirent) dans un répertoire (en supposant que vous connaissiez 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.
Éditer: En supposant que vous parlez d’un vieux système POSIX, sans aucune API spécifique au système d’exploitation, puisque vous n’avez pas spécifié de système d’exploitation.