=head1 PORTABILITY
-This module is designed to be portable across operating systems
-and it currently supports Unix, VMS, DOS, OS/2, Windows and
-Mac OS (Classic). When
-porting to a new OS there are generally three main issues
-that have to be solved:
+This section is at the top in order to provide easier access to
+porters. It is not expected to be rendered by a standard pod
+formatting tool. Please skip straight to the SYNOPSIS section if you
+are not trying to port this module to a new platform.
+
+This module is designed to be portable across operating systems and it
+currently supports Unix, VMS, DOS, OS/2, Windows and Mac OS
+(Classic). When porting to a new OS there are generally three main
+issues that have to be solved:
=over 4
use File::Temp qw/ tempfile tempdir /;
- $dir = tempdir( CLEANUP => 1 );
- ($fh, $filename) = tempfile( DIR => $dir );
+ $fh = tempfile();
+ ($fh, $filename) = tempfile();
($fh, $filename) = tempfile( $template, DIR => $dir);
($fh, $filename) = tempfile( $template, SUFFIX => '.dat');
- $fh = tempfile();
+
+ $dir = tempdir( CLEANUP => 1 );
+ ($fh, $filename) = tempfile( DIR => $dir );
Object interface:
require File::Temp;
use File::Temp ();
+ use File::Temp qw/ :seekable /;
- $fh = new File::Temp($template);
+ $fh = new File::Temp();
+ $fname = $fh->filename;
+
+ $fh = new File::Temp(TEMPLATE => $template);
$fname = $fh->filename;
$tmp = new File::Temp( UNLINK => 0, SUFFIX => '.dat' );
print $tmp "Some data\n";
print "Filename is $tmp\n";
+ $tmp->seek( 0, SEEK_END );
+The following interfaces are provided for compatibility with
+existing APIs. They should not be used in new code.
MkTemp family:
$fh = tmpfile();
($fh, $file) = tmpnam();
- $fh = tmpfile();
-
Compatibility functions:
=cut
# 5.6.0 gives us S_IWOTH, S_IWGRP, our and auto-vivifying filehandls
-# People would like a version on 5.005 so give them what they want :-)
-use 5.005;
+# People would like a version on 5.004 so give them what they want :-)
+use 5.004;
use strict;
use Carp;
use File::Spec 0.8;
use File::Path qw/ rmtree /;
use Fcntl 1.03;
+use IO::Seekable; # For SEEK_*
use Errno;
require VMS::Stdio if $^O eq 'VMS';
+# pre-emptively load Carp::Heavy. If we don't when we run out of file
+# handles and attempt to call croak() we get an error message telling
+# us that Carp::Heavy won't load rather than an error telling us we
+# have run out of file handles. We either preload croak() or we
+# switch the calls to croak from _gettemp() to use die.
+require Carp::Heavy;
+
# Need the Symbol package if we are running older perl
require Symbol if $] < 5.006;
### For the OO interface
-use base qw/ IO::Handle /;
-use overload '""' => "STRINGIFY";
-
+use base qw/ IO::Handle IO::Seekable /;
+use overload '""' => "STRINGIFY", fallback => 1;
# use 'our' on v5.6.0
-use vars qw($VERSION @EXPORT_OK %EXPORT_TAGS $DEBUG);
+use vars qw($VERSION @EXPORT_OK %EXPORT_TAGS $DEBUG $KEEP_ALL);
$DEBUG = 0;
+$KEEP_ALL = 0;
# We are exporting functions
mkstemps
mkdtemp
unlink0
+ cleanup
+ SEEK_SET
+ SEEK_CUR
+ SEEK_END
};
# Groups of functions for export
%EXPORT_TAGS = (
'POSIX' => [qw/ tmpnam tmpfile /],
'mktemp' => [qw/ mktemp mkstemp mkstemps mkdtemp/],
+ 'seekable' => [qw/ SEEK_SET SEEK_CUR SEEK_END /],
);
# add contents of these tags to @EXPORT
-Exporter::export_tags('POSIX','mktemp');
+Exporter::export_tags('POSIX','mktemp','seekable');
# Version number
-$VERSION = '0.14';
+$VERSION = '0.18';
# This is a list of characters that can be used in random filenames
# Maximum number of tries to make a temp file before failing
-use constant MAX_TRIES => 10;
+use constant MAX_TRIES => 1000;
# Minimum number of X characters that should be in a template
use constant MINX => 4;
my $OPENFLAGS = O_CREAT | O_EXCL | O_RDWR;
unless ($^O eq 'MacOS') {
- for my $oflag (qw/ FOLLOW BINARY LARGEFILE EXLOCK NOINHERIT /) {
+ for my $oflag (qw/ NOFOLLOW BINARY LARGEFILE EXLOCK NOINHERIT /) {
my ($bit, $func) = (0, "Fcntl::O_" . $oflag);
no strict 'refs';
$OPENFLAGS |= $bit if eval {
# Make sure that redefined die handlers do not cause problems
- # eg CGI::Carp
+ # e.g. CGI::Carp
local $SIG{__DIE__} = sub {};
local $SIG{__WARN__} = sub {};
$bit = &$func();
no strict 'refs';
$OPENTEMPFLAGS |= $bit if eval {
# Make sure that redefined die handlers do not cause problems
- # eg CGI::Carp
+ # e.g. CGI::Carp
local $SIG{__DIE__} = sub {};
local $SIG{__WARN__} = sub {};
$bit = &$func();
# Substr starts from 0
my $start = length($template) - 1 - $options{"suffixlen"};
- # Check that we have at least MINX x X (eg 'XXXX") at the end of the string
+ # Check that we have at least MINX x X (e.g. 'XXXX") at the end of the string
# (taking suffixlen into account). Any fewer is insecure.
# Do it using substr - no reason to use a pattern match since
# we know where we are looking and what we are looking for
if (substr($template, $start - MINX + 1, MINX) ne 'X' x MINX) {
- ${$options{ErrStr}} = "The template must contain at least ".
+ ${$options{ErrStr}} = "The template must end with at least ".
MINX . " 'X' characters\n";
return ();
}
${$options{ErrStr}} = "Parent directory ($parent) is not a directory";
return ();
}
- unless (-w _) {
+ unless (-w $parent) {
${$options{ErrStr}} = "Parent directory ($parent) is not writable\n";
return ();
}
# but may have O_NOINHERIT. This may or may not be in Fcntl.
local $^F = 2;
- # Store callers umask
- my $umask = umask();
-
- # Set a known umask
- umask(066);
-
# Attempt to open the file
my $open_success = undef;
- if ( $^O eq 'VMS' and $options{"unlink_on_close"} ) {
+ if ( $^O eq 'VMS' and $options{"unlink_on_close"} && !$KEEP_ALL) {
# make it auto delete on close by setting FAB$V_DLT bit
$fh = VMS::Stdio::vmssysopen($path, $OPENFLAGS, 0600, 'fop=dlt');
$open_success = $fh;
} else {
- my $flags = ( $options{"unlink_on_close"} ?
+ my $flags = ( ($options{"unlink_on_close"} && !$KEEP_ALL) ?
$OPENTEMPFLAGS :
$OPENFLAGS );
$open_success = sysopen($fh, $path, $flags, 0600);
}
if ( $open_success ) {
- # Reset umask
- umask($umask) if defined $umask;
+ # in case of odd umask force rw
+ chmod(0600, $path);
# Opened successfully - return file handle and name
return ($fh, $path);
} else {
- # Reset umask
- umask($umask) if defined $umask;
# Error opening file - abort with error
# if the reason was anything but EEXIST
}
} elsif ($options{"mkdir"}) {
- # Store callers umask
- my $umask = umask();
-
- # Set a known umask
- umask(066);
-
# Open the temp directory
if (mkdir( $path, 0700)) {
- # created okay
- # Reset umask
- umask($umask) if defined $umask;
+ # in case of odd umask
+ chmod(0700, $path);
return undef, $path;
} else {
- # Reset umask
- umask($umask) if defined $umask;
-
# Abort with error if the reason for failure was anything
# except EEXIST
unless ($!{EEXIST}) {
} else {
$path =~ s/X(?=X*\z)/$CHARS[ int( rand( $#CHARS ) ) ]/ge;
}
-
return $path;
}
+# Internal routine to force a temp file to be writable after
+# it is created so that we can unlink it. Windows seems to occassionally
+# force a file to be readonly when written to certain temp locations
+sub _force_writable {
+ my $file = shift;
+ chmod 0600, $file;
+}
+
+
# internal routine to check to see if the directory is safe
# First checks to see if the directory is not owned by the
# current user or root. Then checks to see if anyone else
return 1 if $^O eq 'VMS'; # owner delete control at file level
# Check to see whether owner is neither superuser (or a system uid) nor me
- # Use the real uid from the $< variable
+ # Use the effective uid from the $> variable
# UID is in [4]
- if ($info[4] > File::Temp->top_system_uid() && $info[4] != $<) {
+ if ($info[4] > File::Temp->top_system_uid() && $info[4] != $>) {
- Carp::cluck(sprintf "uid=$info[4] topuid=%s \$<=$< path='$path'",
+ Carp::cluck(sprintf "uid=$info[4] topuid=%s euid=$< path='$path'",
File::Temp->top_system_uid());
$$err_ref = "Directory owned neither by root nor the current user"
if (($info[2] & &Fcntl::S_IWGRP) || # Is group writable?
($info[2] & &Fcntl::S_IWOTH) ) { # Is world writable?
# Must be a directory
- unless (-d _) {
+ unless (-d $path) {
$$err_ref = "Path ($path) is not a directory"
if ref($err_ref);
return 0;
}
# Must have sticky bit set
- unless (-k _) {
+ unless (-k $path) {
$$err_ref = "Sticky bit not set on $path when dir is group|world writable"
if ref($err_ref);
return 0;
{
# Will set up two lexical variables to contain all the files to be
- # removed. One array for files, another for directories
- # They will only exist in this block
- # This means we only have to set up a single END block to remove all files
- # @files_to_unlink contains an array ref with the filehandle and filename
- my (@files_to_unlink, @dirs_to_unlink);
+ # removed. One array for files, another for directories They will
+ # only exist in this block.
+
+ # This means we only have to set up a single END block to remove
+ # all files.
+
+ # in order to prevent child processes inadvertently deleting the parent
+ # temp files we use a hash to store the temp files and directories
+ # created by a particular process id.
+
+ # %files_to_unlink contains values that are references to an array of
+ # array references containing the filehandle and filename associated with
+ # the temp file.
+ my (%files_to_unlink, %dirs_to_unlink);
# Set up an end block to use these arrays
END {
- # Files
- foreach my $file (@files_to_unlink) {
- # close the filehandle without checking its state
- # in order to make real sure that this is closed
- # if its already closed then I dont care about the answer
- # probably a better way to do this
- close($file->[0]); # file handle is [0]
-
- if (-f $file->[1]) { # file name is [1]
- unlink $file->[1] or warn "Error removing ".$file->[1];
+ cleanup();
+ }
+
+ # Cleanup function. Always triggered on END but can be invoked
+ # manually.
+ sub cleanup {
+ if (!$KEEP_ALL) {
+ # Files
+ my @files = (exists $files_to_unlink{$$} ?
+ @{ $files_to_unlink{$$} } : () );
+ foreach my $file (@files) {
+ # close the filehandle without checking its state
+ # in order to make real sure that this is closed
+ # if its already closed then I dont care about the answer
+ # probably a better way to do this
+ close($file->[0]); # file handle is [0]
+
+ if (-f $file->[1]) { # file name is [1]
+ _force_writable( $file->[1] ); # for windows
+ unlink $file->[1] or warn "Error removing ".$file->[1];
+ }
}
- }
- # Dirs
- foreach my $dir (@dirs_to_unlink) {
- if (-d $dir) {
- rmtree($dir, $DEBUG, 1);
+ # Dirs
+ my @dirs = (exists $dirs_to_unlink{$$} ?
+ @{ $dirs_to_unlink{$$} } : () );
+ foreach my $dir (@dirs) {
+ if (-d $dir) {
+ rmtree($dir, $DEBUG, 0);
+ }
}
- }
+ # clear the arrays
+ @{ $files_to_unlink{$$} } = ()
+ if exists $files_to_unlink{$$};
+ @{ $dirs_to_unlink{$$} } = ()
+ if exists $dirs_to_unlink{$$};
+ }
}
+
# This is the sub called to register a file for deferred unlinking
# This could simply store the input parameters and defer everything
# until the END block. For now we do a bit of checking at this
# Directory exists so store it
# first on VMS turn []foo into [.foo] for rmtree
$fname = VMS::Filespec::vmspath($fname) if $^O eq 'VMS';
- push (@dirs_to_unlink, $fname);
+ $dirs_to_unlink{$$} = []
+ unless exists $dirs_to_unlink{$$};
+ push (@{ $dirs_to_unlink{$$} }, $fname);
} else {
carp "Request to remove directory $fname could not be completed since it does not exist!\n" if $^W;
if (-f $fname) {
# file exists so store handle and name for later removal
- push(@files_to_unlink, [$fh, $fname]);
+ $files_to_unlink{$$} = []
+ unless exists $files_to_unlink{$$};
+ push(@{ $files_to_unlink{$$} }, [$fh, $fname]);
} else {
carp "Request to remove file $fname could not be completed since it is not there!\n" if $^W;
}
-=head1 OO INTERFACE
+=head1 OBJECT-ORIENTED INTERFACE
This is the primary interface for interacting with
C<File::Temp>. Using the OO interface a temporary file can be created
Note that there is no method to obtain the filehandle from the
C<File::Temp> object. The object itself acts as a filehandle. Also,
the object is configured such that it stringifies to the name of the
-temporary file.
+temporary file, and can be compared to a filename directly. The object
+isa C<IO::Handle> and isa C<IO::Seekable> so all those methods are
+available.
=over 4
Arguments are case insensitive.
+Can call croak() if an error occurs.
+
=cut
sub new {
# Store unlink information in hash slot (plus other constructor info)
%{*$fh} = %args;
- ${*$fh}{UNLINK} = $unlink;
+ # create the object
bless $fh, $class;
+ # final method-based configuration
+ $fh->unlink_on_destroy( $unlink );
+
return $fh;
}
return $self->filename;
}
+=item B<unlink_on_destroy>
+
+Control whether the file is unlinked when the object goes out of scope.
+The file is removed if this value is true and $KEEP_ALL is not.
+
+ $fh->unlink_on_destroy( 1 );
+
+Default is for the file to be removed.
+
+=cut
+
+sub unlink_on_destroy {
+ my $self = shift;
+ if (@_) {
+ ${*$self}{UNLINK} = shift;
+ }
+ return ${*$self}{UNLINK};
+}
+
=item B<DESTROY>
When the object goes out of scope, the destructor is called. This
No error is given if the unlink fails.
+If the global variable $KEEP_ALL is true, the file will not be removed.
+
=cut
sub DESTROY {
my $self = shift;
- if (${*$self}{UNLINK}) {
+ if (${*$self}{UNLINK} && !$KEEP_ALL) {
print "# ---------> Unlinking $self\n" if $DEBUG;
# The unlink1 may fail if the file has been closed
# do an unlink without test. Seems to be silly
# to do this when we are trying to be careful
# about security
+ _force_writable( $self->filename ); # for windows
unlink1( $self, $self->filename )
or unlink($self->filename);
}
This is the basic function to generate temporary files.
The behaviour of the file can be changed using various options:
+ $fh = tempfile();
($fh, $filename) = tempfile();
Create a temporary file in the directory specified for temporary
($fh, $filename) = tempfile($template, UNLINK => 1);
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. In a scalar context (where no filename is
-returned) the file is always deleted either on exit or when it is closed.
+automatically removed when the program exits (dependent on
+$KEEP_ALL). Default is for the file to be removed if a file handle is
+requested and to be kept if the filename is requested. In a scalar
+context (where no filename is returned) the file is always deleted
+either (depending on the operating system) on exit or when it is
+closed (unless $KEEP_ALL is true when the temp file is created).
+
+Use the object-oriented interface if fine-grained control of when
+a file is removed is required.
If the template is not specified, a template is always
automatically generated. This temporary file is placed in tmpdir()
$fh = tempfile( $template, DIR => $dir );
-If called in scalar context, only the filehandle is returned
-and the file will automatically be deleted when closed (see
-the description of tmpfile() elsewhere in this document).
-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 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.
+If called in scalar context, only the filehandle is returned and the
+file will automatically be deleted when closed on operating systems
+that support this (see the description of tmpfile() elsewhere in this
+document). 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 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);
Options can be combined as required.
+Will croak() if there is an error.
+
=cut
sub tempfile {
# 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.
+ # want the file to disappear as soon as they close it (which may be
+ # important if they want a child process to use the file)
# For this reason, tie unlink_on_close to the return context regardless
# of OS.
my $unlink_on_close = ( wantarray ? 0 : 1);
Of course, if the template is not specified, the temporary directory
will be created in tmpdir() and will also be removed at program exit.
+Will croak() if there is an error.
+
=cut
# '
to it, for example F</tmp/temp.XXXX>. The trailing X's are replaced
with unique alphanumeric combinations.
+Will croak() if there is an error.
+
=cut
Returns just the filehandle alone when called in scalar context.
+Will croak() if there is an error.
+
=cut
sub mkstemps {
$tmpdir_name = mkdtemp($template);
Returns the name of the temporary directory created.
-Returns undef on failure.
Directory must be removed by the caller.
+Will croak() if there is an error.
+
=cut
#' # for emacs
Template is the same as that required by mkstemp().
+Will croak() if there is an error.
+
=cut
sub mktemp {
See L<File::Spec/tmpdir> for information on the choice of temporary
directory for a particular operating system.
+Will croak() if there is an error.
+
=cut
sub tmpnam {
Currently this command will probably not work when the temporary
directory is on an NFS file system.
+Will croak() if there is an error.
+
=cut
sub tmpfile {
Because this function uses mktemp(), it can suffer from race conditions.
+Will croak() if there is an error.
+
=cut
sub tempnam {
closest you can come to making sure that the filename unlinked was the
same as the file whose descriptor you hold.
- unlink0($fh, $path) or die "Error unlinking file $path safely";
+ unlink0($fh, $path)
+ or die "Error unlinking file $path safely";
-Returns false on error. The filehandle is not closed since on some
-occasions this is not required.
+Returns false on error but croaks() if there is a security
+anomaly. The filehandle is not closed since on some occasions this is
+not required.
On some platforms, for example Windows NT, it is not possible to
unlink an open file (the file must be closed first). On those
not always go to zero immediately after unlinking. Currently, this
command is expected to fail on NFS disks.
+This function is disabled if the global variable $KEEP_ALL is true
+and an unlink on open file is supported. If the unlink is to be deferred
+to the END block, the file is still registered for removal.
+
+This function should not be called if you are using the object oriented
+interface since the it will interfere with the object destructor deleting
+the file.
+
=cut
sub unlink0 {
# attempt remove the file (does not work on some platforms)
if (_can_unlink_opened_file()) {
+
+ # return early (Without unlink) if we have been instructed to retain files.
+ return 1 if $KEEP_ALL;
+
# XXX: do *not* call this on a directory; possible race
# resulting in recursive removal
croak "unlink0: $path has become a directory!" if -d $path;
to the same file and that the number of links to the file is 1 (all
fields returned by stat() are compared).
- cmpstat($fh, $path) or die "Error comparing handle with file";
+ cmpstat($fh, $path)
+ or die "Error comparing handle with file";
Returns false if the stat information differs or if the link count is
-greater than 1.
+greater than 1. Calls croak if there is a security anomaly.
-On certain platofms, eg Windows, not all the fields returned by stat()
+On certain platforms, for example Windows, not all the fields returned by stat()
can be compared. For example, the C<dev> and C<rdev> fields seem to be
different in Windows. Also, it seems that the size of the file
returned by stat() does not always agree, with C<stat(FH)> being more
}
# this is no longer a file, but may be a directory, or worse
- unless (-f _) {
+ unless (-f $path) {
confess "panic: $path is no longer a file: SB=@fh";
}
mean that the post-unlink comparison of the filehandle state provided
by C<unlink0> is not available.
- unlink1($fh, $path) or die "Error closing and unlinking file";
+ unlink1($fh, $path)
+ or die "Error closing and unlinking file";
Usually called from the object destructor when using the OO interface.
Not exported by default.
+This function is disabled if the global variable $KEEP_ALL is true.
+
+Can call croak() if there is a security anomaly during the stat()
+comparison.
+
=cut
sub unlink1 {
# Close the file
close( $fh ) or return 0;
+ # Make sure the file is writable (for windows)
+ _force_writable( $path );
+
+ # return early (without unlink) if we have been instructed to retain files.
+ return 1 if $KEEP_ALL;
+
# remove the file
return unlink($path);
}
+=item B<cleanup>
+
+Calling this function will cause any temp files or temp directories
+that are registered for removal to be removed. This happens automatically
+when the process exits but can be triggered manually if the caller is sure
+that none of the temp files are required. This method can be registered as
+an Apache callback.
+
+On OSes where temp files are automatically removed when the temp file
+is closed, calling this function will have no effect other than to remove
+temporary directories (which may include temporary files).
+
+ File::Temp::cleanup();
+
+Not exported by default.
+
=back
=head1 PACKAGE VARIABLES
This value can be adjusted to reduce security checking if required.
The value is only relevant when C<safe_level> is set to MEDIUM or higher.
-=back
-
=cut
{
my $TopSystemUID = 10;
+ $TopSystemUID = 197108 if $^O eq 'interix'; # "Administrator"
sub top_system_uid {
my $self = shift;
if (@_) {
}
}
+=item B<$KEEP_ALL>
+
+Controls whether temporary files and directories should be retained
+regardless of any instructions in the program to remove them
+automatically. This is useful for debugging but should not be used in
+production code.
+
+ $File::Temp::KEEP_ALL = 1;
+
+Default is for files to be removed as requested by the caller.
+
+In some cases, files will only be retained if this variable is true
+when the file is created. This means that you can not create a temporary
+file, set this variable and expect the temp file to still be around
+when the program exits.
+
+=item B<$DEBUG>
+
+Controls whether debugging messages should be enabled.
+
+ $File::Temp::DEBUG = 1;
+
+Default is for debugging mode to be disabled.
+
+=back
+
=head1 WARNING
For maximum security, endeavour always to avoid ever looking at,
the performance of I/O operations over NFS will not be as good as for
a local disk.
+=head2 Forking
+
+In some cases files created by File::Temp are removed from within an
+END block. Since END blocks are triggered when a child process exits
+(unless C<POSIX::_exit()> is used by the child) File::Temp takes care
+to only remove those temp files created by a particular process ID. This
+means that a child will not attempt to remove temp files created by the
+parent process.
+
+If you are forking many processes in parallel that are all creating
+temporary files, you may need to reset the random number seed using
+srand(EXPR) in each child else all the children will attempt to walk
+through the same set of random file names and may well cause
+themselves to give up if they exceed the number of retry attempts.
+
+=head2 BINMODE
+
+The file returned by File::Temp will have been opened in binary mode
+if such a mode is available. If that is not correct, use the binmode()
+function to change the mode of the filehandle.
+
=head1 HISTORY
Originally began life in May 1999 as an XS interface to the system
mkstemp() function. In March 2000, the OpenBSD mkstemp() code was
translated to Perl for total control of the code's
security checking, to ensure the presence of the function regardless of
-operating system and to help with portability.
+operating system and to help with portability. The module was shipped
+as a standard part of perl from v5.6.1.
=head1 SEE ALSO
L<POSIX/tmpnam>, L<POSIX/tmpfile>, L<File::Spec>, L<File::Path>
-See L<IO::File> and L<File::MkTemp> for different implementations of
-temporary file handling.
+See L<IO::File> and L<File::MkTemp>, L<Apache::TempFile> for
+different implementations of temporary file handling.
=head1 AUTHOR
Tim Jenness E<lt>tjenness@cpan.orgE<gt>
-Copyright (C) 1999-2003 Tim Jenness and the UK Particle Physics and
+Copyright (C) 1999-2007 Tim Jenness and the UK Particle Physics and
Astronomy Research Council. All Rights Reserved. This program is free
software; you can redistribute it and/or modify it under the same
terms as Perl itself.