File Coverage

inc/File/Temp.pm
Criterion Covered Total %
statement 175 527 33.2
branch 48 348 13.7
condition 5 96 5.2
subroutine 33 61 54.1
pod 18 21 85.7
total 279 1053 26.5


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