modify VMS default prefix for installation
[p5sagit/p5-mst-13.2.git] / lib / File / Spec / Unix.pm
CommitLineData
270d1e39 1package File::Spec::Unix;
2
270d1e39 3use strict;
f168a5e7 4our($VERSION);
b4296952 5
3c32ced9 6$VERSION = '1.2';
270d1e39 7
c27914c9 8use Cwd;
9
270d1e39 10=head1 NAME
11
12File::Spec::Unix - methods used by File::Spec
13
14=head1 SYNOPSIS
15
cbc7acb0 16 require File::Spec::Unix; # Done automatically by File::Spec
270d1e39 17
18=head1 DESCRIPTION
19
20Methods for manipulating file specifications.
21
22=head1 METHODS
23
24=over 2
25
26=item canonpath
27
28No physical check on the filesystem, but a logical cleanup of a
29path. On UNIX eliminated successive slashes and successive "/.".
30
c27914c9 31 $cpath = File::Spec->canonpath( $path ) ;
c27914c9 32
270d1e39 33=cut
34
35sub canonpath {
0994714a 36 my ($self,$path) = @_;
89bb8afa 37
38 # Handle POSIX-style node names beginning with double slash
39 my $node = '';
61c0c206 40 if ( $^O =~ m/^(?:qnx|nto)$/ && $path =~ s:^(//[^/]+)(/|\z):/:s ) {
89bb8afa 41 $node = $1;
42 }
4fabb596 43 $path =~ s|/+|/|g unless($^O eq 'cygwin'); # xx////xx -> xx/xx
cbc7acb0 44 $path =~ s|(/\.)+/|/|g; # xx/././xx -> xx/xx
1b1e14d3 45 $path =~ s|^(\./)+||s unless $path eq "./"; # ./xx -> xx
46 $path =~ s|^/(\.\./)+|/|s; # /../../xx -> xx
9c045eb2 47 $path =~ s|/\Z(?!\n)|| unless $path eq "/"; # xx/ -> xx
89bb8afa 48 return "$node$path";
270d1e39 49}
50
51=item catdir
52
53Concatenate two or more directory names to form a complete path ending
54with a directory. But remove the trailing slash from the resulting
55string, because it doesn't look good, isn't necessary and confuses
56OS2. Of course, if this is the root directory, don't cut off the
57trailing slash :-)
58
59=cut
60
270d1e39 61sub catdir {
cbc7acb0 62 my $self = shift;
270d1e39 63 my @args = @_;
cbc7acb0 64 foreach (@args) {
270d1e39 65 # append a slash to each argument unless it has one there
cbc7acb0 66 $_ .= "/" if $_ eq '' || substr($_,-1) ne "/";
270d1e39 67 }
cbc7acb0 68 return $self->canonpath(join('', @args));
270d1e39 69}
70
71=item catfile
72
73Concatenate one or more directory names and a filename to form a
74complete path ending with a filename
75
76=cut
77
78sub catfile {
cbc7acb0 79 my $self = shift;
270d1e39 80 my $file = pop @_;
81 return $file unless @_;
82 my $dir = $self->catdir(@_);
cbc7acb0 83 $dir .= "/" unless substr($dir,-1) eq "/";
270d1e39 84 return $dir.$file;
85}
86
87=item curdir
88
cbc7acb0 89Returns a string representation of the current directory. "." on UNIX.
270d1e39 90
91=cut
92
93sub curdir {
cbc7acb0 94 return ".";
270d1e39 95}
96
99804bbb 97=item devnull
98
cbc7acb0 99Returns a string representation of the null device. "/dev/null" on UNIX.
99804bbb 100
101=cut
102
103sub devnull {
104 return "/dev/null";
105}
106
270d1e39 107=item rootdir
108
cbc7acb0 109Returns a string representation of the root directory. "/" on UNIX.
270d1e39 110
111=cut
112
113sub rootdir {
114 return "/";
115}
116
cbc7acb0 117=item tmpdir
118
119Returns a string representation of the first writable directory
120from the following list or "" if none are writable:
121
122 $ENV{TMPDIR}
123 /tmp
124
125=cut
126
127my $tmpdir;
128sub tmpdir {
129 return $tmpdir if defined $tmpdir;
130 foreach ($ENV{TMPDIR}, "/tmp") {
131 next unless defined && -d && -w _;
132 $tmpdir = $_;
133 last;
134 }
135 $tmpdir = '' unless defined $tmpdir;
136 return $tmpdir;
137}
138
270d1e39 139=item updir
140
cbc7acb0 141Returns a string representation of the parent directory. ".." on UNIX.
270d1e39 142
143=cut
144
145sub updir {
146 return "..";
147}
148
149=item no_upwards
150
151Given a list of file names, strip out those that refer to a parent
152directory. (Does not strip symlinks, only '.', '..', and equivalents.)
153
154=cut
155
156sub no_upwards {
cbc7acb0 157 my $self = shift;
9c045eb2 158 return grep(!/^\.{1,2}\Z(?!\n)/s, @_);
270d1e39 159}
160
46726cbe 161=item case_tolerant
162
163Returns a true or false value indicating, respectively, that alphabetic
164is not or is significant when comparing file specifications.
165
166=cut
167
168sub case_tolerant {
169 return 0;
170}
171
270d1e39 172=item file_name_is_absolute
173
3c32ced9 174Takes as argument a path and returns true if it is an absolute path.
175
176This does not consult the local filesystem on Unix, Win32, or OS/2. It
177does sometimes on MacOS (see L<File::Spec::MacOS/file_name_is_absolute>).
178It does consult the working environment for VMS (see
179L<File::Spec::VMS/file_name_is_absolute>).
270d1e39 180
181=cut
182
183sub file_name_is_absolute {
cbc7acb0 184 my ($self,$file) = @_;
1b1e14d3 185 return scalar($file =~ m:^/:s);
270d1e39 186}
187
188=item path
189
190Takes no argument, returns the environment variable PATH as an array.
191
192=cut
193
194sub path {
cbc7acb0 195 my @path = split(':', $ENV{PATH});
196 foreach (@path) { $_ = '.' if $_ eq '' }
197 return @path;
270d1e39 198}
199
200=item join
201
202join is the same as catfile.
203
204=cut
205
206sub join {
cbc7acb0 207 my $self = shift;
208 return $self->catfile(@_);
270d1e39 209}
210
c27914c9 211=item splitpath
212
213 ($volume,$directories,$file) = File::Spec->splitpath( $path );
214 ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );
215
216Splits a path in to volume, directory, and filename portions. On systems
217with no concept of volume, returns undef for volume.
218
219For systems with no syntax differentiating filenames from directories,
220assumes that the last file is a path unless $no_file is true or a
221trailing separator or /. or /.. is present. On Unix this means that $no_file
222true makes this return ( '', $path, '' ).
223
224The directory portion may or may not be returned with a trailing '/'.
225
226The results can be passed to L</catpath()> to get back a path equivalent to
227(usually identical to) the original path.
228
229=cut
230
231sub splitpath {
232 my ($self,$path, $nofile) = @_;
233
234 my ($volume,$directory,$file) = ('','','');
235
236 if ( $nofile ) {
237 $directory = $path;
238 }
239 else {
9c045eb2 240 $path =~ m|^ ( (?: .* / (?: \.\.?\Z(?!\n) )? )? ) ([^/]*) |xs;
c27914c9 241 $directory = $1;
242 $file = $2;
243 }
244
245 return ($volume,$directory,$file);
246}
247
248
249=item splitdir
250
251The opposite of L</catdir()>.
252
253 @dirs = File::Spec->splitdir( $directories );
254
255$directories must be only the directory portion of the path on systems
256that have the concept of a volume or that have path syntax that differentiates
257files from directories.
258
200f06d0 259Unlike just splitting the directories on the separator, empty
260directory names (C<''>) can be returned, because these are significant
261on some OSs (e.g. MacOS).
c27914c9 262
200f06d0 263On Unix,
264
265 File::Spec->splitdir( "/a/b//c/" );
c27914c9 266
267Yields:
268
269 ( '', 'a', 'b', '', 'c', '' )
270
271=cut
272
273sub splitdir {
274 my ($self,$directories) = @_ ;
275 #
276 # split() likes to forget about trailing null fields, so here we
277 # check to be sure that there will not be any before handling the
278 # simple case.
279 #
9c045eb2 280 if ( $directories !~ m|/\Z(?!\n)| ) {
c27914c9 281 return split( m|/|, $directories );
282 }
283 else {
284 #
285 # since there was a trailing separator, add a file name to the end,
286 # then do the split, then replace it with ''.
287 #
288 my( @directories )= split( m|/|, "${directories}dummy" ) ;
289 $directories[ $#directories ]= '' ;
290 return @directories ;
291 }
292}
293
294
295=item catpath
296
297Takes volume, directory and file portions and returns an entire path. Under
0994714a 298Unix, $volume is ignored, and directory and file are catenated. A '/' is
299inserted if need be. On other OSs, $volume is significant.
c27914c9 300
301=cut
302
303sub catpath {
304 my ($self,$volume,$directory,$file) = @_;
305
306 if ( $directory ne '' &&
307 $file ne '' &&
308 substr( $directory, -1 ) ne '/' &&
309 substr( $file, 0, 1 ) ne '/'
310 ) {
311 $directory .= "/$file" ;
312 }
313 else {
314 $directory .= $file ;
315 }
316
317 return $directory ;
318}
319
320=item abs2rel
321
322Takes a destination path and an optional base path returns a relative path
323from the base path to the destination path:
324
3c32ced9 325 $rel_path = File::Spec->abs2rel( $path ) ;
326 $rel_path = File::Spec->abs2rel( $path, $base ) ;
c27914c9 327
328If $base is not present or '', then L<cwd()> is used. If $base is relative,
329then it is converted to absolute form using L</rel2abs()>. This means that it
330is taken to be relative to L<cwd()>.
331
332On systems with the concept of a volume, this assumes that both paths
333are on the $destination volume, and ignores the $base volume.
334
335On systems that have a grammar that indicates filenames, this ignores the
336$base filename as well. Otherwise all path components are assumed to be
337directories.
338
339If $path is relative, it is converted to absolute form using L</rel2abs()>.
340This means that it is taken to be relative to L<cwd()>.
341
3c32ced9 342No checks against the filesystem are made on most systems. On MacOS,
343the filesystem may be consulted (see
344L<File::Spec::MacOS/file_name_is_absolute>). On VMS, there is
345interaction with the working environment, as logicals and
346macros are expanded.
c27914c9 347
3c32ced9 348Based on code written by Shigio Yamaguchi.
c27914c9 349
350=cut
351
352sub abs2rel {
353 my($self,$path,$base) = @_;
354
355 # Clean up $path
356 if ( ! $self->file_name_is_absolute( $path ) ) {
357 $path = $self->rel2abs( $path ) ;
358 }
359 else {
360 $path = $self->canonpath( $path ) ;
361 }
362
363 # Figure out the effective $base and clean it up.
364 if ( !defined( $base ) || $base eq '' ) {
365 $base = cwd() ;
366 }
367 elsif ( ! $self->file_name_is_absolute( $base ) ) {
368 $base = $self->rel2abs( $base ) ;
369 }
370 else {
371 $base = $self->canonpath( $base ) ;
372 }
373
374 # Now, remove all leading components that are the same
6fd19b73 375 my @pathchunks = $self->splitdir( $path);
376 my @basechunks = $self->splitdir( $base);
377
378 while (@pathchunks && @basechunks && $pathchunks[0] eq $basechunks[0]) {
c27914c9 379 shift @pathchunks ;
380 shift @basechunks ;
381 }
382
6fd19b73 383 $path = CORE::join( '/', @pathchunks );
384 $base = CORE::join( '/', @basechunks );
385
386 # $base now contains the directories the resulting relative path
c27914c9 387 # must ascend out of before it can descend to $path_directory. So,
388 # replace all names with $parentDir
6fd19b73 389 $base =~ s|[^/]+|..|g ;
c27914c9 390
391 # Glue the two together, using a separator if necessary, and preventing an
392 # empty result.
6fd19b73 393 if ( $path ne '' && $base ne '' ) {
394 $path = "$base/$path" ;
395 } else {
396 $path = "$base$path" ;
397 }
c27914c9 398
399 return $self->canonpath( $path ) ;
400}
401
402=item rel2abs
403
404Converts a relative path to an absolute path.
405
3c32ced9 406 $abs_path = File::Spec->rel2abs( $path ) ;
407 $abs_path = File::Spec->rel2abs( $path, $base ) ;
c27914c9 408
409If $base is not present or '', then L<cwd()> is used. If $base is relative,
410then it is converted to absolute form using L</rel2abs()>. This means that it
411is taken to be relative to L<cwd()>.
412
413On systems with the concept of a volume, this assumes that both paths
3c32ced9 414are on the $base volume, and ignores the $path volume.
c27914c9 415
416On systems that have a grammar that indicates filenames, this ignores the
417$base filename as well. Otherwise all path components are assumed to be
418directories.
419
420If $path is absolute, it is cleaned up and returned using L</canonpath()>.
421
3c32ced9 422No checks against the filesystem are made on most systems. On MacOS,
423the filesystem may be consulted (see
424L<File::Spec::MacOS/file_name_is_absolute>). On VMS, there is
425interaction with the working environment, as logicals and
426macros are expanded.
c27914c9 427
3c32ced9 428Based on code written by Shigio Yamaguchi.
c27914c9 429
430=cut
431
786b702f 432sub rel2abs {
c27914c9 433 my ($self,$path,$base ) = @_;
434
435 # Clean up $path
436 if ( ! $self->file_name_is_absolute( $path ) ) {
437 # Figure out the effective $base and clean it up.
438 if ( !defined( $base ) || $base eq '' ) {
439 $base = cwd() ;
440 }
441 elsif ( ! $self->file_name_is_absolute( $base ) ) {
442 $base = $self->rel2abs( $base ) ;
443 }
444 else {
445 $base = $self->canonpath( $base ) ;
446 }
447
448 # Glom them together
6fd19b73 449 $path = $self->catdir( $base, $path ) ;
c27914c9 450 }
451
452 return $self->canonpath( $path ) ;
453}
454
455
270d1e39 456=back
457
458=head1 SEE ALSO
459
460L<File::Spec>
461
462=cut
463
4641;