1

私が欲しいもの:

 void printFname(FILE * f)
    {    
        char buf[255];
        MagicFunction(f,buf);
        printf("File name: %s",buf);
    }

だから、必要なのは「MagicFunction」だけですが、残念ながらそのようなものは見つかりませんでした...

OS ライブラリを使用して実装する方法はありますか? (windows.h、cocoa.h、posix.h など)

4

4 に答える 4

8

そのような機能はありません。ファイル名が存在しないか、またはFILE *. Unix では、ファイルの名前が変更または削除された後も、プログラムは引き続きファイルへの参照を保持できます。これはFILE *、名前のない があることを意味します。または、ファイルにさらにハード リンクを作成することもできます。これは、ファイルに複数の名前を付けることができることを意味します。あなたはどちらを選びますか?さらに混乱させるために、そのファイルを含むディレクトリにファイルシステムをマウントすることにより、ファイルを一時的に非表示にすることができます。ファイルは元のパス名でディスク上に残りますが、マウントによって隠されているため、そのパスではファイルにアクセスできなくなります。

FILE *ファイルシステム上のファイルにまったく対応していない可能性もあります。通常はそうですが、 を使用して任意のファイル記述子から作成できますfdopen()。そのファイル記述子は、パイプ、ソケット、またはディスク上にパスを持ったことのないその他のファイルのようなオブジェクトである可能性があります。C ライブラリの一部のバージョンでは、(たとえば、fmemopen()glibc で) 文字列ストリームを開くことができるため、FILE *実際にはメモリ バッファーに対応します。

名前が気になる場合は、ファイルを開いたときの名前を記録しておくことをお勧めします。

ファイル名を取得するためのハックな方法がいくつかあります。これをデバッグまたは情報提供の目的で使用している場合は、十分な場合があります。FILE *ファイル記述子はファイルを参照する低レベルの方法であるため、これらのほとんどは、ではなくファイル記述子で操作する必要があります。ファイル記述子を取得するには、 で実行fileno()します。FILE *ファイル記述子が関連付けられていない場合は、必ずエラーをチェックしてくださいFILE *

Linux では、ファイル記述子のreadlink()場所"/proc/self/fd/fileno"で実行できます。filenoこれにより、ファイルが開かれたときにファイルが持っていたファイル名、またはソケットやinotifyハンドルなど、他の種類のファイル記述子を示す文字列が表示されます。FreeBSD と NetBSD には、Linux スタイルの procfs のエミュレーションを含む Linux エミュレーション レイヤーがあります。Linux 互換の procfs をマウントすれば、これらでこれを実行できるかもしれませんが、テストに使用できるものはありません。

Mac OS X では、/proc/self/fd. 元のファイル名を見つけることは気にしないが、ファイルを参照する他のファイル名が機能する場合 (別のプログラムに渡すことができるなど)、次のように作成できます/.vol/deviceid/inode。たとえば、/.vol/234881030/281363. これらの値を取得するfstat()には、ファイル記述子に対して実行し、結果に対してst_devandを使用します。st_inostruct stat

Windows では、ファイルとファイル システムの動作が Unix とはまったく異なります。どうやら、Windows ではファイルをその名前に戻すことができるようです。Windows Vista 以降では、単純に を呼び出すことができますGetFinalPathNameByHandle()。これにはHANDLE;が必要です。HANDLEファイル記述子からを取得するには、 を呼び出します_get_osfhandle()Windows Vista より前のバージョンでは、この記事で説明されているように、もう少し作業を行う必要があります。前者は警告付きで動作する場合がありますが、Windows ではfileno()という名前であることに注意してください。_fileno()

ハッキングの領域にさらに踏み込むと、さらにいくつかのテクニックを使用できます。にシェルアウトするlsofか、パス名の解決に使用するコードを抽出することができます。lsof実際には、カーネル メモリを直接調べて、カーネルの名前キャッシュから情報を抽出します。これには、lsofFAQで概説されているいくつかの制限があります。もちろん、これを行うには、直接または suid/sgid バイナリを使用して、root または同等の権限が必要です。

最後に、開いているファイルに一致する 1 つまたは複数のファイル名を見つけるための移植可能ではあるが遅い解決策として、ファイル記述子を使用してデバイスと inode 番号を見つけ、次のファイルが見つかるまですべてfstat()のファイルを再帰的にトラバースします。stat()一致するデバイスと inode 番号。上記の注意事項を思い出してください。一致するファイルが見つからない場合や、複数の一致するファイルが見つからない場合があります。また、一致するファイルが見つからない場合でも、ファイルはまだそこにあるが、マウント ポイントによって隠されている可能性があります。そしてもちろん、競合状態が発生する可能性があります。階層をたどっているときにファイルが見えないように、何かがファイルの名前を変更する場合があります。

于 2012-12-05T03:23:59.217 に答える
2

そのような標準機能はありません。

于 2012-12-05T03:22:46.113 に答える
0

あなたfopen()自身ですか?その場合は、FILE *ファイル名のハッシュ テーブルを自分で管理してください。

そうでなければ、一般的には不可能です。

于 2012-12-05T03:30:25.707 に答える
0

windows.h,coca.h や unistd.h にもそのような機能はないと思います。ほとんどの場合、あなたはそれを自分で書いています。作るだけ

struct myFile {
FILE *fh;
char *filename;
}

と等しいアドレスを探して、そのような構造を の配列struct myFileおよびの配列に保持します。MagicFunction(f,b)f

于 2012-12-05T03:34:59.847 に答える