use Exporter ();
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
-$VERSION = '2.07_02';
+$VERSION = '2.07_03';
@ISA = qw(Exporter);
@EXPORT = qw(mkpath rmtree);
@EXPORT_OK = qw(make_path remove_tree);
# write permission to:
my $Force_Writeable = grep {$^O eq $_} qw(amigaos dos epoc MSWin32 MacOS os2);
+# Unix-like systems need to stat each directory in order to detect
+# race condition. MS-Windows is immune to this particular attack.
+my $Need_Stat_Check = !($^O eq 'MSWin32');
+
sub _carp {
require Carp;
goto &Carp::carp;
if ( -d _ ) {
$root = VMS::Filespec::pathify($root) if $Is_VMS;
+
if (!chdir($root)) {
# see if we can escalate privileges to get in
# (e.g. funny protection mask such as -w- instead of rwx)
next ROOT_DIR;
};
- ($ldev eq $cur_dev and $lino eq $cur_inode)
- or _croak("directory $canon changed before chdir, expected dev=$ldev ino=$lino, actual dev=$cur_dev ino=$cur_inode, aborting.");
+ if ($Need_Stat_Check) {
+ ($ldev eq $cur_dev and $lino eq $cur_inode)
+ or _croak("directory $canon changed before chdir, expected dev=$ldev ino=$lino, actual dev=$cur_dev ino=$cur_inode, aborting.");
+ }
$perm &= 07777; # don't forget setuid, setgid, sticky bits
my $nperm = $perm | 0700;
@files = map {$_ eq '.' ? '.;' : $_} reverse @files;
($root = VMS::Filespec::unixify($root)) =~ s/\.dir\z//;
}
+
@files = grep {$_ ne $updir and $_ ne $curdir} @files;
if (@files) {
($cur_dev, $cur_inode) = (stat $curdir)[0,1]
or _croak("cannot stat prior working directory $arg->{cwd}: $!, aborting.");
- ($arg->{device} eq $cur_dev and $arg->{inode} eq $cur_inode)
- or _croak("previous directory $arg->{cwd} changed before entering $canon, expected dev=$ldev ino=$lino, actual dev=$cur_dev ino=$cur_inode, aborting.");
+ if ($Need_Stat_Check) {
+ ($arg->{device} eq $cur_dev and $arg->{inode} eq $cur_inode)
+ or _croak("previous directory $arg->{cwd} changed before entering $canon, expected dev=$ldev ino=$lino, actual dev=$cur_dev ino=$cur_inode, aborting.");
+ }
if ($arg->{depth} or !$arg->{keep_root}) {
if ($arg->{safe} &&
use strict;
-use Test::More tests => 120;
+use Test::More tests => 121;
use Config;
BEGIN {
}
SKIP: {
+ skip "This is not a MSWin32 platform", 1
+ unless $^O eq 'MSWin32';
+
+ my $UNC_path_taint = $ENV{PERL_FILE_PATH_UNC_TESTDIR};
+ skip "PERL_FILE_PATH_UNC_TESTDIR environment variable not set", 1
+ unless defined($UNC_path_taint);
+
+ my ($UNC_path) = ($UNC_path_taint =~ m{^([/\\]{2}\w+[/\\]\w+[/\\]\w+)$});
+
+ skip "PERL_FILE_PATH_UNC_TESTDIR environment variable does not point to a directory", 1
+ unless -d $UNC_path;
+
+ my $removed = rmtree($UNC_path);
+ cmp_ok($removed, '>', 0, "removed $removed entries from $UNC_path");
+}
+
+SKIP: {
# test bug http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=487319
skip "Don't need Force_Writeable semantics on $^O", 4
if grep {$^O eq $_} qw(amigaos dos epoc MSWin32 MacOS os2);
cannot unlink file for [^:]+: .* at \1 line \2
cannot restore permissions to \d+ for [^:]+: .* at \1 line \2
cannot make child directory read-write-exec for [^:]+: .* at \1 line \2
-cannot remove directory for [^:]+: .* at \1 line \2
-cannot restore permissions to \d+ for [^:]+: .* at \1 line \2},
+cannot remove directory for [^:]+: .* at \1 line \2},
'rmtree with insufficient privileges'
);
}
unless -d catdir(qw(EXTRA 1));
rmtree 'EXTRA', {safe => 0, error => \$error};
- is( scalar(@$error), 11, 'seven deadly sins' ); # well there used to be 7
+ is( scalar(@$error), 10, 'seven deadly sins' ); # well there used to be 7
rmtree 'EXTRA', {safe => 1, error => \$error};
is( scalar(@$error), 9, 'safe is better' );