Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / perl-5.8.0 / lib / 5.8.0 / File / Path.pm
CommitLineData
86530b38
AT
1package File::Path;
2
3=head1 NAME
4
5File::Path - create or remove directory trees
6
7=head1 SYNOPSIS
8
9 use File::Path;
10
11 mkpath(['/foo/bar/baz', 'blurfl/quux'], 1, 0711);
12 rmtree(['foo/bar/baz', 'blurfl/quux'], 1, 1);
13
14=head1 DESCRIPTION
15
16The C<mkpath> function provides a convenient way to create directories, even
17if your C<mkdir> kernel call won't create more than one level of directory at
18a time. C<mkpath> takes three arguments:
19
20=over 4
21
22=item *
23
24the name of the path to create, or a reference
25to a list of paths to create,
26
27=item *
28
29a boolean value, which if TRUE will cause C<mkpath>
30to print the name of each directory as it is created
31(defaults to FALSE), and
32
33=item *
34
35the numeric mode to use when creating the directories
36(defaults to 0777)
37
38=back
39
40It returns a list of all directories (including intermediates, determined
41using the Unix '/' separator) created.
42
43If a system error prevents a directory from being created, then the
44C<mkpath> function throws a fatal error with C<Carp::croak>. This error
45can be trapped with an C<eval> block:
46
47 eval { mkpath($dir) };
48 if ($@) {
49 print "Couldn't create $dir: $@";
50 }
51
52Similarly, the C<rmtree> function provides a convenient way to delete a
53subtree from the directory structure, much like the Unix command C<rm -r>.
54C<rmtree> takes three arguments:
55
56=over 4
57
58=item *
59
60the root of the subtree to delete, or a reference to
61a list of roots. All of the files and directories
62below each root, as well as the roots themselves,
63will be deleted.
64
65=item *
66
67a boolean value, which if TRUE will cause C<rmtree> to
68print a message each time it examines a file, giving the
69name of the file, and indicating whether it's using C<rmdir>
70or C<unlink> to remove it, or that it's skipping it.
71(defaults to FALSE)
72
73=item *
74
75a boolean value, which if TRUE will cause C<rmtree> to
76skip any files to which you do not have delete access
77(if running under VMS) or write access (if running
78under another OS). This will change in the future when
79a criterion for 'delete permission' under OSs other
80than VMS is settled. (defaults to FALSE)
81
82=back
83
84It returns the number of files successfully deleted. Symlinks are
85simply deleted and not followed.
86
87B<NOTE:> If the third parameter is not TRUE, C<rmtree> is B<unsecure>
88in the face of failure or interruption. Files and directories which
89were not deleted may be left with permissions reset to allow world
90read and write access. Note also that the occurrence of errors in
91rmtree can be determined I<only> by trapping diagnostic messages
92using C<$SIG{__WARN__}>; it is not apparent from the return value.
93Therefore, you must be extremely careful about using C<rmtree($foo,$bar,0>
94in situations where security is an issue.
95
96=head1 AUTHORS
97
98Tim Bunce <F<Tim.Bunce@ig.co.uk>> and
99Charles Bailey <F<bailey@newman.upenn.edu>>
100
101=cut
102
103use 5.006;
104use Carp;
105use File::Basename ();
106use Exporter ();
107use strict;
108use warnings;
109
110our $VERSION = "1.05";
111our @ISA = qw( Exporter );
112our @EXPORT = qw( mkpath rmtree );
113
114my $Is_VMS = $^O eq 'VMS';
115my $Is_MacOS = $^O eq 'MacOS';
116
117# These OSes complain if you want to remove a file that you have no
118# write permission to:
119my $force_writeable = ($^O eq 'os2' || $^O eq 'dos' || $^O eq 'MSWin32' ||
120 $^O eq 'amigaos' || $^O eq 'MacOS' || $^O eq 'epoc');
121
122sub mkpath {
123 my($paths, $verbose, $mode) = @_;
124 # $paths -- either a path string or ref to list of paths
125 # $verbose -- optional print "mkdir $path" for each directory created
126 # $mode -- optional permissions, defaults to 0777
127 local($")=$Is_MacOS ? ":" : "/";
128 $mode = 0777 unless defined($mode);
129 $paths = [$paths] unless ref $paths;
130 my(@created,$path);
131 foreach $path (@$paths) {
132 $path .= '/' if $^O eq 'os2' and $path =~ /^\w:\z/s; # feature of CRT
133 # Logic wants Unix paths, so go with the flow.
134 if ($Is_VMS) {
135 next if $path eq '/';
136 $path = VMS::Filespec::unixify($path);
137 if ($path =~ m:^(/[^/]+)/?\z:) {
138 $path = $1.'/000000';
139 }
140 }
141 next if -d $path;
142 my $parent = File::Basename::dirname($path);
143 unless (-d $parent or $path eq $parent) {
144 push(@created,mkpath($parent, $verbose, $mode));
145 }
146 print "mkdir $path\n" if $verbose;
147 unless (mkdir($path,$mode)) {
148 my $e = $!;
149 # allow for another process to have created it meanwhile
150 croak "mkdir $path: $e" unless -d $path;
151 }
152 push(@created, $path);
153 }
154 @created;
155}
156
157sub rmtree {
158 my($roots, $verbose, $safe) = @_;
159 my(@files);
160 my($count) = 0;
161 $verbose ||= 0;
162 $safe ||= 0;
163
164 if ( defined($roots) && length($roots) ) {
165 $roots = [$roots] unless ref $roots;
166 }
167 else {
168 carp "No root path(s) specified\n";
169 return 0;
170 }
171
172 my($root);
173 foreach $root (@{$roots}) {
174 if ($Is_MacOS) {
175 $root = ":$root" if $root !~ /:/;
176 $root =~ s#([^:])\z#$1:#;
177 } else {
178 $root =~ s#/\z##;
179 }
180 (undef, undef, my $rp) = lstat $root or next;
181 $rp &= 07777; # don't forget setuid, setgid, sticky bits
182 if ( -d _ ) {
183 # notabene: 0777 is for making readable in the first place,
184 # it's also intended to change it to writable in case we have
185 # to recurse in which case we are better than rm -rf for
186 # subtrees with strange permissions
187 chmod(0777, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
188 or carp "Can't make directory $root read+writeable: $!"
189 unless $safe;
190
191 if (opendir my $d, $root) {
192 no strict 'refs';
193 if (!defined ${"\cTAINT"} or ${"\cTAINT"}) {
194 # Blindly untaint dir names
195 @files = map { /^(.*)$/s ; $1 } readdir $d;
196 } else {
197 @files = readdir $d;
198 }
199 closedir $d;
200 }
201 else {
202 carp "Can't read $root: $!";
203 @files = ();
204 }
205
206 # Deleting large numbers of files from VMS Files-11 filesystems
207 # is faster if done in reverse ASCIIbetical order
208 @files = reverse @files if $Is_VMS;
209 ($root = VMS::Filespec::unixify($root)) =~ s#\.dir\z## if $Is_VMS;
210 if ($Is_MacOS) {
211 @files = map("$root$_", @files);
212 } else {
213 @files = map("$root/$_", grep $_!~/^\.{1,2}\z/s,@files);
214 }
215 $count += rmtree(\@files,$verbose,$safe);
216 if ($safe &&
217 ($Is_VMS ? !&VMS::Filespec::candelete($root) : !-w $root)) {
218 print "skipped $root\n" if $verbose;
219 next;
220 }
221 chmod 0777, $root
222 or carp "Can't make directory $root writeable: $!"
223 if $force_writeable;
224 print "rmdir $root\n" if $verbose;
225 if (rmdir $root) {
226 ++$count;
227 }
228 else {
229 carp "Can't remove directory $root: $!";
230 chmod($rp, ($Is_VMS ? VMS::Filespec::fileify($root) : $root))
231 or carp("and can't restore permissions to "
232 . sprintf("0%o",$rp) . "\n");
233 }
234 }
235 else {
236 if ($safe &&
237 ($Is_VMS ? !&VMS::Filespec::candelete($root)
238 : !(-l $root || -w $root)))
239 {
240 print "skipped $root\n" if $verbose;
241 next;
242 }
243 chmod 0666, $root
244 or carp "Can't make file $root writeable: $!"
245 if $force_writeable;
246 print "unlink $root\n" if $verbose;
247 # delete all versions under VMS
248 for (;;) {
249 unless (unlink $root) {
250 carp "Can't unlink file $root: $!";
251 if ($force_writeable) {
252 chmod $rp, $root
253 or carp("and can't restore permissions to "
254 . sprintf("0%o",$rp) . "\n");
255 }
256 last;
257 }
258 ++$count;
259 last unless $Is_VMS && lstat $root;
260 }
261 }
262 }
263
264 $count;
265}
266
2671;