2012-12-13 9 views
8

質問Getting Filename from file descriptor in Cの変形です。これはLinuxに関するものです。ファイルディスクリプタから名前を変更しますか?

通常のファイルを参照するファイルディスクリプタがある場合は、ファイルディスクリプタに新しいファイル名を付けることでファイルディスクリプタを「保存」できますか?私はrename(2)やlink(2)と同様のものを探していますが、ファイル名の代わりにファイル記述子を入力として受け入れます。

rename(2)とlink(2)の問題は、ファイルデリミッタからファイル名に移動しようとしても失敗する可能性があることです。開かれたファイルディスクリプタがすでにリンクされていないファイルを参照している場合について、より正確に考えています。この場合、ファイルにはそれ以上の名前はありません。ファイル記述子を閉じるときにファイルが削除されないようにする方法はないようです。しかし、私は間違っていますか? PosixやLinux APIを使って、名前を付け直すことはできますか?

更新:実際にLinux上で削除されたファイルの内容は、壊れたシンボリックリンクのように見えますが、/proc/<pid>/fd/<fd>にあります。このようなファイルを再マテリアライズするためにlink(2)やln(1)を使うことはできませんが、デバイス間のリンクをしようとしていると思っています。

+0

ただし、fd/ファイルからコンテンツをコピーできます。あなたはそれを再リンクすることはできません愚か。 –

+1

本質的に同じ質問、ここでは良い答え:http://stackoverflow.com/q/4171713/4421 – pixelbeat

答えて

3

質問がlinux、およそlinux> 2.6.39については、AT_EMPTY_PATHフラグを指定してlinkatコマンドを使用して、ファイル記述子に名前を付けることができます。 manページ(http://man7.org/linux/man-pages/man2/link.2.html)を参照してください

linkat(fd,"",destdirfd,"filename",AT_EMPTY_PATH); 

警告:ゼロこののリンクカウントを持つファイルの場合

    • あなたはAT_EMPTY_PATHの定義を取得するために_GNU_SOURCEを定義する必要があり、
    • は仕事に保証するものではありません。私はマニュアルページがこれについて何を言っているのか分かりません。私の推測では、ファイルにゼロのリンクカウントがある場合、ファイルシステムがクラッシュすると矛盾を避けるために、ファイルシステム上でinodeがすでに削除されていると思います。
    • もちろん、古いファイルがターゲットディレクトリの同じファイルシステムになければ、私はそれが動作するとは思っていません。

    これが失敗した場合は、新しいファイルを作成し、sendfileを使用して、それ以上のコンテンツをコピーするよりも、他の可能性(エラーが省略チェック、可能なエラー値のために、各関数のmanページを参照してください)持っていない:

    struct stat s; 
    off_t offset = 0; 
    int targetfd = open("target/filename", O_WRONLY | O_CREAT | O_EXCL); 
    fstat(fd,&s); 
    sendfile(targetfd,fd,&offset, s.st_size); 
    
  • +0

    ありがとう!それはまだ完全に一般的ではありませんが、それは「正しい」方向への一歩です。私が求めていることが本当に正しいか、必要であろうと暗示しているわけではありません。 (私の元々の質問は好奇心の問題でした) –

    +0

    Linuxは本当に "このファイル記述子に名前をつける"一般的なAPIを助けると思います。ファイル記述子が普通のファイルを参照していないか参照していない場合にのみ失敗します。別のパーティションにあるファイルまた、ソースファイルにファイルシステム名がある場合にのみ、既存のファイルをアトミックに置き換える方法があります。これは、 'rename'を使用することで可能になりました。 – pqnet

    2

    質問:ファイル記述子を取る仮想システムコールfrenameが存在し、ファイルに複数の名前(ハードリンク)がある場合、このシステムコールがファイル記述子で使用されたときに移動/名前変更される名前このファイルを参照していますか?

    この質問に対する良い答えはありません。これが、このシステムコールが存在しない理由の1つです。

    renameは、ファイル(inode)へのポインタであるディレクトリエントリを処理します。開いているファイル記述子は、特定のディレクトリエントリには関連付けられておらず、ファイル自体(iノード)にのみ関連付けられています。その観点から、あなたが求めているシステムコールは実際には意味をなさない。 inodeを指し示すディレクトリエントリに戻るための移植可能な方法はありません(また、複数のinodeがあるかもしれません)。いくつかのオペレーティングシステムでは、この後方リンクを見つけるためのさまざまな移植不可能な手段が提供されていますが、常に結果を出すことが保証されているかどうかは保証されていません(通常は保証されません)。しかし、これらの手段は、複数のものがある場合、私の知る限りでは、あなたが探しているもののようなシステムコールにそれらのどれも拡張されていません。

    +0

    混乱のために申し訳ありません。これは私にはっきりと分かったので、私は 'flink()'を提案しています。私は 'frename()'について言及すべきではありません。 –

    +2

    'flink()'は本当にいいですね。これは、0のリンクを持っているがまだ存在するファイルを再接続することを可能にする唯一のことです。しかし、ええ...それは私が知っているすべてのOSの下に存在しません。 – Celada

    関連する問題