C言語Linux:fcloseしたファイルを消すと.nfsファイルができてしまう

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
leon

C言語Linux:fcloseしたファイルを消すと.nfsファイルができてしまう

#1

投稿記事 by leon » 10年前

こんにちは。
Centos5.7環境でのC言語に関する質問です。
下記にソースコードがあります。

実行フォルダに「For_nfs_bug.txt」というファイルがあります。中身は適当です。
これをコピーして、「For_nfs_bug_XXXXXX」(XXXXXXはランダム)という名前のファイルが生成されます。
そして「For_nfs_bug_XXXXXX」をremoveします。
プログラムを終了させないためwhile(1){}で止めています。

エラー等はなく、削除も問題なくできます。しかし、隠しファイルで
「.nfs0000000008a9800f000017d8」のようなファイルができています。nfs以下の文字列はランダムかと思われます。

質問は、この.nfsファイルができないように削除する方法はないか、ということです。
一応考えているのは、コピーの作業を関数にして、その関数を別にコンパイルし、
systemで実行させるということです。(Linuxのcpコマンドのような感じです)

一応追記で何が問題かを書きます。
実際に使うプログラムではFor_nfs_bug.txtのサイズが10MB~30MBと巨大です。さらに、コピーは
1回のプログラムで100回~2000回程度になります。
そのため回数が増えるごとに巨大な.nfsができてしまい、途中でプログラムが止まってしまいます。
おそらくHDの容量を超えるのだと思います。

以上です。
非常に困っています。よろしくお願いします。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
int i, c;
char str[512];
char file2[512];
char tmp[512];
char test[]="For_nfs_bug";
FILE *fp,*fp2;

sprintf(str, "%s.txt", test);

strcpy(tmp, "XXXXXX");
mkstemp(tmp);
sprintf(file2, "%s_%s", test, tmp);
rename(tmp, file2);

//コピー元open
fp = fopen( str, "r" );
if( fp == NULL ){
fputs( "file open error(1)\n", stderr );
exit( EXIT_FAILURE );
}

//コピー先open
fp2 = fopen(file2, "w");
if( fp2 == NULL ){
fputs( "file open error(2)\n", stderr );
exit( EXIT_FAILURE );
}

//コピー実行
while( 1 ){
c = fgetc( fp );
if( c == EOF ){
if( feof( fp ) ){
break;
}
else if( ferror( fp ) ){
fputs( "error(3)\n", stderr );
exit( EXIT_FAILURE );
}
}
fputc( c, fp2 );
}

i = fclose( fp );
if( i != 0 ){
fputs( "error(4)\n", stderr );
exit( EXIT_FAILURE );
}
i = fclose( fp2 );
if( i != 0 ){
fputs( "error(5)\n", stderr );
exit( EXIT_FAILURE );
}

sprintf(str, "rm %s", file2);
system(str);
printf("%s\n", str);

while(1){}

return 0;
}

ISLe()

Re: C言語Linux:fcloseしたファイルを消すと.nfsファイルができてしまう

#2

投稿記事 by ISLe() » 10年前

想像ですが、mkstempで作成されたファイルをオープンしたまま、名前変更・書き込みオープンしているのが問題なのでは?

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
	int i, c;
	char str[512];
	char file2[512];
	char test[]="For_nfs_bug";
	int fd2;
	FILE *fp,*fp2;

	sprintf(str, "%s.txt", test);

	sprintf(file2, "%s_XXXXXX", test);
	fd2 = mkstemp(file2);
	if( fd2 == -1 ) {
		fputs( "tempfile make error\n", stderr );
		exit( EXIT_FAILURE );
	}

//コピー元open
	fp = fopen( str, "r" );
	if( fp == NULL ) {
		fputs( "file open error(1)\n", stderr );
		exit( EXIT_FAILURE );
	}

//コピー先open
	fp2 = fdopen(fd2, "w");
	if( fp2 == NULL ) {
		fputs( "file open error(2)\n", stderr );
		exit( EXIT_FAILURE );
	}

//コピー実行
	while( 1 ) {
		c = fgetc( fp );
		if( c == EOF ) {
			if( feof( fp ) ) {
				break;
			}
			else if( ferror( fp ) ) {
				fputs( "error(3)\n", stderr );
				exit( EXIT_FAILURE );
			}
		}
		fputc( c, fp2 );
	}

	i = fclose( fp );
	if( i != 0 ) {
		fputs( "error(4)\n", stderr );
		exit( EXIT_FAILURE );
	}
	i = fclose( fp2 );
	if( i != 0 ) {
		fputs( "error(5)\n", stderr );
		exit( EXIT_FAILURE );
	}

	sprintf(str, "rm %s", file2);
	system(str);
	printf("%s\n", str);

	while(1) {}

	return 0;
}
mkstempから返るファイルディスクリプタを使ってコピー先をオープンするように書き換えてみました。
想像が当たっていたなら、これで直るはずですが。

leon

Re: C言語Linux:fcloseしたファイルを消すと.nfsファイルができてしまう

#3

投稿記事 by leon » 10年前

ISLe様

回答ありがとうございます。
想像で理解できるとは羨ましい限りです。
仰るとおりで、.nfsファイルはなくなりました。

最後に一つだけ質問させてください。
fdopen関数にはあまり馴染みがありません。
また、このプログラムは他人が見る可能性もあり、
fdopenは避けてfopenに統一しようと考えました。
そこで、 私の元のプログラム内のmkstemp部分を
オフトピック
fd = mkstemp(tmp);
close(fd);
としました。これで.nfsファイルは出現しなくなりました。
この書き方は正しいものでしょうか?
それともISLe様の通りfdopenで開いて、その後fcloseで閉じる方法でないと
いけないでしょうか。

よろしくお願いします。

ISLe()

Re: C言語Linux:fcloseしたファイルを消すと.nfsファイルができてしまう

#4

投稿記事 by ISLe() » 10年前

馴染みがないのはmkstemp関数にも言えるのではないでしょうか。
mkstemp関数が使えてfdopen関数が使えないようなことはないと思いますが。

書き方として正しいか正しくないかと言ったら正しいです。
ただし期待するように動くかどうかは別の話です。
いったんクローズしたら、同じファイル名でオープンできない可能性が増すのではないでしょうかね。

閉鎖

“C言語何でも質問掲示板” へ戻る