# Version number
-$VERSION = '0.10';
+$VERSION = '0.11';
# This is a list of characters that can be used in random filenames
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()
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);
# 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
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
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
chdir 't' if -d 't';
@INC = '../lib';
require Test; import Test;
- plan(tests => 16);
+ plan(tests => 20);
}
use strict;
);
ok( (-f $tempfile) );
+# Should still be around after closing
+ok( close( $fh ) );
+ok( (-f $tempfile) );
+# Check again at exit
push(@files, $tempfile);
# TEMPDIR test
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";