File Coverage

inc/File/Temp.pm
Criterion Covered Total %
statement 77 482 15.9
branch 5 324 1.5
condition 0 93 0.0
subroutine 25 57 43.8
pod 18 20 90.0
total 125 976 12.8


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