web-dev-qa-db-ja.com

Cのファイル記述子からファイル名を取得する

Cでファイル記述子(Linux)のファイル名を取得することは可能ですか?

93
adk

/proc/self/fd/NNNreadlink を使用できます。ここで、NNNはファイル記述子です。これにより、ファイルが開かれたときの名前がわかりますが、それ以降にファイルが移動または削除された場合、正確ではなくなる可能性があります(Linuxは名前の変更を追跡できる場合もあります)。確認するには、statに指定されたファイル名とfstatにあるfdを確認し、st_devst_inoが同じであることを確認します。

もちろん、すべてのファイル記述子がファイルを参照しているわけではありません。ファイル記述子には、pipe:[1538488]などの奇妙なテキスト文字列が表示されます。実際のファイル名はすべて絶対パスであるため、どれが簡単に十分かを判断できます。さらに、他の人が指摘したように、ファイルはそれらを指す複数のハードリンクを持つことができます-これはそれが開かれたものだけを報告します。特定のファイルのすべての名前を検索する場合は、ファイルシステム全体を走査するだけです。

107
bdonlan

Mac OS Xでこの問題が発生しました。/proc仮想ファイルシステム。したがって、受け入れられているソリューションは機能しません。

代わりに、F_GETPATHfcntlのコマンド:

 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
}

MAXPATHLENがどこで定義されているか覚えていないので、PATH_MAX syslimitsからは問題ありません。

77
zneak

Windowsでは、 GetFileInformationByHandleExFileNameInfo を渡すと、ファイル名を取得できます。

23

Tylerが指摘しているように、特定のFDは0のファイル名(さまざまな場合)または> 1(複数の「ハードリンク」に対応することがあるため、「直接かつ確実に」必要なことを行う方法はありません。 )。すべての制限付きの機能が必要な場合(速度と、1ではなく0、2、...の結果が得られる可能性)、最初に fstat を使用します。 FD-これは、結果のstruct statで、ファイルが存在するデバイス、ハードリンクの数、特殊ファイルかどうかなどを示します。これにより、すでに質問に答えているかもしれません。ハードリンクが0の場合、実際にはディスク上に対応するファイル名がないことがわかります。

統計から希望が得られた場合、すべてのハードリンクが見つかるまで(または、1つ以上必要ない場合はいずれか1つだけが必要な場合は最初のリンクのみ)、関連するデバイス上のディレクトリの「ツリーを歩く」必要があります)。そのために、 readdir (そしてもちろんopendir&c)を使用して、struct direntで見つかるまでサブディレクトリを再帰的に開き、元のstruct statと同じiノード番号を受け取ります(その時点で、名前だけでなくパス全体が必要な場合は、ディレクトリのチェーンを逆方向にたどって再構築する必要があります)。

この一般的なアプローチは受け入れられるが、より詳細なCコードが必要な場合はお知らせください。書くのは難しくありません(役に立たない場合、つまり必然的にパフォーマンスが低下したり、アプリケーションの目的で!= 1の結果を得る可能性;-)。

15
Alex Martelli

これを不可能として書き留める前に、 lsof コマンドのソースコードを確認することをお勧めします。

制限があるかもしれませんが、lsofはファイル記述子とファイル名を決定できるようです。この情報は/ procファイルシステムに存在するため、プログラムから取得できるはずです。

8
Duck

Struct statを使用して、fstat()を使用してファイルのiノードを取得できます。次に、readdir()を使用して、見つかったiノードをディレクトリ内に存在するiノード(struct dirent)と比較し(ディレクトリを知っていると仮定します。そうでない場合は、ファイルシステム全体を検索する必要があります)、対応するファイル名を見つけます。不快な?

6
PetrosB

不可能な。ファイル記述子は、ファイルシステム内で複数の名前を持っている場合もあれば、まったく名前を持たない場合もあります。

編集:OSを指定しなかったため、OS固有のAPIを持たない単純な古いPOSIXシステムについて話していると仮定します。

3
Tyler McHenry