web-dev-qa-db-fra.com

Récupère le nom de fichier du descripteur de fichier en C

Est-il possible d’obtenir le nom de fichier d’un descripteur de fichier (Linux) en C?

93
adk

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.

107
bdonlan

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.

77
zneak

Sous Windows, avec GetFileInformationByHandleEx , en passant FileNameInfo , vous pouvez récupérer le nom du fichier.

23
Martin v. Löwis

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

15
Alex Martelli

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.

8
Duck

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?

6
PetrosB

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.

3
Tyler McHenry