Re: [PATCH] Update File-Path to 2.00
[p5sagit/p5-mst-13.2.git] / lib / File / Path.pm
CommitLineData
1fc4cb55 1package File::Path;
fed7345c 2
3=head1 NAME
4
12c2e016 5File::Path - Create or remove directory trees
6
7=head1 VERSION
8
9This document describes version 2.00 of File::Path, released
102007-xx-xx.
fed7345c 11
12=head1 SYNOPSIS
13
8b87c192 14 use File::Path;
fed7345c 15
12c2e016 16 # modern
17 mkpath( 'foo/bar/baz', '/zug/zwang', {verbose => 1} );
18
19 rmtree(
20 'foo/bar/baz', '/zug/zwang',
91c4f65e 21 { verbose => 1, error => \my $err_list }
12c2e016 22 );
23
24 # traditional
8b87c192 25 mkpath(['/foo/bar/baz', 'blurfl/quux'], 1, 0711);
26 rmtree(['foo/bar/baz', 'blurfl/quux'], 1, 1);
fed7345c 27
28=head1 DESCRIPTION
29
12c2e016 30The C<mkpath> function provides a convenient way to create directories,
31even if your C<mkdir> kernel call won't create more than one level
32of directory at a time. Similarly, the C<rmtree> function provides
33a convenient way to delete a subtree from the directory structure,
34much like the Unix command C<rm -r>.
35
36Both functions may be called in one of two ways, the traditional,
37compatible with code written since the dawn of time, and modern,
38that offers a more flexible and readable idiom. New code should use
39the modern interface.
40
41=head2 FUNCTIONS
42
43The modern way of calling C<mkpath> and C<rmtree> is with an optional
44hash reference at the end of the parameter list that holds various
45keys that can be used to control the function's behaviour, following
46a plain list of directories upon which to operate.
47
48=head3 C<mkpath>
49
50The following keys are recognised as as parameters to C<mkpath>.
51It returns the list of files actually created during the call.
52
53 my @created = mkpath(
54 qw(/tmp /flub /home/nobody),
55 {verbose => 1, mode => 0750},
56 );
57 print "created $_\n" for @created;
58
59=over 4
60
61=item mode
62
63The numeric mode to use when creating the directories (defaults
64to 07777), to be modified by the current C<umask>. (C<mask> is
65recognised as an alias for this parameter).
66
67=item verbose
68
69If present, will cause C<mkpath> to print the name of each directory
70as it is created. By default nothing is printed.
71
72=item error
73
74If present, will be interpreted as a reference to a list, and will
75be used to store any errors that are encountered. See the ERROR
76HANDLING section below to find out more.
77
78If this parameter is not used, any errors encountered will raise a
79fatal error that need to be trapped in an C<eval> block, or the
80program will halt.
81
82=back
83
84=head3 C<rmtree>
85
86=over 4
87
88=item verbose
89
90If present, will cause C<rmtree> to print the name of each file as
91it is unlinked. By default nothing is printed.
92
93=item skip_others
94
95When set to a true value, will cause C<rmtree> to skip any files
96to which you do not have delete access (if running under VMS) or
97write access (if running under another OS). This will change in
98the future when a criterion for 'delete permission' under OSs other
99than VMS is settled.
100
101=item keep_root
102
103When set to a true value, will cause everything except the specified
104base directories to be unlinked. This comes in handy when cleaning
105out an application's scratch directory.
106
107 rmtree( '/tmp', {keep_root => 1} );
108
109=item result
110
111If present, will be interpreted as a reference to a list, and will
112be used to store the list of all files and directories unlinked
113during the call. If nothing is unlinked, a reference to an empty
114list is returned (rather than C<undef>).
115
116 rmtree( '/tmp', {result => \my $list} );
117 print "unlinked $_\n" for @$list;
118
119=item error
120
121If present, will be interpreted as a reference to a list,
122and will be used to store any errors that are encountered.
123See the ERROR HANDLING section below to find out more.
124
125If this parameter is not used, any errors encountered will
126raise a fatal error that need to be trapped in an C<eval>
127block, or the program will halt.
128
129=back
130
131=head2 TRADITIONAL INTERFACE
132
133The old interface for C<mkpath> and C<rmtree> take a
134reference to a list of directories (to create or remove),
135followed by a series of positional numeric modal parameters that
136control their behaviour.
137
138This design made it difficult to add
139additional functionality, as well as posed the problem
140of what to do when you don't care how the initial
141positional parameters are specified but only the last
142one needs to be specified. The calls themselves are also
143less self-documenting.
144
145C<mkpath> takes three arguments:
fed7345c 146
147=over 4
148
149=item *
150
12c2e016 151The name of the path to create, or a reference
fed7345c 152to a list of paths to create,
153
154=item *
155
156a boolean value, which if TRUE will cause C<mkpath>
157to print the name of each directory as it is created
158(defaults to FALSE), and
159
160=item *
161
162the numeric mode to use when creating the directories
e2ba98a1 163(defaults to 0777), to be modified by the current umask.
fed7345c 164
165=back
166
037c8c09 167It returns a list of all directories (including intermediates, determined
cc61921f 168using the Unix '/' separator) created. In scalar context it returns
169the number of directories created.
fed7345c 170
070ed461 171If a system error prevents a directory from being created, then the
99c4c5e8 172C<mkpath> function throws a fatal error with C<Carp::croak>. This error
173can be trapped with an C<eval> block:
070ed461 174
175 eval { mkpath($dir) };
176 if ($@) {
177 print "Couldn't create $dir: $@";
178 }
179
12c2e016 180In the traditional form, C<rmtree> takes three arguments:
fed7345c 181
182=over 4
183
184=item *
185
186the root of the subtree to delete, or a reference to
187a list of roots. All of the files and directories
188below each root, as well as the roots themselves,
567d72c2 189will be deleted.
fed7345c 190
191=item *
192
193a boolean value, which if TRUE will cause C<rmtree> to
748a9306 194print a message each time it examines a file, giving the
195name of the file, and indicating whether it's using C<rmdir>
196or C<unlink> to remove it, or that it's skipping it.
fed7345c 197(defaults to FALSE)
198
199=item *
200
201a boolean value, which if TRUE will cause C<rmtree> to
748a9306 202skip any files to which you do not have delete access
203(if running under VMS) or write access (if running
204under another OS). This will change in the future when
205a criterion for 'delete permission' under OSs other
96e4d5b1 206than VMS is settled. (defaults to FALSE)
fed7345c 207
208=back
209
cc61921f 210It returns the number of files, directories and symlinks successfully
211deleted. Symlinks are simply deleted and not followed.
fed7345c 212
12c2e016 213Note also that the occurrence of errors in C<rmtree> using the
214traditional interface can be determined I<only> by trapping diagnostic
215messages using C<$SIG{__WARN__}>; it is not apparent from the return
216value. (The modern interface may use the C<error> parameter to
217record any problems encountered.
218
219=head2 ERROR HANDLING
220
221If C<mkpath> or C<rmtree> encounter an error, a diagnostic message
222will be printed to C<STDERR> via C<carp> (for non-fatal errors),
223or via C<croak> (for fatal errors).
224
225If this behaviour is not desirable, the C<error> attribute may be
226used to hold a reference to a variable, which will be used to store
227the diagnostics. The result is a reference to a list of hash
228references. For each hash reference, the key is the name of the
229file, and the value is the error message (usually the contents of
230C<$!>). An example usage looks like:
231
232 rmpath( 'foo/bar', 'bar/rat', {error => \my $err} );
233 for my $diag (@$err) {
234 my ($file, $message) = each %$diag;
235 print "problem unlinking $file: $message\n";
236 }
237
238If no errors are encountered, C<$err> will point to an empty list
239(thus there is no need to test for C<undef>). If a general error
240is encountered (for instance, C<rmtree> attempts to remove a directory
241tree that does not exist), the diagnostic key will be empty, only
242the value will be set:
243
244 rmpath( '/no/such/path', {error => \my $err} );
245 for my $diag (@$err) {
246 my ($file, $message) = each %$diag;
247 if ($file eq '') {
248 print "general error: $message\n";
249 }
250 }
251
252=head2 NOTES
253
254=head3 HEURISTICS
255
256The functions detect (as far as possible) which way they are being
257called and will act appropriately. It is important to remember that
258the heuristic for detecting the old style is either the presence
259of an array reference, or two or three parameters total and second
260and third parameters are numeric. Hence...
261
262 mkpath '486', '487', '488';
263
264... will not assume the modern style and create three directories, rather
265it will create one directory verbosely, setting the permission to
2660750 (488 being the decimal equivalent of octal 750). Here, old
267style trumps new. It must, for backwards compatibility reasons.
e2ba98a1 268
12c2e016 269If you want to ensure there is absolutely no ambiguity about which
270way the function will behave, make sure the first parameter is a
271reference to a one-element list, to force the old style interpretation:
e2ba98a1 272
12c2e016 273 mkpath ['486'], '487', '488';
274
275and get only one directory created. Or add a reference to an empty
276parameter hash, to force the new style:
277
278 mkpath '486', '487', '488', {};
279
280... and hence create the three directories. If the empty hash
281reference seems a little strange to your eyes, or you suspect a
282subsequent programmer might I<helpfully> optimise it away, you
283can add a parameter set to a default value:
284
285 mkpath '486', '487', '488', {verbose => 0};
286
287=head3 RACE CONDITIONS
288
289There are race conditions internal to the implementation of C<rmtree>
290making it unsafe to use on directory trees which may be altered or
291moved while C<rmtree> is running, and in particular on any directory
292trees with any path components or subdirectories potentially writable
293by untrusted users.
294
295Additionally, if the C<skip_others> parareter is not set (or the
296third parameter in the traditional inferface is not TRUE) and
297C<rmtree> is interrupted, it may leave files and directories with
298permissions altered to allow deletion.
299
300C<File::Path> blindly exports C<mkpath> and C<rmtree> into the
301current namespace. These days, this is considered bad style, but
302to change it now would break too much code. Nonetheless, you are
303invited to specify what it is you are expecting to use:
304
305 use File::Path 'rmtree';
96e4d5b1 306
b8d5f521 307=head1 DIAGNOSTICS
308
309=over 4
310
311=item *
312
313On Windows, if C<mkpath> gives you the warning: B<No such file or
314directory>, this may mean that you've exceeded your filesystem's
315maximum path length.
316
317=back
318
12c2e016 319=head1 SEE ALSO
320
321=over 4
322
323=item *
324
325L<Find::File::Rule>
326
327When removing directory trees, if you want to examine each file
328before deciding whether to deleting it (and possibly leaving large
329swathes alone), F<File::Find::Rule> offers a convenient and flexible
330approach.
331
332=back
333
334=head1 BUGS
335
336Please report all bugs on the RT queue:
337
338L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=File-Path>
339
fed7345c 340=head1 AUTHORS
341
96e4d5b1 342Tim Bunce <F<Tim.Bunce@ig.co.uk>> and
12c2e016 343Charles Bailey <F<bailey@newman.upenn.edu>>.
344
345Currently maintained by David Landgren <F<david@landgren.net>>.
346
347=head1 COPYRIGHT
348
349This module is copyright (C) Charles Bailey, Tim Bunce and
350David Landgren 1995-2007. All rights reserved.
351
352=head1 LICENSE
353
354This library is free software; you can redistribute it and/or modify
355it under the same terms as Perl itself.
fed7345c 356
fed7345c 357=cut
358
12c2e016 359use 5.005_04;
037c8c09 360use strict;
68dc0745 361
12c2e016 362use File::Basename ();
363use File::Spec ();
364BEGIN {
91c4f65e 365 if ($] < 5.006) {
12c2e016 366 # can't say 'opendir my $dh, $dirname'
367 # need to initialise $dh
368 eval "use Symbol";
369 }
370}
371
372use Exporter ();
373use vars qw($VERSION @ISA @EXPORT);
374$VERSION = '2.00';
375@ISA = qw(Exporter);
376@EXPORT = qw(mkpath rmtree);
fed7345c 377
68dc0745 378my $Is_VMS = $^O eq 'VMS';
ffb9ee5f 379my $Is_MacOS = $^O eq 'MacOS';
037c8c09 380
381# These OSes complain if you want to remove a file that you have no
382# write permission to:
12c2e016 383my $Force_Writeable = ($^O eq 'os2' || $^O eq 'dos' || $^O eq 'MSWin32' ||
fa6a1c44 384 $^O eq 'amigaos' || $^O eq 'MacOS' || $^O eq 'epoc');
748a9306 385
12c2e016 386sub _carp {
8878f897 387 require Carp;
388 goto &Carp::carp;
389}
390
12c2e016 391sub _croak {
8878f897 392 require Carp;
393 goto &Carp::croak;
394}
395
a5f75d66 396sub mkpath {
12c2e016 397 my $new_style = (
398 ref($_[0]) eq 'ARRAY'
399 or (@_ == 2 and $_[1] =~ /\A\d+\z/)
400 or (@_ == 3 and $_[1] =~ /\A\d+\z/ and $_[2] =~ /\A\d+\z/)
401 ) ? 0 : 1;
402
403 my $arg;
404 my $paths;
405
406 if ($new_style) {
407 if (ref $_[-1] eq 'HASH') {
408 $arg = pop @_;
409 exists $arg->{mask} and $arg->{mode} = delete $arg->{mask};
410 $arg->{mode} = 0777 unless exists $arg->{mode};
411 ${$arg->{error}} = [] if exists $arg->{error};
412 }
413 else {
414 @{$arg}{qw(verbose mode)} = (0, 0777);
415 }
416 $paths = [@_];
417 }
418 else {
419 my ($verbose, $mode);
420 ($paths, $verbose, $mode) = @_;
421 $paths = [$paths] unless ref($paths) eq 'ARRAY';
422 $arg->{verbose} = defined $verbose ? $verbose : 0;
423 $arg->{mode} = defined $mode ? $mode : 0777;
424 }
425 return _mkpath($arg, $paths);
426}
427
428sub _mkpath {
429 my $arg = shift;
430 my $paths = shift;
431
ffb9ee5f 432 local($")=$Is_MacOS ? ":" : "/";
037c8c09 433 my(@created,$path);
68dc0745 434 foreach $path (@$paths) {
12c2e016 435 next unless length($path);
1b1e14d3 436 $path .= '/' if $^O eq 'os2' and $path =~ /^\w:\z/s; # feature of CRT
037c8c09 437 # Logic wants Unix paths, so go with the flow.
e3830a4e 438 if ($Is_VMS) {
439 next if $path eq '/';
440 $path = VMS::Filespec::unixify($path);
491527d0 441 }
e3830a4e 442 next if -d $path;
443 my $parent = File::Basename::dirname($path);
444 unless (-d $parent or $path eq $parent) {
12c2e016 445 push(@created,_mkpath($arg, [$parent]));
446 }
447 print "mkdir $path\n" if $arg->{verbose};
448 if (mkdir($path,$arg->{mode})) {
449 push(@created, $path);
dde45d8e 450 }
12c2e016 451 else {
452 my $save_bang = $!;
453 my ($e, $e1) = ($save_bang, $^E);
dde45d8e 454 $e .= "; $e1" if $e ne $e1;
c3420933 455 # allow for another process to have created it meanwhile
12c2e016 456 if (!-d $path) {
457 $! = $save_bang;
458 if ($arg->{error}) {
459 push @{${$arg->{error}}}, {$path => $e};
460 }
461 else {
462 _croak("mkdir $path: $e");
463 }
67e4c828 464 }
fed7345c 465 }
12c2e016 466 }
467 return @created;
fed7345c 468}
469
470sub rmtree {
12c2e016 471 my $new_style = (
472 ref($_[0]) eq 'ARRAY'
473 or (@_ == 2 and $_[1] =~ /\A\d+\z/)
474 or (@_ == 3 and $_[1] =~ /\A\d+\z/ and $_[2] =~ /\A\d+\z/)
475 ) ? 0 : 1;
476
477 my $arg;
478 my $paths;
479
480 if ($new_style) {
481 if (ref $_[-1] eq 'HASH') {
482 $arg = pop @_;
483 ${$arg->{error}} = [] if exists $arg->{error};
484 ${$arg->{result}} = [] if exists $arg->{result};
485 }
486 else {
487 @{$arg}{qw(verbose safe)} = (0, 0);
488 }
489 $arg->{depth} = 0;
490 $paths = [@_];
491 }
492 else {
493 my ($verbose, $safe);
494 ($paths, $verbose, $safe) = @_;
495 $paths = [$paths] unless ref($paths) eq 'ARRAY';
496 $arg->{verbose} = defined $verbose ? $verbose : 0;
497 $arg->{safe} = defined $safe ? $safe : 0;
498 }
fed7345c 499
12c2e016 500 if (@$paths < 1) {
501 if ($arg->{error}) {
502 push @{${$arg->{error}}}, {'' => "No root path(s) specified"};
ee79a11f 503 }
504 else {
1158ce34 505 $arg->{verbose} and _carp ("No root path(s) specified\n");
12c2e016 506 }
ee79a11f 507 return 0;
508 }
12c2e016 509 return _rmtree($arg, $paths);
510}
ee79a11f 511
12c2e016 512sub _rmtree {
513 my $arg = shift;
514 my $paths = shift;
515 my($count) = 0;
516 my (@files, $root);
517 foreach $root (@{$paths}) {
ffb9ee5f 518 if ($Is_MacOS) {
519 $root = ":$root" if $root !~ /:/;
12c2e016 520 $root =~ s/([^:])\z/$1:/;
521 }
522 else {
ffb9ee5f 523 $root =~ s#/\z##;
524 }
12c2e016 525 my $rp = (lstat $root)[2] or next;
7025f710 526 $rp &= 07777; # don't forget setuid, setgid, sticky bits
527 if ( -d _ ) {
e2ba98a1 528 # notabene: 0700 is for making readable in the first place,
037c8c09 529 # it's also intended to change it to writable in case we have
530 # to recurse in which case we are better than rm -rf for
531 # subtrees with strange permissions
12c2e016 532 if (!chmod($rp | 0700,
533 ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
534 ) {
535 if (!$arg->{safe}) {
536 if ($arg->{error}) {
537 push @{${$arg->{error}}},
538 {$root => "Can't make directory read+writeable: $!"};
539 }
540 else {
541 _carp ("Can't make directory $root read+writeable: $!");
542 }
543 }
544 }
545
546 my $d;
547 $d = gensym() if $] < 5.006;
548 if (!opendir $d, $root) {
549 if ($arg->{error}) {
550 push @{${$arg->{error}}}, {$root => "opendir: $!"};
551 }
552 else {
553 _carp ("Can't read $root: $!");
554 }
555 @files = ();
556 }
557 else {
7068481f 558 no strict 'refs';
559 if (!defined ${"\cTAINT"} or ${"\cTAINT"}) {
12c2e016 560 # Blindly untaint dir names if taint mode is
561 # active, or any perl < 5.006
562 @files = map { /\A(.*)\z/s; $1 } readdir $d;
563 }
564 else {
7068481f 565 @files = readdir $d;
566 }
ff21075d 567 closedir $d;
568 }
037c8c09 569
570 # Deleting large numbers of files from VMS Files-11 filesystems
571 # is faster if done in reverse ASCIIbetical order
572 @files = reverse @files if $Is_VMS;
1b1e14d3 573 ($root = VMS::Filespec::unixify($root)) =~ s#\.dir\z## if $Is_VMS;
ffb9ee5f 574 if ($Is_MacOS) {
575 @files = map("$root$_", @files);
ffb9ee5f 576 }
12c2e016 577 else {
578 my $updir = File::Spec->updir();
579 my $curdir = File::Spec->curdir();
bfbf02a1 580 @files = map(File::Spec->catfile($root,$_),
12c2e016 581 grep {$_ ne $updir and $_ ne $curdir}
582 @files
583 );
584 }
585 $arg->{depth}++;
586 $count += _rmtree($arg, \@files);
587 $arg->{depth}--;
588 if ($arg->{depth} or !$arg->{keep_root}) {
589 if ($arg->{safe} &&
037c8c09 590 ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) {
12c2e016 591 print "skipped $root\n" if $arg->{verbose};
037c8c09 592 next;
593 }
12c2e016 594 if (!chmod $rp | 0700, $root) {
595 if ($Force_Writeable) {
596 if ($arg->{error}) {
597 push @{${$arg->{error}}},
598 {$root => "Can't make directory writeable: $!"};
599 }
600 else {
601 _carp ("Can't make directory $root writeable: $!")
602 }
603 }
604 }
605 print "rmdir $root\n" if $arg->{verbose};
96e4d5b1 606 if (rmdir $root) {
12c2e016 607 push @{${$arg->{result}}}, $root if $arg->{result};
96e4d5b1 608 ++$count;
609 }
610 else {
12c2e016 611 if ($arg->{error}) {
612 push @{${$arg->{error}}}, {$root => "rmdir: $!"};
613 }
614 else {
615 _carp ("Can't remove directory $root: $!");
96e4d5b1 616 }
12c2e016 617 if (!chmod($rp,
618 ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
619 ) {
620 my $mask = sprintf("0%o",$rp);
621 if ($arg->{error}) {
622 push @{${$arg->{error}}}, {$root => "restore chmod: $!"};
037c8c09 623 }
624 else {
12c2e016 625 _carp("and can't restore permissions to $mask\n");
626 }
627 }
628 }
629 }
630 }
631 else {
632 if ($arg->{safe} &&
64f6ddac 633 ($Is_VMS ? !&VMS::Filespec::candelete($root)
634 : !(-l $root || -w $root)))
635 {
12c2e016 636 print "skipped $root\n" if $arg->{verbose};
037c8c09 637 next;
638 }
12c2e016 639 if (!chmod $rp | 0600, $root) {
640 if ($Force_Writeable) {
641 if ($arg->{error}) {
642 push @{${$arg->{error}}},
643 {$root => "Can't make file writeable: $!"};
644 }
645 else {
646 _carp ("Can't make file $root writeable: $!")
647 }
648 }
649 }
650 print "unlink $root\n" if $arg->{verbose};
037c8c09 651 # delete all versions under VMS
94d4f21c 652 for (;;) {
12c2e016 653 if (unlink $root) {
654 push @{${$arg->{result}}}, $root if $arg->{result};
655 }
656 else {
657 if ($arg->{error}) {
658 push @{${$arg->{error}}},
659 {$root => "unlink: $!"};
660 }
661 else {
662 _carp ("Can't unlink file $root: $!");
663 }
664 if ($Force_Writeable) {
665 if (!chmod $rp, $root) {
666 my $mask = sprintf("0%o",$rp);
667 if ($arg->{error}) {
668 push @{${$arg->{error}}}, {$root => "restore chmod: $!"};
669 }
670 else {
671 _carp("and can't restore permissions to $mask\n");
672 }
673 }
96e4d5b1 674 }
94d4f21c 675 last;
96e4d5b1 676 }
94d4f21c 677 ++$count;
678 last unless $Is_VMS && lstat $root;
037c8c09 679 }
680 }
fed7345c 681 }
682
12c2e016 683 return $count;
fed7345c 684}
685
6861;