これに対するフォローアップの質問として、ファイルに追加して、存在しない場合は作成したい場合の@cafの回答から構築される別のアプローチを考えました。name
これが私が思いついたものです:
- file と同じファイルシステムのシステム一時ディレクトリに、モード 0700 の一時ディレクトリを作成します
name
。 ファイルname
を読み取り専用で開きますO_CREAT
。name
シンボリックリンクであればOSが追従する場合があります。一時ディレクトリに一時ファイルを作成し、 to fileによって作成された一時ファイルを試行するために使用します。mkstemp
rename
mkstemp
name
ファイルname
を読み取り専用で開きますO_CREAT | O_EXCL
。name
一時ディレクトリ内の一時的な名前へのハード リンクの作成を繰り返し試みます。link
「リンクターゲットが存在します」(errno) 以外のエラーが原因で呼び出しが失敗した場合EEXIST
は、終了します。(誰かがやってきて、 のファイルを削除したのかもしれません。誰name
にもわかりません)。- (ハードリンク)で使用
lstat
します。temp_name
の場合S_ISLNK(lst.st_mode)
、終了します。 open
temp_name
書き込みおよび追加用 (O_WRONLY | O_APPEND
)。- すべて書き出す。ファイル記述子を閉じます。
unlink
ハードリンク。- 一時ディレクトリを削除します。
(ちなみに、これはすべて、私が取り組んでいるオープン ソース プロジェクトのものです。このアプローチの実装のソースは、ここで確認できます。)
この手順は、シンボリック リンク攻撃に対して安全ですか? たとえば、悪意のあるプロセスが、チェックname
中に inode が通常のファイルを表していることを確認し、その inode を、ハード リンクが新しいシンボリック リンクを指しているシンボリック リンクにすることは可能ですか?lstat
temp_name
悪意のあるプロセスが影響を与えることはできないと想定していますtemp_name
。
編集: link
ターゲットを上書きしないため、「プレースホルダー」の一時ファイルを作成することは、私がやりたかったことではありません。その後、コードを更新し、上記の手順を更新しました。
EDIT2:この問題name
の影響を受けやすいとは思わないファイルが存在しない場合は、ステップ 2 の代替手順を使用してファイルを作成しています。
EDIT3:一時的な空の通常のファイルの名前を に変更するよりもさらに優れています。これには、リンクを解除してからname
名前を変更する効果もあります。name
O_RDONLY | O_CREAT | O_EXCL
状態の POSIX 標準open
:
O_EXCL
とO_CREAT
が設定され、path
シンボリック リンクに名前が付けられている場合、シンボリック リンクの内容に関係なく、open()
失敗して に設定さerrno
れます。EEXIST