This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update ExtUtils-Install to 1.51
[perl5.git] / lib / Cwd.pm
index dc52b72..3bf704f 100644 (file)
@@ -1,5 +1,4 @@
 package Cwd;
-$VERSION = $VERSION = '2.20';
 
 =head1 NAME
 
@@ -36,7 +35,8 @@ absolute path of the current working directory.
 
 Returns the current working directory.
 
-Re-implements the getcwd(3) (or getwd(3)) functions in Perl.
+Exposes the POSIX function getcwd(3) or re-implements it if it's not
+available.
 
 =item cwd
 
@@ -148,6 +148,19 @@ Originally by the perl5-porters.
 
 Maintained by Ken Williams <KWILLIAMS@cpan.org>
 
+=head1 COPYRIGHT
+
+Copyright (c) 2004 by the Perl 5 Porters.  All rights reserved.
+
+This program is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself.
+
+Portions of the C code in this library are copyright (c) 1994 by the
+Regents of the University of California.  All rights reserved.  The
+license on this code is compatible with the licensing of the rest of
+the distribution - please see the source code in F<Cwd.xs> for the
+details.
+
 =head1 SEE ALSO
 
 L<File::chdir>
@@ -156,7 +169,11 @@ L<File::chdir>
 
 use strict;
 use Exporter;
-use vars qw(@ISA @EXPORT @EXPORT_OK);
+use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
+
+$VERSION = '3.29';
+my $xs_version = $VERSION;
+$VERSION = eval $VERSION;
 
 @ISA = qw/ Exporter /;
 @EXPORT = qw(cwd getcwd fastcwd fastgetcwd);
@@ -185,12 +202,21 @@ if ($^O eq 'os2') {
     return 1;
 }
 
+# If loading the XS stuff doesn't work, we can fall back to pure perl
 eval {
+  if ( $] >= 5.006 ) {
     require XSLoader;
-    local $^W = 0;
-    XSLoader::load('Cwd');
+    XSLoader::load( __PACKAGE__, $xs_version);
+  } else {
+    require DynaLoader;
+    push @ISA, 'DynaLoader';
+    __PACKAGE__->bootstrap( $xs_version );
+  }
 };
 
+# Must be after the DynaLoader stuff:
+$VERSION = eval $VERSION;
+
 # Big nasty table of function aliases
 my %METHOD_MAP =
   (
@@ -279,6 +305,7 @@ foreach my $try ('/bin/pwd',
         last;
     }
 }
