Honor trailing \n in messages, as is done for warn().
[p5sagit/p5-mst-13.2.git] / lib / Cwd.pm
CommitLineData
a0d0e21e 1package Cwd;
2require 5.000;
3require Exporter;
4633a7c4 4require Config;
5
6# Use osname for portability switches (doubled to cheaply avoid -w warning)
7my $osname = $Config::Config{'osname'} || $Config::Config{'osname'};
8
a0d0e21e 9
f06db76b 10=head1 NAME
11
12getcwd - get pathname of current working directory
13
14=head1 SYNOPSIS
15
4633a7c4 16 use Cwd;
17 $dir = cwd;
18
19 use Cwd;
20 $dir = getcwd;
f06db76b 21
22 use Cwd;
4633a7c4 23 $dir = fastgetcwd;
f06db76b 24
25 use Cwd 'chdir';
26 chdir "/tmp";
27 print $ENV{'PWD'};
28
29=head1 DESCRIPTION
30
31The getcwd() function re-implements the getcwd(3) (or getwd(3)) functions
4633a7c4 32in Perl.
f06db76b 33
cb1a09d0 34The fastcwd() function looks the same as getcwd(), but runs faster.
f06db76b 35It's also more dangerous because you might conceivably chdir() out of a
36directory that you can't chdir() back into.
37
4633a7c4 38The cwd() function looks the same as getcwd and fastgetcwd but is
39implemented using the most natural and safe form for the current
40architecture. For most systems it is identical to `pwd` (but without
41the trailing line terminator). It is recommended that cwd (or another
42*cwd() function) is used in I<all> code to ensure portability.
43
44If you ask to override your chdir() built-in function, then your PWD
45environment variable will be kept up to date. (See
46L<perlsub/Overriding builtin functions>.) Note that it will only be
47kept up to date it all packages which use chdir import it from Cwd.
48
f06db76b 49=cut
50
a0d0e21e 51@ISA = qw(Exporter);
4633a7c4 52@EXPORT = qw(cwd getcwd fastcwd);
a0d0e21e 53@EXPORT_OK = qw(chdir);
54
4633a7c4 55# use strict;
56
57sub _backtick_pwd { # The 'natural and safe form' for UNIX (pwd may be setuid root)
58 my $cwd;
59 chop($cwd = `pwd`);
60 $cwd;
61}
62
63# Since some ports may predefine cwd internally (e.g., NT)
64# we take care not to override an existing definition for cwd().
65
66*cwd = \&_backtick_pwd unless defined &cwd;
a0d0e21e 67
748a9306 68
a0d0e21e 69# By Brandon S. Allbery
70#
71# Usage: $cwd = getcwd();
72
73sub getcwd
74{
75 my($dotdots, $cwd, @pst, @cst, $dir, @tst);
76
77 unless (@cst = stat('.'))
78 {
79 warn "stat(.): $!";
80 return '';
81 }
82 $cwd = '';
42793c05 83 $dotdots = '';
a0d0e21e 84 do
85 {
86 $dotdots .= '/' if $dotdots;
87 $dotdots .= '..';
88 @pst = @cst;
89 unless (opendir(PARENT, $dotdots))
90 {
91 warn "opendir($dotdots): $!";
92 return '';
93 }
94 unless (@cst = stat($dotdots))
95 {
96 warn "stat($dotdots): $!";
97 closedir(PARENT);
98 return '';
99 }
100 if ($pst[0] == $cst[0] && $pst[1] == $cst[1])
101 {
102 $dir = '';
103 }
104 else
105 {
106 do
107 {
3edbfbe5 108 unless (defined ($dir = readdir(PARENT)))
109 {
a0d0e21e 110 warn "readdir($dotdots): $!";
111 closedir(PARENT);
112 return '';
113 }
114 unless (@tst = lstat("$dotdots/$dir"))
115 {
116 warn "lstat($dotdots/$dir): $!";
37120919 117 # Just because you can't lstat this directory
118 # doesn't mean you'll never find the right one.
119 # closedir(PARENT);
120 # return '';
a0d0e21e 121 }
122 }
123 while ($dir eq '.' || $dir eq '..' || $tst[0] != $pst[0] ||
124 $tst[1] != $pst[1]);
125 }
126 $cwd = "$dir/$cwd";
127 closedir(PARENT);
128 } while ($dir);
3edbfbe5 129 chop($cwd); # drop the trailing /
a0d0e21e 130 $cwd;
131}
132
133
134
135# By John Bazik
136#
137# Usage: $cwd = &fastcwd;
138#
139# This is a faster version of getcwd. It's also more dangerous because
140# you might chdir out of a directory that you can't chdir back into.
141
142sub fastcwd {
143 my($odev, $oino, $cdev, $cino, $tdev, $tino);
144 my(@path, $path);
145 local(*DIR);
146
147 ($cdev, $cino) = stat('.');
148 for (;;) {
40000a8c 149 my $direntry;
a0d0e21e 150 ($odev, $oino) = ($cdev, $cino);
151 chdir('..');
152 ($cdev, $cino) = stat('.');
153 last if $odev == $cdev && $oino == $cino;
154 opendir(DIR, '.');
155 for (;;) {
40000a8c 156 $direntry = readdir(DIR);
157 next if $direntry eq '.';
158 next if $direntry eq '..';
a0d0e21e 159
40000a8c 160 last unless defined $direntry;
161 ($tdev, $tino) = lstat($direntry);
a0d0e21e 162 last unless $tdev != $odev || $tino != $oino;
163 }
164 closedir(DIR);
40000a8c 165 unshift(@path, $direntry);
a0d0e21e 166 }
167 chdir($path = '/' . join('/', @path));
168 $path;
169}
170
171
4633a7c4 172# Keeps track of current working directory in PWD environment var
a0d0e21e 173# Usage:
174# use Cwd 'chdir';
175# chdir $newdir;
176
4633a7c4 177my $chdir_init = 0;
a0d0e21e 178
4633a7c4 179sub chdir_init {
180 if ($ENV{'PWD'} and $osname ne 'os2') {
a0d0e21e 181 my($dd,$di) = stat('.');
182 my($pd,$pi) = stat($ENV{'PWD'});
183 if (!defined $dd or !defined $pd or $di != $pi or $dd != $pd) {
4633a7c4 184 $ENV{'PWD'} = cwd();
a0d0e21e 185 }
186 }
187 else {
4633a7c4 188 $ENV{'PWD'} = cwd();
a0d0e21e 189 }
4633a7c4 190 # Strip an automounter prefix (where /tmp_mnt/foo/bar == /foo/bar)
a0d0e21e 191 if ($ENV{'PWD'} =~ m|(/[^/]+(/[^/]+/[^/]+))(.*)|) {
192 my($pd,$pi) = stat($2);
193 my($dd,$di) = stat($1);
194 if (defined $pd and defined $dd and $di == $pi and $dd == $pd) {
195 $ENV{'PWD'}="$2$3";
196 }
197 }
198 $chdir_init = 1;
199}
200
201sub chdir {
4633a7c4 202 my $newdir = shift || ''; # allow for no arg (chdir to HOME dir)
203 $newdir =~ s|///*|/|g;
a0d0e21e 204 chdir_init() unless $chdir_init;
4633a7c4 205 return 0 unless CORE::chdir $newdir;
206 if ($osname eq 'VMS') { return $ENV{'PWD'} = $ENV{'DEFAULT'} }
748a9306 207
a0d0e21e 208 if ($newdir =~ m#^/#) {
209 $ENV{'PWD'} = $newdir;
4633a7c4 210 } else {
211 my @curdir = split(m#/#,$ENV{'PWD'});
212 @curdir = ('') unless @curdir;
213 my $component;
a0d0e21e 214 foreach $component (split(m#/#, $newdir)) {
215 next if $component eq '.';
216 pop(@curdir),next if $component eq '..';
217 push(@curdir,$component);
218 }
219 $ENV{'PWD'} = join('/',@curdir) || '/';
220 }
4633a7c4 221 1;
a0d0e21e 222}
223
4633a7c4 224
225# --- PORTING SECTION ---
226
227# VMS: $ENV{'DEFAULT'} points to default directory at all times
228# 08-Dec-1994 Charles Bailey bailey@genetics.upenn.edu
229# Note: Use of Cwd::getcwd() or Cwd::chdir() (but not Cwd::fastcwd())
230# causes the logical name PWD to be defined in the process
231# logical name table as the default device and directory
232# seen by Perl. This may not be the same as the default device
233# and directory seen by DCL after Perl exits, since the effects
234# the CRTL chdir() function persist only until Perl exits.
235# This does not apply to other systems (where only chdir() sets PWD).
236
237sub _vms_cwd {
238 return $ENV{'DEFAULT'}
239}
240sub _vms_pwd {
241 return $ENV{'PWD'} = $ENV{'DEFAULT'}
242}
243sub _os2_cwd {
244 $ENV{'PWD'} = `cmd /c cd`;
245 chop $ENV{'PWD'};
246 $ENV{'PWD'} =~ s:\\:/:g ;
247 return $ENV{'PWD'};
248}
249
250if ($osname eq 'VMS') {
251
252 *cwd = \&_vms_pwd;
253 *getcwd = \&_vms_pwd;
254 *fastgetcwd = \&_vms_cwd;
255}
256elsif ($osname eq 'NT') {
257
258 *getcwd = \&cwd;
259 *fastgetcwd = \&cwd;
260}
261elsif ($osname eq 'os2') {
262 *cwd = \&_os2_cwd;
263 *getcwd = \&_os2_cwd;
264 *fastgetcwd = \&_os2_cwd;
265 *fastcwd = \&_os2_cwd;
266}
267
268# package main; eval join('',<DATA>) || die $@; # quick test
269
a0d0e21e 2701;
271
4633a7c4 272__END__
273BEGIN { import Cwd qw(:DEFAULT chdir); }
274print join("\n", cwd, getcwd, fastcwd, "");
275chdir('..');
276print join("\n", cwd, getcwd, fastcwd, "");
277print "$ENV{PWD}\n";