[perl #8599] s/catenate/concatenate/
[p5sagit/p5-mst-13.2.git] / lib / File / Spec / Unix.pm
index fcbe767..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.
@@ -193,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;
@@ -214,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 
@@ -296,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