2017-01-08 5 views
2

アトミックに "File2が存在しない場合File1の名前をFile2に変更します。そうでなければエラーを返します"という非プラットフォーム固有の方法はありますか? File2が存在するかどうかを確認してファイル名を変更することはできますが、他のプロセスがチェックとrename()の間にFile2を作成すると競合が発生する可能性があります。クロスプラットフォームのrenameat2()rename-if-not-exists機能

Linuxでは、RENAME_NOREPLACEフラグが設定されている場合、これを正確に実行するrenameat2()機能があります。残念ながら、マンページによれば、

renameat2()はLinux固有のものです。

すべてのlibc実装がこの呼び出しをサポートしているのか、glibcだけをサポートしているのかはわかりません。

私の用途では、同じディレクトリ内で名前を変更するだけで十分です。別のパスに移動する必要はありません。

これは潜在的にhttps://stackoverflow.com/a/230581/5562035Atomically swap contents of two files on Linux

+0

どのような意味で原子ですか?とりわけ、 'rename()'と 'renameat()'のLinuxドキュメントでは、 "oldpathとnewpathの両方がファイル名を変更しているウィンドウが存在するでしょう。 –

+0

常識を使用してください。 –

+0

ターゲットファイルが存在するかどうかのチェックと、別のプロセスがターゲットファイルを作成する際の名前変更の間には、時間枠が存在しないはずです。この条件がなければ、 'if(!file_exists(path_2)){rename(path_1、path_2)}' – buggy3

答えて

2

に関連しては、「ファイル2が存在しない場合はそれ以外の場合はエラーを与える、ファイル2にファイル1の名前を変更する」原子を行うための非プラットフォーム固有の方法はありますか?

C標準ライブラリは、ファイル名を変更するだけrename()を提供し、標準ではその機能については、これを言う:「という文字列で指定されたファイルは、newによって指された場合は前rename関数の呼び出しに存在しているが、動作は実装定義です。したがって、「非プラットフォーム固有」が「C標準で指定されている」と解釈された場合は、そのようなメカニズムはありません。私たちはPOSIXによって指定された施設をできるようにする「非プラットフォーム固有」の範囲を拡大した場合

、しかし、あなたは、link()に頼ることができ

がアトミック既存のファイルの新しいリンクを作成するものと

ファイルのリンク数は1だけインクリメントされる。 [...第2引数]が既存のディレクトリエントリに解決されるかシンボリックリンクを参照する場合、 [および] は失敗します。

したがって、あなたは指定されたパス名が既存のファイルまたはシンボリックリンクを指定して、成功時に元のリンクを削除すると失敗し、最初のファイルに新しい(ハード)リンクを作成することができます。

あなたが興味を持っている最も顕著ではないPOSIXプラットフォームはWindowsでしょう。私は、あなたがWindows上で尋ねることを何らかの方法で行うかどうかは不明ですが、存在する場合、条件付きコンパイルを使用してPOSIXまたはWindowsのいずれかの実装を選択するラッパー関数を作成することを検討できます。

関連する問題