号
それはfstat
がシンボリックリンクをたどることは事実ではありません。代わりに、open
がシンボリックリンクに続きます。 fstat
になると、遅すぎて情報がなくなります。
なぜあなたが知る必要があるのか、私たちはその問題を解決することができます。 (別の質問を開きます。)ファイルがどのように動作するか
:
をここではいくつかの擬似C /シェルコードは次のとおりです。
system("echo 'Hello, World!' >A.txt");
system("ln A.txt B.txt");
system("ln -s A.txt C.txt");
fdes = open("C.txt");
unlink("A.txt");
unlink("C.txt");
data = read(fdes);
write(stdout, data);
結果:あなたのプログラムを印刷"Hello, world!"
。
+--Application--+ +--Kernel--+ +-------Disk-------+
| | | | | |
| fdes --------------> file ---------> inode #973 <-------+
| | | | | "Hello World!" | |
+---------------+ +----------+ | | |
| directory ---------+
| "B.txt" |
| |
+------------------+
カーネルに関する限り、ファイルのオープンは "inode#973"です。カーネルメモリのデータ構造には、現在の位置などの追加情報がありますが、パスがわかりません。カーネルはその情報を知ることは期待されていません。
パスが何であるかをカーネルに問い合わせた場合、はとなります。「あなたはB.txtを持っています」と表示されます。しかし、あなたは "B.txt"を開いたことはなく、 "A.txt"へのシンボリックリンクである "C.txt"を開いて、 "A.txt"と "C.txt"の両方を削除しました。始める)。
単純なアナロジーは:
あなたは古い友人からの電話を取得します。彼は、「私は電話帳であなたの番号を調べましたか、私はそれを覚えましたか、誰かにあなたの番号を尋ねなければなりませんでしたか?
あなたは答えを知る方法がありません。あなたが知っているのは、誰がラインの反対側にいるのかです。開いているファイルには、名前(ハードリンクやシンボリックリンク)の情報が格納されていないのと同じように、アクセス権とデータに関する情報だけが格納されています。
解決策:lstat
(はい、競合状態があります)を使用してください。ファイルを自分で開かなかった場合(親プロセスから取得した場合やソケットで取得した場合など)、シンボリックリンクで開かれたかどうかを知ることは多かれ少なかれです。
'fstat'と' lstat'の両方を使い、inodeを比較するのはどうですか? –
シンボリックリンクは、最終的に開くファイルです。 fdからそれを開くためにどのパスが使われているのか分かりません。(もはや存在しないかもしれません) –
@KerrekSB: 'lstat'関数はシンボリックリンクのinodeを返しますが、これは役に立ちません。 O_NOFOLLOW以外に –