11

Cのファイル記述子からファイル名を取得するという質問の変形。これはLinuxについてです。

通常のファイルを参照するファイル記述子がある場合、新しいファイル名を付けてファイル記述子を「保存」できますか(もちろん、同じデバイス上のどこかにあります)?rename(2)またはlink(2)に似たものを探していますが、ファイル名の代わりにファイル記述子を入力として受け入れます。

rename(2)とlink(2)の問題は、ファイル記述子からファイル名に移動しようとしても、失敗する可能性があることです。開いたファイル記述子がすでにリンク解除されたファイルを参照している場合について、より正確に考えています。この場合、ファイルには名前がありません。ファイル記述子をclose()したときにファイルが削除されるのを防ぐ方法はないようです。しかし、私は間違っていますか?PosixまたはLinuxAPIを使用して、名前を付け直すことはできますか?

/proc/<pid>/fd/<fd>更新:壊れたシンボリックリンクのように見えても、Linuxで削除されたファイルの内容を実際に見ることができます。ただし、link(2)またはln(1)を使用してこのようなファイルを再実体化することはできません。これは、クロスデバイスリンクを実行しようとしていると見なされるためです。

4

2 に答える 2

6

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

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

警告:

  • _GNU_SOURCEの定義を取得するには、を定義する必要がありますAT_EMPTY_PATH
  • リンク数がゼロのファイルの場合、これが機能することは保証されません。マニュアルページがこれについて何を言っているのか理解できません。私の推測では、ファイルのリンク数がゼロの場合、ファイルシステムがクラッシュした場合の不整合を回避するために、iノードはファイルシステム上ですでに削除されています。
  • もちろん、古いファイルがターゲットディレクトリの同じファイルシステム上にない場合は、機能しないと思います。

これが失敗した場合は、新しいファイルを作成し、その上にコンテンツをコピーする以外に方法はありませsendfileん(エラーチェックは省略されています。考えられるエラー値については、各関数のマニュアルページを参照してください)。

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);
于 2014-08-06T07:25:06.223 に答える
5

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

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

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

于 2012-12-13T22:16:23.637 に答える