Sync up with Digest-MD5-2.38 from CPAN
[p5sagit/p5-mst-13.2.git] / lib / File / Spec / Unix.pm
CommitLineData
270d1e39 1package File::Spec::Unix;
2
270d1e39 3use strict;
07824bd1 4use vars qw($VERSION);
b4296952 5
21887892 6$VERSION = '3.29';
486bcc50 7$VERSION = eval $VERSION;
270d1e39 8
9=head1 NAME
10
6fad8743 11File::Spec::Unix - File::Spec for Unix, base for other File::Spec modules
270d1e39 12
13=head1 SYNOPSIS
14
cbc7acb0 15 require File::Spec::Unix; # Done automatically by File::Spec
270d1e39 16
17=head1 DESCRIPTION
18
6fad8743 19Methods for manipulating file specifications. Other File::Spec
20modules, such as File::Spec::Mac, inherit from File::Spec::Unix and
21override specific methods.
270d1e39 22
23=head1 METHODS
24
25=over 2
26
59605c55 27=item canonpath()
270d1e39 28
29No physical check on the filesystem, but a logical cleanup of a
6fad8743 30path. On UNIX eliminates successive slashes and successive "/.".
270d1e39 31
c27914c9 32 $cpath = File::Spec->canonpath( $path ) ;
c27914c9 33
60598624 34Note that this does *not* collapse F<x/../y> sections into F<y>. This
35is by design. If F</foo> on your system is a symlink to F</bar/baz>,
36then F</foo/../quux> is actually F</bar/quux>, not F</quux> as a naive
37F<../>-removal would give you. If you want to do this kind of
38processing, you probably want C<Cwd>'s C<realpath()> function to
39actually traverse the filesystem cleaning up paths like this.
40
270d1e39 41=cut
42
43sub canonpath {
0994714a 44 my ($self,$path) = @_;
bf7c0a3d 45 return unless defined $path;
89bb8afa 46
04ca015e 47 # Handle POSIX-style node names beginning with double slash (qnx, nto)
04ca015e 48 # (POSIX says: "a pathname that begins with two successive slashes
49 # may be interpreted in an implementation-defined manner, although
50 # more than two leading slashes shall be treated as a single slash.")
89bb8afa 51 my $node = '';
e9475de8 52 my $double_slashes_special = $^O eq 'qnx' || $^O eq 'nto';
4a4ab19c 53
54
55 if ( $double_slashes_special
56 && ( $path =~ s{^(//[^/]+)/?\z}{}s || $path =~ s{^(//[^/]+)/}{/}s ) ) {
89bb8afa 57 $node = $1;
58 }
7aa86a29 59 # This used to be
9d5071ba 60 # $path =~ s|/+|/|g unless ($^O eq 'cygwin');
7aa86a29 61 # but that made tests 29, 30, 35, 46, and 213 (as of #13272) to fail
62 # (Mainly because trailing "" directories didn't get stripped).
63 # Why would cygwin avoid collapsing multiple slashes into one? --jhi
e9475de8 64 $path =~ s|/{2,}|/|g; # xx////xx -> xx/xx
65 $path =~ s{(?:/\.)+(?:/|\z)}{/}g; # xx/././xx -> xx/xx
66 $path =~ s|^(?:\./)+||s unless $path eq "./"; # ./xx -> xx
67 $path =~ s|^/(?:\.\./)+|/|; # /../../xx -> xx
9596c75c 68 $path =~ s|^/\.\.$|/|; # /.. -> /
e9475de8 69 $path =~ s|/\z|| unless $path eq "/"; # xx/ -> xx
89bb8afa 70 return "$node$path";
270d1e39 71}
72
59605c55 73=item catdir()
270d1e39 74
75Concatenate two or more directory names to form a complete path ending
76with a directory. But remove the trailing slash from the resulting
77string, because it doesn't look good, isn't necessary and confuses
78OS2. Of course, if this is the root directory, don't cut off the
79trailing slash :-)
80
81=cut
82
270d1e39 83sub catdir {
cbc7acb0 84 my $self = shift;
638113eb 85
86 $self->canonpath(join('/', @_, '')); # '' because need a trailing '/'
270d1e39 87}
88
89=item catfile
90
91Concatenate one or more directory names and a filename to form a
92complete path ending with a filename
93
94=cut
95
96sub catfile {
cbc7acb0 97 my $self = shift;
63c6dcc1 98 my $file = $self->canonpath(pop @_);
270d1e39 99 return $file unless @_;
100 my $dir = $self->catdir(@_);
cbc7acb0 101 $dir .= "/" unless substr($dir,-1) eq "/";
270d1e39 102 return $dir.$file;
103}
104
105=item curdir
106
cbc7acb0 107Returns a string representation of the current directory. "." on UNIX.
270d1e39 108
109=cut
110
486bcc50 111sub curdir { '.' }
270d1e39 112
99804bbb 113=item devnull
114
cbc7acb0 115Returns a string representation of the null device. "/dev/null" on UNIX.
99804bbb 116
117=cut
118
486bcc50 119sub devnull { '/dev/null' }
99804bbb 120
270d1e39 121=item rootdir
122
cbc7acb0 123Returns a string representation of the root directory. "/" on UNIX.
270d1e39 124
125=cut
126
486bcc50 127sub rootdir { '/' }
270d1e39 128
cbc7acb0 129=item tmpdir
130
07824bd1 131Returns a string representation of the first writable directory from
132the following list or the current directory if none from the list are
133writable:
cbc7acb0 134
135 $ENV{TMPDIR}
136 /tmp
137
b4c5e263 138Since perl 5.8.0, if running under taint mode, and if $ENV{TMPDIR}
139is tainted, it is not used.
140
cbc7acb0 141=cut
142
143my $tmpdir;
07824bd1 144sub _tmpdir {
cbc7acb0 145 return $tmpdir if defined $tmpdir;
07824bd1 146 my $self = shift;
147 my @dirlist = @_;
5b577f92 148 {
149 no strict 'refs';
150 if (${"\cTAINT"}) { # Check for taint mode on perl >= 5.8.0
151 require Scalar::Util;
07824bd1 152 @dirlist = grep { ! Scalar::Util::tainted($_) } @dirlist;
5b577f92 153 }
b4c5e263 154 }
155 foreach (@dirlist) {
cbc7acb0 156 next unless defined && -d && -w _;
157 $tmpdir = $_;
158 last;
159 }
07824bd1 160 $tmpdir = $self->curdir unless defined $tmpdir;
161 $tmpdir = defined $tmpdir && $self->canonpath($tmpdir);
cbc7acb0 162 return $tmpdir;
163}
164
07824bd1 165sub tmpdir {
166 return $tmpdir if defined $tmpdir;
60598624 167 $tmpdir = $_[0]->_tmpdir( $ENV{TMPDIR}, "/tmp" );
07824bd1 168}
169
270d1e39 170=item updir
171
cbc7acb0 172Returns a string representation of the parent directory. ".." on UNIX.
270d1e39 173
174=cut
175
486bcc50 176sub updir { '..' }
270d1e39 177
178=item no_upwards
179
180Given a list of file names, strip out those that refer to a parent
181directory. (Does not strip symlinks, only '.', '..', and equivalents.)
182
183=cut
184
185sub no_upwards {
cbc7acb0 186 my $self = shift;
e9475de8 187 return grep(!/^\.{1,2}\z/s, @_);
270d1e39 188}
189
46726cbe 190=item case_tolerant
191
192Returns a true or false value indicating, respectively, that alphabetic
193is not or is significant when comparing file specifications.
194
195=cut
196
486bcc50 197sub case_tolerant { 0 }
46726cbe 198
270d1e39 199=item file_name_is_absolute
200
3c32ced9 201Takes as argument a path and returns true if it is an absolute path.
202
2586ba89 203This does not consult the local filesystem on Unix, Win32, OS/2 or Mac
204OS (Classic). It does consult the working environment for VMS (see
3c32ced9 205L<File::Spec::VMS/file_name_is_absolute>).
270d1e39 206
207=cut
208
209sub file_name_is_absolute {
cbc7acb0 210 my ($self,$file) = @_;
1b1e14d3 211 return scalar($file =~ m:^/:s);
270d1e39 212}
213
214=item path
215
216Takes no argument, returns the environment variable PATH as an array.
217
218=cut
219
220sub path {
802aa3ba 221 return () unless exists $ENV{PATH};
cbc7acb0 222 my @path = split(':', $ENV{PATH});
223 foreach (@path) { $_ = '.' if $_ eq '' }
224 return @path;
270d1e39 225}
226
227=item join
228
229join is the same as catfile.
230
231=cut
232
233sub join {
cbc7acb0 234 my $self = shift;
235 return $self->catfile(@_);
270d1e39 236}
237
c27914c9 238=item splitpath
239
240 ($volume,$directories,$file) = File::Spec->splitpath( $path );
241 ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );
242
40d020d9 243Splits a path into volume, directory, and filename portions. On systems
244with no concept of volume, returns '' for volume.
c27914c9 245
246For systems with no syntax differentiating filenames from directories,
247assumes that the last file is a path unless $no_file is true or a
248trailing separator or /. or /.. is present. On Unix this means that $no_file
249true makes this return ( '', $path, '' ).
250
251The directory portion may or may not be returned with a trailing '/'.
252
253The results can be passed to L</catpath()> to get back a path equivalent to
254(usually identical to) the original path.
255
256=cut
257
258sub splitpath {
259 my ($self,$path, $nofile) = @_;
260
261 my ($volume,$directory,$file) = ('','','');
262
263 if ( $nofile ) {
264 $directory = $path;
265 }
266 else {
e9475de8 267 $path =~ m|^ ( (?: .* / (?: \.\.?\z )? )? ) ([^/]*) |xs;
c27914c9 268 $directory = $1;
269 $file = $2;
270 }
271
272 return ($volume,$directory,$file);
273}
274
275
276=item splitdir
277
278The opposite of L</catdir()>.
279
280 @dirs = File::Spec->splitdir( $directories );
281
282$directories must be only the directory portion of the path on systems
283that have the concept of a volume or that have path syntax that differentiates
284files from directories.
285
200f06d0 286Unlike just splitting the directories on the separator, empty
287directory names (C<''>) can be returned, because these are significant
2586ba89 288on some OSs.
c27914c9 289
200f06d0 290On Unix,
291
292 File::Spec->splitdir( "/a/b//c/" );
c27914c9 293
294Yields:
295
296 ( '', 'a', 'b', '', 'c', '' )
297
298=cut
299
300sub splitdir {
e021ab8e 301 return split m|/|, $_[1], -1; # Preserve trailing fields
c27914c9 302}
303
304
59605c55 305=item catpath()
c27914c9 306
307Takes volume, directory and file portions and returns an entire path. Under
3099fc99 308Unix, $volume is ignored, and directory and file are concatenated. A '/' is
529a1a84 309inserted if needed (though if the directory portion doesn't start with
310'/' it is not added). On other OSs, $volume is significant.
c27914c9 311
312=cut
313
314sub catpath {
315 my ($self,$volume,$directory,$file) = @_;
316
317 if ( $directory ne '' &&
318 $file ne '' &&
319 substr( $directory, -1 ) ne '/' &&
320 substr( $file, 0, 1 ) ne '/'
321 ) {
322 $directory .= "/$file" ;
323 }
324 else {
325 $directory .= $file ;
326 }
327
328 return $directory ;
329}
330
331=item abs2rel
332
333Takes a destination path and an optional base path returns a relative path
334from the base path to the destination path:
335
3c32ced9 336 $rel_path = File::Spec->abs2rel( $path ) ;
337 $rel_path = File::Spec->abs2rel( $path, $base ) ;
c27914c9 338
c063e98f 339If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
340relative, then it is converted to absolute form using
341L</rel2abs()>. This means that it is taken to be relative to
342L<cwd()|Cwd>.
c27914c9 343
c27914c9 344On systems that have a grammar that indicates filenames, this ignores the
638113eb 345$base filename. Otherwise all path components are assumed to be
c27914c9 346directories.
347
348If $path is relative, it is converted to absolute form using L</rel2abs()>.
59605c55 349This means that it is taken to be relative to L<cwd()|Cwd>.
c27914c9 350
2586ba89 351No checks against the filesystem are made. On VMS, there is
3c32ced9 352interaction with the working environment, as logicals and
353macros are expanded.
c27914c9 354
3c32ced9 355Based on code written by Shigio Yamaguchi.
c27914c9 356
357=cut
358
359sub abs2rel {
360 my($self,$path,$base) = @_;
9d5071ba 361 $base = $self->_cwd() unless defined $base and length $base;
c27914c9 362
81a4c762 363 ($path, $base) = map $self->canonpath($_), $path, $base;
c27914c9 364
e0dc0ff1 365 if (grep $self->file_name_is_absolute($_), $path, $base) {
81a4c762 366 ($path, $base) = map $self->rel2abs($_), $path, $base;
e0dc0ff1 367 }
368 else {
369 # save a couple of cwd()s if both paths are relative
81a4c762 370 ($path, $base) = map $self->catdir('/', $_), $path, $base;
e0dc0ff1 371 }
9d5071ba 372
110c90cc 373 my ($path_volume) = $self->splitpath($path, 1);
374 my ($base_volume) = $self->splitpath($base, 1);
375
376 # Can't relativize across volumes
377 return $path unless $path_volume eq $base_volume;
378
9d5071ba 379 my $path_directories = ($self->splitpath($path, 1))[1];
380 my $base_directories = ($self->splitpath($base, 1))[1];
c27914c9 381
fa52125f 382 # For UNC paths, the user might give a volume like //foo/bar that
383 # strictly speaking has no directory portion. Treat it as if it
384 # had the root directory for that volume.
385 if (!length($base_directories) and $self->file_name_is_absolute($base)) {
386 $base_directories = $self->rootdir;
387 }
388
c27914c9 389 # Now, remove all leading components that are the same
9d5071ba 390 my @pathchunks = $self->splitdir( $path_directories );
391 my @basechunks = $self->splitdir( $base_directories );
6fd19b73 392
fa52125f 393 if ($base_directories eq $self->rootdir) {
394 shift @pathchunks;
395 return $self->canonpath( $self->catpath('', $self->catdir( @pathchunks ), '') );
396 }
397
9d5071ba 398 while (@pathchunks && @basechunks && $self->_same($pathchunks[0], $basechunks[0])) {
c27914c9 399 shift @pathchunks ;
400 shift @basechunks ;
401 }
9d5071ba 402 return $self->curdir unless @pathchunks || @basechunks;
6fd19b73 403
404 # $base now contains the directories the resulting relative path
9d5071ba 405 # must ascend out of before it can descend to $path_directory.
406 my $result_dirs = $self->catdir( ($self->updir) x @basechunks, @pathchunks );
407 return $self->canonpath( $self->catpath('', $result_dirs, '') );
408}
c27914c9 409
9d5071ba 410sub _same {
411 $_[1] eq $_[2];
c27914c9 412}
413
59605c55 414=item rel2abs()
c27914c9 415
416Converts a relative path to an absolute path.
417
3c32ced9 418 $abs_path = File::Spec->rel2abs( $path ) ;
419 $abs_path = File::Spec->rel2abs( $path, $base ) ;
c27914c9 420
0fab864c 421If $base is not present or '', then L<cwd()|Cwd> is used. If $base is
422relative, then it is converted to absolute form using
423L</rel2abs()>. This means that it is taken to be relative to
424L<cwd()|Cwd>.
c27914c9 425
638113eb 426On systems that have a grammar that indicates filenames, this ignores
427the $base filename. Otherwise all path components are assumed to be
c27914c9 428directories.
429
430If $path is absolute, it is cleaned up and returned using L</canonpath()>.
431
2586ba89 432No checks against the filesystem are made. On VMS, there is
3c32ced9 433interaction with the working environment, as logicals and
434macros are expanded.
c27914c9 435
3c32ced9 436Based on code written by Shigio Yamaguchi.
c27914c9 437
438=cut
439
786b702f 440sub rel2abs {
c27914c9 441 my ($self,$path,$base ) = @_;
442
443 # Clean up $path
444 if ( ! $self->file_name_is_absolute( $path ) ) {
445 # Figure out the effective $base and clean it up.
446 if ( !defined( $base ) || $base eq '' ) {
0fab864c 447 $base = $self->_cwd();
c27914c9 448 }
449 elsif ( ! $self->file_name_is_absolute( $base ) ) {
450 $base = $self->rel2abs( $base ) ;
451 }
452 else {
453 $base = $self->canonpath( $base ) ;
454 }
455
456 # Glom them together
6fd19b73 457 $path = $self->catdir( $base, $path ) ;
c27914c9 458 }
459
460 return $self->canonpath( $path ) ;
461}
462
270d1e39 463=back
464
99f36a73 465=head1 COPYRIGHT
466
467Copyright (c) 2004 by the Perl 5 Porters. All rights reserved.
468
469This program is free software; you can redistribute it and/or modify
470it under the same terms as Perl itself.
471
270d1e39 472=head1 SEE ALSO
473
474L<File::Spec>
475
476=cut
477
0fab864c 478# Internal routine to File::Spec, no point in making this public since
479# it is the standard Cwd interface. Most of the platform-specific
480# File::Spec subclasses use this.
481sub _cwd {
c063e98f 482 require Cwd;
7241d76a 483 Cwd::getcwd();
c063e98f 484}
485
9596c75c 486
487# Internal method to reduce xx\..\yy -> yy
488sub _collapse {
489 my($fs, $path) = @_;
490
491 my $updir = $fs->updir;
492 my $curdir = $fs->curdir;
493
494 my($vol, $dirs, $file) = $fs->splitpath($path);
495 my @dirs = $fs->splitdir($dirs);
c47834cd 496 pop @dirs if @dirs && $dirs[-1] eq '';
9596c75c 497
498 my @collapsed;
499 foreach my $dir (@dirs) {
500 if( $dir eq $updir and # if we have an updir
501 @collapsed and # and something to collapse
502 length $collapsed[-1] and # and its not the rootdir
503 $collapsed[-1] ne $updir and # nor another updir
504 $collapsed[-1] ne $curdir # nor the curdir
505 )
506 { # then
507 pop @collapsed; # collapse
508 }
509 else { # else
510 push @collapsed, $dir; # just hang onto it
511 }
512 }
513
514 return $fs->catpath($vol,
515 $fs->catdir(@collapsed),
516 $file
517 );
518}
519
520
270d1e39 5211;