+my $found_pwd_cmd = defined($pwd_cmd);
 unless ($pwd_cmd) {
     # Isn't this wrong?  _backtick_pwd() will fail if somenone has
     # pwd in their path but it is not /bin/pwd or /usr/bin/pwd?
@@ -292,7 +319,10 @@ sub _croak { require Carp; Carp::croak(@_) }
 
 # The 'natural and safe form' for UNIX (pwd may be setuid root)
 sub _backtick_pwd {
-    local @ENV{qw(PATH IFS CDPATH ENV BASH_ENV)};
+    # Localize %ENV entries in a way that won't create new hash keys
+    my @localize = grep exists $ENV{$_}, qw(PATH IFS CDPATH ENV BASH_ENV);
+    local @ENV{@localize};
+    
     my $cwd = `$pwd_cmd`;
     # Belt-and-suspenders in case someone said "undef $/".
     local $/ = "\n";
@@ -307,8 +337,20 @@ sub _backtick_pwd {
 unless ($METHOD_MAP{$^O}{cwd} or defined &cwd) {
     # The pwd command is not available in some chroot(2)'ed environments
     my $sep = $Config::Config{path_sep} || ':';
-    if( $^O eq 'MacOS' || (defined $ENV{PATH} &&
-                          grep { -x "$_/pwd" } split($sep, $ENV{PATH})) )
+    my $os = $^O;  # Protect $^O from tainting
+
+
+    # Try again to find a pwd, this time searching the whole PATH.
+    if (defined $ENV{PATH} and $os ne 'MSWin32') {  # no pwd on Windows
+       my @candidates = split($sep, $ENV{PATH});
+       while (!$found_pwd_cmd and @candidates) {
+           my $candidate = shift @candidates;
+           $found_pwd_cmd = 1 if -x "$candidate/pwd";
+       }
+    }
+
+    # MacOS has some special magic to make `pwd` work.
+    if( $os eq 'MacOS' || $found_pwd_cmd )
     {
        *cwd = \&_backtick_pwd;
     }
@@ -317,20 +359,26 @@ unless ($METHOD_MAP{$^O}{cwd} or defined &cwd) {
     }
 }
 
+if ($^O eq 'cygwin') {
+  # We need to make sure cwd() is called with no args, because it's
+  # got an arg-less prototype and will die if args are present.
+  local $^W = 0;
+  my $orig_cwd = \&cwd;
+  *cwd = sub { &$orig_cwd() }
+}
+
+
 # set a reasonable (and very safe) default for fastgetcwd, in case it
 # isn't redefined later (20001212 rspier)
 *fastgetcwd = \&cwd;
 
-# By Brandon S. Allbery
-#
-# Usage: $cwd = getcwd();
-
-sub getcwd
+# A non-XS version of getcwd() - also used to bootstrap the perl build
+# process, when miniperl is running and no XS loading happens.
+sub _perl_getcwd
 {
     abs_path('.');
 }
 
-
 # By John Bazik
 #
 # Usage: $cwd = &fastcwd;
@@ -338,7 +386,7 @@ sub getcwd
 # This is a faster version of getcwd.  It's also more dangerous because
 # you might chdir out of a directory that you can't chdir back into.
     
-sub fastcwd {
+sub fastcwd_ {
     my($odev, $oino, $cdev, $cino, $tdev, $tino);
     my(@path, $path);
     local(*DIR);
@@ -376,6 +424,7 @@ sub fastcwd {
        if $cdev != $orig_cdev || $cino != $orig_cino;
     $path;
 }
+if (not defined &fastcwd) { *fastcwd = \&fastcwd_ }
 
 
 # Keeps track of current working directory in PWD environment var
@@ -432,7 +481,9 @@ sub chdir {
        return 1;
     }
 
-    if ($newdir =~ m#^/#s) {
+    if (ref $newdir eq 'GLOB') { # in case a file/dir handle is passed in
+       $ENV{'PWD'} = cwd();
+    } elsif ($newdir =~ m#^/#s) {
        $ENV{'PWD'} = $newdir;
     } else {
        my @curdir = split(m#/#,$ENV{'PWD'});
@@ -449,9 +500,7 @@ sub chdir {
 }
 
 
-# In case the XS version doesn't load.
-*abs_path = \&_perl_abs_path unless defined &abs_path;
-sub _perl_abs_path(;$)
+sub _perl_abs_path
 {
     my $start = @_ ? shift : '.';
     my($dotdots, $cwd, @pst, @cst, $dir, @tst);
@@ -481,7 +530,7 @@ sub _perl_abs_path(;$)
            return abs_path($link_target);
        }
        
-       return abs_path($dir) . '/' . $file;
+       return $dir ? abs_path($dir) . "/$file" : "/$file";
     }
 
     $cwd = '';
@@ -493,8 +542,8 @@ sub _perl_abs_path(;$)
        local *PARENT;
        unless (opendir(PARENT, $dotdots))
        {
-           _carp("opendir($dotdots): $!");
-           return '';
+           # probably a permissions issue.  Try the native command.
+           return File::Spec->rel2abs( $start, _backtick_pwd() );
        }
        unless (@cst = stat($dotdots))
        {
@@ -529,12 +578,9 @@ sub _perl_abs_path(;$)
 }
 
 
-# added function alias for those of us more
-# used to the libc function.  --tchrist 27-Jan-00
-*realpath = \&abs_path;
-
 my $Curdir;
 sub fast_abs_path {
+    local $ENV{PWD} = $ENV{PWD} || ''; # Guard against clobberage
     my $cwd = getcwd();
     require File::Spec;
     my $path = @_ ? shift : ($Curdir ||= File::Spec->curdir);
@@ -564,7 +610,9 @@ sub fast_abs_path {
            return fast_abs_path($link_target);
        }
        
-       return fast_abs_path(File::Spec->catpath($vol, $dir, '')) . '/' . $file;
+       return $dir eq File::Spec->rootdir
+         ? File::Spec->catpath($vol, $dir, $file)
+         : fast_abs_path(File::Spec->catpath($vol, $dir, '')) . '/' . $file;
     }
 
     if (!CORE::chdir($path)) {
@@ -598,11 +646,38 @@ sub _vms_cwd {
 
 sub _vms_abs_path {
     return $ENV{'DEFAULT'} unless @_;
+    my $path = shift;
 
-    # may need to turn foo.dir into [.foo]
-    my $path = VMS::Filespec::pathify($_[0]);
-    $path = $_[0] unless defined $path;
+    if (-l $path) {
+        my $link_target = readlink($path);
+        die "Can't resolve link $path: $!" unless defined $link_target;
+           
+        return _vms_abs_path($link_target);
+    }
+
+    if (defined &VMS::Filespec::vms_realpath) {
+        my $path = $_[0];
+        if ($path =~ m#(?<=\^)/# ) {
+            # Unix format
+            return VMS::Filespec::vms_realpath($path);
+        }
+
+       # VMS format
+
+       my $new_path = VMS::Filespec::vms_realname($path); 
+
+       # Perl expects directories to be in directory format
+       $new_path = VMS::Filespec::pathify($new_path) if -d $path;
+       return $new_path;
+    }
+
+    # Fallback to older algorithm if correct ones are not
+    # available.
 
+    # may need to turn foo.dir into [.foo]
+    my $pathified = VMS::Filespec::pathify($path);
+    $path = $pathified if defined $pathified;
+       
     return VMS::Filespec::rmsexpand($path);
 }
 
@@ -614,15 +689,17 @@ sub _os2_cwd {
 }
 
 sub _win32_cwd {
-    $ENV{'PWD'} = Win32::GetCwd();
+    if (defined &DynaLoader::boot_DynaLoader) {
+       $ENV{'PWD'} = Win32::GetCwd();
+    }
+    else { # miniperl
+       chomp($ENV{'PWD'} = `cd`);
+    }
     $ENV{'PWD'} =~ s:\\:/:g ;
     return $ENV{'PWD'};
 }
 
-*_NT_cwd = \&_win32_cwd if (!defined &_NT_cwd && 
-                            defined &Win32::GetCwd);
-
-*_NT_cwd = \&_os2_cwd unless defined &_NT_cwd;
+*_NT_cwd = defined &Win32::GetCwd ? \&_win32_cwd : \&_os2_cwd;
 
 sub _dos_cwd {
     if (!defined &Dos::GetCwd) {
@@ -651,7 +728,7 @@ sub _qnx_abs_path {
     my $path = @_ ? shift : '.';
     local *REALPATH;
 
-    open(REALPATH, '-|', '/usr/bin/fullpath', '-t', $path) or
+    defined( open(REALPATH, '-|') || exec '/usr/bin/fullpath', '-t', $path ) or
       die "Can't open /usr/bin/fullpath: $!";
     my $realpath = <REALPATH>;
     close REALPATH;
@@ -671,11 +748,18 @@ sub _epoc_cwd {
 if (exists $METHOD_MAP{$^O}) {
   my $map = $METHOD_MAP{$^O};
   foreach my $name (keys %$map) {
-    no warnings;       # assignments trigger 'subroutine redefined' warning
+    local $^W = 0;  # assignments trigger 'subroutine redefined' warning
     no strict 'refs';
     *{$name} = \&{$map->{$name}};
   }
 }
 
+# In case the XS version doesn't load.
+*abs_path = \&_perl_abs_path unless defined &abs_path;
+*getcwd = \&_perl_getcwd unless defined &getcwd;
+
+# added function alias for those of us more
+# used to the libc function.  --tchrist 27-Jan-00
+*realpath = \&abs_path;
 
 1;