File Coverage

inc/File/Temp.pm
Criterion Covered Total %
statement 176 528 33.3
branch 49 348 14.0
condition 5 96 5.2
subroutine 33 61 54.1
pod 18 21 85.7
total 281 1054 26.6


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