chdir "/tmp";
print $ENV{'PWD'};
- use Cwd 'abs_path';
+ use Cwd 'abs_path'; # aka realpath()
print abs_path($ENV{'PWD'});
use Cwd 'fast_abs_path';
in Perl.
The abs_path() function takes a single argument and returns the
-absolute pathname for that argument. It uses the same algorithm as
-getcwd(). (actually getcwd() is abs_path("."))
+absolute pathname for that argument. It uses the same algorithm
+as getcwd(). (Actually, getcwd() is abs_path(".")) Symbolic links
+and relative-path components ("." and "..") are resolved to return
+the canonical pathname, just like realpath(3). Also callable as
+realpath().
The fastcwd() function looks the same as getcwd(), but runs faster.
It's also more dangerous because it might conceivably chdir() you out
=cut
-## use strict;
+use strict;
use Carp;
-$VERSION = '2.01';
+our $VERSION = '2.04';
-require Exporter;
-@ISA = qw(Exporter);
-@EXPORT = qw(cwd getcwd fastcwd fastgetcwd);
-@EXPORT_OK = qw(chdir abs_path fast_abs_path);
+use base qw/ Exporter /;
+our @EXPORT = qw(cwd getcwd fastcwd fastgetcwd);
+our @EXPORT_OK = qw(chdir abs_path fast_abs_path realpath fast_realpath);
# The 'natural and safe form' for UNIX (pwd may be setuid root)
sub _backtick_pwd {
- my $cwd;
- chop($cwd = `pwd`);
+ my $cwd = `pwd`;
+ # `pwd` may fail e.g. if the disk is full
+ chomp($cwd) if defined $cwd;
$cwd;
}
# Since some ports may predefine cwd internally (e.g., NT)
# we take care not to override an existing definition for cwd().
-*cwd = \&_backtick_pwd unless defined &cwd;
+unless(defined &cwd) {
+ # The pwd command is not available in some chroot(2)'ed environments
+ if($^O eq 'MacOS' || grep { -x "$_/pwd" } split(':', $ENV{PATH})) {
+ *cwd = \&_backtick_pwd;
+ }
+ else {
+ *cwd = \&getcwd;
+ }
+}
+# set a reasonable (and very safe) default for fastgetcwd, in case it
+# isn't redefined later (20001212 rspier)
+*fastgetcwd = \&cwd;
# By Brandon S. Allbery
#
# 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.
-# List of metachars taken from do_exec() in doio.c
-my $quoted_shell_meta = quotemeta('$&*(){}[]";\\|?<>~`'."'\n");
-
sub fastcwd {
my($odev, $oino, $cdev, $cino, $tdev, $tino);
my(@path, $path);
unshift(@path, $direntry);
}
$path = '/' . join('/', @path);
+ if ($^O eq 'apollo') { $path = "/".$path; }
# At this point $path may be tainted (if tainting) and chdir would fail.
# To be more useful we untaint it then check that we landed where we started.
- $path = $1 if $path =~ /^(.*)$/; # untaint
+ $path = $1 if $path =~ /^(.*)\z/s; # untaint
CORE::chdir($path) || return undef;
($cdev, $cino) = stat('.');
die "Unstable directory path, current directory changed unexpectedly"
my $chdir_init = 0;
sub chdir_init {
- if ($ENV{'PWD'} and $^O ne 'os2' and $^O ne 'dos') {
+ if ($ENV{'PWD'} and $^O ne 'os2' and $^O ne 'dos' and $^O ne 'MSWin32') {
my($dd,$di) = stat('.');
my($pd,$pi) = stat($ENV{'PWD'});
if (!defined $dd or !defined $pd or $di != $pi or $dd != $pd) {
}
}
else {
- $ENV{'PWD'} = cwd();
+ my $wd = cwd();
+ $wd = Win32::GetFullPathName($wd) if $^O eq 'MSWin32';
+ $ENV{'PWD'} = $wd;
}
# Strip an automounter prefix (where /tmp_mnt/foo/bar == /foo/bar)
- if ($ENV{'PWD'} =~ m|(/[^/]+(/[^/]+/[^/]+))(.*)|) {
+ if ($^O ne 'MSWin32' and $ENV{'PWD'} =~ m|(/[^/]+(/[^/]+/[^/]+))(.*)|s) {
my($pd,$pi) = stat($2);
my($dd,$di) = stat($1);
if (defined $pd and defined $dd and $di == $pi and $dd == $pd) {
}
sub chdir {
- my $newdir = shift || ''; # allow for no arg (chdir to HOME dir)
- $newdir =~ s|///*|/|g;
+ my $newdir = @_ ? shift : ''; # allow for no arg (chdir to HOME dir)
+ $newdir =~ s|///*|/|g unless $^O eq 'MSWin32';
chdir_init() unless $chdir_init;
return 0 unless CORE::chdir $newdir;
- if ($^O eq 'VMS') { return $ENV{'PWD'} = $ENV{'DEFAULT'} }
+ if ($^O eq 'VMS') {
+ return $ENV{'PWD'} = $ENV{'DEFAULT'}
+ }
+ elsif ($^O eq 'MacOS') {
+ return $ENV{'PWD'} = cwd();
+ }
+ elsif ($^O eq 'MSWin32') {
+ $ENV{'PWD'} = Win32::GetFullPathName($newdir);
+ return 1;
+ }
- if ($newdir =~ m#^/#) {
+ if ($newdir =~ m#^/#s) {
$ENV{'PWD'} = $newdir;
} else {
my @curdir = split(m#/#,$ENV{'PWD'});
$cwd;
}
+# added function alias for those of us more
+# used to the libc function. --tchrist 27-Jan-00
+*realpath = \&abs_path;
+
sub fast_abs_path {
my $cwd = getcwd();
- my $path = shift || '.';
+ my $path = @_ ? shift : '.';
CORE::chdir($path) || croak "Cannot chdir to $path:$!";
my $realpath = getcwd();
CORE::chdir($cwd) || croak "Cannot chdir back to $cwd:$!";
$realpath;
}
+# added function alias to follow principle of least surprise
+# based on previous aliasing. --tchrist 27-Jan-00
+*fast_realpath = \&fast_abs_path;
+
# --- PORTING SECTION ---
}
sub _qnx_abs_path {
- my $path = shift || '.';
+ my $path = @_ ? shift : '.';
my $realpath=`/usr/bin/fullpath -t $path`;
chop $realpath;
return $realpath;
}
+sub _epoc_cwd {
+ $ENV{'PWD'} = EPOC::getcwd();
+ return $ENV{'PWD'};
+}
+
{
- local $^W = 0; # assignments trigger 'subroutine redefined' warning
+ no warnings; # assignments trigger 'subroutine redefined' warning
if ($^O eq 'VMS') {
*cwd = \&_vms_cwd;
*abs_path = \&_qnx_abs_path;
*fast_abs_path = \&_qnx_abs_path;
}
+ elsif ($^O eq 'cygwin') {
+ *getcwd = \&cwd;
+ *fastgetcwd = \&cwd;
+ *fastcwd = \&cwd;
+ *abs_path = \&fast_abs_path;
+ }
+ elsif ($^O eq 'epoc') {
+ *cwd = \&_epoc_cwd;
+ *getcwd = \&_epoc_cwd;
+ *fastgetcwd = \&_epoc_cwd;
+ *fastcwd = \&_epoc_cwd;
+ *abs_path = \&fast_abs_path;
+ }
+ elsif ($^O eq 'MacOS') {
+ *getcwd = \&cwd;
+ *fastgetcwd = \&cwd;
+ *fastcwd = \&cwd;
+ *abs_path = \&fast_abs_path;
+ }
}
# package main; eval join('',<DATA>) || die $@; # quick test