@@ -1431,7 +1431,7 @@ sub tempfile {
14311431
14321432 } elsif ($options {TMPDIR }) {
14331433
1434- $template = File::Spec-> catfile(File::Spec -> tmpdir , $template );
1434+ $template = File::Spec-> catfile(_wrap_file_spec_tmpdir() , $template );
14351435
14361436 }
14371437
@@ -1443,7 +1443,7 @@ sub tempfile {
14431443
14441444 } else {
14451445
1446- $template = File::Spec-> catfile(File::Spec -> tmpdir , TEMPXXX);
1446+ $template = File::Spec-> catfile(_wrap_file_spec_tmpdir() , TEMPXXX);
14471447
14481448 }
14491449
@@ -1506,6 +1506,58 @@ sub tempfile {
15061506
15071507}
15081508
1509+ # On Windows under taint mode, File::Spec could suggest "C:\" as a tempdir
1510+ # which might not be writable. If that is the case, we fallback to a
1511+ # user directory. See https://rt.cpan.org/Ticket/Display.html?id=60340
1512+
1513+ {
1514+ my ($alt_tmpdir , $checked );
1515+
1516+ sub _wrap_file_spec_tmpdir {
1517+ return File::Spec-> tmpdir unless $^O eq " MSWin32" && ${^TAINT};
1518+
1519+ if ( $checked ) {
1520+ return $alt_tmpdir ? $alt_tmpdir : File::Spec-> tmpdir;
1521+ }
1522+
1523+ # probe what File::Spec gives and find a fallback
1524+ my $xxpath = _replace_XX( " X" x 10 , 0 );
1525+
1526+ # First, see if File::Spec->tmpdir is writable
1527+ my $tmpdir = File::Spec-> tmpdir;
1528+ my $testpath = File::Spec-> catdir( $tmpdir , $xxpath );
1529+ if (mkdir ( $testpath , 0700) ) {
1530+ $checked = 1;
1531+ rmdir $testpath ;
1532+ return $tmpdir ;
1533+ }
1534+
1535+ # Next, see if CSIDL_LOCAL_APPDATA is writable
1536+ require Win32;
1537+ my $local_app = File::Spec-> catdir(
1538+ Win32::GetFolderPath( Win32::CSIDL_LOCAL_APPDATA() ), ' Temp'
1539+ );
1540+ $testpath = File::Spec-> catdir( $local_app , $xxpath );
1541+ if ( -e $local_app or mkdir ( $local_app , 0700 ) ) {
1542+ if (mkdir ( $testpath , 0700) ) {
1543+ $checked = 1;
1544+ rmdir $testpath ;
1545+ return $alt_tmpdir = $local_app ;
1546+ }
1547+ }
1548+
1549+ # Can't find something writable
1550+ croak << "HERE" ;
1551+ Couldn't find a writable temp directory in taint mode. Tried:
1552+ $tmpdir
1553+ $local_app
1554+
1555+ Try setting and untainting the TMPDIR environment variable.
1556+ HERE
1557+
1558+ }
1559+ }
1560+
15091561=item B<tempdir >
15101562
15111563This is the recommended interface for creation of temporary
@@ -1620,7 +1672,7 @@ sub tempdir {
16201672 } elsif ($options {TMPDIR }) {
16211673
16221674 # Prepend tmpdir
1623- $template = File::Spec-> catdir(File::Spec -> tmpdir , $template );
1675+ $template = File::Spec-> catdir(_wrap_file_spec_tmpdir() , $template );
16241676
16251677 }
16261678
@@ -1634,7 +1686,7 @@ sub tempdir {
16341686
16351687 } else {
16361688
1637- $template = File::Spec-> catdir(File::Spec -> tmpdir , TEMPXXX);
1689+ $template = File::Spec-> catdir(_wrap_file_spec_tmpdir() , TEMPXXX);
16381690
16391691 }
16401692
@@ -1901,8 +1953,9 @@ Current API available since 0.05.
19011953sub tmpnam {
19021954
19031955 # Retrieve the temporary directory name
1904- my $tmpdir = File::Spec -> tmpdir ;
1956+ my $tmpdir = _wrap_file_spec_tmpdir() ;
19051957
1958+ # XXX I don't know under what circumstances this occurs, -- xdg 2016-04-02
19061959 croak " Error temporary directory is not writable"
19071960 if $tmpdir eq ' ' ;
19081961
@@ -2490,7 +2543,10 @@ destruction), then you will get a warning from File::Path::rmtree().
24902543=head2 Taint mode
24912544
24922545If you need to run code under taint mode, updating to the latest
2493- L<File::Spec> is highly recommended.
2546+ L<File::Spec> is highly recommended. On Windows, if the directory
2547+ given by L<File::Spec::tmpdir> isn't writable, File::Temp will attempt
2548+ to fallback to the user's local application data directory or croak
2549+ with an error.
24942550
24952551=head2 BINMODE
24962552
0 commit comments