質問

新しい記述子がファイルテーブル内の同じ内部ファイル構造/エントリを共有しないように、既存のファイル記述子から新しいファイル記述子を作成するにはどうすればよいでしょうか?特に、ファイル オフセット (およびできればアクセス許可、共有、モード) などの属性は、新しいファイル記述子と古いファイル記述子の間で共有すべきではありません。

Windows と Linux の両方で、 dup() ファイル記述子が複製されますが、両方の記述子は依然としてプロセスのファイル テーブル内の同じファイル構造を指します。いずれかの記述子をシークすると、他の記述子の位置も調整されます。

注記

それ以来、Windows と Linux の両方について回答を受け取りましたが、質問の調整が少し頻繁になりすぎたため、人々が回答するのが難しくなりました。投票を調整して、両方の Windows をカバーする最もクリーンな回答を受け入れます そして リナックス。皆さんに申し訳ありませんが、私はまだ SO パラダイムに慣れていません。素晴らしい回答をありがとうございました!

役に立ちましたか?

解決

つまり、基本的に、本当に必要なのは、ファイル記述子を与えて、基本的に同じファイルをもう一度開いて、別の位置、共有、モードなどを取得することです。そして、これを Windows で実行したいとします (「ファイル記述子」は基本的に外部オブジェクトであり、OS によって直接使用されるものではありません)。 または ランタイムライブラリはまったくありません。

驚くべきことに、そこには、 少なくとも MS VC++ ではそれを行う方法があります。2 つのステップを除くすべてのステップでは Win32 API のみを使用するため、他のコンパイラ/ライブラリへの移植はかなり合理的であるはずです (ほとんどの場合、これら 2 つの関数のバージョンが提供されていると思います)。これらは、Unix スタイルのファイル記述子をネイティブ Win32 ファイル ハンドルに変換し、ネイティブ Win32 ファイル ハンドルを Unix スタイルのファイル記述子に変換し直すためのものです。

  1. _get_osfhandle() を使用してファイル記述子をネイティブ ファイル ハンドルに変換します
  2. GetFileInformationByHandleEx(FILE_NAME_INFO) でファイルの名前を取得します。1
  3. CreateFile を使用してそのファイルへの新しいハンドルを開きます
  4. _open_osfhandle() を使用してそのハンドルのファイル記述子を作成します。

さあ、出来上がり, 、同じファイルを参照する新しいファイル記述子がありますが、独自の権限、位置などを持ちます。

質問の終わりに向かって、「アクセス許可」も必要であるように聞こえますが、実際には意味がないようです。アクセス許可は、ファイルの開き方ではなく、ファイル自体に付加されるため、ファイルを開いたり再度開いたりしても、ファイルのアクセス許可には影響しません。本当に知りたい場合は、GetFileInformationByHandle を使用して取得できますが、Windows のファイル アクセス許可は Unix の (従来の) ファイル アクセス許可とはかなり異なることに注意してください。Unix にはすべてのファイルに対する所有者/グループ/ワールド権限があり、ほとんどのシステムには ACL もあります (ただし、その動作方法にはさらにバリエーションがあります)。Windows には権限がまったくないか (FAT または FAT32 上のファイルなど)、または ACL (NTFS 上のファイルなど) が使用されていますが、Unix でほとんどの人が慣れ親しんでいる従来の所有者/グループ/ワールド権限に相当するものは何もありません。

おそらく、ファイルが読み取り、書き込み、またはその両方のために開かれたかどうかを参照するために「アクセス許可」を使用している可能性があります。これを取得することは、前述のどれよりもかなり醜いです。問題は、そのほとんどが Win32 ではなくライブラリ内にあるため、コンパイラ間で移植可能に近い方法がおそらくないことです。MS VC++ 9.0 SP1 では (保証されません) どれでも 他のコンパイラ)、これを行うことができます:

#include <stdio.h>

int get_perms(int fd) {
    int i;
 FILE * base = __iob_func();

    for (i=0; i<_IOB_ENTRIES; i++) 
        if (base[i]._file == fd)
            return base[i]._flag;     // we've found our file
    return 0; // file wasn't found.
}

これには洞窟探索が含まれていたため、実際に機能するかどうかを確認する簡単なテストを作成しました。

#ifdef TEST
#include <io.h>

void show_perms(int perms, char const *caption) { 
 printf("File opened for %s\n", caption);
 printf("Read permission = %d\n", (perms & _IOREAD)!=0);
 printf("Write permission = %d\n", (perms & _IOWRT)!=0);
}

int main(int argc, char **argv) { 
 FILE *file1, *file2;
 int perms1, perms2;

 file1=fopen(argv[1], "w");
 perms1 = get_perms(_fileno(file1));
 fclose(file1);

 file2=fopen(argv[1], "r");
 perms2 = get_perms(_fileno(file2));
 fclose(file2);

 show_perms(perms1, "writing");
 show_perms(perms2, "reading");
 return 0;
}
#endif

そして結果は成功を示しているようです:

File opened for writing
Read permission = 0
Write permission = 1
File opened for reading
Read permission = 1
Write permission = 0

次に、返されたフラグを stdio.h で定義されている _IOREAD、_IOWRT、および _IORW に対してテストできます。以前に警告したにもかかわらず、ライブラリのこの部分はかなり安定しているので (確かに保証はできませんが)、大きな変更が実際に行われる可能性はおそらくかなり低いと思われることを指摘しておきます。

ただし、逆の方向には基本的にチャンスはありません まったく 他のライブラリでも動作するということです。それ できた MS VC++ をバックエンドとして使用する Intel、MinGW、Comeau など、MS ライブラリを使用する他のコンパイラでも動作します (ただし、確実に動作するという保証はありません)。これらの中で、最も機能する可能性が高いのは Comeau で、最も可能性が低いのは MinGW だと思います (ただし、これは単なる推測です。どれも動作しない可能性が十分にあります)。

  1. 再頒布可能ファイルが必要です Win32 FileID API ライブラリ

他のヒント

ですから、私はもう少し、この上に読んでお勧めします。 dup()と関連する関数は、開いているファイルのテーブル内の同じエントリにファイルディスクリプタ・テーブル・ポインティングに重複する値を作成するのに役立ちます。これは、を意図したを同じオフセットすることです。あなたがopen()を呼び出す場合は、開いているファイルテーブルに新しいエントリを作成します。

これは、別のオープンファイルテーブルにオフセットしているファイル記述子とその新しいファイル・ディスクリプタの複製を作成するために、任意の意味をなさない(これは単語が意味を「複製」何矛盾するよう)。

私はあなたの質問が実際に何であるかわかりません。私はそれが重複したと同じものではありません、意味します。あなたは読み取ることができます:

/proc/self/fd/[descriptor]

とそのファイルディスクリプタを開くために使用された文字列を取得します。クマ心の中で、これはあなたが実際に再びopen()を呼び出すのあなたの観察に注意そのうちのいくつかは、いくつかの落とし穴を、提供することができます。

たぶん、あなたはもう少し説明することができ、私は助けに更新しようとすることができます。

なぜ、あなただけの窓の上に(オープン)またはのCreateFile()で二回目のファイルを開けないのですか?これは、あなたに異なるアクセス権のすべての自由を与えるとオフセットを分離します。

もちろんこれは、あなたが排他的にファイルを開くことができないという欠点があるが、それは非常に簡単にあなたの問題を解決します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top