This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
speed up building with less disk IO pod moves+__END__+misc
[perl5.git] / dist / PathTools / lib / File / Spec / Mac.pm
... / ...
CommitLineData
1package File::Spec::Mac;
2
3use strict;
4use vars qw(@ISA $VERSION);
5require File::Spec::Unix;
6
7$VERSION = '3.51';
8$VERSION =~ tr/_//;
9
10@ISA = qw(File::Spec::Unix);
11
12my $macfiles;
13if ($^O eq 'MacOS') {
14 $macfiles = eval { require Mac::Files };
15}
16
17sub case_tolerant { 1 }
18
19
20=head1 NAME
21
22File::Spec::Mac - File::Spec for Mac OS (Classic)
23
24=head1 SYNOPSIS
25
26 require File::Spec::Mac; # Done internally by File::Spec if needed
27
28=head1 DESCRIPTION
29
30Methods for manipulating file specifications.
31
32=head1 METHODS
33
34=over 2
35
36=item canonpath
37
38On Mac OS, there's nothing to be done. Returns what it's given.
39
40=cut
41
42sub canonpath {
43 my ($self,$path) = @_;
44 return $path;
45}
46
47=item catdir()
48
49Concatenate two or more directory names to form a path separated by colons
50(":") ending with a directory. Resulting paths are B<relative> by default,
51but can be forced to be absolute (but avoid this, see below). Automatically
52puts a trailing ":" on the end of the complete path, because that's what's
53done in MacPerl's environment and helps to distinguish a file path from a
54directory path.
55
56B<IMPORTANT NOTE:> Beginning with version 1.3 of this module, the resulting
57path is relative by default and I<not> absolute. This decision was made due
58to portability reasons. Since C<File::Spec-E<gt>catdir()> returns relative paths
59on all other operating systems, it will now also follow this convention on Mac
60OS. Note that this may break some existing scripts.
61
62The intended purpose of this routine is to concatenate I<directory names>.
63But because of the nature of Macintosh paths, some additional possibilities
64are allowed to make using this routine give reasonable results for some
65common situations. In other words, you are also allowed to concatenate
66I<paths> instead of directory names (strictly speaking, a string like ":a"
67is a path, but not a name, since it contains a punctuation character ":").
68
69So, beside calls like
70
71 catdir("a") = ":a:"
72 catdir("a","b") = ":a:b:"
73 catdir() = "" (special case)
74
75calls like the following
76
77 catdir(":a:") = ":a:"
78 catdir(":a","b") = ":a:b:"
79 catdir(":a:","b") = ":a:b:"
80 catdir(":a:",":b:") = ":a:b:"
81 catdir(":") = ":"
82
83are allowed.
84
85Here are the rules that are used in C<catdir()>; note that we try to be as
86compatible as possible to Unix:
87
88=over 2
89
90=item 1.
91
92The resulting path is relative by default, i.e. the resulting path will have a
93leading colon.
94
95=item 2.
96
97A trailing colon is added automatically to the resulting path, to denote a
98directory.
99
100=item 3.
101
102Generally, each argument has one leading ":" and one trailing ":"
103removed (if any). They are then joined together by a ":". Special
104treatment applies for arguments denoting updir paths like "::lib:",
105see (4), or arguments consisting solely of colons ("colon paths"),
106see (5).
107
108=item 4.
109
110When an updir path like ":::lib::" is passed as argument, the number
111of directories to climb up is handled correctly, not removing leading
112or trailing colons when necessary. E.g.
113
114 catdir(":::a","::b","c") = ":::a::b:c:"
115 catdir(":::a::","::b","c") = ":::a:::b:c:"
116
117=item 5.
118
119Adding a colon ":" or empty string "" to a path at I<any> position
120doesn't alter the path, i.e. these arguments are ignored. (When a ""
121is passed as the first argument, it has a special meaning, see
122(6)). This way, a colon ":" is handled like a "." (curdir) on Unix,
123while an empty string "" is generally ignored (see
124C<Unix-E<gt>canonpath()> ). Likewise, a "::" is handled like a ".."
125(updir), and a ":::" is handled like a "../.." etc. E.g.
126
127 catdir("a",":",":","b") = ":a:b:"
128 catdir("a",":","::",":b") = ":a::b:"
129
130=item 6.
131
132If the first argument is an empty string "" or is a volume name, i.e. matches
133the pattern /^[^:]+:/, the resulting path is B<absolute>.
134
135=item 7.
136
137Passing an empty string "" as the first argument to C<catdir()> is
138like passingC<File::Spec-E<gt>rootdir()> as the first argument, i.e.
139
140 catdir("","a","b") is the same as
141
142 catdir(rootdir(),"a","b").
143
144This is true on Unix, where C<catdir("","a","b")> yields "/a/b" and
145C<rootdir()> is "/". Note that C<rootdir()> on Mac OS is the startup
146volume, which is the closest in concept to Unix' "/". This should help
147to run existing scripts originally written for Unix.
148
149=item 8.
150
151For absolute paths, some cleanup is done, to ensure that the volume
152name isn't immediately followed by updirs. This is invalid, because
153this would go beyond "root". Generally, these cases are handled like
154their Unix counterparts:
155
156 Unix:
157 Unix->catdir("","") = "/"
158 Unix->catdir("",".") = "/"
159 Unix->catdir("","..") = "/" # can't go
160 # beyond root
161 Unix->catdir("",".","..","..","a") = "/a"
162 Mac:
163 Mac->catdir("","") = rootdir() # (e.g. "HD:")
164 Mac->catdir("",":") = rootdir()
165 Mac->catdir("","::") = rootdir() # can't go
166 # beyond root
167 Mac->catdir("",":","::","::","a") = rootdir() . "a:"
168 # (e.g. "HD:a:")
169
170However, this approach is limited to the first arguments following
171"root" (again, see C<Unix-E<gt>canonpath()> ). If there are more
172arguments that move up the directory tree, an invalid path going
173beyond root can be created.
174
175=back
176
177As you've seen, you can force C<catdir()> to create an absolute path
178by passing either an empty string or a path that begins with a volume
179name as the first argument. However, you are strongly encouraged not
180to do so, since this is done only for backward compatibility. Newer
181versions of File::Spec come with a method called C<catpath()> (see
182below), that is designed to offer a portable solution for the creation
183of absolute paths. It takes volume, directory and file portions and
184returns an entire path. While C<catdir()> is still suitable for the
185concatenation of I<directory names>, you are encouraged to use
186C<catpath()> to concatenate I<volume names> and I<directory
187paths>. E.g.
188
189 $dir = File::Spec->catdir("tmp","sources");
190 $abs_path = File::Spec->catpath("MacintoshHD:", $dir,"");
191
192yields
193
194 "MacintoshHD:tmp:sources:" .
195
196=cut
197
198sub catdir {
199 my $self = shift;
200 return '' unless @_;
201 my @args = @_;
202 my $first_arg;
203 my $relative;
204
205 # take care of the first argument
206
207 if ($args[0] eq '') { # absolute path, rootdir
208 shift @args;
209 $relative = 0;
210 $first_arg = $self->rootdir;
211
212 } elsif ($args[0] =~ /^[^:]+:/) { # absolute path, volume name
213 $relative = 0;
214 $first_arg = shift @args;
215 # add a trailing ':' if need be (may be it's a path like HD:dir)
216 $first_arg = "$first_arg:" unless ($first_arg =~ /:\Z(?!\n)/);
217
218 } else { # relative path
219 $relative = 1;
220 if ( $args[0] =~ /^::+\Z(?!\n)/ ) {
221 # updir colon path ('::', ':::' etc.), don't shift
222 $first_arg = ':';
223 } elsif ($args[0] eq ':') {
224 $first_arg = shift @args;
225 } else {
226 # add a trailing ':' if need be
227 $first_arg = shift @args;
228 $first_arg = "$first_arg:" unless ($first_arg =~ /:\Z(?!\n)/);
229 }
230 }
231
232 # For all other arguments,
233 # (a) ignore arguments that equal ':' or '',
234 # (b) handle updir paths specially:
235 # '::' -> concatenate '::'
236 # '::' . '::' -> concatenate ':::' etc.
237 # (c) add a trailing ':' if need be
238
239 my $result = $first_arg;
240 while (@args) {
241 my $arg = shift @args;
242 unless (($arg eq '') || ($arg eq ':')) {
243 if ($arg =~ /^::+\Z(?!\n)/ ) { # updir colon path like ':::'
244 my $updir_count = length($arg) - 1;
245 while ((@args) && ($args[0] =~ /^::+\Z(?!\n)/) ) { # while updir colon path
246 $arg = shift @args;
247 $updir_count += (length($arg) - 1);
248 }
249 $arg = (':' x $updir_count);
250 } else {
251 $arg =~ s/^://s; # remove a leading ':' if any
252 $arg = "$arg:" unless ($arg =~ /:\Z(?!\n)/); # ensure trailing ':'
253 }
254 $result .= $arg;
255 }#unless
256 }
257
258 if ( ($relative) && ($result !~ /^:/) ) {
259 # add a leading colon if need be
260 $result = ":$result";
261 }
262
263 unless ($relative) {
264 # remove updirs immediately following the volume name
265 $result =~ s/([^:]+:)(:*)(.*)\Z(?!\n)/$1$3/;
266 }
267
268 return $result;
269}
270
271=item catfile
272
273Concatenate one or more directory names and a filename to form a
274complete path ending with a filename. Resulting paths are B<relative>
275by default, but can be forced to be absolute (but avoid this).
276
277B<IMPORTANT NOTE:> Beginning with version 1.3 of this module, the
278resulting path is relative by default and I<not> absolute. This
279decision was made due to portability reasons. Since
280C<File::Spec-E<gt>catfile()> returns relative paths on all other
281operating systems, it will now also follow this convention on Mac OS.
282Note that this may break some existing scripts.
283
284The last argument is always considered to be the file portion. Since
285C<catfile()> uses C<catdir()> (see above) for the concatenation of the
286directory portions (if any), the following with regard to relative and
287absolute paths is true:
288
289 catfile("") = ""
290 catfile("file") = "file"
291
292but
293
294 catfile("","") = rootdir() # (e.g. "HD:")
295 catfile("","file") = rootdir() . file # (e.g. "HD:file")
296 catfile("HD:","file") = "HD:file"
297
298This means that C<catdir()> is called only when there are two or more
299arguments, as one might expect.
300
301Note that the leading ":" is removed from the filename, so that
302
303 catfile("a","b","file") = ":a:b:file" and
304
305 catfile("a","b",":file") = ":a:b:file"
306
307give the same answer.
308
309To concatenate I<volume names>, I<directory paths> and I<filenames>,
310you are encouraged to use C<catpath()> (see below).
311
312=cut
313
314sub catfile {
315 my $self = shift;
316 return '' unless @_;
317 my $file = pop @_;
318 return $file unless @_;
319 my $dir = $self->catdir(@_);
320 $file =~ s/^://s;
321 return $dir.$file;
322}
323
324=item curdir
325
326Returns a string representing the current directory. On Mac OS, this is ":".
327
328=cut
329
330sub curdir {
331 return ":";
332}
333
334=item devnull
335
336Returns a string representing the null device. On Mac OS, this is "Dev:Null".
337
338=cut
339
340sub devnull {
341 return "Dev:Null";
342}
343
344=item rootdir
345
346Returns a string representing the root directory. Under MacPerl,
347returns the name of the startup volume, since that's the closest in
348concept, although other volumes aren't rooted there. The name has a
349trailing ":", because that's the correct specification for a volume
350name on Mac OS.
351
352If Mac::Files could not be loaded, the empty string is returned.
353
354=cut
355
356sub rootdir {
357#
358# There's no real root directory on Mac OS. The name of the startup
359# volume is returned, since that's the closest in concept.
360#
361 return '' unless $macfiles;
362 my $system = Mac::Files::FindFolder(&Mac::Files::kOnSystemDisk,
363 &Mac::Files::kSystemFolderType);
364 $system =~ s/:.*\Z(?!\n)/:/s;
365 return $system;
366}
367
368=item tmpdir
369
370Returns the contents of $ENV{TMPDIR}, if that directory exits or the
371current working directory otherwise. Under MacPerl, $ENV{TMPDIR} will
372contain a path like "MacintoshHD:Temporary Items:", which is a hidden
373directory on your startup volume.
374
375=cut
376
377sub tmpdir {
378 my $cached = $_[0]->_cached_tmpdir('TMPDIR');
379 return $cached if defined $cached;
380 $_[0]->_cache_tmpdir($_[0]->_tmpdir( $ENV{TMPDIR} ), 'TMPDIR');
381}
382
383=item updir
384
385Returns a string representing the parent directory. On Mac OS, this is "::".
386
387=cut
388
389sub updir {
390 return "::";
391}
392
393=item file_name_is_absolute
394
395Takes as argument a path and returns true, if it is an absolute path.
396If the path has a leading ":", it's a relative path. Otherwise, it's an
397absolute path, unless the path doesn't contain any colons, i.e. it's a name
398like "a". In this particular case, the path is considered to be relative
399(i.e. it is considered to be a filename). Use ":" in the appropriate place
400in the path if you want to distinguish unambiguously. As a special case,
401the filename '' is always considered to be absolute. Note that with version
4021.2 of File::Spec::Mac, this does no longer consult the local filesystem.
403
404E.g.
405
406 File::Spec->file_name_is_absolute("a"); # false (relative)
407 File::Spec->file_name_is_absolute(":a:b:"); # false (relative)
408 File::Spec->file_name_is_absolute("MacintoshHD:");
409 # true (absolute)
410 File::Spec->file_name_is_absolute(""); # true (absolute)
411
412
413=cut
414
415sub file_name_is_absolute {
416 my ($self,$file) = @_;
417 if ($file =~ /:/) {
418 return (! ($file =~ m/^:/s) );
419 } elsif ( $file eq '' ) {
420 return 1 ;
421 } else {
422 return 0; # i.e. a file like "a"
423 }
424}
425
426=item path
427
428Returns the null list for the MacPerl application, since the concept is
429usually meaningless under Mac OS. But if you're using the MacPerl tool under
430MPW, it gives back $ENV{Commands} suitably split, as is done in
431:lib:ExtUtils:MM_Mac.pm.
432
433=cut
434
435sub path {
436#
437# The concept is meaningless under the MacPerl application.
438# Under MPW, it has a meaning.
439#
440 return unless exists $ENV{Commands};
441 return split(/,/, $ENV{Commands});
442}
443
444=item splitpath
445
446 ($volume,$directories,$file) = File::Spec->splitpath( $path );
447 ($volume,$directories,$file) = File::Spec->splitpath( $path,
448 $no_file );
449
450Splits a path into volume, directory, and filename portions.
451
452On Mac OS, assumes that the last part of the path is a filename unless
453$no_file is true or a trailing separator ":" is present.
454
455The volume portion is always returned with a trailing ":". The directory portion
456is always returned with a leading (to denote a relative path) and a trailing ":"
457(to denote a directory). The file portion is always returned I<without> a leading ":".
458Empty portions are returned as empty string ''.
459
460The results can be passed to C<catpath()> to get back a path equivalent to
461(usually identical to) the original path.
462
463
464=cut
465
466sub splitpath {
467 my ($self,$path, $nofile) = @_;
468 my ($volume,$directory,$file);
469
470 if ( $nofile ) {
471 ( $volume, $directory ) = $path =~ m|^((?:[^:]+:)?)(.*)|s;
472 }
473 else {
474 $path =~
475 m|^( (?: [^:]+: )? )
476 ( (?: .*: )? )
477 ( .* )
478 |xs;
479 $volume = $1;
480 $directory = $2;
481 $file = $3;
482 }
483
484 $volume = '' unless defined($volume);
485 $directory = ":$directory" if ( $volume && $directory ); # take care of "HD::dir"
486 if ($directory) {
487 # Make sure non-empty directories begin and end in ':'
488 $directory .= ':' unless (substr($directory,-1) eq ':');
489 $directory = ":$directory" unless (substr($directory,0,1) eq ':');
490 } else {
491 $directory = '';
492 }
493 $file = '' unless defined($file);
494
495 return ($volume,$directory,$file);
496}
497
498
499=item splitdir
500
501The opposite of C<catdir()>.
502
503 @dirs = File::Spec->splitdir( $directories );
504
505$directories should be only the directory portion of the path on systems
506that have the concept of a volume or that have path syntax that differentiates
507files from directories. Consider using C<splitpath()> otherwise.
508
509Unlike just splitting the directories on the separator, empty directory names
510(C<"">) can be returned. Since C<catdir()> on Mac OS always appends a trailing
511colon to distinguish a directory path from a file path, a single trailing colon
512will be ignored, i.e. there's no empty directory name after it.
513
514Hence, on Mac OS, both
515
516 File::Spec->splitdir( ":a:b::c:" ); and
517 File::Spec->splitdir( ":a:b::c" );
518
519yield:
520
521 ( "a", "b", "::", "c")
522
523while
524
525 File::Spec->splitdir( ":a:b::c::" );
526
527yields:
528
529 ( "a", "b", "::", "c", "::")
530
531
532=cut
533
534sub splitdir {
535 my ($self, $path) = @_;
536 my @result = ();
537 my ($head, $sep, $tail, $volume, $directories);
538
539 return @result if ( (!defined($path)) || ($path eq '') );
540 return (':') if ($path eq ':');
541
542 ( $volume, $sep, $directories ) = $path =~ m|^((?:[^:]+:)?)(:*)(.*)|s;
543
544 # deprecated, but handle it correctly
545 if ($volume) {
546 push (@result, $volume);
547 $sep .= ':';
548 }
549
550 while ($sep || $directories) {
551 if (length($sep) > 1) {
552 my $updir_count = length($sep) - 1;
553 for (my $i=0; $i<$updir_count; $i++) {
554 # push '::' updir_count times;
555 # simulate Unix '..' updirs
556 push (@result, '::');
557 }
558 }
559 $sep = '';
560 if ($directories) {
561 ( $head, $sep, $tail ) = $directories =~ m|^((?:[^:]+)?)(:*)(.*)|s;
562 push (@result, $head);
563 $directories = $tail;
564 }
565 }
566 return @result;
567}
568
569
570=item catpath
571
572 $path = File::Spec->catpath($volume,$directory,$file);
573
574Takes volume, directory and file portions and returns an entire path. On Mac OS,
575$volume, $directory and $file are concatenated. A ':' is inserted if need be. You
576may pass an empty string for each portion. If all portions are empty, the empty
577string is returned. If $volume is empty, the result will be a relative path,
578beginning with a ':'. If $volume and $directory are empty, a leading ":" (if any)
579is removed form $file and the remainder is returned. If $file is empty, the
580resulting path will have a trailing ':'.
581
582
583=cut
584
585sub catpath {
586 my ($self,$volume,$directory,$file) = @_;
587
588 if ( (! $volume) && (! $directory) ) {
589 $file =~ s/^:// if $file;
590 return $file ;
591 }
592
593 # We look for a volume in $volume, then in $directory, but not both
594
595 my ($dir_volume, $dir_dirs) = $self->splitpath($directory, 1);
596
597 $volume = $dir_volume unless length $volume;
598 my $path = $volume; # may be ''
599 $path .= ':' unless (substr($path, -1) eq ':'); # ensure trailing ':'
600
601 if ($directory) {
602 $directory = $dir_dirs if $volume;
603 $directory =~ s/^://; # remove leading ':' if any
604 $path .= $directory;
605 $path .= ':' unless (substr($path, -1) eq ':'); # ensure trailing ':'
606 }
607
608 if ($file) {
609 $file =~ s/^://; # remove leading ':' if any
610 $path .= $file;
611 }
612
613 return $path;
614}
615
616=item abs2rel
617
618Takes a destination path and an optional base path and returns a relative path
619from the base path to the destination path:
620
621 $rel_path = File::Spec->abs2rel( $path ) ;
622 $rel_path = File::Spec->abs2rel( $path, $base ) ;
623
624Note that both paths are assumed to have a notation that distinguishes a
625directory path (with trailing ':') from a file path (without trailing ':').
626
627If $base is not present or '', then the current working directory is used.
628If $base is relative, then it is converted to absolute form using C<rel2abs()>.
629This means that it is taken to be relative to the current working directory.
630
631If $path and $base appear to be on two different volumes, we will not
632attempt to resolve the two paths, and we will instead simply return
633$path. Note that previous versions of this module ignored the volume
634of $base, which resulted in garbage results part of the time.
635
636If $base doesn't have a trailing colon, the last element of $base is
637assumed to be a filename. This filename is ignored. Otherwise all path
638components are assumed to be directories.
639
640If $path is relative, it is converted to absolute form using C<rel2abs()>.
641This means that it is taken to be relative to the current working directory.
642
643Based on code written by Shigio Yamaguchi.
644
645
646=cut
647
648# maybe this should be done in canonpath() ?
649sub _resolve_updirs {
650 my $path = shift @_;
651 my $proceed;
652
653 # resolve any updirs, e.g. "HD:tmp::file" -> "HD:file"
654 do {
655 $proceed = ($path =~ s/^(.*):[^:]+::(.*?)\z/$1:$2/);
656 } while ($proceed);
657
658 return $path;
659}
660
661
662sub abs2rel {
663 my($self,$path,$base) = @_;
664
665 # Clean up $path
666 if ( ! $self->file_name_is_absolute( $path ) ) {
667 $path = $self->rel2abs( $path ) ;
668 }
669
670 # Figure out the effective $base and clean it up.
671 if ( !defined( $base ) || $base eq '' ) {
672 $base = $self->_cwd();
673 }
674 elsif ( ! $self->file_name_is_absolute( $base ) ) {
675 $base = $self->rel2abs( $base ) ;
676 $base = _resolve_updirs( $base ); # resolve updirs in $base
677 }
678 else {
679 $base = _resolve_updirs( $base );
680 }
681
682 # Split up paths - ignore $base's file
683 my ( $path_vol, $path_dirs, $path_file ) = $self->splitpath( $path );
684 my ( $base_vol, $base_dirs ) = $self->splitpath( $base );
685
686 return $path unless lc( $path_vol ) eq lc( $base_vol );
687
688 # Now, remove all leading components that are the same
689 my @pathchunks = $self->splitdir( $path_dirs );
690 my @basechunks = $self->splitdir( $base_dirs );
691
692 while ( @pathchunks &&
693 @basechunks &&
694 lc( $pathchunks[0] ) eq lc( $basechunks[0] ) ) {
695 shift @pathchunks ;
696 shift @basechunks ;
697 }
698
699 # @pathchunks now has the directories to descend in to.
700 # ensure relative path, even if @pathchunks is empty
701 $path_dirs = $self->catdir( ':', @pathchunks );
702
703 # @basechunks now contains the number of directories to climb out of.
704 $base_dirs = (':' x @basechunks) . ':' ;
705
706 return $self->catpath( '', $self->catdir( $base_dirs, $path_dirs ), $path_file ) ;
707}
708
709=item rel2abs
710
711Converts a relative path to an absolute path:
712
713 $abs_path = File::Spec->rel2abs( $path ) ;
714 $abs_path = File::Spec->rel2abs( $path, $base ) ;
715
716Note that both paths are assumed to have a notation that distinguishes a
717directory path (with trailing ':') from a file path (without trailing ':').
718
719If $base is not present or '', then $base is set to the current working
720directory. If $base is relative, then it is converted to absolute form
721using C<rel2abs()>. This means that it is taken to be relative to the
722current working directory.
723
724If $base doesn't have a trailing colon, the last element of $base is
725assumed to be a filename. This filename is ignored. Otherwise all path
726components are assumed to be directories.
727
728If $path is already absolute, it is returned and $base is ignored.
729
730Based on code written by Shigio Yamaguchi.
731
732=cut
733
734sub rel2abs {
735 my ($self,$path,$base) = @_;
736
737 if ( ! $self->file_name_is_absolute($path) ) {
738 # Figure out the effective $base and clean it up.
739 if ( !defined( $base ) || $base eq '' ) {
740 $base = $self->_cwd();
741 }
742 elsif ( ! $self->file_name_is_absolute($base) ) {
743 $base = $self->rel2abs($base) ;
744 }
745
746 # Split up paths
747
748 # ignore $path's volume
749 my ( $path_dirs, $path_file ) = ($self->splitpath($path))[1,2] ;
750
751 # ignore $base's file part
752 my ( $base_vol, $base_dirs ) = $self->splitpath($base) ;
753
754 # Glom them together
755 $path_dirs = ':' if ($path_dirs eq '');
756 $base_dirs =~ s/:$//; # remove trailing ':', if any
757 $base_dirs = $base_dirs . $path_dirs;
758
759 $path = $self->catpath( $base_vol, $base_dirs, $path_file );
760 }
761 return $path;
762}
763
764
765=back
766
767=head1 AUTHORS
768
769See the authors list in I<File::Spec>. Mac OS support by Paul Schinder
770<schinder@pobox.com> and Thomas Wegner <wegner_thomas@yahoo.com>.
771
772=head1 COPYRIGHT
773
774Copyright (c) 2004 by the Perl 5 Porters. All rights reserved.
775
776This program is free software; you can redistribute it and/or modify
777it under the same terms as Perl itself.
778
779=head1 SEE ALSO
780
781See L<File::Spec> and L<File::Spec::Unix>. This package overrides the
782implementation of these methods, not the semantics.
783
784=cut
785
7861;