5 File::Path - Create or remove directory trees
9 This document describes version 2.01 of File::Path, released
17 mkpath( 'foo/bar/baz', '/zug/zwang', {verbose => 1} );
20 'foo/bar/baz', '/zug/zwang',
21 { verbose => 1, error => \my $err_list }
25 mkpath(['/foo/bar/baz', 'blurfl/quux'], 1, 0711);
26 rmtree(['foo/bar/baz', 'blurfl/quux'], 1, 1);
30 The C<mkpath> function provides a convenient way to create directories
31 of arbitrary depth. Similarly, the C<rmtree> function provides a
32 convenient way to delete an entire directory subtree from the
33 filesystem, much like the Unix command C<rm -r>.
35 Both functions may be called in one of two ways, the traditional,
36 compatible with code written since the dawn of time, and modern,
37 that offers a more flexible and readable idiom. New code should use
42 The modern way of calling C<mkpath> and C<rmtree> is with a list
43 of directories to create, or remove, respectively, followed by an
44 optional hash reference containing keys to control the
49 The following keys are recognised as parameters to C<mkpath>.
50 The function returns the list of files actually created during the
54 qw(/tmp /flub /home/nobody),
55 {verbose => 1, mode => 0750},
57 print "created $_\n" for @created;
63 The numeric permissions mode to apply to each created directory
64 (defaults to 0777), to be modified by the current C<umask>. If the
65 directory already exists (and thus does not need to be created),
66 the permissions will not be modified.
68 C<mask> is recognised as an alias for this parameter.
72 If present, will cause C<mkpath> to print the name of each directory
73 as it is created. By default nothing is printed.
77 If present, will be interpreted as a reference to a list, and will
78 be used to store any errors that are encountered. See the ERROR
79 HANDLING section for more information.
81 If this parameter is not used, certain error conditions may raise
82 a fatal error that will cause the program will halt, unless trapped
93 If present, will cause C<rmtree> to print the name of each file as
94 it is unlinked. By default nothing is printed.
98 When set to a true value, will cause C<rmtree> to skip the files
99 for which the process lacks the required privileges needed to delete
100 files, such as delete privileges on VMS. In other words, the code
101 will make no attempt to alter file permissions. Thus, if the process
102 is interrupted, no filesystem object will be left in a more
107 When set to a true value, will cause all files and subdirectories
108 to be removed, except the initially specified directories. This comes
109 in handy when cleaning out an application's scratch directory.
111 rmtree( '/tmp', {keep_root => 1} );
115 If present, will be interpreted as a reference to a list, and will
116 be used to store the list of all files and directories unlinked
117 during the call. If nothing is unlinked, a reference to an empty
118 list is returned (rather than C<undef>).
120 rmtree( '/tmp', {result => \my $list} );
121 print "unlinked $_\n" for @$list;
123 This is a useful alternative to the C<verbose> key.
127 If present, will be interpreted as a reference to a list,
128 and will be used to store any errors that are encountered.
129 See the ERROR HANDLING section for more information.
131 Removing things is a much more dangerous proposition than
132 creating things. As such, there are certain conditions that
133 C<rmtree> may encounter that are so dangerous that the only
134 sane action left is to kill the program.
136 Use C<error> to trap all that is reasonable (problems with
137 permissions and the like), and let it die if things get out
138 of hand. This is the safest course of action.
142 =head2 TRADITIONAL INTERFACE
144 The old interfaces of C<mkpath> and C<rmtree> take a reference to
145 a list of directories (to create or remove), followed by a series
146 of positional, numeric, modal parameters that control their behaviour.
148 This design made it difficult to add additional functionality, as
149 well as posed the problem of what to do when the calling code only
150 needs to set the last parameter. Even though the code doesn't care
151 how the initial positional parameters are set, the programmer is
152 forced to learn what the defaults are, and specify them.
154 Worse, if it turns out in the future that it would make more sense
155 to change the default behaviour of the first parameter (for example,
156 to avoid a security vulnerability), all existing code will remain
157 hard-wired to the wrong defaults.
159 Finally, a series of numeric parameters are much less self-documenting
160 in terms of communicating to the reader what the code is doing. Named
161 parameters do not have this problem.
163 In the traditional API, C<mkpath> takes three arguments:
169 The name of the path to create, or a reference to a list of paths
174 a boolean value, which if TRUE will cause C<mkpath> to print the
175 name of each directory as it is created (defaults to FALSE), and
179 the numeric mode to use when creating the directories (defaults to
180 0777), to be modified by the current umask.
184 It returns a list of all directories (including intermediates, determined
185 using the Unix '/' separator) created. In scalar context it returns
186 the number of directories created.
188 If a system error prevents a directory from being created, then the
189 C<mkpath> function throws a fatal error with C<Carp::croak>. This error
190 can be trapped with an C<eval> block:
192 eval { mkpath($dir) };
194 print "Couldn't create $dir: $@";
197 In the traditional API, C<rmtree> takes three arguments:
203 the root of the subtree to delete, or a reference to a list of
204 roots. All of the files and directories below each root, as well
205 as the roots themselves, will be deleted. If you want to keep
206 the roots themselves, you must use the modern API.
210 a boolean value, which if TRUE will cause C<rmtree> to print a
211 message each time it examines a file, giving the name of the file,
212 and indicating whether it's using C<rmdir> or C<unlink> to remove
213 it, or that it's skipping it. (defaults to FALSE)
217 a boolean value, which if TRUE will cause C<rmtree> to skip any
218 files to which you do not have delete access (if running under VMS)
219 or write access (if running under another OS). This will change
220 in the future when a criterion for 'delete permission' under OSs
221 other than VMS is settled. (defaults to FALSE)
225 It returns the number of files, directories and symlinks successfully
226 deleted. Symlinks are simply deleted and not followed.
228 Note also that the occurrence of errors in C<rmtree> using the
229 traditional interface can be determined I<only> by trapping diagnostic
230 messages using C<$SIG{__WARN__}>; it is not apparent from the return
231 value. (The modern interface may use the C<error> parameter to
232 record any problems encountered).
234 =head2 ERROR HANDLING
236 If C<mkpath> or C<rmtree> encounter an error, a diagnostic message
237 will be printed to C<STDERR> via C<carp> (for non-fatal errors),
238 or via C<croak> (for fatal errors).
240 If this behaviour is not desirable, the C<error> attribute may be
241 used to hold a reference to a variable, which will be used to store
242 the diagnostics. The result is a reference to a list of hash
243 references. For each hash reference, the key is the name of the
244 file, and the value is the error message (usually the contents of
245 C<$!>). An example usage looks like:
247 rmpath( 'foo/bar', 'bar/rat', {error => \my $err} );
248 for my $diag (@$err) {
249 my ($file, $message) = each %$diag;
250 print "problem unlinking $file: $message\n";
253 If no errors are encountered, C<$err> will point to an empty list
254 (thus there is no need to test for C<undef>). If a general error
255 is encountered (for instance, C<rmtree> attempts to remove a directory
256 tree that does not exist), the diagnostic key will be empty, only
257 the value will be set:
259 rmpath( '/no/such/path', {error => \my $err} );
260 for my $diag (@$err) {
261 my ($file, $message) = each %$diag;
263 print "general error: $message\n";
269 C<File::Path> blindly exports C<mkpath> and C<rmtree> into the
270 current namespace. These days, this is considered bad style, but
271 to change it now would break too much code. Nonetheless, you are
272 invited to specify what it is you are expecting to use:
274 use File::Path 'rmtree';
278 The functions detect (as far as possible) which way they are being
279 called and will act appropriately. It is important to remember that
280 the heuristic for detecting the old style is either the presence
281 of an array reference, or two or three parameters total and second
282 and third parameters are numeric. Hence...
284 mkpath 486, 487, 488;
286 ... will not assume the modern style and create three directories, rather
287 it will create one directory verbosely, setting the permission to
288 0750 (488 being the decimal equivalent of octal 750). Here, old
289 style trumps new. It must, for backwards compatibility reasons.
291 If you want to ensure there is absolutely no ambiguity about which
292 way the function will behave, make sure the first parameter is a
293 reference to a one-element list, to force the old style interpretation:
295 mkpath [486], 487, 488;
297 and get only one directory created. Or add a reference to an empty
298 parameter hash, to force the new style:
300 mkpath 486, 487, 488, {};
302 ... and hence create the three directories. If the empty hash
303 reference seems a little strange to your eyes, or you suspect a
304 subsequent programmer might I<helpfully> optimise it away, you
305 can add a parameter set to a default value:
307 mkpath 486, 487, 488, {verbose => 0};
309 =head3 SECURITY CONSIDERATIONS
311 There were race conditions 1.x implementations of File::Path's
312 C<rmtree> function (although sometimes patched depending on the OS
313 distribution or platform). The 2.0 version contains code to avoid the
314 problem mentioned in CVE-2002-0435.
316 See the following pages for more information:
318 http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=286905
319 http://www.nntp.perl.org/group/perl.perl5.porters/2005/01/msg97623.html
320 http://www.debian.org/security/2005/dsa-696
322 Additionally, unless the C<safe> parameter is set (or the
323 third parameter in the traditional interface is TRUE), should a
324 C<rmtree> be interrupted, files that were originally in read-only
325 mode may now have their permissions set to a read-write (or "delete
330 FATAL errors will cause the program to halt (C<croak>), since the
331 problem is so severe that it would be dangerous to continue. (This
332 can always be trapped with C<eval>, but it's not a good idea. Under
333 the circumstances, dying is the best thing to do).
335 SEVERE errors may be trapped using the modern interface. If the
336 they are not trapped, or the old interface is used, such an error
337 will cause the program will halt.
339 All other errors may be trapped using the modern interface, otherwise
340 they will be C<carp>ed about. Program execution will not be halted.
344 =item mkdir [path]: [errmsg] (SEVERE)
346 C<mkpath> was unable to create the path. Probably some sort of
347 permissions error at the point of departure, or insufficient resources
348 (such as free inodes on Unix).
350 =item No root path(s) specified
352 C<mkpath> was not given any paths to create. This message is only
353 emitted if the routine is called with the traditional interface.
354 The modern interface will remain silent if given nothing to do.
356 =item No such file or directory
358 On Windows, if C<mkpath> gives you this warning, it may mean that
359 you have exceeded your filesystem's maximum path length.
361 =item cannot fetch initial working directory: [errmsg]
363 C<rmtree> attempted to determine the initial directory by calling
364 C<Cwd::getcwd>, but the call failed for some reason. No attempt
365 will be made to delete anything.
367 =item cannot stat initial working directory: [errmsg]
369 C<rmtree> attempted to stat the initial directory (after having
370 successfully obtained its name via C<getcwd>), however, the call
371 failed for some reason. No attempt will be made to delete anything.
373 =item cannot chdir to [dir]: [errmsg]
375 C<rmtree> attempted to set the working directory in order to
376 begin deleting the objects therein, but was unsuccessful. This is
377 usually a permissions issue. The routine will continue to delete
378 other things, but this directory will be left intact.
380 =item directory [dir] changed before chdir, expected dev=[n] inode=[n], actual dev=[n] ino=[n], aborting. (FATAL)
382 C<rmtree> recorded the device and inode of a directory, and then
383 moved into it. It then performed a C<stat> on the current directory
384 and detected that the device and inode were no longer the same. As
385 this is at the heart of the race condition problem, the program
386 will die at this point.
388 =item cannot make directory [dir] read+writeable: [errmsg]
390 C<rmtree> attempted to change the permissions on the current directory
391 to ensure that subsequent unlinkings would not run into problems,
392 but was unable to do so. The permissions remain as they were, and
393 the program will carry on, doing the best it can.
395 =item cannot read [dir]: [errmsg]
397 C<rmtree> tried to read the contents of the directory in order
398 to acquire the names of the directory entries to be unlinked, but
399 was unsuccessful. This is usually a permissions issue. The
400 program will continue, but the files in this directory will remain
403 =item cannot reset chmod [dir]: [errmsg]
405 C<rmtree>, after having deleted everything in a directory, attempted
406 to restore its permissions to the original state but failed. The
407 directory may wind up being left behind.
409 =item cannot chdir to [parent-dir] from [child-dir]: [errmsg], aborting. (FATAL)
411 C<rmtree>, after having deleted everything and restored the permissions
412 of a directory, was unable to chdir back to the parent. This is usually
413 a sign that something evil this way comes.
415 =item cannot stat prior working directory [dir]: [errmsg], aborting. (FATAL)
417 C<rmtree> was unable to stat the parent directory after have returned
418 from the child. Since there is no way of knowing if we returned to
419 where we think we should be (by comparing device and inode) the only
420 way out is to C<croak>.
422 =item previous directory [parent-dir] changed before entering [child-dir], expected dev=[n] inode=[n], actual dev=[n] ino=[n], aborting. (FATAL)
424 When C<rmtree> returned from deleting files in a child directory, a
425 check revealed that the parent directory it returned to wasn't the one
426 it started out from. This is considered a sign of malicious activity.
428 =item cannot make directory [dir] writeable: [errmsg]
430 Just before removing a directory (after having successfully removed
431 everything it contained), C<rmtree> attempted to set the permissions
432 on the directory to ensure it could be removed and failed. Program
433 execution continues, but the directory may possibly not be deleted.
435 =item cannot remove directory [dir]: [errmsg]
437 C<rmtree> attempted to remove a directory, but failed. This may because
438 some objects that were unable to be removed remain in the directory, or
439 a permissions issue. The directory will be left behind.
441 =item cannot restore permissions of [dir] to [0nnn]: [errmsg]
443 After having failed to remove a directory, C<rmtree> was unable to
444 restore its permissions from a permissive state back to a possibly
445 more restrictive setting. (Permissions given in octal).
447 =item cannot make file [file] writeable: [errmsg]
449 C<rmtree> attempted to force the permissions of a file to ensure it
450 could be deleted, but failed to do so. It will, however, still attempt
453 =item cannot unlink file [file]: [errmsg]
455 C<rmtree> failed to remove a file. Probably a permissions issue.
457 =item cannot restore permissions of [file] to [0nnn]: [errmsg]
459 After having failed to remove a file, C<rmtree> was also unable
460 to restore the permissions on the file to a possibly less permissive
461 setting. (Permissions given in octal).
473 When removing directory trees, if you want to examine each file to
474 decide whether to delete it (and possibly leaving large swathes
475 alone), F<File::Find::Rule> offers a convenient and flexible approach
476 to examining directory trees.
482 Please report all bugs on the RT queue:
484 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=File-Path>
486 =head1 ACKNOWLEDGEMENTS
488 Paul Szabo identified the race condition originally, and Brendan
489 O'Dea wrote an implementation for Debian that addressed the problem.
490 That code was used as a basis for the current code. Their efforts
491 are greatly appreciated.
495 Tim Bunce <F<Tim.Bunce@ig.co.uk>> and Charles Bailey
496 <F<bailey@newman.upenn.edu>>. Currently maintained by David Landgren
497 <F<david@landgren.net>>.
501 This module is copyright (C) Charles Bailey, Tim Bunce and
502 David Landgren 1995-2007. All rights reserved.
506 This library is free software; you can redistribute it and/or modify
507 it under the same terms as Perl itself.
515 use File::Basename ();
520 # can't say 'opendir my $dh, $dirname'
521 # need to initialise $dh
527 use vars qw($VERSION @ISA @EXPORT);
530 @EXPORT = qw(mkpath rmtree);
532 my $Is_VMS = $^O eq 'VMS';
533 my $Is_MacOS = $^O eq 'MacOS';
535 # These OSes complain if you want to remove a file that you have no
536 # write permission to:
537 my $Force_Writeable = ($^O eq 'os2' || $^O eq 'dos' || $^O eq 'MSWin32' ||
538 $^O eq 'amigaos' || $^O eq 'MacOS' || $^O eq 'epoc');
556 $object = '' unless defined $object;
557 push @{${$arg->{error}}}, {$object => "$message: $!"};
560 _carp(defined($object) ? "$message for $object: $!" : "$message: $!");
566 UNIVERSAL::isa($_[0],'ARRAY')
567 or (@_ == 2 and (defined $_[1] ? $_[1] =~ /\A\d+\z/ : 1))
569 and (defined $_[1] ? $_[1] =~ /\A\d+\z/ : 1)
570 and (defined $_[2] ? $_[2] =~ /\A\d+\z/ : 1)
578 my ($verbose, $mode);
579 ($paths, $verbose, $mode) = @_;
580 $paths = [$paths] unless UNIVERSAL::isa($paths,'ARRAY');
581 $arg->{verbose} = defined $verbose ? $verbose : 0;
582 $arg->{mode} = defined $mode ? $mode : 0777;
585 if (@_ > 0 and UNIVERSAL::isa($_[-1], 'HASH')) {
587 exists $arg->{mask} and $arg->{mode} = delete $arg->{mask};
588 $arg->{mode} = 0777 unless exists $arg->{mode};
589 ${$arg->{error}} = [] if exists $arg->{error};
592 @{$arg}{qw(verbose mode)} = (0, 0777);
596 return _mkpath($arg, $paths);
603 local($")=$Is_MacOS ? ":" : "/";
605 foreach $path (@$paths) {
606 next unless length($path);
607 $path .= '/' if $^O eq 'os2' and $path =~ /^\w:\z/s; # feature of CRT
608 # Logic wants Unix paths, so go with the flow.
610 next if $path eq '/';
611 $path = VMS::Filespec::unixify($path);
614 my $parent = File::Basename::dirname($path);
615 unless (-d $parent or $path eq $parent) {
616 push(@created,_mkpath($arg, [$parent]));
618 print "mkdir $path\n" if $arg->{verbose};
619 if (mkdir($path,$arg->{mode})) {
620 push(@created, $path);
624 my ($e, $e1) = ($save_bang, $^E);
625 $e .= "; $e1" if $e ne $e1;
626 # allow for another process to have created it meanwhile
630 push @{${$arg->{error}}}, {$path => $e};
633 _croak("mkdir $path: $e");
643 UNIVERSAL::isa($_[0],'ARRAY')
644 or (@_ == 2 and (defined $_[1] ? $_[1] =~ /\A\d+\z/ : 1))
646 and (defined $_[1] ? $_[1] =~ /\A\d+\z/ : 1)
647 and (defined $_[2] ? $_[2] =~ /\A\d+\z/ : 1)
655 my ($verbose, $safe);
656 ($paths, $verbose, $safe) = @_;
657 $arg->{verbose} = defined $verbose ? $verbose : 0;
658 $arg->{safe} = defined $safe ? $safe : 0;
660 if (defined($paths) and length($paths)) {
661 $paths = [$paths] unless UNIVERSAL::isa($paths,'ARRAY');
664 _carp ("No root path(s) specified\n");
669 if (@_ > 0 and UNIVERSAL::isa($_[-1],'HASH')) {
671 ${$arg->{error}} = [] if exists $arg->{error};
672 ${$arg->{result}} = [] if exists $arg->{result};
675 @{$arg}{qw(verbose safe)} = (0, 0);
683 $arg->{cwd} = getcwd() or do {
684 _error($arg, "cannot fetch initial working directory");
687 for ($arg->{cwd}) { /\A(.*)\Z/; $_ = $1 } # untaint
689 @{$arg}{qw(device inode)} = (stat $arg->{cwd})[0,1] or do {
690 _error($arg, "cannot stat initial working directory", $arg->{cwd});
694 return _rmtree($arg, $paths);
702 my $curdir = File::Spec->curdir();
703 my $updir = File::Spec->updir();
707 foreach $root (@$paths) {
709 $root = ":$root" unless $root =~ /:/;
710 $root .= ":" unless $root =~ /:\z/;
716 # since we chdir into each directory, it may not be obvious
717 # to figure out where we are if we generate a message about
718 # a file name. We therefore construct a semi-canonical
719 # filename, anchored from the directory being unlinked (as
720 # opposed to being truly canonical, anchored from the root (/).
722 my $canon = $arg->{prefix}
723 ? File::Spec->catfile($arg->{prefix}, $root)
727 my ($ldev, $lino, $perm) = (lstat $root)[0,1,2] or next ROOT_DIR;
730 $root = VMS::Filespec::pathify($root) if $Is_VMS;
732 # see if we can escalate privileges to get in
733 # (e.g. funny protection mask such as -w- instead of rwx)
735 my $nperm = $perm | 0700;
736 if (!($arg->{safe} or $nperm == $perm or chmod($nperm, $root))) {
737 _error($arg, "cannot make child directory read-write-exec", $canon);
740 elsif (!chdir($root)) {
741 _error($arg, "cannot chdir to child", $canon);
746 my ($device, $inode, $perm) = (stat $curdir)[0,1,2] or do {
747 _error($arg, "cannot stat current working directory", $canon);
751 ($ldev eq $device and $lino eq $inode)
752 or _croak("directory $canon changed before chdir, expected dev=$ldev inode=$lino, actual dev=$device ino=$inode, aborting.");
754 $perm &= 07777; # don't forget setuid, setgid, sticky bits
755 my $nperm = $perm | 0700;
757 # notabene: 0700 is for making readable in the first place,
758 # it's also intended to change it to writable in case we have
759 # to recurse in which case we are better than rm -rf for
760 # subtrees with strange permissions
762 if (!($arg->{safe} or $nperm == $perm or chmod($nperm, $curdir))) {
763 _error($arg, "cannot make directory read+writeable", $canon);
768 $d = gensym() if $] < 5.006;
769 if (!opendir $d, $curdir) {
770 _error($arg, "cannot opendir", $canon);
775 if (!defined ${"\cTAINT"} or ${"\cTAINT"}) {
776 # Blindly untaint dir names if taint mode is
777 # active, or any perl < 5.006
778 @files = map { /\A(.*)\z/s; $1 } readdir $d;
787 # Deleting large numbers of files from VMS Files-11
788 # filesystems is faster if done in reverse ASCIIbetical order.
789 # include '.' to '.;' from blead patch #31775
790 @files = map {$_ eq '.' ? '.;' : $_} reverse @files;
791 ($root = VMS::Filespec::unixify($root)) =~ s/\.dir\z//;
793 @files = grep {$_ ne $updir and $_ ne $curdir} @files;
796 # remove the contained files before the directory itself
798 @{$narg}{qw(device inode cwd prefix depth)}
799 = ($device, $inode, $updir, $canon, $arg->{depth}+1);
800 $count += _rmtree($narg, \@files);
803 # restore directory permissions of required now (in case the rmdir
804 # below fails), while we are still in the directory and may do so
805 # without a race via '.'
806 if ($nperm != $perm and not chmod($perm, $curdir)) {
807 _error($arg, "cannot reset chmod", $canon);
810 # don't leave the client code in an unexpected directory
812 or _croak("cannot chdir to $arg->{cwd} from $canon: $!, aborting.");
814 # ensure that a chdir upwards didn't take us somewhere other
815 # than we expected (see CVE-2002-0435)
816 ($device, $inode) = (stat $curdir)[0,1]
817 or _croak("cannot stat prior working directory $arg->{cwd}: $!, aborting.");
819 ($arg->{device} eq $device and $arg->{inode} eq $inode)
820 or _croak("previous directory $arg->{cwd} changed before entering $canon, expected dev=$ldev inode=$lino, actual dev=$device ino=$inode, aborting.");
822 if ($arg->{depth} or !$arg->{keep_root}) {
824 ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) {
825 print "skipped $root\n" if $arg->{verbose};
828 if (!chmod $perm | 0700, $root) {
829 if ($Force_Writeable) {
830 _error($arg, "cannot make directory writeable", $canon);
833 print "rmdir $root\n" if $arg->{verbose};
835 push @{${$arg->{result}}}, $root if $arg->{result};
839 _error($arg, "cannot remove directory", $canon);
840 if (!chmod($perm, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
842 _error($arg, sprintf("cannot restore permissions to 0%o",$perm), $canon);
850 $root = VMS::Filespec::vmsify("./$root")
851 if $Is_VMS && !File::Spec->file_name_is_absolute($root);
854 ($Is_VMS ? !&VMS::Filespec::candelete($root)
855 : !(-l $root || -w $root)))
857 print "skipped $root\n" if $arg->{verbose};
861 my $nperm = $perm & 07777 | 0600;
862 if ($nperm != $perm and not chmod $nperm, $root) {
863 if ($Force_Writeable) {
864 _error($arg, "cannot make file writeable", $canon);
867 print "unlink $canon\n" if $arg->{verbose};
868 # delete all versions under VMS
871 push @{${$arg->{result}}}, $root if $arg->{result};
874 _error($arg, "cannot unlink file", $canon);
875 $Force_Writeable and chmod($perm, $root) or
876 _error($arg, sprintf("cannot restore permissions to 0%o",$perm), $canon);
880 last unless $Is_VMS && lstat $root;