Cでファイル記述子(Linux)のファイル名を取得することは可能ですか?
8 に答える
NNNがファイル記述子である場所でreadlink
使用できます。/proc/self/fd/NNN
これにより、開いたときのファイルの名前がわかりますが、それ以降にファイルが移動または削除された場合は、正確でなくなる可能性があります(ただし、Linuxは名前の変更を追跡できる場合があります)。確認するにstat
は、指定されたファイル名とfstat
使用しているfdを確認しst_dev
、とst_ino
が同じであることを確認します。
もちろん、すべてのファイル記述子がファイルを参照しているわけではありません。ファイル記述子には、などの奇妙なテキスト文字列が表示されpipe:[1538488]
ます。実際のファイル名はすべて絶対パスになるため、どれで十分かを簡単に判断できます。さらに、他の人が指摘しているように、ファイルはそれらを指す複数のハードリンクを持つことができます-これはそれが開かれたものだけを報告します。特定のファイルのすべての名前を検索する場合は、ファイルシステム全体をトラバースする必要があります。
Mac OS Xでこの問題が発生しました。/proc
仮想ファイルシステムがないため、受け入れられたソリューションは機能しません。
代わりに、次のF_GETPATH
コマンドがありfcntl
ます。
F_GETPATH Get the path of the file descriptor Fildes. The argu-
ment must be a buffer of size MAXPATHLEN or greater.
したがって、ファイル記述子に関連付けられたファイルを取得するには、次のスニペットを使用できます。
#include <sys/syslimits.h>
#include <fcntl.h>
char filePath[PATH_MAX];
if (fcntl(fd, F_GETPATH, filePath) != -1)
{
// do something with the file path
}
どこで定義されているか覚えていないので、syslimitsからは問題ないとMAXPATHLEN
思いました。PATH_MAX
Windows では、GetFileInformationByHandleExでFileNameInfoを渡すと、ファイル名を取得できます。
タイラーが指摘しているように、特定の FD が 0 個のファイル名 (さまざまな場合) または > 1 個 (複数の「ハード リンク」が後者の状況を一般的に説明する方法である) に対応する可能性があるため、必要なことを「直接的かつ確実に」実行する方法はありません。 )。すべての制限 (速度、および 1 ではなく 0、2、... の結果が得られる可能性) を備えた機能が引き続き必要な場合は、次の方法で実行できます。最初に、FDをfstatします。 、結果struct stat
の 、ファイルが存在するデバイス、ハードリンクの数、特別なファイルかどうかなど。これはすでにあなたの質問に答えているかもしれません-たとえば、ハードリンクが0の場合、実際には対応するファイル名がないことがわかりますディスク上。
統計から希望が得られる場合は、すべてのハード リンクが見つかるまで、関連するデバイスのディレクトリの「ツリーをたどる」必要があります (または、複数必要なく、いずれかが必要な場合は最初のリンクのみ)。 )。そのためには、readdirstruct dirent
(そしてもちろん opendir &c) を使用して再帰的にサブディレクトリを開き、このようにして受け取った元の inode 番号と同じ inode 番号を見つけますstruct stat
(名前だけでなくパス全体が必要な場合は、その時点で、再構築するには、ディレクトリのチェーンを逆方向にたどる必要があります)。
この一般的なアプローチが受け入れられるが、より詳細な C コードが必要な場合は、私たちに知らせてください。書くのは難しくありません (ただし、役に立たない場合は書きたくありません。つまり、必然的に遅いパフォーマンスに耐えられなかったり、あなたのアプリケーションの目的のために != 1 の結果を得る可能性;-)。
これを不可能として書き留める前に、 lsofコマンドのソースコードを確認することをお勧めします。
制限があるかもしれませんが、lsofはファイル記述子とファイル名を決定できるようです。この情報は/procファイルシステムに存在するため、プログラムから取得できるはずです。
fstat() を使用して、struct stat によってファイルの inode を取得できます。次に、 readdir() を使用して、見つけた i ノードをディレクトリに存在するもの (struct dirent) と比較し (ディレクトリを知っていると仮定します。そうでない場合は、ファイルシステム全体を検索する必要があります)、対応するファイル名を見つけることができます。汚い?
不可能。ファイル記述子は、ファイルシステムで複数の名前を持つ場合もあれば、名前がまったくない場合もあります。
編集:OSを指定しなかったため、OS固有のAPIを使用せずに、普通の古いPOSIXシステムについて話していると仮定します。