0

Linux、またはより一般的には十分にPOSIXに準拠したシステムを想定して、指定された名前のファイルを開くことが成功するかどうかをチェックする既製の方法はありますか?最も楽観的に私はと同じプロトタイプを持つ関数の実装を探していますopen(2)

int test_open(const char *pathname, int flags);

open(2)これは、同じパラメータを使用したシステムコールの予想される成功または失敗に応じて結果を返しますが、実際にはファイルを作成したり開いたりすることはありません。適切にライセンスされた(プロプライエタリソフトウェアプロジェクトで再利用可能な)オープンソースである必要があります。

open(2)マニュアルページには、open(2)失敗する多くの理由がリストされています。1つのerrno値で複数の理由をデコードできますが、errnoLinuxとPOSIXでは異なります。しかし、それにもかかわらず大まかに言えば:

  1. 一般に、によって項目化された次のケースerrnoが最も関連性があると思います:、、、、、(POSIXとLinuxの両方)。EACCESSEEXISTENOENTEISDIRENOTDIR
  2. それほど重要ELOOPEMFILEはありENFILEません:、、、、、、、、、、、、、(POSIXは追加しENAMETOOLONGます)。ENODEVENXIOEOVERFLOWEPERMEROFSETXTBSYEWOULDBLOCKEAGAIN
  3. 無関係(より一時的な状態):、、(ENOMEMPOSIXは、を追加EINTRします)。ENOSPCEIOENOSR

(現在、のオンラインPOSIXマニュアルページをすばやく見つけることができませんopen()。LinuxマシンにインストールされているPOSIXマニュアルページを個人的に参照しています。オンラインリンクが見つかったら、質問を編集します。)

背景と期待:私のアプリケーション/システム構成アーキテクチャでは、入力値を永続的に保存する前に検証する必要があります。検証と保存の手順が実行された後でのみ、ファイルは書き込みに使用されます。不正な値を受け入れることは非常に不便です(また、不正なファイルパスを使用するように実際に変更しようとすると、操作が妨げられます)。この特殊なケース(100を超える構成値の1つにすぎません)を例外にすることはできません。

open()ファイル( includeのフラグ)を作成して、検証に副作用を導入したくないO_CREAT私が探しているチェックは、最も一般的なケースでは100%確実に実装できないことは明らかです。これが、考えられるエラー状態を3つのグループに分類する根本的な理由です。ディレクトリのアクセス許可、ディレクトリの存在、ファイルを開くのを妨げる同じ名前の何かがすでに存在するかどうか、ファイル名が意味をなすかどうか(私のグループ1の条件)を分析することで、非常に知識に基づいた推測を行うことができます。(グループ2は、シンボリックリンクの数、ファイル記述子の制限、名前の長さの制限、O_NOATIMEアクセス許可、ファイルシステムの書き込み可能性、およびおそらくEWOULDBLOCKPOSIXをチェックします。EAGAINケースは実行できますが、実行するのがより面倒で、おそらく移植性が低く、それらを分類する理由がそれほど重要ではない悪の入力がない限り、発生する可能性は低いと予想されます)。

PS今、私のプログラミング言語であるタグを追加しましcたが、言語はあまり関連性がありません。

4

1 に答える 1

3

(Jiteがコメントしたように)他のプロセスが環境を変更した可能性があるため(たとえば、親ディレクトリを削除したり、ファイルシステムをいっぱいにしたり、ディスククォータを超えたりしたなど)、これを行うためのフェイルプルーフの方法はありません。test_openそして、さらにopenまたはcreatsyscall。または、ディスク(またはファイルシステムを含むメディア(USBスティックなど))が焼けているか、プラグが抜かれている可能性があります。

結果を確認し、失敗したときにopen使用することをお勧めします。errno

access以前にいくつかのことを確認するために使用できます。しかし、失敗を防ぐ方法がないので、なぜわざわざするのですか?

realpath(3)関数を使用してファイルパスのディレクトリ部分を検証する場合があります....しかし、それが役に立たない場合でも、他のプロセスによって、ユーザーtest_openと実際のディレクトリの間のディレクトリが作成または削除された可能性があります。open

于 2013-02-19T11:43:43.080 に答える