File Coverage

inc/File/Temp.pm
Criterion Covered Total %
statement 77 490 15.7
branch 5 328 1.5
condition 0 99 0.0
subroutine 25 57 43.8
pod 18 20 90.0
total 125 994 12.5


line stmt bran cond sub pod time code
1             #line 1
2             package File::Temp;
3              
4             #line 137
5              
6             # 5.6.0 gives us S_IWOTH, S_IWGRP, our and auto-vivifying filehandls
7             # People would like a version on 5.004 so give them what they want :-)
8             use 5.004;
9             use strict;
10             use Carp;
11             use File::Spec 0.8;
12             use File::Path qw/ rmtree /;
13             use Fcntl 1.03;
14             use IO::Seekable; # For SEEK_*
15             use Errno;
16             require VMS::Stdio if $^O eq 'VMS';
17              
18             # pre-emptively load Carp::Heavy. If we don't when we run out of file
19             # handles and attempt to call croak() we get an error message telling
20             # us that Carp::Heavy won't load rather than an error telling us we
21             # have run out of file handles. We either preload croak() or we
22             # switch the calls to croak from _gettemp() to use die.
23             eval { require Carp::Heavy; };
24              
25             # Need the Symbol package if we are running older perl
26             require Symbol if $] < 5.006;
27              
28             ### For the OO interface
29             use base qw/ IO::Handle IO::Seekable /;
30             use overload '""' => "STRINGIFY", fallback => 1;
31              
32             # use 'our' on v5.6.0
33             use vars qw($VERSION @EXPORT_OK %EXPORT_TAGS $DEBUG $KEEP_ALL);
34              
35             $DEBUG = 0;
36             $KEEP_ALL = 0;
37              
38             # We are exporting functions
39              
40             use base qw/Exporter/;
41              
42             # Export list - to allow fine tuning of export table
43              
44             @EXPORT_OK = qw{
45             tempfile
46             tempdir
47             tmpnam
48             tmpfile
49             mktemp
50             mkstemp
51             mkstemps
52             mkdtemp
53             unlink0
54             cleanup
55             SEEK_SET
56             SEEK_CUR
57             SEEK_END
58             };
59              
60             # Groups of functions for export
61              
62             %EXPORT_TAGS = (
63             'POSIX' => [qw/ tmpnam tmpfile /],
64             'mktemp' => [qw/ mktemp mkstemp mkstemps mkdtemp/],
65             'seekable' => [qw/ SEEK_SET SEEK_CUR SEEK_END /],
66             );
67              
68             # add contents of these tags to @EXPORT
69             Exporter::export_tags('POSIX','mktemp','seekable');
70              
71             # Version number
72              
73             $VERSION = '0.21';
74              
75             # This is a list of characters that can be used in random filenames
76              
77             my @CHARS = (qw/ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
78             a b c d e f g h i j k l m n o p q r s t u v w x y z
79             0 1 2 3 4 5 6 7 8 9 _
80             /);
81              
82             # Maximum number of tries to make a temp file before failing
83              
84             use constant MAX_TRIES => 1000;
85              
86             # Minimum number of X characters that should be in a template
87             use constant MINX => 4;
88              
89             # Default template when no template supplied
90              
91             use constant TEMPXXX => 'X' x 10;
92              
93             # Constants for the security level
94              
95             use constant STANDARD => 0;
96             use constant MEDIUM => 1;
97             use constant HIGH => 2;
98              
99             # OPENFLAGS. If we defined the flag to use with Sysopen here this gives
100             # us an optimisation when many temporary files are requested
101              
102             my $OPENFLAGS = O_CREAT | O_EXCL | O_RDWR;
103             my $LOCKFLAG;
104              
105             unless ($^O eq 'MacOS') {
106             for my $oflag (qw/ NOFOLLOW BINARY LARGEFILE NOINHERIT /) {
107             my ($bit, $func) = (0, "Fcntl::O_" . $oflag);
108             no strict 'refs';
109             $OPENFLAGS |= $bit if eval {
110             # Make sure that redefined die handlers do not cause problems
111             # e.g. CGI::Carp
112             local $SIG{__DIE__} = sub {};
113             local $SIG{__WARN__} = sub {};
114             $bit = &$func();
115             1;
116             };
117             }
118             # Special case O_EXLOCK
119             $LOCKFLAG = eval {
120             local $SIG{__DIE__} = sub {};
121             local $SIG{__WARN__} = sub {};
122             &Fcntl::O_EXLOCK();
123             };
124             }
125              
126             # On some systems the O_TEMPORARY flag can be used to tell the OS
127             # to automatically remove the file when it is closed. This is fine
128             # in most cases but not if tempfile is called with UNLINK=>0 and
129             # the filename is requested -- in the case where the filename is to
130             # be passed to another routine. This happens on windows. We overcome
131             # this by using a second open flags variable
132              
133             my $OPENTEMPFLAGS = $OPENFLAGS;
134             unless ($^O eq 'MacOS') {
135             for my $oflag (qw/ TEMPORARY /) {
136             my ($bit, $func) = (0, "Fcntl::O_" . $oflag);
137             local($@);
138             no strict 'refs';
139             $OPENTEMPFLAGS |= $bit if eval {
140 1     1   16194 # Make sure that redefined die handlers do not cause problems
  1         3  
141 1     1   3 # e.g. CGI::Carp
  1         1  
  1         19  
142 1     1   2 local $SIG{__DIE__} = sub {};
  1         1  
  1         80  
143 1     1   5 local $SIG{__WARN__} = sub {};
  1         18  
  1         25  
144 1     1   3 $bit = &$func();
  1         1  
  1         49  
145 1     1   4 1;
  1         12  
  1         203  
146 1     1   412 };
  1         5380  
  1         44  
147 1     1   4 }
  1         2  
  1         63  
148             }
149              
150             # Private hash tracking which files have been created by each process id via the OO interface
151             my %FILES_CREATED_BY_OBJECT;
152              
153             # INTERNAL ROUTINES - not to be used outside of package
154              
155             # Generic routine for getting a temporary filename
156             # modelled on OpenBSD _gettemp() in mktemp.c
157              
158             # The template must contain X's that are to be replaced
159             # with the random values
160              
161 1     1   4 # Arguments:
  1         1  
  1         68  
162 1     1   5  
  1         0  
  1         5  
163             # TEMPLATE - string containing the XXXXX's that is converted
164             # to a random filename and opened if required
165 1     1   48  
  1         1  
  1         58  
166             # Optionally, a hash can also be supplied containing specific options
167             # "open" => if true open the temp file, else just return the name
168             # default is 0
169             # "mkdir"=> if true, we are creating a temp directory rather than tempfile
170             # default is 0
171             # "suffixlen" => number of characters at end of PATH to be ignored.
172 1     1   3 # default is 0.
  1         1  
  1         94  
