This is patch.2b1e to perl5.002beta1. This is simply
[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
34The fastgetcwd() function looks the same as getcwd(), but runs faster.
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): $!";
117 closedir(PARENT);
118 return '';
119 }
120 }
121 while ($dir eq '.' || $dir eq '..' || $tst[0] != $pst[0] ||
122 $tst[1] != $pst[1]);
123 }
124 $cwd = "$dir/$cwd";
125 closedir(PARENT);
126 } while ($dir);
3edbfbe5 127 chop($cwd); # drop the trailing /
a0d0e21e 128 $cwd;
129}
130
131
132
133# By John Bazik
134#
135# Usage: $cwd = &fastcwd;
136#
137# This is a faster version of getcwd. It's also more dangerous because
138# you might chdir out of a directory that you can't chdir back into.
139
140sub fastcwd {
141 my($odev, $oino, $cdev, $cino, $tdev, $tino);
142 my(@path, $path);
143 local(*DIR);
144
145 ($cdev, $cino) = stat('.');
146 for (;;) {
40000a8c 147 my $direntry;
a0d0e21e 148 ($odev, $oino) = ($cdev, $cino);
149 chdir('..');
150 ($cdev, $cino) = stat('.');
151 last if $odev == $cdev && $oino == $cino;
152 opendir(DIR, '.');
153 for (;;) {
40000a8c 154 $direntry = readdir(DIR);
155 next if $direntry eq '.';
156 next if $direntry eq '..';
a0d0e21e 157
40000a8c 158 last unless defined $direntry;
159 ($tdev, $tino) = lstat($direntry);
a0d0e21e 160 last unless $tdev != $odev || $tino != $oino;
161 }
162 closedir(DIR);
40000a8c 163 unshift(@path, $direntry);
a0d0e21e 164 }
165 chdir($path = '/' . join('/', @path));
166 $path;
167}
168
169
4633a7c4 170# Keeps track of current working directory in PWD environment var
a0d0e21e 171# Usage:
172# use Cwd 'chdir';
173# chdir $newdir;
174
4633a7c4 175my $chdir_init = 0;
a0d0e21e 176
4633a7c4 177sub chdir_init {
178 if ($ENV{'PWD'} and $osname ne 'os2') {
a0d0e21e 179 my($dd,$di) = stat('.');
180 my($pd,$pi) = stat($ENV{'PWD'});
181 if (!defined $dd or !defined $pd or $di != $pi or $dd != $pd) {
4633a7c4 182 $ENV{'PWD'} = cwd();
a0d0e21e 183 }
184 }
185 else {
4633a7c4 186 $ENV{'PWD'} = cwd();
a0d0e21e 187 }
4633a7c4 188 # Strip an automounter prefix (where /tmp_mnt/foo/bar == /foo/bar)
a0d0e21e 189 if ($ENV{'PWD'} =~ m|(/[^/]+(/[^/]+/[^/]+))(.*)|) {
190 my($pd,$pi) = stat($2);
191 my($dd,$di) = stat($1);
192 if (defined $pd and defined $dd and $di == $pi and $dd == $pd) {
193 $ENV{'PWD'}="$2$3";
194 }
195 }
196 $chdir_init = 1;
197}
198
199sub chdir {
4633a7c4 200 my $newdir = shift || ''; # allow for no arg (chdir to HOME dir)
201 $newdir =~ s|///*|/|g;
a0d0e21e 202 chdir_init() unless $chdir_init;
4633a7c4 203 return 0 unless CORE::chdir $newdir;
204 if ($osname eq 'VMS') { return $ENV{'PWD'} = $ENV{'DEFAULT'} }
748a9306 205
a0d0e21e 206 if ($newdir =~ m#^/#) {
207 $ENV{'PWD'} = $newdir;
4633a7c4 208 } else {
209 my @curdir = split(m#/#,$ENV{'PWD'});
210 @curdir = ('') unless @curdir;
211 my $component;
a0d0e21e 212 foreach $component (split(m#/#, $newdir)) {
213 next if $component eq '.';
214 pop(@curdir),next if $component eq '..';
215 push(@curdir,$component);
216 }
217 $ENV{'PWD'} = join('/',@curdir) || '/';
218 }
4633a7c4 219 1;
a0d0e21e 220}
221
4633a7c4 222
223# --- PORTING SECTION ---
224
225# VMS: $ENV{'DEFAULT'} points to default directory at all times
226# 08-Dec-1994 Charles Bailey bailey@genetics.upenn.edu
227# Note: Use of Cwd::getcwd() or Cwd::chdir() (but not Cwd::fastcwd())
228# causes the logical name PWD to be defined in the process
229# logical name table as the default device and directory
230# seen by Perl. This may not be the same as the default device
231# and directory seen by DCL after Perl exits, since the effects
232# the CRTL chdir() function persist only until Perl exits.
233# This does not apply to other systems (where only chdir() sets PWD).
234
235sub _vms_cwd {
236 return $ENV{'DEFAULT'}
237}
238sub _vms_pwd {
239 return $ENV{'PWD'} = $ENV{'DEFAULT'}
240}
241sub _os2_cwd {
242 $ENV{'PWD'} = `cmd /c cd`;
243 chop $ENV{'PWD'};
244 $ENV{'PWD'} =~ s:\\:/:g ;
245 return $ENV{'PWD'};
246}
247
248if ($osname eq 'VMS') {
249
250 *cwd = \&_vms_pwd;
251 *getcwd = \&_vms_pwd;
252 *fastgetcwd = \&_vms_cwd;
253}
254elsif ($osname eq 'NT') {
255
256 *getcwd = \&cwd;
257 *fastgetcwd = \&cwd;
258}
259elsif ($osname eq 'os2') {
260 *cwd = \&_os2_cwd;
261 *getcwd = \&_os2_cwd;
262 *fastgetcwd = \&_os2_cwd;
263 *fastcwd = \&_os2_cwd;
264}
265
266# package main; eval join('',<DATA>) || die $@; # quick test
267
a0d0e21e 2681;
269
4633a7c4 270__END__
271BEGIN { import Cwd qw(:DEFAULT chdir); }
272print join("\n", cwd, getcwd, fastcwd, "");
273chdir('..');
274print join("\n", cwd, getcwd, fastcwd, "");
275print "$ENV{PWD}\n";