develooper Front page | perl.perl5.porters | Postings from November 2000

PATCH: File::Temp fix on WindowsNT/VMS

Thread Next
Tim Jenness
November 24, 2000 20:38
PATCH: File::Temp fix on WindowsNT/VMS
Message ID:

This patch to File::Temp corrects a problem on NT (and I believe
VMS) where temporary files are being unlinked on close rather than
unlinked on exit. It includes a patch to the test to check for this
and now unlinks_on_close only when the filehandle is requested.
The bulk of the patch is the test and documentation/comment enhancements.

Hopefully this will get into 5.6.1 as well as the development branch.

Tim Jenness
JCMT software engineer/Support scientist

---	Fri Nov 24 18:26:14 2000
+++	Fri Nov 24 18:27:24 2000
@@ -166,7 +166,7 @@
 # Version number 
-$VERSION = '0.10';
+$VERSION = '0.11';
 # This is a list of characters that can be used in random filenames
@@ -881,7 +881,8 @@
 Return the filename and filehandle as before except that the file is
 automatically removed when the program exits. Default is for the file
 to be removed if a file handle is requested and to be kept if the
-filename is requested.
+filename is requested. In a scalar context (where no filename is 
+returned) the file is always deleted either on exit or when it is closed.
 If the template is not specified, a template is always
 automatically generated. This temporary file is placed in tmpdir()
@@ -896,8 +897,11 @@
 This is the preferred mode of operation, as if you only 
 have a filehandle, you can never create a race condition
 by fumbling with the filename. On systems that can not unlink
-an open file (for example, Windows NT) the file is marked for
-deletion when the program ends (equivalent to setting UNLINK to 1).
+an open file or can not mark a file as temporary when it is opened
+(for example, Windows NT uses the C<O_TEMPORARY> flag))
+the file is marked for deletion when the program ends (equivalent
+to setting UNLINK to 1). The C<UNLINK> flag is ignored if present.
   (undef, $filename) = tempfile($template, OPEN => 0);
@@ -978,19 +982,33 @@
   # Now add a suffix
   $template .= $options{"SUFFIX"};
+  # Determine whether we should tell _gettemp to unlink the file
+  # On unix this is irrelevant and can be worked out after the file is
+  # opened (simply by unlinking the open filehandle). On Windows or VMS
+  # we have to indicate temporary-ness when we open the file. In general
+  # we only want a true temporary file if we are returning just the 
+  # filehandle - if the user wants the filename they probably do not
+  # want the file to disappear as soon as they close it.
+  # For this reason, tie unlink_on_close to the return context regardless
+  # of OS.
+  my $unlink_on_close = ( wantarray ? 0 : 1);
   # Create the file
   my ($fh, $path);
   croak "Error in tempfile() using $template"
     unless (($fh, $path) = _gettemp($template,
 				    "open" => $options{'OPEN'},
 				    "mkdir"=> 0 ,
-                                   "unlink_on_close" => $options{'UNLINK'},
+                                    "unlink_on_close" => $unlink_on_close,
 				    "suffixlen" => length($options{'SUFFIX'}),
 				   ) );
   # Set up an exit handler that can do whatever is right for the
-  # system. Do not check return status since this is all done with
-  # END blocks
+  # system. This removes files at exit when requested explicitly or when
+  # system is asked to unlink_on_close but is unable to do so because
+  # of OS limitations.
+  # The latter should be achieved by using a tied filehandle.
+  # Do not check return status since this is all done with END blocks.
   _deferred_unlink($fh, $path, 0) if $options{"UNLINK"};
   # Return
@@ -1731,6 +1749,15 @@
     fcntl($tmpfh, F_SETFD, 0)
         or die "Can't clear close-on-exec flag on temp fh: $!\n";
+=head2 Temporary files and NFS
+Some problems are associated with using temporary files that reside
+on NFS file systems and it is recommended that a local filesystem
+is used whenever possible. Some of the security tests will most probably
+fail when the temp file is not local. Additionally, be aware that
+the performance of I/O operations over NFS will not be as good as for
+a local disk.
 =head1 HISTORY
 Originally began life in May 1999 as an XS interface to the system
@@ -1743,8 +1770,8 @@
 L<POSIX/tmpnam>, L<POSIX/tmpfile>, L<File::Spec>, L<File::Path>
-See L<File::MkTemp> for a different implementation of temporary
-file handling.
+See L<IO::File> and L<File::MkTemp> for different implementations of 
+temporary file handling.
 =head1 AUTHOR
--- ftmp-tempfile.t.orig	Fri Nov 24 18:29:43 2000
+++ ftmp-tempfile.t	Fri Nov 24 18:31:18 2000
@@ -5,7 +5,7 @@
 	chdir 't' if -d 't';
 	@INC = '../lib';
 	require Test; import Test;
-	plan(tests => 16);
+	plan(tests => 20);
 use strict;
@@ -51,6 +51,10 @@
 ok( (-f $tempfile) );
+# Should still be around after closing
+ok( close( $fh ) ); 
+ok( (-f $tempfile) );
+# Check again at exit
 push(@files, $tempfile);
 # TEMPDIR test
@@ -113,5 +117,29 @@
 ok( close( $fh ) );
 push( @still_there, $tempfile); # check at END
+# Would like to create a temp file and just retrieve the handle
+# but the test is problematic since:
+#  - We dont know the filename so we cant check that it is tidied
+#    correctly
+#  - The unlink0 required on unix for tempfile creation will fail
+#    on NFS
+# Try to do what we can.
+# Tempfile croaks on error so we need an eval
+$fh = eval { tempfile( 'ftmpXXXXX', DIR => File::Spec->tmpdir ) };
+if ($fh) {
+  # print something to it to make sure something is there
+  ok( print $fh "Test\n" );
+  # Close it - can not check it is gone since we dont know the name
+  ok( close($fh) );
+} else {
+  skip "Skip Failed probably due to NFS", 1;
+  skip "Skip Failed probably due to NFS", 1;
 # Now END block will execute to test the removal of directories
+print "# End of tests. Execute END blocks\n";

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About