173             # "unlink_on_close" => indicates that, if possible, the OS should remove
174             # the file as soon as it is closed. Usually indicates
175             # use of the O_TEMPORARY flag to sysopen.
176             # Usually irrelevant on unix
177             # "use_exlock" => Indicates that O_EXLOCK should be used. Default is true.
178              
179             # Optionally a reference to a scalar can be passed into the function
180             # On error this will be used to store the reason for the error
181             # "ErrStr" => \$errstr
182              
183             # "open" and "mkdir" can not both be true
184             # "unlink_on_close" is not used when "mkdir" is true.
185              
186             # The default options are equivalent to mktemp().
187              
188             # Returns:
189             # filehandle - open file handle (if called with doopen=1, else undef)
190             # temp name - name of the temp file or directory
191              
192             # For example:
193             # ($fh, $name) = _gettemp($template, "open" => 1);
194              
195             # for the current version, failures are associated with
196             # stored in an error string and returned to give the reason whilst debugging
197             # This routine is not called by any external function
198             sub _gettemp {
199              
200             croak 'Usage: ($fh, $name) = _gettemp($template, OPTIONS);'
201             unless scalar(@_) >= 1;
202              
203             # the internal error string - expect it to be overridden
204             # Need this in case the caller decides not to supply us a value
205             # need an anonymous scalar
206             my $tempErrStr;
207              
208             # Default options
209             my %options = (
210             "open" => 0,
211             "mkdir" => 0,
212             "suffixlen" => 0,
213             "unlink_on_close" => 0,
214             "use_exlock" => 1,
215             "ErrStr" => \$tempErrStr,
216 1     1   4 );
  1         1  
  1         66  
217              
218             # Read the template
219 1     1   7 my $template = shift;
  1         1  
  1         40  
220             if (ref($template)) {
221             # Use a warning here since we have not yet merged ErrStr
222             carp "File::Temp::_gettemp: template must not be a reference";
223 1     1   4 return ();
  1         1  
  1         39  
224             }
225              
226             # Check that the number of entries on stack are even
227 1     1   3 if (scalar(@_) % 2 != 0) {
  1         1  
  1         34  
228 1     1   4 # Use a warning here since we have not yet merged ErrStr
  1         1  
  1         31  
229 1     1   3 carp "File::Temp::_gettemp: Must have even number of options";
  1         1  
  1         70  
230             return ();
231             }
232              
233             # Read the options and merge with defaults
234             %options = (%options, @_) if @_;
235              
236             # Make sure the error string is set to undef
237             ${$options{ErrStr}} = undef;
238              
239             # Can not open the file and make a directory in a single call
240 1     1   4 if ($options{"open"} && $options{"mkdir"}) {
  1         1  
  1         127  
241             ${$options{ErrStr}} = "doopen and domkdir can not both be true\n";
242             return ();
243             }
244              
245             # Find the start of the end of the Xs (position of last X)
246             # Substr starts from 0
247             my $start = length($template) - 1 - $options{"suffixlen"};
248              
249             # Check that we have at least MINX x X (e.g. 'XXXX") at the end of the string
250             # (taking suffixlen into account). Any fewer is insecure.
251              
252             # Do it using substr - no reason to use a pattern match since
253             # we know where we are looking and what we are looking for
254              
255             if (substr($template, $start - MINX + 1, MINX) ne 'X' x MINX) {
256             ${$options{ErrStr}} = "The template must end with at least ".
257             MINX . " 'X' characters\n";
258             return ();
259             }
260              
261             # Replace all the X at the end of the substring with a
262             # random character or just all the XX at the end of a full string.
263             # Do it as an if, since the suffix adjusts which section to replace
264             # and suffixlen=0 returns nothing if used in the substr directly
265             # and generate a full path from the template
266              
267             my $path = _replace_XX($template, $options{"suffixlen"});
268              
269              
270 1     1   3 # Split the path into constituent parts - eventually we need to check
  1         4  
  1         3734  
271             # whether the directory exists
272             # We need to know whether we are making a temp directory
273             # or a tempfile
274              
275             my ($volume, $directories, $file);
276             my $parent; # parent directory
277             if ($options{"mkdir"}) {
278             # There is no filename at the end
279             ($volume, $directories, $file) = File::Spec->splitpath( $path, 1);
280              
281             # The parent is then $directories without the last directory
282             # Split the directory and put it back together again
283             my @dirs = File::Spec->splitdir($directories);
284              
285             # If @dirs only has one entry (i.e. the directory template) that means
286             # we are in the current directory
287             if ($#dirs == 0) {
288             $parent = File::Spec->curdir;
289             } else {
290              
291             if ($^O eq 'VMS') { # need volume to avoid relative dir spec
292             $parent = File::Spec->catdir($volume, @dirs[0..$#dirs-1]);
293             $parent = 'sys$disk:[]' if $parent eq '';
294             } else {
295              
296             # Put it back together without the last one
297             $parent = File::Spec->catdir(@dirs[0..$#dirs-1]);
298              
299             # ...and attach the volume (no filename)
300             $parent = File::Spec->catpath($volume, $parent, '');
301             }
302              
303             }
304              
305             } else {
306              
307             # Get rid of the last filename (use File::Basename for this?)
308             ($volume, $directories, $file) = File::Spec->splitpath( $path );
309              
310             # Join up without the file part
311             $parent = File::Spec->catpath($volume,$directories,'');
312              
313             # If $parent is empty replace with curdir
314             $parent = File::Spec->curdir
315             unless $directories ne '';
316              
317             }
318              
319             # Check that the parent directories exist
320             # Do this even for the case where we are simply returning a name
321             # not a file -- no point returning a name that includes a directory
322             # that does not exist or is not writable
323              
324             unless (-e $parent) {
325             ${$options{ErrStr}} = "Parent directory ($parent) does not exist";
326             return ();
327             }
328             unless (-d $parent) {
329             ${$options{ErrStr}} = "Parent directory ($parent) is not a directory";
330             return ();
331             }
332 0 0   0   0  
333             # Check the stickiness of the directory and chown giveaway if required
334             # If the directory is world writable the sticky bit
335             # must be set
336              
337             if (File::Temp->safe_level == MEDIUM) {
338 0         0 my $safeerr;
339             unless (_is_safe($parent,\$safeerr)) {
340             ${$options{ErrStr}} = "Parent directory ($parent) is not safe ($safeerr)";
341 0         0 return ();
342             }
343             } elsif (File::Temp->safe_level == HIGH) {
344             my $safeerr;
345             unless (_is_verysafe($parent, \$safeerr)) {
346             ${$options{ErrStr}} = "Parent directory ($parent) is not safe ($safeerr)";
347             return ();
348             }
349             }
350              
351 0         0  
352 0 0       0 # Now try MAX_TRIES time to open the file
353             for (my $i = 0; $i < MAX_TRIES; $i++) {
354 0         0  
355 0         0 # Try to open the file if requested
356             if ($options{"open"}) {
357             my $fh;
358              
359 0 0       0 # If we are running before perl5.6.0 we can not auto-vivify
360             if ($] < 5.006) {
361 0         0 $fh = &Symbol::gensym;
362 0         0 }
363              
364             # Try to make sure this will be marked close-on-exec
365             # XXX: Win32 doesn't respect this, nor the proper fcntl,
366 0 0       0 # but may have O_NOINHERIT. This may or may not be in Fcntl.
367             local $^F = 2;
368              
369 0         0 # Attempt to open the file
  0         0  
370             my $open_success = undef;
371             if ( $^O eq 'VMS' and $options{"unlink_on_close"} && !$KEEP_ALL) {
372 0 0 0     0 # make it auto delete on close by setting FAB$V_DLT bit
373 0         0 $fh = VMS::Stdio::vmssysopen($path, $OPENFLAGS, 0600, 'fop=dlt');
  0         0  
374 0         0 $open_success = $fh;
375             } else {
376             my $flags = ( ($options{"unlink_on_close"} && !$KEEP_ALL) ?
377             $OPENTEMPFLAGS :
378             $OPENFLAGS );
379 0         0 $flags |= $LOCKFLAG if (defined $LOCKFLAG && $options{use_exlock});
380             $open_success = sysopen($fh, $path, $flags, 0600);
381             }
382             if ( $open_success ) {
383              
384             # in case of odd umask force rw
385             chmod(0600, $path);
386              
387 0 0       0 # Opened successfully - return file handle and name
388 0         0 return ($fh, $path);
  0         0  
389              
390 0         0 } else {
391              
392             # Error opening file - abort with error
393             # if the reason was anything but EEXIST
394             unless ($!{EEXIST}) {
395             ${$options{ErrStr}} = "Could not create temp file $path: $!";
396             return ();
397             }
398              
399 0         0 # Loop round for another try
400              
401             }
402             } elsif ($options{"mkdir"}) {
403              
404             # Open the temp directory
405             if (mkdir( $path, 0700)) {
406             # in case of odd umask
407 0         0 chmod(0700, $path);
408 0         0  
409 0 0       0 return undef, $path;
410             } else {
411 0         0  
412             # Abort with error if the reason for failure was anything
413             # except EEXIST
414             unless ($!{EEXIST}) {
415 0         0 ${$options{ErrStr}} = "Could not create directory $path: $!";
416             return ();
417             }
418              
419 0 0       0 # Loop round for another try
420 0         0  
421             }
422              
423 0 0       0 } else {
424 0         0  
425 0 0       0 # Return true if the file can not be found
426             # Directory has been checked previously
427              
428             return (undef, $path) unless -e $path;
429 0         0  
430             # Try again until MAX_TRIES
431              
432 0         0 }
433              
434             # Did not successfully open the tempfile/dir
435             # so try again with a different set of random letters
436             # No point in trying to increment unless we have only
437             # 1 X say and the randomness could come up with the same
438             # file MAX_TRIES in a row.
439              
440 0         0 # Store current attempt - in principal this implies that the
441             # 3rd time around the open attempt that the first temp file
442             # name could be generated again. Probably should store each
443 0         0 # attempt and make sure that none are repeated
444              
445             my $original = $path;
446 0 0       0 my $counter = 0; # Stop infinite loop
447             my $MAX_GUESS = 50;
448              
449             do {
450              
451             # Generate new name from original template
452             $path = _replace_XX($template, $options{"suffixlen"});
453              
454             $counter++;
455              
456 0 0       0 } until ($path ne $original || $counter > $MAX_GUESS);
457 0         0  
  0         0  
458 0         0 # Check for out of control looping
459             if ($counter > $MAX_GUESS) {
460 0 0       0 ${$options{ErrStr}} = "Tried to get a new temp name different to the previous value $MAX_GUESS times.\nSomething wrong with template?? ($template)";
461 0         0 return ();
  0         0  
462 0         0 }
463              
464             }
465              
466             # If we get here, we have run out of tries
467             ${ $options{ErrStr} } = "Have exceeded the maximum number of attempts ("
468             . MAX_TRIES . ") to open temp file/dir";
469 0 0       0  
    0          
470 0         0 return ();
471 0 0       0  
472 0         0 }
  0         0  
473 0         0  
474             # Internal routine to replace the XXXX... with random characters
475             # This has to be done by _gettemp() every time it fails to
476 0         0 # open a temp file/dir
477 0 0       0  
478 0         0 # Arguments: $template (the template with XXX),
  0         0  
479 0         0 # $ignore (number of characters at end to ignore)
480              
481             # Returns: modified template
482              
483             sub _replace_XX {
484              
485 0         0 croak 'Usage: _replace_XX($template, $ignore)'
486             unless scalar(@_) == 2;
487              
488 0 0       0 my ($path, $ignore) = @_;
    0          
489 0         0  
490             # Do it as an if, since the suffix adjusts which section to replace
491             # and suffixlen=0 returns nothing if used in the substr directly
492 0 0       0 # Alternatively, could simply set $ignore to length($path)-1
493 0         0 # Don't want to always use substr when not required though.
494             my $end = ( $] >= 5.006 ? "\\z" : "\\Z" );
495              
496             if ($ignore) {
497             substr($path, 0, - $ignore) =~ s/X(?=X*$end)/$CHARS[ int( rand( @CHARS ) ) ]/ge;
498             } else {
499 0         0 $path =~ s/X(?=X*$end)/$CHARS[ int( rand( @CHARS ) ) ]/ge;
500             }
501             return $path;
502 0         0 }
503 0 0 0     0  
      0        
504             # Internal routine to force a temp file to be writable after
505 0         0 # it is created so that we can unlink it. Windows seems to occassionally
506 0         0 # force a file to be readonly when written to certain temp locations
507             sub _force_writable {
508 0 0 0     0 my $file = shift;
509             chmod 0600, $file;
510             }
511 0 0 0     0  
512 0         0  
513             # internal routine to check to see if the directory is safe
514 0 0       0 # First checks to see if the directory is not owned by the
515             # current user or root. Then checks to see if anyone else
516             # can write to the directory and if so, checks to see if
517 0         0 # it has the sticky bit set
518              
519             # Will not work on systems that do not support sticky bit
520 0         0  
521             #Args: directory path to check
522             # Optionally: reference to scalar to contain error message
523             # Returns true if the path is safe and false otherwise.
524             # Returns undef if can not even run stat() on the path
525              
526 0 0       0 # This routine based on version written by Tom Christiansen
527 0         0  
  0         0  
528 0         0 # Presumably, by the time we actually attempt to create the
529             # file or directory in this directory, it may not be safe
530             # anymore... Have to run _is_safe directly after the open.
531              
532             sub _is_safe {
533              
534             my $path = shift;
535             my $err_ref = shift;
536              
537 0 0       0 # Stat path
538             my @info = stat($path);
539 0         0 unless (scalar(@info)) {
540             $$err_ref = "stat(path) returned no values";
541 0         0 return 0;
542             }
543             ;
544             return 1 if $^O eq 'VMS'; # owner delete control at file level
545              
546 0 0       0 # Check to see whether owner is neither superuser (or a system uid) nor me
547 0         0 # Use the effective uid from the $> variable
  0         0  
548 0         0 # UID is in [4]
549             if ($info[4] > File::Temp->top_system_uid() && $info[4] != $>) {
550              
551             Carp::cluck(sprintf "uid=$info[4] topuid=%s euid=$> path='$path'",
552             File::Temp->top_system_uid());
553              
554             $$err_ref = "Directory owned neither by root nor the current user"
555             if ref($err_ref);
556             return 0;
557             }
558              
559             # check whether group or other can write file
560 0 0       0 # use 066 to detect either reading or writing
561             # use 022 to check writability
562             # Do it with S_IWOTH and S_IWGRP for portability (maybe)
563             # mode is in info[2]
564             if (($info[2] & &Fcntl::S_IWGRP) || # Is group writable?
565             ($info[2] & &Fcntl::S_IWOTH) ) { # Is world writable?
566             # Must be a directory
567             unless (-d $path) {
568             $$err_ref = "Path ($path) is not a directory"
569             if ref($err_ref);
570             return 0;
571             }
572             # Must have sticky bit set
573             unless (-k $path) {
574             $$err_ref = "Sticky bit not set on $path when dir is group|world writable"
575             if ref($err_ref);
576             return 0;
577 0         0 }
578 0         0 }
579 0         0  
580             return 1;
581 0   0     0 }
582              
583             # Internal routine to check whether a directory is safe
584 0         0 # for temp files. Safer than _is_safe since it checks for
585             # the possibility of chown giveaway and if that is a possibility
586 0         0 # checks each directory in the path to see if it is safe (with _is_safe)
587              
588             # If _PC_CHOWN_RESTRICTED is not set, does the full test of each
589             # directory anyway.
590              
591 0 0       0 # Takes optional second arg as scalar ref to error reason
592 0         0  
  0         0  
593 0         0 sub _is_verysafe {
594              
595             # Need POSIX - but only want to bother if really necessary due to overhead
596             require POSIX;
597              
598             my $path = shift;
599 0         0 print "_is_verysafe testing $path\n" if $DEBUG;
  0         0  
600             return 1 if $^O eq 'VMS'; # owner delete control at file level
601              
602 0         0 my $err_ref = shift;
603              
604             # Should Get the value of _PC_CHOWN_RESTRICTED if it is defined
605             # and If it is not there do the extensive test
606             local($@);
607             my $chown_restricted;
608             $chown_restricted = &POSIX::_PC_CHOWN_RESTRICTED()
609             if eval { &POSIX::_PC_CHOWN_RESTRICTED(); 1};
610              
611             # If chown_resticted is set to some value we should test it
612             if (defined $chown_restricted) {
613              
614             # Return if the current directory is safe
615             return _is_safe($path,$err_ref) if POSIX::sysconf( $chown_restricted );
616              
617 0 0   0   0 }
618              
619             # To reach this point either, the _PC_CHOWN_RESTRICTED symbol
620 0         0 # was not avialable or the symbol was there but chown giveaway
621             # is allowed. Either way, we now have to test the entire tree for
622             # safety.
623              
624             # Convert path to an absolute directory if required
625             unless (File::Spec->file_name_is_absolute($path)) {
626 0 0       0 $path = File::Spec->rel2abs($path);
627             }
628 0 0       0  
629 0         0 # Split directory into components - assume no file
  0         0  
630             my ($volume, $directories, undef) = File::Spec->splitpath( $path, 1);
631 0         0  
  0         0  
632             # Slightly less efficient than having a function in File::Spec
633 0         0 # to chop off the end of a directory or even a function that
634             # can handle ../ in a directory tree
635             # Sometimes splitdir() returns a blank at the end
636             # so we will probably check the bottom directory twice in some cases
637             my @dirs = File::Spec->splitdir($directories);
638              
639             # Concatenate one less directory each time around
640 0     0   0 foreach my $pos (0.. $#dirs) {
641 0         0 # Get a directory name
642             my $dir = File::Spec->catpath($volume,
643             File::Spec->catdir(@dirs[0.. $#dirs - $pos]),
644             ''
645             );
646              
647             print "TESTING DIR $dir\n" if $DEBUG;
648              
649             # Check the directory
650             return 0 unless _is_safe($dir,$err_ref);
651              
652             }
653              
654             return 1;
655             }
656              
657              
658              
659             # internal routine to determine whether unlink works on this
660             # platform for files that are currently open.
661             # Returns true if we can, false otherwise.
662              
663             # Currently WinNT, OS/2 and VMS can not unlink an opened file
664             # On VMS this is because the O_EXCL flag is used to open the
665             # temporary file. Currently I do not know enough about the issues
666 0     0   0 # on VMS to decide whether O_EXCL is a requirement.
667 0         0  
668             sub _can_unlink_opened_file {
669              
670 0         0 if ($^O eq 'MSWin32' || $^O eq 'os2' || $^O eq 'VMS' || $^O eq 'dos' || $^O eq 'MacOS') {
671 0 0       0 return 0;
672 0         0 } else {
673 0         0 return 1;
674             }
675              
676 0 0       0 }
677              
678             # internal routine to decide which security levels are allowed
679             # see safe_level() for more information on this
680              
681 0 0 0     0 # Controls whether the supplied security level is allowed
682              
683 0         0 # $cando = _can_do_level( $level )
684              
685             sub _can_do_level {
686 0 0       0  
687             # Get security level
688 0         0 my $level = shift;
689              
690             # Always have to be able to do STANDARD
691             return 1 if $level == STANDARD;
692              
693             # Currently, the systems that can do HIGH or MEDIUM are identical
694             if ( $^O eq 'MSWin32' || $^O eq 'os2' || $^O eq 'cygwin' || $^O eq 'dos' || $^O eq 'MacOS' || $^O eq 'mpeix') {
695             return 0;
696 0 0 0     0 } else {
697             return 1;
698             }
699 0 0       0  
700 0 0       0 }
701              
702 0         0 # This routine sets up a deferred unlinking of a specified
703             # filename and filehandle. It is used in the following cases:
704             # - Called by unlink0 if an opened file can not be unlinked
705 0 0       0 # - Called by tempfile() if files are to be removed on shutdown
706 0 0       0 # - Called by tempdir() if directories are to be removed on shutdown
707              
708 0         0 # Arguments:
709             # _deferred_unlink( $fh, $fname, $isdir );
710             #
711             # - filehandle (so that it can be expclicitly closed if open
712 0         0 # - filename (the thing we want to remove)
713             # - isdir (flag to indicate that we are being given a directory)
714             # [and hence no filehandle]
715              
716             # Status is not referred to since all the magic is done with an END block
717              
718             {
719             # Will set up two lexical variables to contain all the files to be
720             # removed. One array for files, another for directories They will
721             # only exist in this block.
722              
723             # This means we only have to set up a single END block to remove
724             # all files.
725              
726             # in order to prevent child processes inadvertently deleting the parent
727             # temp files we use a hash to store the temp files and directories
728 0     0   0 # created by a particular process id.
729              
730 0         0 # %files_to_unlink contains values that are references to an array of
731 0 0       0 # array references containing the filehandle and filename associated with
732 0 0       0 # the temp file.
733             my (%files_to_unlink, %dirs_to_unlink);
734 0         0  
735             # Set up an end block to use these arrays
736             END {
737             local($., $@, $!, $^E, $?);
738 0         0 cleanup();
739 0         0 }
740              
741 0 0       0 # Cleanup function. Always triggered on END but can be invoked
  0         0  
  0         0  
742             # manually.
743             sub cleanup {
744 0 0       0 if (!$KEEP_ALL) {
745             # Files
746             my @files = (exists $files_to_unlink{$$} ?
747 0 0       0 @{ $files_to_unlink{$$} } : () );
748             foreach my $file (@files) {
749             # close the filehandle without checking its state
750             # in order to make real sure that this is closed
751             # if its already closed then I dont care about the answer
752             # probably a better way to do this
753             close($file->[0]); # file handle is [0]
754              
755             if (-f $file->[1]) { # file name is [1]
756             _force_writable( $file->[1] ); # for windows
757 0 0       0 unlink $file->[1] or warn "Error removing ".$file->[1];
758 0         0 }
759             }
760             # Dirs
761             my @dirs = (exists $dirs_to_unlink{$$} ?
762 0         0 @{ $dirs_to_unlink{$$} } : () );
763             foreach my $dir (@dirs) {
764             if (-d $dir) {
765             # Some versions of rmtree will abort if you attempt to remove
766             # the directory you are sitting in. We protect that and turn it
767             # into a warning. We do this because this occurs during
768             # cleanup and so can not be caught by the user.
769 0         0 eval { rmtree($dir, $DEBUG, 0); };
770             warn $@ if ($@ && $^W);
771             }
772 0         0 }
773              
774 0         0 # clear the arrays
775             @{ $files_to_unlink{$$} } = ()
776             if exists $files_to_unlink{$$};
777             @{ $dirs_to_unlink{$$} } = ()
778             if exists $dirs_to_unlink{$$};
779 0 0       0 }
780             }
781              
782 0 0       0  
783             # This is the sub called to register a file for deferred unlinking
784             # This could simply store the input parameters and defer everything
785             # until the END block. For now we do a bit of checking at this
786 0         0 # point in order to make sure that (1) we have a file/dir to delete
787             # and (2) we have been called with the correct arguments.
788             sub _deferred_unlink {
789              
790             croak 'Usage: _deferred_unlink($fh, $fname, $isdir)'
791             unless scalar(@_) == 3;
792              
793             my ($fh, $fname, $isdir) = @_;
794              
795             warn "Setting up deferred removal of $fname\n"
796             if $DEBUG;
797              
798             # If we have a directory, check that it is a directory
799             if ($isdir) {
800              
801             if (-d $fname) {
802 0 0 0 0   0  
      0        
      0        
      0        
803 0         0 # Directory exists so store it
804             # first on VMS turn []foo into [.foo] for rmtree
805 0         0 $fname = VMS::Filespec::vmspath($fname) if $^O eq 'VMS';
806             $dirs_to_unlink{$$} = []
807             unless exists $dirs_to_unlink{$$};
808             push (@{ $dirs_to_unlink{$$} }, $fname);
809              
810             } else {
811             carp "Request to remove directory $fname could not be completed since it does not exist!\n" if $^W;
812             }
813              
814             } else {
815              
816             if (-f $fname) {
817              
818             # file exists so store handle and name for later removal
819             $files_to_unlink{$$} = []
820 0     0   0 unless exists $files_to_unlink{$$};
821             push(@{ $files_to_unlink{$$} }, [$fh, $fname]);
822              
823 0 0       0 } else {
824             carp "Request to remove file $fname could not be completed since it is not there!\n" if $^W;
825             }
826 0 0 0     0  
      0        
      0        
      0        
      0        
827 0         0 }
828              
829 0         0 }
830              
831              
832             }
833              
834             #line 1007
835              
836             sub new {
837             my $proto = shift;
838             my $class = ref($proto) || $proto;
839              
840             # read arguments and convert keys to upper case
841             my %args = @_;
842             %args = map { uc($_), $args{$_} } keys %args;
843              
844             # see if they are unlinking (defaulting to yes)
845             my $unlink = (exists $args{UNLINK} ? $args{UNLINK} : 1 );
846             delete $args{UNLINK};
847              
848             # template (store it in an array so that it will
849             # disappear from the arg list of tempfile)
850             my @template = ( exists $args{TEMPLATE} ? $args{TEMPLATE} : () );
851             delete $args{TEMPLATE};
852              
853             # Protect OPEN
854             delete $args{OPEN};
855              
856             # Open the file and retain file handle and file name
857             my ($fh, $path) = tempfile( @template, %args );
858              
859             print "Tmp: $fh - $path\n" if $DEBUG;
860              
861             # Store the filename in the scalar slot
862             ${*$fh} = $path;
863              
864             # Cache the filename by pid so that the destructor can decide whether to remove it
865             $FILES_CREATED_BY_OBJECT{$$}{$path} = 1;
866              
867             # Store unlink information in hash slot (plus other constructor info)
868             %{*$fh} = %args;
869 1     1   22  
870 1         3 # create the object
871             bless $fh, $class;
872              
873             # final method-based configuration
874             $fh->unlink_on_destroy( $unlink );
875              
876 1 50   1 1 3 return $fh;
877             }
878              
879 1 50       4 #line 1065
  0         0  
880 1         2  
881             sub newdir {
882             my $self = shift;
883              
884             # need to handle args as in tempdir because we have to force CLEANUP
885 0         0 # default without passing CLEANUP to tempdir
886             my $template = (scalar(@_) % 2 == 1 ? shift(@_) : undef );
887 0 0       0 my %options = @_;
888 0         0 my $cleanup = (exists $options{CLEANUP} ? $options{CLEANUP} : 1 );
889 0 0       0  
890             delete $options{CLEANUP};
891              
892             my $tempdir;
893             if (defined $template) {
894 1 50       2 $tempdir = tempdir( $template, %options );
  0         0  
895 1         1 } else {
896 0 0       0 $tempdir = tempdir( %options );
897             }
898             return bless { DIRNAME => $tempdir,
899             CLEANUP => $cleanup,
900             LAUNCHPID => $$,
901 0         0 }, "File::Temp::Dir";
  0         0  
902 0 0 0     0 }
903              
904             #line 1100
905              
906             sub filename {
907 0         0 my $self = shift;
908 1 50       3 return ${*$self};
909 0           }
910 1 50       8  
911             sub STRINGIFY {
912             my $self = shift;
913             return $self->filename;
914             }
915              
916             #line 1130
917              
918             sub unlink_on_destroy {
919             my $self = shift;
920             if (@_) {
921             ${*$self}{UNLINK} = shift;
922 0 0   0     }
923             return ${*$self}{UNLINK};
924             }
925 0            
926             #line 1159
927 0 0          
928             sub DESTROY {
929             local($., $@, $!, $^E, $?);
930             my $self = shift;
931 0 0          
932             # Make sure we always remove the file from the global hash
933 0 0         # on destruction. This prevents the hash from growing uncontrollably
934             # and post-destruction there is no reason to know about the file.
935             my $file = $self->filename;
936             my $was_created_by_proc;
937 0 0         if (exists $FILES_CREATED_BY_OBJECT{$$}{$file}) {
938             $was_created_by_proc = 1;
939 0 0         delete $FILES_CREATED_BY_OBJECT{$$}{$file};
940 0           }
  0            
941              
942             if (${*$self}{UNLINK} && !$KEEP_ALL) {
943 0 0         print "# ---------> Unlinking $self\n" if $DEBUG;
944              
945             # only delete if this process created it
946             return unless $was_created_by_proc;
947              
948 0 0         # The unlink1 may fail if the file has been closed
949             # by the caller. This leaves us with the decision
950             # of whether to refuse to remove the file or simply
951             # do an unlink without test. Seems to be silly
952 0 0         # to do this when we are trying to be careful
953 0           # about security
  0            
954             _force_writable( $file ); # for windows
955             unlink1( $self, $file )
956 0 0         or unlink($file);
957             }
958             }
959              
960             #line 1293
961              
962             sub tempfile {
963              
964             # Can not check for argument count since we can have any
965             # number of args
966              
967             # Default options
968             my %options = (
969             "DIR" => undef, # Directory prefix
970             "SUFFIX" => '', # Template suffix
971             "UNLINK" => 0, # Do not unlink file on exit
972             "OPEN" => 1, # Open file
973             "TMPDIR" => 0, # Place tempfile in tempdir if template specified
974             "EXLOCK" => 1, # Open file with O_EXLOCK
975             );
976              
977             # Check to see whether we have an odd or even number of arguments
978             my $template = (scalar(@_) % 2 == 1 ? shift(@_) : undef);
979              
980             # Read the options and merge with defaults
981             %options = (%options, @_) if @_;
982              
983             # First decision is whether or not to open the file
984             if (! $options{"OPEN"}) {
985              
986             warn "tempfile(): temporary filename requested but not opened.\nPossibly unsafe, consider using tempfile() with OPEN set to true\n"
987             if $^W;
988              
989             }
990              
991             if ($options{"DIR"} and $^O eq 'VMS') {
992              
993             # on VMS turn []foo into [.foo] for concatenation
994             $options{"DIR"} = VMS::Filespec::vmspath($options{"DIR"});
995             }
996              
997             # Construct the template
998              
999             # Have a choice of trying to work around the mkstemp/mktemp/tmpnam etc
1000             # functions or simply constructing a template and using _gettemp()
1001             # explicitly. Go for the latter
1002              
1003             # First generate a template if not defined and prefix the directory
1004             # If no template must prefix the temp directory
1005             if (defined $template) {
1006             # End up with current directory if neither DIR not TMPDIR are set
1007             if ($options{"DIR"}) {
1008              
1009 0     0 1   $template = File::Spec->catfile($options{"DIR"}, $template);
1010 0   0        
1011             } elsif ($options{TMPDIR}) {
1012              
1013 0           $template = File::Spec->catfile(File::Spec->tmpdir, $template );
1014 0            
  0            
1015             }
1016              
1017 0 0         } else {
1018 0            
1019             if ($options{"DIR"}) {
1020              
1021             $template = File::Spec->catfile($options{"DIR"}, TEMPXXX);
1022 0 0          
1023 0           } else {
1024              
1025             $template = File::Spec->catfile(File::Spec->tmpdir, TEMPXXX);
1026 0            
1027             }
1028              
1029 0           }
1030              
1031 0 0         # Now add a suffix
1032             $template .= $options{"SUFFIX"};
1033              
1034 0           # Determine whether we should tell _gettemp to unlink the file
  0            
1035             # On unix this is irrelevant and can be worked out after the file is
1036             # opened (simply by unlinking the open filehandle). On Windows or VMS
1037 0           # we have to indicate temporary-ness when we open the file. In general
1038             # we only want a true temporary file if we are returning just the
1039             # filehandle - if the user wants the filename they probably do not
1040 0           # want the file to disappear as soon as they close it (which may be
  0            
1041             # important if they want a child process to use the file)
1042             # For this reason, tie unlink_on_close to the return context regardless
1043 0           # of OS.
1044             my $unlink_on_close = ( wantarray ? 0 : 1);
1045              
1046 0           # Create the file
1047             my ($fh, $path, $errstr);
1048 0           croak "Error in tempfile() using $template: $errstr"
1049             unless (($fh, $path) = _gettemp($template,
1050             "open" => $options{'OPEN'},
1051             "mkdir"=> 0 ,
1052             "unlink_on_close" => $unlink_on_close,
1053             "suffixlen" => length($options{'SUFFIX'}),
1054             "ErrStr" => \$errstr,
1055             "use_exlock" => $options{EXLOCK},
1056             ) );
1057              
1058             # Set up an exit handler that can do whatever is right for the
1059             # system. This removes files at exit when requested explicitly or when
1060             # system is asked to unlink_on_close but is unable to do so because
1061             # of OS limitations.
1062             # The latter should be achieved by using a tied filehandle.
1063             # Do not check return status since this is all done with END blocks.
1064             _deferred_unlink($fh, $path, 0) if $options{"UNLINK"};
1065              
1066             # Return
1067 0     0 1   if (wantarray()) {
1068              
1069             if ($options{'OPEN'}) {
1070             return ($fh, $path);
1071 0 0         } else {
1072 0           return (undef, $path);
1073 0 0         }
1074              
1075 0           } else {
1076              
1077 0           # Unlink the file. It is up to unlink0 to decide what to do with
1078 0 0         # this (whether to unlink now or to defer until later)
1079 0           unlink0($fh, $path) or croak "Error unlinking file $path using unlink0";
1080              
1081 0           # Return just the filehandle.
1082             return $fh;
1083 0           }
1084              
1085              
1086             }
1087              
1088             #line 1482
1089              
1090             # '
1091              
1092             sub tempdir {
1093              
1094             # Can not check for argument count since we can have any
1095             # number of args
1096              
1097             # Default options
1098             my %options = (
1099             "CLEANUP" => 0, # Remove directory on exit
1100             "DIR" => '', # Root directory
1101             "TMPDIR" => 0, # Use tempdir with template
1102 0     0 1   );
1103 0            
  0            
1104             # Check to see whether we have an odd or even number of arguments
1105             my $template = (scalar(@_) % 2 == 1 ? shift(@_) : undef );
1106              
1107 0     0 0   # Read the options and merge with defaults
1108 0           %options = (%options, @_) if @_;
1109              
1110             # Modify or generate the template
1111              
1112             # Deal with the DIR and TMPDIR options
1113             if (defined $template) {
1114              
1115             # Need to strip directory path if using DIR or TMPDIR
1116             if ($options{'TMPDIR'} || $options{'DIR'}) {
1117              
1118             # Strip parent directory from the filename
1119             #
1120             # There is no filename at the end
1121             $template = VMS::Filespec::vmspath($template) if $^O eq 'VMS';
1122             my ($volume, $directories, undef) = File::Spec->splitpath( $template, 1);
1123              
1124             # Last directory is then our template
1125             $template = (File::Spec->splitdir($directories))[-1];
1126              
1127             # Prepend the supplied directory or temp dir
1128             if ($options{"DIR"}) {
1129              
1130             $template = File::Spec->catdir($options{"DIR"}, $template);
1131              
1132 0     0 1   } elsif ($options{TMPDIR}) {
1133 0 0          
1134 0           # Prepend tmpdir
  0            
1135             $template = File::Spec->catdir(File::Spec->tmpdir, $template);
1136 0            
  0            
1137             }
1138              
1139             }
1140              
1141             } else {
1142              
1143             if ($options{"DIR"}) {
1144              
1145             $template = File::Spec->catdir($options{"DIR"}, TEMPXXX);
1146              
1147             } else {
1148              
1149             $template = File::Spec->catdir(File::Spec->tmpdir, TEMPXXX);
1150              
1151             }
1152              
1153             }
1154              
1155             # Create the directory
1156             my $tempdir;
1157             my $suffixlen = 0;
1158             if ($^O eq 'VMS') { # dir names can end in delimiters
1159             $template =~ m/([\.\]:>]+)$/;
1160             $suffixlen = length($1);
1161 0     0     }
1162 0           if ( ($^O eq 'MacOS') && (substr($template, -1) eq ':') ) {
1163             # dir name has a trailing ':'
1164             ++$suffixlen;
1165             }
1166              
1167 0           my $errstr;
1168 0           croak "Error in tempdir() using $template: $errstr"
1169 0 0         unless ((undef, $tempdir) = _gettemp($template,
1170 0           "open" => 0,
1171 0           "mkdir"=> 1 ,
1172             "suffixlen" => $suffixlen,
1173             "ErrStr" => \$errstr,
1174 0 0 0       ) );
  0            
1175 0 0          
1176             # Install exit handler; must be dynamic to get lexical
1177             if ( $options{'CLEANUP'} && -d $tempdir) {
1178 0 0         _deferred_unlink(undef, $tempdir, 1);
1179             }
1180              
1181             # Return the dir name
1182             return $tempdir;
1183              
1184             }
1185              
1186 0           #line 1604
1187 0 0          
1188              
1189              
1190             sub mkstemp {
1191              
1192             croak "Usage: mkstemp(template)"
1193             if scalar(@_) != 1;
1194              
1195             my $template = shift;
1196              
1197             my ($fh, $path, $errstr);
1198             croak "Error in mkstemp using $template: $errstr"
1199             unless (($fh, $path) = _gettemp($template,
1200             "open" => 1,
1201             "mkdir"=> 0 ,
1202             "suffixlen" => 0,
1203             "ErrStr" => \$errstr,
1204             ) );
1205              
1206             if (wantarray()) {
1207             return ($fh, $path);
1208             } else {
1209             return $fh;
1210             }
1211              
1212             }
1213              
1214              
1215             #line 1647
1216              
1217             sub mkstemps {
1218              
1219             croak "Usage: mkstemps(template, suffix)"
1220             if scalar(@_) != 2;
1221              
1222              
1223             my $template = shift;
1224             my $suffix = shift;
1225              
1226             $template .= $suffix;
1227              
1228             my ($fh, $path, $errstr);
1229             croak "Error in mkstemps using $template: $errstr"
1230             unless (($fh, $path) = _gettemp($template,
1231             "open" => 1,
1232             "mkdir"=> 0 ,
1233             "suffixlen" => length($suffix),
1234             "ErrStr" => \$errstr,
1235             ) );
1236              
1237             if (wantarray()) {
1238             return ($fh, $path);
1239             } else {
1240             return $fh;
1241             }
1242              
1243             }
1244              
1245             #line 1690
1246              
1247             #' # for emacs
1248              
1249             sub mkdtemp {
1250              
1251             croak "Usage: mkdtemp(template)"
1252             if scalar(@_) != 1;
1253              
1254             my $template = shift;
1255             my $suffixlen = 0;
1256             if ($^O eq 'VMS') { # dir names can end in delimiters
1257             $template =~ m/([\.\]:>]+)$/;
1258             $suffixlen = length($1);
1259             }
1260             if ( ($^O eq 'MacOS') && (substr($template, -1) eq ':') ) {
1261             # dir name has a trailing ':'
1262             ++$suffixlen;
1263             }
1264             my ($junk, $tmpdir, $errstr);
1265             croak "Error creating temp directory from template $template\: $errstr"
1266             unless (($junk, $tmpdir) = _gettemp($template,
1267             "open" => 0,
1268             "mkdir"=> 1 ,
1269             "suffixlen" => $suffixlen,
1270             "ErrStr" => \$errstr,
1271             ) );
1272              
1273             return $tmpdir;
1274              
1275             }
1276              
1277             #line 1733
1278              
1279             sub mktemp {
1280              
1281             croak "Usage: mktemp(template)"
1282             if scalar(@_) != 1;
1283              
1284             my $template = shift;
1285              
1286             my ($tmpname, $junk, $errstr);
1287             croak "Error getting name to temp file from template $template: $errstr"
1288             unless (($junk, $tmpname) = _gettemp($template,
1289             "open" => 0,
1290             "mkdir"=> 0 ,
1291             "suffixlen" => 0,
1292             "ErrStr" => \$errstr,
1293             ) );
1294              
1295             return $tmpname;
1296             }
1297              
1298             #line 1795
1299              
1300 0     0 1   sub tmpnam {
1301              
1302             # Retrieve the temporary directory name
1303             my $tmpdir = File::Spec->tmpdir;
1304              
1305             croak "Error temporary directory is not writable"
1306             if $tmpdir eq '';
1307              
1308             # Use a ten character template and append to tmpdir
1309             my $template = File::Spec->catfile($tmpdir, TEMPXXX);
1310 0 0          
1311             if (wantarray() ) {
1312             return mkstemp($template);
1313 0 0         } else {
1314             return mktemp($template);
1315             }
1316 0 0          
1317             }
1318 0 0          
1319             #line 1831
1320              
1321             sub tmpfile {
1322              
1323 0 0 0       # Simply call tmpnam() in a list context
1324             my ($fh, $file) = tmpnam();
1325              
1326 0           # Make sure file is removed when filehandle is closed
1327             # This will fail on NFS
1328             unlink0($fh, $file)
1329             or return undef;
1330              
1331             return $fh;
1332              
1333             }
1334              
1335             #line 1876
1336              
1337 0 0         sub tempnam {
1338              
1339 0 0         croak 'Usage tempnam($dir, $prefix)' unless scalar(@_) == 2;
    0          
1340              
1341 0           my ($dir, $prefix) = @_;
1342              
1343             # Add a string to the prefix
1344             $prefix .= 'XXXXXXXX';
1345 0            
1346             # Concatenate the directory to the file
1347             my $template = File::Spec->catfile($dir, $prefix);
1348              
1349             return mktemp($template);
1350              
1351 0 0         }
1352              
1353 0           #line 1948
1354              
1355             sub unlink0 {
1356              
1357 0           croak 'Usage: unlink0(filehandle, filename)'
1358             unless scalar(@_) == 2;
1359              
1360             # Read args
1361             my ($fh, $path) = @_;
1362              
1363             cmpstat($fh, $path) or return 0;
1364 0            
1365             # attempt remove the file (does not work on some platforms)
1366             if (_can_unlink_opened_file()) {
1367              
1368             # return early (Without unlink) if we have been instructed to retain files.
1369             return 1 if $KEEP_ALL;
1370              
1371             # XXX: do *not* call this on a directory; possible race
1372             # resulting in recursive removal
1373             croak "unlink0: $path has become a directory!" if -d $path;
1374             unlink($path) or return 0;
1375              
1376 0 0         # Stat the filehandle
1377             my @fh = stat $fh;
1378              
1379 0           print "Link count = $fh[3] \n" if $DEBUG;
1380              
1381             # Make sure that the link count is zero
1382             # - Cygwin provides deferred unlinking, however,
1383             # on Win9x the link count remains 1
1384             # On NFS the link count may still be 1 but we cant know that
1385             # we are on NFS
1386             return ( $fh[3] == 0 or $^O eq 'cygwin' ? 1 : 0);
1387              
1388 0 0         } else {
1389             _deferred_unlink($fh, $path, 0);
1390             return 1;
1391             }
1392              
1393             }
1394              
1395             #line 2013
1396 0 0          
1397             sub cmpstat {
1398              
1399 0 0         croak 'Usage: cmpstat(filehandle, filename)'
1400             unless scalar(@_) == 2;
1401 0 0          
1402 0           # Read args
1403             my ($fh, $path) = @_;
1404 0            
1405             warn "Comparing stat\n"
1406             if $DEBUG;
1407              
1408             # Stat the filehandle - which may be closed if someone has manually
1409             # closed the file. Can not turn off warnings without using $^W
1410             # unless we upgrade to 5.006 minimum requirement
1411 0 0         my @fh;
1412             {
1413             local ($^W) = 0;
1414 0           @fh = stat $fh;
1415             }
1416             return unless @fh;
1417              
1418             if ($fh[3] > 1 && $^W) {
1419             carp "unlink0: fstat found too many links; SB=@fh" if $^W;
1420             }
1421              
1422             # Stat the path
1423             my @path = stat $path;
1424              
1425             unless (@path) {
1426             carp "unlink0: $path is gone already" if $^W;
1427             return;
1428             }
1429              
1430             # this is no longer a file, but may be a directory, or worse
1431             unless (-f $path) {
1432             confess "panic: $path is no longer a file: SB=@fh";
1433             }
1434              
1435             # Do comparison of each member of the array
1436             # On WinNT dev and rdev seem to be different
1437             # depending on whether it is a file or a handle.
1438             # Cannot simply compare all members of the stat return
1439             # Select the ones we can use
1440             my @okstat = (0..$#fh); # Use all by default
1441             if ($^O eq 'MSWin32') {
1442             @okstat = (1,2,3,4,5,7,8,9,10);
1443             } elsif ($^O eq 'os2') {
1444             @okstat = (0, 2..$#fh);
1445             } elsif ($^O eq 'VMS') { # device and file ID are sufficient
1446             @okstat = (0, 1);
1447             } elsif ($^O eq 'dos') {
1448             @okstat = (0,2..7,11..$#fh);
1449             } elsif ($^O eq 'mpeix') {
1450             @okstat = (0..4,8..10);
1451             }
1452              
1453             # Now compare each entry explicitly by number
1454             for (@okstat) {
1455             print "Comparing: $_ : $fh[$_] and $path[$_]\n" if $DEBUG;
1456             # Use eq rather than == since rdev, blksize, and blocks (6, 11,
1457             # and 12) will be '' on platforms that do not support them. This
1458             # is fine since we are only comparing integers.
1459             unless ($fh[$_] eq $path[$_]) {
1460             warn "Did not match $_ element of stat\n" if $DEBUG;
1461             return 0;
1462             }
1463             }
1464              
1465             return 1;
1466             }
1467              
1468             #line 2106
1469              
1470             sub unlink1 {
1471             croak 'Usage: unlink1(filehandle, filename)'
1472             unless scalar(@_) == 2;
1473              
1474             # Read args
1475             my ($fh, $path) = @_;
1476              
1477             cmpstat($fh, $path) or return 0;
1478              
1479             # Close the file
1480             close( $fh ) or return 0;
1481              
1482             # Make sure the file is writable (for windows)
1483             _force_writable( $path );
1484              
1485             # return early (without unlink) if we have been instructed to retain files.
1486             return 1 if $KEEP_ALL;
1487              
1488             # remove the file
1489             return unlink($path);
1490             }
1491 0     0 1    
1492             #line 2221
1493              
1494             {
1495             # protect from using the variable itself
1496             my $LEVEL = STANDARD;
1497             sub safe_level {
1498 0 0         my $self = shift;
1499             if (@_) {
1500             my $level = shift;
1501 0 0         if (($level != STANDARD) && ($level != MEDIUM) && ($level != HIGH)) {
1502             carp "safe_level: Specified level ($level) not STANDARD, MEDIUM or HIGH - ignoring\n" if $^W;
1503             } else {
1504             # Dont allow this on perl 5.005 or earlier
1505             if ($] < 5.006 && $level != STANDARD) {
1506 0 0         # Cant do MEDIUM or HIGH checks
1507             croak "Currently requires perl 5.006 or newer to do the safe checks";
1508             }
1509 0 0 0       # Check that we are allowed to change level
1510             # Silently ignore if we can not.
1511             $LEVEL = $level if _can_do_level($level);
1512             }
1513             }
1514 0 0         return $LEVEL;
1515 0           }
1516             }
1517              
1518 0           #line 2266
1519              
1520             {
1521 0 0         my $TopSystemUID = 10;
    0          
1522             $TopSystemUID = 197108 if $^O eq 'interix'; # "Administrator"
1523 0           sub top_system_uid {
1524             my $self = shift;
1525             if (@_) {
1526             my $newuid = shift;
1527             croak "top_system_uid: UIDs should be numeric"
1528 0           unless $newuid =~ /^\d+$/s;
1529             $TopSystemUID = $newuid;
1530             }
1531             return $TopSystemUID;
1532             }
1533             }
1534              
1535             #line 2401
1536 0 0          
1537             package File::Temp::Dir;
1538 0            
1539             use File::Path qw/ rmtree /;
1540             use strict;
1541             use overload '""' => "STRINGIFY", fallback => 1;
1542 0            
1543             # private class specifically to support tempdir objects
1544             # created by File::Temp->newdir
1545              
1546             # ostensibly the same method interface as File::Temp but without
1547             # inheriting all the IO::Seekable methods and other cruft
1548              
1549 0           # Read-only - returns the name of the temp directory
1550 0            
1551 0 0         sub dirname {
1552 0           my $self = shift;
1553 0           return $self->{DIRNAME};
1554             }
1555 0 0 0        
1556             sub STRINGIFY {
1557 0           my $self = shift;
1558             return $self->dirname;
1559             }
1560 0            
1561 0 0         sub unlink_on_destroy {
1562             my $self = shift;
1563             if (@_) {
1564             $self->{CLEANUP} = shift;
1565             }
1566             return $self->{CLEANUP};
1567             }
1568              
1569             sub DESTROY {
1570 0 0 0       my $self = shift;
1571 0           local($., $@, $!, $^E, $?);
1572             if ($self->unlink_on_destroy &&
1573             $$ == $self->{LAUNCHPID} && !$File::Temp::KEEP_ALL) {
1574             if (-d $self->{DIRNAME}) {
1575 0           # Some versions of rmtree will abort if you attempt to remove
1576             # the directory you are sitting in. We protect that and turn it
1577             # into a warning. We do this because this occurs during object
1578             # destruction and so can not be caught by the user.
1579             eval { rmtree($self->{DIRNAME}, $File::Temp::DEBUG, 0); };
1580             warn $@ if ($@ && $^W);
1581             }
1582             }
1583             }
1584              
1585              
1586             1;