• ベストアンサー

unlinkしたファイルを元に戻す方法?

UNIX系OSでは(Windowsとかでもできるのでしょうか?) プログラム中で使う一時ファイルを、 プログラムが途中で異常終了したりした場合でも 確実に消えてなくなるように、 int fd = open( "temp.dat", O_RDWR|O_CREAT ) ; unlink( "temp.dat" ) ; というように、一時ファイルを作った直後にunlink、という手段が よく使われますが・・・ この、unlinkしてしまって、ファイルディスクリプタだけになったファイルを、 別のファイルに自力で書き写す以外に、 再びファイルとして残すことってできないのでしょうか? 要するに・・・ プログラムが途中で異常終了したりしたときは、 確実に消えてほしいけれど、 必要な場合は残したい、でも、残す処理が途中で中断したりして、 半端なファイルが残ってほしくない、 ・・・というような要件なのですが。。

質問者が選んだベストアンサー

  • ベストアンサー
  • chirubou
  • ベストアンサー率37% (189/502)
回答No.6

なるほど、確かにそういうのって欲しいですよね。よーく分かります。 でも Linux ではできないこともないのですが、普通の Unix だと、fd だけになってしまうと、そこからディレクトリを辿ることはできませんので、fd からファイル(名)を復活させることは、残念ながら、できません。 私だったら、(いい加減なコードですが)以下のように fork() してしまうでしょうね(wait() の引数やマクロは特にいい加減です。スイマセン)。要は親プロセスで処理の正常終了を見張るというものです。ただし、SIGKILL がくるとファイルは消せませんし、シグナルをちゃんと考える必要があるとすると結構面倒です。 fd = open(); if( ( pid = fork() ) = 0 ) [ 処理 } else if( pid > 0 ) { int status; if( wait(&status) == pid ) { if( WIFEXITED(st) && EXITSTATUS(st) == 0 ) exit( 0 ); unlink(...); exit( 1 ); } else { fork エラー }

noname#43437
質問者

お礼

遅くなりましたが、大変参考になる意見ありがとうございました!

その他の回答 (5)

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.5

書き写す以外に標準的な方法はないでしょうねぇ^^; それに、「open() と unlink() の間で以上終了したら、どうするんだ?」というのもありますしね。 一時ファイルがたくさんあって、少しでもタイピングを減らしたいなら、atexit() を使えば少しは減るかもしれませんね。 === #include <unistd.h> #include <stdlib.h> #include <stdio.h> struct fileLink { int fdes; const char *fnam; struct fileLink *next; }; struct fileLink *flptr = NULL; void finally(void) { while (flptr != NULL) { char buf[BUFSIZ]; ssize_t sz; int fd = open(flptr->fnam, ...); lseek(flptr->fdes, 0, SEEK_SET); while ((sz = read(flptr->fdes, buf, BUFSIZ)) > 0) write(fd, buf, sz); close(fd); flptr = flptr.next; } } void create_tmp(void) { const char fn[] = "hogehoge"; static struct fileLink fl; fl.fnam = fn; fl.fdes = open(fn, ...); fl.next = flptr; flptr = &fl; unlink(fn); /* ... */ } int main(void) { atexit(&finally); /* ... */ create_tmp(); /* ... */ return 0; } === でも、わたしなら、atexit()を使わず、まじめに書き写しますけど(笑)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★一時ファイルの扱いは次の関数に任せるのはどうですか。 ・http://www.bohyoh.com/CandCPP/C/Library/tmpfile.html→『tmpfile』  http://www.bohyoh.com/CandCPP/C/Library/tmpnam.html→『tmpnam』  その他にも  http://www1.cts.ne.jp/~clab/hsample/File/File07.html→『ユニークなファイル名で開く』  を参照して下さい。 ・あと一時ファイルは『テンポラリ・フォルダ』に作成するようにします。  そうすればプログラムが途中で異常終了して一時ファイルが残ったとしても  『テンポラリ・フォルダ』のファイルは削除しても良いと考え放置しても問題はない。 ・また必要な場合で残すときは『テンポラリ・フォルダ』に作成したファイルをリネーム付きで  残したいフォルダに移動すれば可能です。移動はパス名の変更だけですので一瞬です。  異常終了しなかった場合はプログラムの終了時に一時ファイルを削除するようにします。  よって  (1)プログラム起動時に一時ファイル名を取得(テンポラリ・フォルダ名も取得)  (2)一時ファイルはテンポラリ・フォルダ名+一時ファイル名で作成/出力  (3)必要な場合は一時ファイル名を残したいフォルダへリネーム付きで移動  (4)プログラム終了時に一時ファイルを削除  という手順でどうですか。  テンポラリ・フォルダの意味を有効に使って下さい。 ・以上。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

>プログラムの処理中に電源断やOSフリーズなどというのも >考慮しなくてはいけないので・・・ 考え方を変えて、一時ファイルが残っても、問題ないような設計をされては、いかがでしょうか。一時ファイルが残ったときに、なにがまずいのかが、具体的に判りませんので、的はずれかも知れませんが・・・ 例として、以下のような方法が、あります。(OSはUNIXとします) 1.一時ファイルは、必ず、所定の専用のディレクトリ下につくる。 2.当該プロセス起動時に、所定のディレクトリ下のファイルを全て削除する。(一時ファイルの残骸を全て削除) 3.その後、一時ファイルを作り、使用する。 尚、一時ファイルはOSにファイル名を作成させる方法もありますが、プロセスが、重複しないファイル名を作ることも可能です。 例として、"TEMP"+時間をファイル名にします。 時間は、現在時刻=「年月日時分秒+マイクロ秒」とします。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

>プログラムの処理中に電源断やOSフリーズ その状況でも消すとするとunlinkですかね。しかし、unlinkしちゃったものは事実上消しちゃったファイルと同じですから。取り消すことは不可能だと思います。 そう言えば、ファイルを残したい場合はどんな場合でしょうか?デバッグ用でしょうか?いつでも残した場合もあるとしたらログを残したりするほうが賢明ですが。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.1

自分自身のプロセスでは簡単には管理しようがないと思います。 方法としては、 (1)プログラムをスレッド化して、親となるプログラムで残す/消すを監視する。 (2)ファイルの残す/消すの管理自体を別プロセスを起動して、そちらに任せる。 (3)シェル・スクリプトで残す/消すの処理を行う。終了コードを元に判断する。 (4)異常終了をすべて自分で刈り取り(sigactionなど)、その時点でunlinkする。 ぐらいですかね。

noname#43437
質問者

お礼

なるほど、 ファイルの削除などの処理を外部に任せる方法、ですね。 ただ、最悪の場合、 プログラムの処理中に電源断やOSフリーズなどというのも 考慮しなくてはいけないので・・・ 悩んでおります。

関連するQ&A

専門家に質問してみよう