[Namazu-devel-ja 148] Re: フィルタ動作確認用スクリプト

SATOH Fumiyasu fumiya @ samba.gr.jp
2004年 9月 10日 (金) 15:50:50 JST


At Fri, 10 Sep 2004 12:54:13 +0900,
Yukio USUDA wrote:
> > > 一時ファイルの作成なら、IO::File->new_tmpfile; ではダメ
> > > なんでしょうか?
> > 
> > 外部プログラムの多くで、テンポラリファイル名を指定しないといけません
> > から、それはできないのです。
> > -- 
> 
> IO::File->new_tmpfile はファイル名を取得できないようなので、
> 外部プログラムに渡すためには使えないようですが、探してみたら
> File::Temp::tempnam というものもありました。
> http://search.cpan.org/~jhi/perl-5.8.0/lib/File/Temp.pm

ちょっと ad-hoc ですが、こんな感じ? 名前に time
(or Time::HiRes::time) を入れると名前衝突の可能性が
ぐっと減るんですが、名前が長くなりすぎるのが難点。

Index: pl/util.pl
===================================================================
RCS file: /storage/cvsroot/namazu/pl/util.pl,v
retrieving revision 1.29
diff -u -p -r1.29 util.pl
--- pl/util.pl	18 Mar 2004 15:52:11 -0000	1.29
+++ pl/util.pl	10 Sep 2004 06:37:17 -0000
@@ -25,6 +25,7 @@
 
 package util;
 use strict;
+use POSIX qw(EEXIST);
 use IO::File;
 require 'time.pl';
 
@@ -232,9 +233,22 @@ sub tmpnam ($) {
     my ($base) = @_;
     cdie("util::tmpnam: Set \$var::OUTPUT_DIR first!\n") 
 	if $var::OUTPUT_DIR eq "";
-    my $tmpnam = "$var::OUTPUT_DIR/$base.tmp";
-    dprint("tmpnam: $tmpnam\n");
-    return $tmpnam;
+    my $tmpnam_base = "$var::OUTPUT_DIR/$base" . sprintf('-%lx', $$);
+    for (my $try = 0; $try < 1000; $try++) {
+	my $tmpnam = $tmpnam_base . sprintf('-%x.tmp', rand(0x10000));;
+	my $fh = IO::File->new($tmpnam, O_RDWR|O_CREAT|O_EXCL);
+	if (!defined($fh)) {
+	    if ($! != EEXIST) {
+		cdie("tmpnam: cannot create temporary file: $!\n");
+	    }
+	    # $tmpnam already exists. Try again.
+	    next;
+	}
+	dprint("tmpnam: $tmpnam\n");
+	return wantarray ? ($tmpnam, $fh) : $tmpnam;
+    }
+
+    cdie("tmpnam: cannot create temporary file: no namespace\n");
 }
 
 # cdie ... clean files before die

見ての通り、同時にたくさん生成すると、名前が衝突または枯渇して
しまうので、死にます。

-- 
-- Name: SATOH Fumiyasu  -- Home: http://www.sfo.jp (in Japanese only)
-- Mail: fumiya at net-thrust.com, samba.gr.jp, namazu.org or ...



Namazu-devel-ja メーリングリストの案内