[perl #8599] s/catenate/concatenate/
[p5sagit/p5-mst-13.2.git] / lib / File / Spec / Unix.pm
index 01d5f48..904b657 100644 (file)
@@ -1,9 +1,9 @@
 package File::Spec::Unix;
 
 use strict;
-our($VERSION);
+use vars qw($VERSION);
 
-$VERSION = '1.3';
+$VERSION = '1.4';
 
 use Cwd;
 
@@ -37,12 +37,21 @@ path. On UNIX eliminates successive slashes and successive "/.".
 sub canonpath {
     my ($self,$path) = @_;
     
-    # Handle POSIX-style node names beginning with double slash
+    # Handle POSIX-style node names beginning with double slash (qnx, nto)
+    # Handle network path names beginning with double slash (cygwin)
+    # (POSIX says: "a pathname that begins with two successive slashes
+    # may be interpreted in an implementation-defined manner, although
+    # more than two leading slashes shall be treated as a single slash.")
     my $node = '';
-    if ( $^O =~ m/^(?:qnx|nto)$/ && $path =~ s:^(//[^/]+)(/|\z):/:s ) {
+    if ( $^O =~ m/^(?:qnx|nto|cygwin)$/ && $path =~ s:^(//[^/]+)(/|\z):/:s ) {
       $node = $1;
     }
-    $path =~ s|/+|/|g unless($^O eq 'cygwin');     # xx////xx  -> xx/xx
+    # This used to be
+    # $path =~ s|/+|/|g unless($^O eq 'cygwin');
+    # but that made tests 29, 30, 35, 46, and 213 (as of #13272) to fail
+    # (Mainly because trailing "" directories didn't get stripped).
+    # Why would cygwin avoid collapsing multiple slashes into one? --jhi
+    $path =~ s|/+|/|g;                             # xx////xx  -> xx/xx
     $path =~ s@(/\.)+(/|\Z(?!\n))@/@g;             # xx/././xx -> xx/xx
     $path =~ s|^(\./)+||s unless $path eq "./";    # ./xx      -> xx
     $path =~ s|^/(\.\./)+|/|s;                     # /../../xx -> xx
@@ -79,7 +88,7 @@ complete path ending with a filename
 
 sub catfile {
     my $self = shift;
-    my $file = pop @_;
+    my $file = $self->canonpath(pop @_);
     return $file unless @_;
     my $dir = $self->catdir(@_);
     $dir .= "/" unless substr($dir,-1) eq "/";
@@ -118,26 +127,46 @@ sub rootdir {
 
 =item tmpdir
 
-Returns a string representation of the first writable directory
-from the following list or "" if none are writable:
+Returns a string representation of the first writable directory from
+the following list or the current directory if none from the list are
+writable:
 
     $ENV{TMPDIR}
     /tmp
 
+Since perl 5.8.0, if running under taint mode, and if $ENV{TMPDIR}
+is tainted, it is not used.
+
 =cut
 
 my $tmpdir;
-sub tmpdir {
+sub _tmpdir {
     return $tmpdir if defined $tmpdir;
-    foreach ($ENV{TMPDIR}, "/tmp") {
+    my $self = shift;
+    my @dirlist = @_;
+    {
+       no strict 'refs';
+       if (${"\cTAINT"}) { # Check for taint mode on perl >= 5.8.0
+            require Scalar::Util;
+           @dirlist = grep { ! Scalar::Util::tainted($_) } @dirlist;
+       }
+    }
+    foreach (@dirlist) {
        next unless defined && -d && -w _;
        $tmpdir = $_;
        last;
     }
-    $tmpdir = '' unless defined $tmpdir;
+    $tmpdir = $self->curdir unless defined $tmpdir;
+    $tmpdir = defined $tmpdir && $self->canonpath($tmpdir);
     return $tmpdir;
 }
 
+sub tmpdir {
+    return $tmpdir if defined $tmpdir;
+    my $self = shift;
+    $tmpdir = $self->_tmpdir( $ENV{TMPDIR}, "/tmp" );
+}
+
 =item updir
 
 Returns a string representation of the parent directory.  ".." on UNIX.
@@ -175,9 +204,8 @@ sub case_tolerant {
 
 Takes as argument a path and returns true if it is an absolute path.
 
-This does not consult the local filesystem on Unix, Win32, or OS/2.  It
-does sometimes on MacOS (see L<File::Spec::MacOS/file_name_is_absolute>).
-It does consult the working environment for VMS (see
+This does not consult the local filesystem on Unix, Win32, OS/2 or Mac 
+OS (Classic).  It does consult the working environment for VMS (see
 L<File::Spec::VMS/file_name_is_absolute>).
 
 =cut
@@ -194,6 +222,7 @@ Takes no argument, returns the environment variable PATH as an array.
 =cut
 
 sub path {
+    return () unless exists $ENV{PATH};
     my @path = split(':', $ENV{PATH});
     foreach (@path) { $_ = '.' if $_ eq '' }
     return @path;
@@ -215,8 +244,8 @@ sub join {
     ($volume,$directories,$file) = File::Spec->splitpath( $path );
     ($volume,$directories,$file) = File::Spec->splitpath( $path, $no_file );
 
-Splits a path in to volume, directory, and filename portions. On systems
-with no concept of volume, returns undef for volume. 
+Splits a path into volume, directory, and filename portions. On systems
+with no concept of volume, returns '' for volume. 
 
 For systems with no syntax differentiating filenames from directories, 
 assumes that the last file is a path unless $no_file is true or a 
@@ -260,7 +289,7 @@ files from directories.
 
 Unlike just splitting the directories on the separator, empty
 directory names (C<''>) can be returned, because these are significant
-on some OSs (e.g. MacOS).
+on some OSs.
 
 On Unix,
 
@@ -297,8 +326,9 @@ sub splitdir {
 =item catpath()
 
 Takes volume, directory and file portions and returns an entire path. Under
-Unix, $volume is ignored, and directory and file are catenated.  A '/' is
-inserted if need be.  On other OSs, $volume is significant.
+Unix, $volume is ignored, and directory and file are concatenated.  A '/' is
+inserted if needed (though if the directory portion doesn't start with
+'/' it is not added).  On other OSs, $volume is significant.
 
 =cut
 
@@ -341,9 +371,7 @@ directories.
 If $path is relative, it is converted to absolute form using L</rel2abs()>.
 This means that it is taken to be relative to L<cwd()|Cwd>.
 
-No checks against the filesystem are made on most systems.  On MacOS,
-the filesystem may be consulted (see
-L<File::Spec::MacOS/file_name_is_absolute>).  On VMS, there is
+No checks against the filesystem are made.  On VMS, there is
 interaction with the working environment, as logicals and
 macros are expanded.
 
@@ -421,9 +449,7 @@ directories.
 
 If $path is absolute, it is cleaned up and returned using L</canonpath()>.
 
-No checks against the filesystem are made on most systems.  On MacOS,
-the filesystem may be consulted (see
-L<File::Spec::MacOS/file_name_is_absolute>).  On VMS, there is
+No checks against the filesystem are made.  On VMS, there is
 interaction with the working environment, as logicals and
 macros are expanded.