6 getcwd - get pathname of current working directory
25 The getcwd() function re-implements the getcwd(3) (or getwd(3)) functions
28 The fastcwd() function looks the same as getcwd(), but runs faster.
29 It's also more dangerous because it might conceivably chdir() you out
30 of a directory that it can't chdir() you back into. If fastcwd
31 encounters a problem it will return undef but will probably leave you
32 in a different directory. For a measure of extra security, if
33 everything appears to have worked, the fastcwd() function will check
34 that it leaves you in the same directory that it started in. If it has
35 changed it will C<die> with the message "Unstable directory path,
36 current directory changed unexpectedly". That should never happen.
38 The cwd() function looks the same as getcwd and fastgetcwd but is
39 implemented using the most natural and safe form for the current
40 architecture. For most systems it is identical to `pwd` (but without
41 the trailing line terminator).
43 It is recommended that cwd (or another *cwd() function) is used in
44 I<all> code to ensure portability.
46 If you ask to override your chdir() built-in function, then your PWD
47 environment variable will be kept up to date. (See
48 L<perlsub/Overriding Builtin Functions>.) Note that it will only be
49 kept up to date if all packages which use chdir import it from Cwd.
61 @EXPORT = qw(cwd getcwd fastcwd fastgetcwd);
62 @EXPORT_OK = qw(chdir abs_path fast_abs_path);
65 # The 'natural and safe form' for UNIX (pwd may be setuid root)
73 # Since some ports may predefine cwd internally (e.g., NT)
74 # we take care not to override an existing definition for cwd().
76 *cwd = \&_backtick_pwd unless defined &cwd;
79 # By Brandon S. Allbery
81 # Usage: $cwd = getcwd();
90 # Usage: $cwd = &fastcwd;
92 # This is a faster version of getcwd. It's also more dangerous because
93 # you might chdir out of a directory that you can't chdir back into.
95 # List of metachars taken from do_exec() in doio.c
96 my $quoted_shell_meta = quotemeta('$&*(){}[]";\\|?<>~`'."'\n");
99 my($odev, $oino, $cdev, $cino, $tdev, $tino);
103 my($orig_cdev, $orig_cino) = stat('.');
104 ($cdev, $cino) = ($orig_cdev, $orig_cino);
107 ($odev, $oino) = ($cdev, $cino);
108 chdir('..') || return undef;
109 ($cdev, $cino) = stat('.');
110 last if $odev == $cdev && $oino == $cino;
111 opendir(DIR, '.') || return undef;
113 $direntry = readdir(DIR);
114 last unless defined $direntry;
115 next if $direntry eq '.';
116 next if $direntry eq '..';
118 ($tdev, $tino) = lstat($direntry);
119 last unless $tdev != $odev || $tino != $oino;
122 return undef unless defined $direntry; # should never happen
123 unshift(@path, $direntry);
125 $path = '/' . join('/', @path);
126 # At this point $path may be tainted (if tainting) and chdir would fail.
127 # To be more useful we untaint it then check that we landed where we started.
128 $path = $1 if $path =~ /^(.*)$/; # untaint
129 chdir($path) || return undef;
130 ($cdev, $cino) = stat('.');
131 die "Unstable directory path, current directory changed unexpectedly"
132 if $cdev != $orig_cdev || $cino != $orig_cino;
137 # Keeps track of current working directory in PWD environment var
145 if ($ENV{'PWD'} and $^O ne 'os2' and $^O ne 'dos') {
146 my($dd,$di) = stat('.');
147 my($pd,$pi) = stat($ENV{'PWD'});
148 if (!defined $dd or !defined $pd or $di != $pi or $dd != $pd) {
155 # Strip an automounter prefix (where /tmp_mnt/foo/bar == /foo/bar)
156 if ($ENV{'PWD'} =~ m|(/[^/]+(/[^/]+/[^/]+))(.*)|) {
157 my($pd,$pi) = stat($2);
158 my($dd,$di) = stat($1);
159 if (defined $pd and defined $dd and $di == $pi and $dd == $pd) {
167 my $newdir = shift || ''; # allow for no arg (chdir to HOME dir)
168 $newdir =~ s|///*|/|g;
169 chdir_init() unless $chdir_init;
170 return 0 unless CORE::chdir $newdir;
171 if ($^O eq 'VMS') { return $ENV{'PWD'} = $ENV{'DEFAULT'} }
173 if ($newdir =~ m#^/#) {
174 $ENV{'PWD'} = $newdir;
176 my @curdir = split(m#/#,$ENV{'PWD'});
177 @curdir = ('') unless @curdir;
179 foreach $component (split(m#/#, $newdir)) {
180 next if $component eq '.';
181 pop(@curdir),next if $component eq '..';
182 push(@curdir,$component);
184 $ENV{'PWD'} = join('/',@curdir) || '/';
189 # Taken from Cwd.pm It is really getcwd with an optional
190 # parameter instead of '.'
195 my $start = @_ ? shift : '.';
196 my($dotdots, $cwd, @pst, @cst, $dir, @tst);
198 unless (@cst = stat( $start ))
200 carp "stat($start): $!";
209 unless (opendir(PARENT, $dotdots))
211 carp "opendir($dotdots): $!";
214 unless (@cst = stat($dotdots))
216 carp "stat($dotdots): $!";
220 if ($pst[0] == $cst[0] && $pst[1] == $cst[1])
228 unless (defined ($dir = readdir(PARENT)))
230 carp "readdir($dotdots): $!";
234 $tst[0] = $pst[0]+1 unless (@tst = lstat("$dotdots/$dir"))
236 while ($dir eq '.' || $dir eq '..' || $tst[0] != $pst[0] ||
239 $cwd = (defined $dir ? "$dir" : "" ) . "/$cwd" ;
241 } while (defined $dir);
242 chop($cwd) unless $cwd eq '/'; # drop the trailing /
248 my $path = shift || '.';
249 chdir($path) || croak "Cannot chdir to $path:$!";
250 my $realpath = getcwd();
251 chdir($cwd) || croak "Cannot chdir back to $cwd:$!";
256 # --- PORTING SECTION ---
258 # VMS: $ENV{'DEFAULT'} points to default directory at all times
259 # 06-Mar-1996 Charles Bailey bailey@genetics.upenn.edu
260 # Note: Use of Cwd::chdir() causes the logical name PWD to be defined
261 # in the process logical name table as the default device and directory
262 # seen by Perl. This may not be the same as the default device
263 # and directory seen by DCL after Perl exits, since the effects
264 # the CRTL chdir() function persist only until Perl exits.
267 return $ENV{'DEFAULT'};
271 return $ENV{'DEFAULT'} unless @_;
272 my $path = VMS::Filespec::pathify($_[0]);
273 croak("Invalid path name $_[0]") unless defined $path;
274 return VMS::Filespec::rmsexpand($path);
278 $ENV{'PWD'} = `cmd /c cd`;
280 $ENV{'PWD'} =~ s:\\:/:g ;
285 $ENV{'PWD'} = Win32::GetCwd();
286 $ENV{'PWD'} =~ s:\\:/:g ;
290 *_NT_cwd = \&_win32_cwd if (!defined &_NT_cwd &&
291 defined &Win32::GetCwd);
293 *_NT_cwd = \&_os2_cwd unless defined &_NT_cwd;
296 if (!defined &Dos::GetCwd) {
297 $ENV{'PWD'} = `command /c cd`;
299 $ENV{'PWD'} =~ s:\\:/:g ;
301 $ENV{'PWD'} = Dos::GetCwd();
307 $ENV{'PWD'} = `/usr/bin/fullpath -t`;
313 my $path = shift || '.';
314 my $realpath=`/usr/bin/fullpath -t $path`;
320 local $^W = 0; # assignments trigger 'subroutine redefined' warning
324 *getcwd = \&_vms_cwd;
325 *fastcwd = \&_vms_cwd;
326 *fastgetcwd = \&_vms_cwd;
327 *abs_path = \&_vms_abs_path;
328 *fast_abs_path = \&_vms_abs_path;
330 elsif ($^O eq 'NT' or $^O eq 'MSWin32') {
331 # We assume that &_NT_cwd is defined as an XSUB or in the core.
334 *fastcwd = \&_NT_cwd;
335 *fastgetcwd = \&_NT_cwd;
336 *abs_path = \&fast_abs_path;
338 elsif ($^O eq 'os2') {
339 # sys_cwd may keep the builtin command
340 *cwd = defined &sys_cwd ? \&sys_cwd : \&_os2_cwd;
344 *abs_path = \&fast_abs_path;
346 elsif ($^O eq 'dos') {
348 *getcwd = \&_dos_cwd;
349 *fastgetcwd = \&_dos_cwd;
350 *fastcwd = \&_dos_cwd;
351 *abs_path = \&fast_abs_path;
353 elsif ($^O eq 'qnx') {
355 *getcwd = \&_qnx_cwd;
356 *fastgetcwd = \&_qnx_cwd;
357 *fastcwd = \&_qnx_cwd;
358 *abs_path = \&_qnx_abs_path;
359 *fast_abs_path = \&_qnx_abs_path;
363 # package main; eval join('',<DATA>) || die $@; # quick test
368 BEGIN { import Cwd qw(:DEFAULT chdir); }
369 print join("\n", cwd, getcwd, fastcwd, "");
371 print join("\n", cwd, getcwd, fastcwd, "");