| Filename | /usr/share/perl/5.10/File/Path.pm |
| Statements | Executed 34 statements in 2.86ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 3.38ms | 3.87ms | File::Path::BEGIN@6 |
| 1 | 1 | 1 | 66µs | 66µs | File::Path::BEGIN@3 |
| 1 | 1 | 1 | 16µs | 20µs | File::Path::BEGIN@4 |
| 1 | 1 | 1 | 13µs | 73µs | File::Path::BEGIN@19 |
| 1 | 1 | 1 | 11µs | 26µs | File::Path::BEGIN@295 |
| 1 | 1 | 1 | 8µs | 8µs | File::Path::BEGIN@8 |
| 1 | 1 | 1 | 5µs | 5µs | File::Path::BEGIN@7 |
| 1 | 1 | 1 | 5µs | 5µs | File::Path::BEGIN@10 |
| 1 | 1 | 1 | 4µs | 4µs | File::Path::BEGIN@18 |
| 0 | 0 | 0 | 0s | 0s | File::Path::_carp |
| 0 | 0 | 0 | 0s | 0s | File::Path::_croak |
| 0 | 0 | 0 | 0s | 0s | File::Path::_error |
| 0 | 0 | 0 | 0s | 0s | File::Path::_is_subdir |
| 0 | 0 | 0 | 0s | 0s | File::Path::_mkpath |
| 0 | 0 | 0 | 0s | 0s | File::Path::_rmtree |
| 0 | 0 | 0 | 0s | 0s | File::Path::_slash_lc |
| 0 | 0 | 0 | 0s | 0s | File::Path::make_path |
| 0 | 0 | 0 | 0s | 0s | File::Path::mkpath |
| 0 | 0 | 0 | 0s | 0s | File::Path::remove_tree |
| 0 | 0 | 0 | 0s | 0s | File::Path::rmtree |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package File::Path; | ||||
| 2 | |||||
| 3 | 3 | 82µs | 1 | 66µs | # spent 66µs within File::Path::BEGIN@3 which was called:
# once (66µs+0s) by Template::BEGIN@32 at line 3 # spent 66µs making 1 call to File::Path::BEGIN@3 |
| 4 | 3 | 29µs | 2 | 24µs | # spent 20µs (16+4) within File::Path::BEGIN@4 which was called:
# once (16µs+4µs) by Template::BEGIN@32 at line 4 # spent 20µs making 1 call to File::Path::BEGIN@4
# spent 4µs making 1 call to strict::import |
| 5 | |||||
| 6 | 3 | 127µs | 2 | 3.93ms | # spent 3.87ms (3.38+489µs) within File::Path::BEGIN@6 which was called:
# once (3.38ms+489µs) by Template::BEGIN@32 at line 6 # spent 3.87ms making 1 call to File::Path::BEGIN@6
# spent 60µs making 1 call to Exporter::import |
| 7 | 3 | 22µs | 1 | 5µs | # spent 5µs within File::Path::BEGIN@7 which was called:
# once (5µs+0s) by Template::BEGIN@32 at line 7 # spent 5µs making 1 call to File::Path::BEGIN@7 |
| 8 | 3 | 44µs | 1 | 8µs | # spent 8µs within File::Path::BEGIN@8 which was called:
# once (8µs+0s) by Template::BEGIN@32 at line 8 # spent 8µs making 1 call to File::Path::BEGIN@8 |
| 9 | |||||
| 10 | # spent 5µs within File::Path::BEGIN@10 which was called:
# once (5µs+0s) by Template::BEGIN@32 at line 16 | ||||
| 11 | 1 | 5µs | if ($] < 5.006) { | ||
| 12 | # can't say 'opendir my $dh, $dirname' | ||||
| 13 | # need to initialise $dh | ||||
| 14 | eval "use Symbol"; | ||||
| 15 | } | ||||
| 16 | 1 | 18µs | 1 | 5µs | } # spent 5µs making 1 call to File::Path::BEGIN@10 |
| 17 | |||||
| 18 | 3 | 86µs | 1 | 4µs | # spent 4µs within File::Path::BEGIN@18 which was called:
# once (4µs+0s) by Template::BEGIN@32 at line 18 # spent 4µs making 1 call to File::Path::BEGIN@18 |
| 19 | 3 | 1.57ms | 2 | 133µs | # spent 73µs (13+60) within File::Path::BEGIN@19 which was called:
# once (13µs+60µs) by Template::BEGIN@32 at line 19 # spent 73µs making 1 call to File::Path::BEGIN@19
# spent 60µs making 1 call to vars::import |
| 20 | 1 | 700ns | $VERSION = '2.07_03'; | ||
| 21 | 1 | 9µs | @ISA = qw(Exporter); | ||
| 22 | 1 | 800ns | @EXPORT = qw(mkpath rmtree); | ||
| 23 | 1 | 800ns | @EXPORT_OK = qw(make_path remove_tree); | ||
| 24 | |||||
| 25 | 1 | 2µs | my $Is_VMS = $^O eq 'VMS'; | ||
| 26 | 1 | 600ns | my $Is_MacOS = $^O eq 'MacOS'; | ||
| 27 | |||||
| 28 | # These OSes complain if you want to remove a file that you have no | ||||
| 29 | # write permission to: | ||||
| 30 | 1 | 2µs | my $Force_Writeable = grep {$^O eq $_} qw(amigaos dos epoc MSWin32 MacOS os2); | ||
| 31 | |||||
| 32 | # Unix-like systems need to stat each directory in order to detect | ||||
| 33 | # race condition. MS-Windows is immune to this particular attack. | ||||
| 34 | 1 | 600ns | my $Need_Stat_Check = !($^O eq 'MSWin32'); | ||
| 35 | |||||
| 36 | sub _carp { | ||||
| 37 | require Carp; | ||||
| 38 | goto &Carp::carp; | ||||
| 39 | } | ||||
| 40 | |||||
| 41 | sub _croak { | ||||
| 42 | require Carp; | ||||
| 43 | goto &Carp::croak; | ||||
| 44 | } | ||||
| 45 | |||||
| 46 | sub _error { | ||||
| 47 | my $arg = shift; | ||||
| 48 | my $message = shift; | ||||
| 49 | my $object = shift; | ||||
| 50 | |||||
| 51 | if ($arg->{error}) { | ||||
| 52 | $object = '' unless defined $object; | ||||
| 53 | $message .= ": $!" if $!; | ||||
| 54 | push @{${$arg->{error}}}, {$object => $message}; | ||||
| 55 | } | ||||
| 56 | else { | ||||
| 57 | _carp(defined($object) ? "$message for $object: $!" : "$message: $!"); | ||||
| 58 | } | ||||
| 59 | } | ||||
| 60 | |||||
| 61 | sub make_path { | ||||
| 62 | push @_, {} unless @_ and UNIVERSAL::isa($_[-1],'HASH'); | ||||
| 63 | goto &mkpath; | ||||
| 64 | } | ||||
| 65 | |||||
| 66 | sub mkpath { | ||||
| 67 | my $old_style = !(@_ and UNIVERSAL::isa($_[-1],'HASH')); | ||||
| 68 | |||||
| 69 | my $arg; | ||||
| 70 | my $paths; | ||||
| 71 | |||||
| 72 | if ($old_style) { | ||||
| 73 | my ($verbose, $mode); | ||||
| 74 | ($paths, $verbose, $mode) = @_; | ||||
| 75 | $paths = [$paths] unless UNIVERSAL::isa($paths,'ARRAY'); | ||||
| 76 | $arg->{verbose} = $verbose; | ||||
| 77 | $arg->{mode} = defined $mode ? $mode : 0777; | ||||
| 78 | } | ||||
| 79 | else { | ||||
| 80 | $arg = pop @_; | ||||
| 81 | $arg->{mode} = delete $arg->{mask} if exists $arg->{mask}; | ||||
| 82 | $arg->{mode} = 0777 unless exists $arg->{mode}; | ||||
| 83 | ${$arg->{error}} = [] if exists $arg->{error}; | ||||
| 84 | $paths = [@_]; | ||||
| 85 | } | ||||
| 86 | return _mkpath($arg, $paths); | ||||
| 87 | } | ||||
| 88 | |||||
| 89 | sub _mkpath { | ||||
| 90 | my $arg = shift; | ||||
| 91 | my $paths = shift; | ||||
| 92 | |||||
| 93 | my(@created,$path); | ||||
| 94 | foreach $path (@$paths) { | ||||
| 95 | next unless defined($path) and length($path); | ||||
| 96 | $path .= '/' if $^O eq 'os2' and $path =~ /^\w:\z/s; # feature of CRT | ||||
| 97 | # Logic wants Unix paths, so go with the flow. | ||||
| 98 | if ($Is_VMS) { | ||||
| 99 | next if $path eq '/'; | ||||
| 100 | $path = VMS::Filespec::unixify($path); | ||||
| 101 | } | ||||
| 102 | next if -d $path; | ||||
| 103 | my $parent = File::Basename::dirname($path); | ||||
| 104 | unless (-d $parent or $path eq $parent) { | ||||
| 105 | push(@created,_mkpath($arg, [$parent])); | ||||
| 106 | } | ||||
| 107 | print "mkdir $path\n" if $arg->{verbose}; | ||||
| 108 | if (mkdir($path,$arg->{mode})) { | ||||
| 109 | push(@created, $path); | ||||
| 110 | } | ||||
| 111 | else { | ||||
| 112 | my $save_bang = $!; | ||||
| 113 | my ($e, $e1) = ($save_bang, $^E); | ||||
| 114 | $e .= "; $e1" if $e ne $e1; | ||||
| 115 | # allow for another process to have created it meanwhile | ||||
| 116 | if (!-d $path) { | ||||
| 117 | $! = $save_bang; | ||||
| 118 | if ($arg->{error}) { | ||||
| 119 | push @{${$arg->{error}}}, {$path => $e}; | ||||
| 120 | } | ||||
| 121 | else { | ||||
| 122 | _croak("mkdir $path: $e"); | ||||
| 123 | } | ||||
| 124 | } | ||||
| 125 | } | ||||
| 126 | } | ||||
| 127 | return @created; | ||||
| 128 | } | ||||
| 129 | |||||
| 130 | sub remove_tree { | ||||
| 131 | push @_, {} unless @_ and UNIVERSAL::isa($_[-1],'HASH'); | ||||
| 132 | goto &rmtree; | ||||
| 133 | } | ||||
| 134 | |||||
| 135 | sub _is_subdir { | ||||
| 136 | my($dir, $test) = @_; | ||||
| 137 | |||||
| 138 | my($dv, $dd) = File::Spec->splitpath($dir, 1); | ||||
| 139 | my($tv, $td) = File::Spec->splitpath($test, 1); | ||||
| 140 | |||||
| 141 | # not on same volume | ||||
| 142 | return 0 if $dv ne $tv; | ||||
| 143 | |||||
| 144 | my @d = File::Spec->splitdir($dd); | ||||
| 145 | my @t = File::Spec->splitdir($td); | ||||
| 146 | |||||
| 147 | # @t can't be a subdir if it's shorter than @d | ||||
| 148 | return 0 if @t < @d; | ||||
| 149 | |||||
| 150 | return join('/', @d) eq join('/', splice @t, 0, +@d); | ||||
| 151 | } | ||||
| 152 | |||||
| 153 | sub rmtree { | ||||
| 154 | my $old_style = !(@_ and UNIVERSAL::isa($_[-1],'HASH')); | ||||
| 155 | |||||
| 156 | my $arg; | ||||
| 157 | my $paths; | ||||
| 158 | |||||
| 159 | if ($old_style) { | ||||
| 160 | my ($verbose, $safe); | ||||
| 161 | ($paths, $verbose, $safe) = @_; | ||||
| 162 | $arg->{verbose} = $verbose; | ||||
| 163 | $arg->{safe} = defined $safe ? $safe : 0; | ||||
| 164 | |||||
| 165 | if (defined($paths) and length($paths)) { | ||||
| 166 | $paths = [$paths] unless UNIVERSAL::isa($paths,'ARRAY'); | ||||
| 167 | } | ||||
| 168 | else { | ||||
| 169 | _carp ("No root path(s) specified\n"); | ||||
| 170 | return 0; | ||||
| 171 | } | ||||
| 172 | } | ||||
| 173 | else { | ||||
| 174 | $arg = pop @_; | ||||
| 175 | ${$arg->{error}} = [] if exists $arg->{error}; | ||||
| 176 | ${$arg->{result}} = [] if exists $arg->{result}; | ||||
| 177 | $paths = [@_]; | ||||
| 178 | } | ||||
| 179 | |||||
| 180 | $arg->{prefix} = ''; | ||||
| 181 | $arg->{depth} = 0; | ||||
| 182 | |||||
| 183 | my @clean_path; | ||||
| 184 | $arg->{cwd} = getcwd() or do { | ||||
| 185 | _error($arg, "cannot fetch initial working directory"); | ||||
| 186 | return 0; | ||||
| 187 | }; | ||||
| 188 | for ($arg->{cwd}) { /\A(.*)\Z/; $_ = $1 } # untaint | ||||
| 189 | |||||
| 190 | for my $p (@$paths) { | ||||
| 191 | # need to fixup case and map \ to / on Windows | ||||
| 192 | my $ortho_root = $^O eq 'MSWin32' ? _slash_lc($p) : $p; | ||||
| 193 | my $ortho_cwd = $^O eq 'MSWin32' ? _slash_lc($arg->{cwd}) : $arg->{cwd}; | ||||
| 194 | my $ortho_root_length = length($ortho_root); | ||||
| 195 | $ortho_root_length-- if $^O eq 'VMS'; # don't compare '.' with ']' | ||||
| 196 | if ($ortho_root_length && _is_subdir($ortho_root, $ortho_cwd)) { | ||||
| 197 | local $! = 0; | ||||
| 198 | _error($arg, "cannot remove path when cwd is $arg->{cwd}", $p); | ||||
| 199 | next; | ||||
| 200 | } | ||||
| 201 | |||||
| 202 | if ($Is_MacOS) { | ||||
| 203 | $p = ":$p" unless $p =~ /:/; | ||||
| 204 | $p .= ":" unless $p =~ /:\z/; | ||||
| 205 | } | ||||
| 206 | elsif ($^O eq 'MSWin32') { | ||||
| 207 | $p =~ s{[/\\]\z}{}; | ||||
| 208 | } | ||||
| 209 | else { | ||||
| 210 | $p =~ s{/\z}{}; | ||||
| 211 | } | ||||
| 212 | push @clean_path, $p; | ||||
| 213 | } | ||||
| 214 | |||||
| 215 | @{$arg}{qw(device inode perm)} = (lstat $arg->{cwd})[0,1] or do { | ||||
| 216 | _error($arg, "cannot stat initial working directory", $arg->{cwd}); | ||||
| 217 | return 0; | ||||
| 218 | }; | ||||
| 219 | |||||
| 220 | return _rmtree($arg, \@clean_path); | ||||
| 221 | } | ||||
| 222 | |||||
| 223 | sub _rmtree { | ||||
| 224 | my $arg = shift; | ||||
| 225 | my $paths = shift; | ||||
| 226 | |||||
| 227 | my $count = 0; | ||||
| 228 | my $curdir = File::Spec->curdir(); | ||||
| 229 | my $updir = File::Spec->updir(); | ||||
| 230 | |||||
| 231 | my (@files, $root); | ||||
| 232 | ROOT_DIR: | ||||
| 233 | foreach $root (@$paths) { | ||||
| 234 | # since we chdir into each directory, it may not be obvious | ||||
| 235 | # to figure out where we are if we generate a message about | ||||
| 236 | # a file name. We therefore construct a semi-canonical | ||||
| 237 | # filename, anchored from the directory being unlinked (as | ||||
| 238 | # opposed to being truly canonical, anchored from the root (/). | ||||
| 239 | |||||
| 240 | my $canon = $arg->{prefix} | ||||
| 241 | ? File::Spec->catfile($arg->{prefix}, $root) | ||||
| 242 | : $root | ||||
| 243 | ; | ||||
| 244 | |||||
| 245 | my ($ldev, $lino, $perm) = (lstat $root)[0,1,2] or next ROOT_DIR; | ||||
| 246 | |||||
| 247 | if ( -d _ ) { | ||||
| 248 | $root = VMS::Filespec::pathify($root) if $Is_VMS; | ||||
| 249 | |||||
| 250 | if (!chdir($root)) { | ||||
| 251 | # see if we can escalate privileges to get in | ||||
| 252 | # (e.g. funny protection mask such as -w- instead of rwx) | ||||
| 253 | $perm &= 07777; | ||||
| 254 | my $nperm = $perm | 0700; | ||||
| 255 | if (!($arg->{safe} or $nperm == $perm or chmod($nperm, $root))) { | ||||
| 256 | _error($arg, "cannot make child directory read-write-exec", $canon); | ||||
| 257 | next ROOT_DIR; | ||||
| 258 | } | ||||
| 259 | elsif (!chdir($root)) { | ||||
| 260 | _error($arg, "cannot chdir to child", $canon); | ||||
| 261 | next ROOT_DIR; | ||||
| 262 | } | ||||
| 263 | } | ||||
| 264 | |||||
| 265 | my ($cur_dev, $cur_inode, $perm) = (stat $curdir)[0,1,2] or do { | ||||
| 266 | _error($arg, "cannot stat current working directory", $canon); | ||||
| 267 | next ROOT_DIR; | ||||
| 268 | }; | ||||
| 269 | |||||
| 270 | if ($Need_Stat_Check) { | ||||
| 271 | ($ldev eq $cur_dev and $lino eq $cur_inode) | ||||
| 272 | or _croak("directory $canon changed before chdir, expected dev=$ldev ino=$lino, actual dev=$cur_dev ino=$cur_inode, aborting."); | ||||
| 273 | } | ||||
| 274 | |||||
| 275 | $perm &= 07777; # don't forget setuid, setgid, sticky bits | ||||
| 276 | my $nperm = $perm | 0700; | ||||
| 277 | |||||
| 278 | # notabene: 0700 is for making readable in the first place, | ||||
| 279 | # it's also intended to change it to writable in case we have | ||||
| 280 | # to recurse in which case we are better than rm -rf for | ||||
| 281 | # subtrees with strange permissions | ||||
| 282 | |||||
| 283 | if (!($arg->{safe} or $nperm == $perm or chmod($nperm, $curdir))) { | ||||
| 284 | _error($arg, "cannot make directory read+writeable", $canon); | ||||
| 285 | $nperm = $perm; | ||||
| 286 | } | ||||
| 287 | |||||
| 288 | my $d; | ||||
| 289 | $d = gensym() if $] < 5.006; | ||||
| 290 | if (!opendir $d, $curdir) { | ||||
| 291 | _error($arg, "cannot opendir", $canon); | ||||
| 292 | @files = (); | ||||
| 293 | } | ||||
| 294 | else { | ||||
| 295 | 3 | 849µs | 2 | 42µs | # spent 26µs (11+16) within File::Path::BEGIN@295 which was called:
# once (11µs+16µs) by Template::BEGIN@32 at line 295 # spent 26µs making 1 call to File::Path::BEGIN@295
# spent 15µs making 1 call to strict::unimport |
| 296 | if (!defined ${"\cTAINT"} or ${"\cTAINT"}) { | ||||
| 297 | # Blindly untaint dir names if taint mode is | ||||
| 298 | # active, or any perl < 5.006 | ||||
| 299 | @files = map { /\A(.*)\z/s; $1 } readdir $d; | ||||
| 300 | } | ||||
| 301 | else { | ||||
| 302 | @files = readdir $d; | ||||
| 303 | } | ||||
| 304 | closedir $d; | ||||
| 305 | } | ||||
| 306 | |||||
| 307 | if ($Is_VMS) { | ||||
| 308 | # Deleting large numbers of files from VMS Files-11 | ||||
| 309 | # filesystems is faster if done in reverse ASCIIbetical order. | ||||
| 310 | # include '.' to '.;' from blead patch #31775 | ||||
| 311 | @files = map {$_ eq '.' ? '.;' : $_} reverse @files; | ||||
| 312 | ($root = VMS::Filespec::unixify($root)) =~ s/\.dir\z//; | ||||
| 313 | } | ||||
| 314 | |||||
| 315 | @files = grep {$_ ne $updir and $_ ne $curdir} @files; | ||||
| 316 | |||||
| 317 | if (@files) { | ||||
| 318 | # remove the contained files before the directory itself | ||||
| 319 | my $narg = {%$arg}; | ||||
| 320 | @{$narg}{qw(device inode cwd prefix depth)} | ||||
| 321 | = ($cur_dev, $cur_inode, $updir, $canon, $arg->{depth}+1); | ||||
| 322 | $count += _rmtree($narg, \@files); | ||||
| 323 | } | ||||
| 324 | |||||
| 325 | # restore directory permissions of required now (in case the rmdir | ||||
| 326 | # below fails), while we are still in the directory and may do so | ||||
| 327 | # without a race via '.' | ||||
| 328 | if ($nperm != $perm and not chmod($perm, $curdir)) { | ||||
| 329 | _error($arg, "cannot reset chmod", $canon); | ||||
| 330 | } | ||||
| 331 | |||||
| 332 | # don't leave the client code in an unexpected directory | ||||
| 333 | chdir($arg->{cwd}) | ||||
| 334 | or _croak("cannot chdir to $arg->{cwd} from $canon: $!, aborting."); | ||||
| 335 | |||||
| 336 | # ensure that a chdir upwards didn't take us somewhere other | ||||
| 337 | # than we expected (see CVE-2002-0435) | ||||
| 338 | ($cur_dev, $cur_inode) = (stat $curdir)[0,1] | ||||
| 339 | or _croak("cannot stat prior working directory $arg->{cwd}: $!, aborting."); | ||||
| 340 | |||||
| 341 | if ($Need_Stat_Check) { | ||||
| 342 | ($arg->{device} eq $cur_dev and $arg->{inode} eq $cur_inode) | ||||
| 343 | or _croak("previous directory $arg->{cwd} changed before entering $canon, expected dev=$ldev ino=$lino, actual dev=$cur_dev ino=$cur_inode, aborting."); | ||||
| 344 | } | ||||
| 345 | |||||
| 346 | if ($arg->{depth} or !$arg->{keep_root}) { | ||||
| 347 | if ($arg->{safe} && | ||||
| 348 | ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) { | ||||
| 349 | print "skipped $root\n" if $arg->{verbose}; | ||||
| 350 | next ROOT_DIR; | ||||
| 351 | } | ||||
| 352 | if ($Force_Writeable and !chmod $perm | 0700, $root) { | ||||
| 353 | _error($arg, "cannot make directory writeable", $canon); | ||||
| 354 | } | ||||
| 355 | print "rmdir $root\n" if $arg->{verbose}; | ||||
| 356 | if (rmdir $root) { | ||||
| 357 | push @{${$arg->{result}}}, $root if $arg->{result}; | ||||
| 358 | ++$count; | ||||
| 359 | } | ||||
| 360 | else { | ||||
| 361 | _error($arg, "cannot remove directory", $canon); | ||||
| 362 | if ($Force_Writeable && !chmod($perm, ($Is_VMS ? VMS::Filespec::fileify($root) : $root)) | ||||
| 363 | ) { | ||||
| 364 | _error($arg, sprintf("cannot restore permissions to 0%o",$perm), $canon); | ||||
| 365 | } | ||||
| 366 | } | ||||
| 367 | } | ||||
| 368 | } | ||||
| 369 | else { | ||||
| 370 | # not a directory | ||||
| 371 | $root = VMS::Filespec::vmsify("./$root") | ||||
| 372 | if $Is_VMS | ||||
| 373 | && !File::Spec->file_name_is_absolute($root) | ||||
| 374 | && ($root !~ m/(?<!\^)[\]>]+/); # not already in VMS syntax | ||||
| 375 | |||||
| 376 | if ($arg->{safe} && | ||||
| 377 | ($Is_VMS ? !&VMS::Filespec::candelete($root) | ||||
| 378 | : !(-l $root || -w $root))) | ||||
| 379 | { | ||||
| 380 | print "skipped $root\n" if $arg->{verbose}; | ||||
| 381 | next ROOT_DIR; | ||||
| 382 | } | ||||
| 383 | |||||
| 384 | my $nperm = $perm & 07777 | 0600; | ||||
| 385 | if ($Force_Writeable and $nperm != $perm and not chmod $nperm, $root) { | ||||
| 386 | _error($arg, "cannot make file writeable", $canon); | ||||
| 387 | } | ||||
| 388 | print "unlink $canon\n" if $arg->{verbose}; | ||||
| 389 | # delete all versions under VMS | ||||
| 390 | for (;;) { | ||||
| 391 | if (unlink $root) { | ||||
| 392 | push @{${$arg->{result}}}, $root if $arg->{result}; | ||||
| 393 | } | ||||
| 394 | else { | ||||
| 395 | _error($arg, "cannot unlink file", $canon); | ||||
| 396 | $Force_Writeable and chmod($perm, $root) or | ||||
| 397 | _error($arg, sprintf("cannot restore permissions to 0%o",$perm), $canon); | ||||
| 398 | last; | ||||
| 399 | } | ||||
| 400 | ++$count; | ||||
| 401 | last unless $Is_VMS && lstat $root; | ||||
| 402 | } | ||||
| 403 | } | ||||
| 404 | } | ||||
| 405 | return $count; | ||||
| 406 | } | ||||
| 407 | |||||
| 408 | sub _slash_lc { | ||||
| 409 | # fix up slashes and case on MSWin32 so that we can determine that | ||||
| 410 | # c:\path\to\dir is underneath C:/Path/To | ||||
| 411 | my $path = shift; | ||||
| 412 | $path =~ tr{\\}{/}; | ||||
| 413 | return lc($path); | ||||
| 414 | } | ||||
| 415 | |||||
| 416 | 1 | 8µs | 1; | ||
| 417 | __END__ |