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