source: for-distributions/trunk/bin/windows/perl/lib/Cwd.pm@ 14489

Last change on this file since 14489 was 14489, checked in by oranfry, 17 years ago

upgrading to perl 5.8

File size: 17.4 KB
Line 
1package Cwd;
2
3=head1 NAME
4
5Cwd - get pathname of current working directory
6
7=head1 SYNOPSIS
8
9 use Cwd;
10 my $dir = getcwd;
11
12 use Cwd 'abs_path';
13 my $abs_path = abs_path($file);
14
15=head1 DESCRIPTION
16
17This module provides functions for determining the pathname of the
18current working directory. It is recommended that getcwd (or another
19*cwd() function) be used in I<all> code to ensure portability.
20
21By default, it exports the functions cwd(), getcwd(), fastcwd(), and
22fastgetcwd() (and, on Win32, getdcwd()) into the caller's namespace.
23
24
25=head2 getcwd and friends
26
27Each of these functions are called without arguments and return the
28absolute path of the current working directory.
29
30=over 4
31
32=item getcwd
33
34 my $cwd = getcwd();
35
36Returns the current working directory.
37
38Re-implements the getcwd(3) (or getwd(3)) functions in Perl.
39
40=item cwd
41
42 my $cwd = cwd();
43
44The cwd() is the most natural form for the current architecture. For
45most systems it is identical to `pwd` (but without the trailing line
46terminator).
47
48=item fastcwd
49
50 my $cwd = fastcwd();
51
52A more dangerous version of getcwd(), but potentially faster.
53
54It might conceivably chdir() you out of a directory that it can't
55chdir() you back into. If fastcwd encounters a problem it will return
56undef but will probably leave you in a different directory. For a
57measure of extra security, if everything appears to have worked, the
58fastcwd() function will check that it leaves you in the same directory
59that it started in. If it has changed it will C<die> with the message
60"Unstable directory path, current directory changed
61unexpectedly". That should never happen.
62
63=item fastgetcwd
64
65 my $cwd = fastgetcwd();
66
67The fastgetcwd() function is provided as a synonym for cwd().
68
69=item getdcwd
70
71 my $cwd = getdcwd();
72 my $cwd = getdcwd('C:');
73
74The getdcwd() function is also provided on Win32 to get the current working
75directory on the specified drive, since Windows maintains a separate current
76working directory for each drive. If no drive is specified then the current
77drive is assumed.
78
79This function simply calls the Microsoft C library _getdcwd() function.
80
81=back
82
83
84=head2 abs_path and friends
85
86These functions are exported only on request. They each take a single
87argument and return the absolute pathname for it. If no argument is
88given they'll use the current working directory.
89
90=over 4
91
92=item abs_path
93
94 my $abs_path = abs_path($file);
95
96Uses the same algorithm as getcwd(). Symbolic links and relative-path
97components ("." and "..") are resolved to return the canonical
98pathname, just like realpath(3).
99
100=item realpath
101
102 my $abs_path = realpath($file);
103
104A synonym for abs_path().
105
106=item fast_abs_path
107
108 my $abs_path = fast_abs_path($file);
109
110A more dangerous, but potentially faster version of abs_path.
111
112=back
113
114=head2 $ENV{PWD}
115
116If you ask to override your chdir() built-in function,
117
118 use Cwd qw(chdir);
119
120then your PWD environment variable will be kept up to date. Note that
121it will only be kept up to date if all packages which use chdir import
122it from Cwd.
123
124
125=head1 NOTES
126
127=over 4
128
129=item *
130
131Since the path seperators are different on some operating systems ('/'
132on Unix, ':' on MacPerl, etc...) we recommend you use the File::Spec
133modules wherever portability is a concern.
134
135=item *
136
137Actually, on Mac OS, the C<getcwd()>, C<fastgetcwd()> and C<fastcwd()>
138functions are all aliases for the C<cwd()> function, which, on Mac OS,
139calls `pwd`. Likewise, the C<abs_path()> function is an alias for
140C<fast_abs_path()>.
141
142=back
143
144=head1 AUTHOR
145
146Originally by the perl5-porters.
147
148Maintained by Ken Williams <[email protected]>
149
150=head1 COPYRIGHT
151
152Copyright (c) 2004 by the Perl 5 Porters. All rights reserved.
153
154This program is free software; you can redistribute it and/or modify
155it under the same terms as Perl itself.
156
157Portions of the C code in this library are copyright (c) 1994 by the
158Regents of the University of California. All rights reserved. The
159license on this code is compatible with the licensing of the rest of
160the distribution - please see the source code in F<Cwd.xs> for the
161details.
162
163=head1 SEE ALSO
164
165L<File::chdir>
166
167=cut
168
169use strict;
170use Exporter;
171use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
172
173$VERSION = '3.12';
174
175@ISA = qw/ Exporter /;
176@EXPORT = qw(cwd getcwd fastcwd fastgetcwd);
177push @EXPORT, qw(getdcwd) if $^O eq 'MSWin32';
178@EXPORT_OK = qw(chdir abs_path fast_abs_path realpath fast_realpath);
179
180# sys_cwd may keep the builtin command
181
182# All the functionality of this module may provided by builtins,
183# there is no sense to process the rest of the file.
184# The best choice may be to have this in BEGIN, but how to return from BEGIN?
185
186if ($^O eq 'os2') {
187 local $^W = 0;
188
189 *cwd = defined &sys_cwd ? \&sys_cwd : \&_os2_cwd;
190 *getcwd = \&cwd;
191 *fastgetcwd = \&cwd;
192 *fastcwd = \&cwd;
193
194 *fast_abs_path = \&sys_abspath if defined &sys_abspath;
195 *abs_path = \&fast_abs_path;
196 *realpath = \&fast_abs_path;
197 *fast_realpath = \&fast_abs_path;
198
199 return 1;
200}
201
202# If loading the XS stuff doesn't work, we can fall back to pure perl
203eval {
204 if ( $] >= 5.006 ) {
205 require XSLoader;
206 XSLoader::load( __PACKAGE__, $VERSION );
207 } else {
208 require DynaLoader;
209 push @ISA, 'DynaLoader';
210 __PACKAGE__->bootstrap( $VERSION );
211 }
212};
213
214# Must be after the DynaLoader stuff:
215$VERSION = eval $VERSION;
216
217# Big nasty table of function aliases
218my %METHOD_MAP =
219 (
220 VMS =>
221 {
222 cwd => '_vms_cwd',
223 getcwd => '_vms_cwd',
224 fastcwd => '_vms_cwd',
225 fastgetcwd => '_vms_cwd',
226 abs_path => '_vms_abs_path',
227 fast_abs_path => '_vms_abs_path',
228 },
229
230 MSWin32 =>
231 {
232 # We assume that &_NT_cwd is defined as an XSUB or in the core.
233 cwd => '_NT_cwd',
234 getcwd => '_NT_cwd',
235 fastcwd => '_NT_cwd',
236 fastgetcwd => '_NT_cwd',
237 abs_path => 'fast_abs_path',
238 realpath => 'fast_abs_path',
239 },
240
241 dos =>
242 {
243 cwd => '_dos_cwd',
244 getcwd => '_dos_cwd',
245 fastgetcwd => '_dos_cwd',
246 fastcwd => '_dos_cwd',
247 abs_path => 'fast_abs_path',
248 },
249
250 qnx =>
251 {
252 cwd => '_qnx_cwd',
253 getcwd => '_qnx_cwd',
254 fastgetcwd => '_qnx_cwd',
255 fastcwd => '_qnx_cwd',
256 abs_path => '_qnx_abs_path',
257 fast_abs_path => '_qnx_abs_path',
258 },
259
260 cygwin =>
261 {
262 getcwd => 'cwd',
263 fastgetcwd => 'cwd',
264 fastcwd => 'cwd',
265 abs_path => 'fast_abs_path',
266 realpath => 'fast_abs_path',
267 },
268
269 epoc =>
270 {
271 cwd => '_epoc_cwd',
272 getcwd => '_epoc_cwd',
273 fastgetcwd => '_epoc_cwd',
274 fastcwd => '_epoc_cwd',
275 abs_path => 'fast_abs_path',
276 },
277
278 MacOS =>
279 {
280 getcwd => 'cwd',
281 fastgetcwd => 'cwd',
282 fastcwd => 'cwd',
283 abs_path => 'fast_abs_path',
284 },
285 );
286
287$METHOD_MAP{NT} = $METHOD_MAP{MSWin32};
288$METHOD_MAP{nto} = $METHOD_MAP{qnx};
289
290
291# Find the pwd command in the expected locations. We assume these
292# are safe. This prevents _backtick_pwd() consulting $ENV{PATH}
293# so everything works under taint mode.
294my $pwd_cmd;
295foreach my $try ('/bin/pwd',
296 '/usr/bin/pwd',
297 '/QOpenSys/bin/pwd', # OS/400 PASE.
298 ) {
299
300 if( -x $try ) {
301 $pwd_cmd = $try;
302 last;
303 }
304}
305unless ($pwd_cmd) {
306 # Isn't this wrong? _backtick_pwd() will fail if somenone has
307 # pwd in their path but it is not /bin/pwd or /usr/bin/pwd?
308 # See [perl #16774]. --jhi
309 $pwd_cmd = 'pwd';
310}
311
312# Lazy-load Carp
313sub _carp { require Carp; Carp::carp(@_) }
314sub _croak { require Carp; Carp::croak(@_) }
315
316# The 'natural and safe form' for UNIX (pwd may be setuid root)
317sub _backtick_pwd {
318 # Localize %ENV entries in a way that won't create new hash keys
319 my @localize = grep exists $ENV{$_}, qw(PATH IFS CDPATH ENV BASH_ENV);
320 local @ENV{@localize};
321
322 my $cwd = `$pwd_cmd`;
323 # Belt-and-suspenders in case someone said "undef $/".
324 local $/ = "\n";
325 # `pwd` may fail e.g. if the disk is full
326 chomp($cwd) if defined $cwd;
327 $cwd;
328}
329
330# Since some ports may predefine cwd internally (e.g., NT)
331# we take care not to override an existing definition for cwd().
332
333unless ($METHOD_MAP{$^O}{cwd} or defined &cwd) {
334 # The pwd command is not available in some chroot(2)'ed environments
335 my $sep = $Config::Config{path_sep} || ':';
336 my $os = $^O; # Protect $^O from tainting
337 if( $os eq 'MacOS' || (defined $ENV{PATH} &&
338 $os ne 'MSWin32' && # no pwd on Windows
339 grep { -x "$_/pwd" } split($sep, $ENV{PATH})) )
340 {
341 *cwd = \&_backtick_pwd;
342 }
343 else {
344 *cwd = \&getcwd;
345 }
346}
347
348# set a reasonable (and very safe) default for fastgetcwd, in case it
349# isn't redefined later (20001212 rspier)
350*fastgetcwd = \&cwd;
351
352# By Brandon S. Allbery
353#
354# Usage: $cwd = getcwd();
355
356sub getcwd
357{
358 abs_path('.');
359}
360
361
362# By John Bazik
363#
364# Usage: $cwd = &fastcwd;
365#
366# This is a faster version of getcwd. It's also more dangerous because
367# you might chdir out of a directory that you can't chdir back into.
368
369sub fastcwd_ {
370 my($odev, $oino, $cdev, $cino, $tdev, $tino);
371 my(@path, $path);
372 local(*DIR);
373
374 my($orig_cdev, $orig_cino) = stat('.');
375 ($cdev, $cino) = ($orig_cdev, $orig_cino);
376 for (;;) {
377 my $direntry;
378 ($odev, $oino) = ($cdev, $cino);
379 CORE::chdir('..') || return undef;
380 ($cdev, $cino) = stat('.');
381 last if $odev == $cdev && $oino == $cino;
382 opendir(DIR, '.') || return undef;
383 for (;;) {
384 $direntry = readdir(DIR);
385 last unless defined $direntry;
386 next if $direntry eq '.';
387 next if $direntry eq '..';
388
389 ($tdev, $tino) = lstat($direntry);
390 last unless $tdev != $odev || $tino != $oino;
391 }
392 closedir(DIR);
393 return undef unless defined $direntry; # should never happen
394 unshift(@path, $direntry);
395 }
396 $path = '/' . join('/', @path);
397 if ($^O eq 'apollo') { $path = "/".$path; }
398 # At this point $path may be tainted (if tainting) and chdir would fail.
399 # Untaint it then check that we landed where we started.
400 $path =~ /^(.*)\z/s # untaint
401 && CORE::chdir($1) or return undef;
402 ($cdev, $cino) = stat('.');
403 die "Unstable directory path, current directory changed unexpectedly"
404 if $cdev != $orig_cdev || $cino != $orig_cino;
405 $path;
406}
407if (not defined &fastcwd) { *fastcwd = \&fastcwd_ }
408
409
410# Keeps track of current working directory in PWD environment var
411# Usage:
412# use Cwd 'chdir';
413# chdir $newdir;
414
415my $chdir_init = 0;
416
417sub chdir_init {
418 if ($ENV{'PWD'} and $^O ne 'os2' and $^O ne 'dos' and $^O ne 'MSWin32') {
419 my($dd,$di) = stat('.');
420 my($pd,$pi) = stat($ENV{'PWD'});
421 if (!defined $dd or !defined $pd or $di != $pi or $dd != $pd) {
422 $ENV{'PWD'} = cwd();
423 }
424 }
425 else {
426 my $wd = cwd();
427 $wd = Win32::GetFullPathName($wd) if $^O eq 'MSWin32';
428 $ENV{'PWD'} = $wd;
429 }
430 # Strip an automounter prefix (where /tmp_mnt/foo/bar == /foo/bar)
431 if ($^O ne 'MSWin32' and $ENV{'PWD'} =~ m|(/[^/]+(/[^/]+/[^/]+))(.*)|s) {
432 my($pd,$pi) = stat($2);
433 my($dd,$di) = stat($1);
434 if (defined $pd and defined $dd and $di == $pi and $dd == $pd) {
435 $ENV{'PWD'}="$2$3";
436 }
437 }
438 $chdir_init = 1;
439}
440
441sub chdir {
442 my $newdir = @_ ? shift : ''; # allow for no arg (chdir to HOME dir)
443 $newdir =~ s|///*|/|g unless $^O eq 'MSWin32';
444 chdir_init() unless $chdir_init;
445 my $newpwd;
446 if ($^O eq 'MSWin32') {
447 # get the full path name *before* the chdir()
448 $newpwd = Win32::GetFullPathName($newdir);
449 }
450
451 return 0 unless CORE::chdir $newdir;
452
453 if ($^O eq 'VMS') {
454 return $ENV{'PWD'} = $ENV{'DEFAULT'}
455 }
456 elsif ($^O eq 'MacOS') {
457 return $ENV{'PWD'} = cwd();
458 }
459 elsif ($^O eq 'MSWin32') {
460 $ENV{'PWD'} = $newpwd;
461 return 1;
462 }
463
464 if ($newdir =~ m#^/#s) {
465 $ENV{'PWD'} = $newdir;
466 } else {
467 my @curdir = split(m#/#,$ENV{'PWD'});
468 @curdir = ('') unless @curdir;
469 my $component;
470 foreach $component (split(m#/#, $newdir)) {
471 next if $component eq '.';
472 pop(@curdir),next if $component eq '..';
473 push(@curdir,$component);
474 }
475 $ENV{'PWD'} = join('/',@curdir) || '/';
476 }
477 1;
478}
479
480
481sub _perl_abs_path
482{
483 my $start = @_ ? shift : '.';
484 my($dotdots, $cwd, @pst, @cst, $dir, @tst);
485
486 unless (@cst = stat( $start ))
487 {
488 _carp("stat($start): $!");
489 return '';
490 }
491
492 unless (-d _) {
493 # Make sure we can be invoked on plain files, not just directories.
494 # NOTE that this routine assumes that '/' is the only directory separator.
495
496 my ($dir, $file) = $start =~ m{^(.*)/(.+)$}
497 or return cwd() . '/' . $start;
498
499 # Can't use "-l _" here, because the previous stat was a stat(), not an lstat().
500 if (-l $start) {
501 my $link_target = readlink($start);
502 die "Can't resolve link $start: $!" unless defined $link_target;
503
504 require File::Spec;
505 $link_target = $dir . '/' . $link_target
506 unless File::Spec->file_name_is_absolute($link_target);
507
508 return abs_path($link_target);
509 }
510
511 return $dir ? abs_path($dir) . "/$file" : "/$file";
512 }
513
514 $cwd = '';
515 $dotdots = $start;
516 do
517 {
518 $dotdots .= '/..';
519 @pst = @cst;
520 local *PARENT;
521 unless (opendir(PARENT, $dotdots))
522 {
523 _carp("opendir($dotdots): $!");
524 return '';
525 }
526 unless (@cst = stat($dotdots))
527 {
528 _carp("stat($dotdots): $!");
529 closedir(PARENT);
530 return '';
531 }
532 if ($pst[0] == $cst[0] && $pst[1] == $cst[1])
533 {
534 $dir = undef;
535 }
536 else
537 {
538 do
539 {
540 unless (defined ($dir = readdir(PARENT)))
541 {
542 _carp("readdir($dotdots): $!");
543 closedir(PARENT);
544 return '';
545 }
546 $tst[0] = $pst[0]+1 unless (@tst = lstat("$dotdots/$dir"))
547 }
548 while ($dir eq '.' || $dir eq '..' || $tst[0] != $pst[0] ||
549 $tst[1] != $pst[1]);
550 }
551 $cwd = (defined $dir ? "$dir" : "" ) . "/$cwd" ;
552 closedir(PARENT);
553 } while (defined $dir);
554 chop($cwd) unless $cwd eq '/'; # drop the trailing /
555 $cwd;
556}
557
558
559my $Curdir;
560sub fast_abs_path {
561 local $ENV{PWD} = $ENV{PWD} || ''; # Guard against clobberage
562 my $cwd = getcwd();
563 require File::Spec;
564 my $path = @_ ? shift : ($Curdir ||= File::Spec->curdir);
565
566 # Detaint else we'll explode in taint mode. This is safe because
567 # we're not doing anything dangerous with it.
568 ($path) = $path =~ /(.*)/;
569 ($cwd) = $cwd =~ /(.*)/;
570
571 unless (-e $path) {
572 _croak("$path: No such file or directory");
573 }
574
575 unless (-d _) {
576 # Make sure we can be invoked on plain files, not just directories.
577
578 my ($vol, $dir, $file) = File::Spec->splitpath($path);
579 return File::Spec->catfile($cwd, $path) unless length $dir;
580
581 if (-l $path) {
582 my $link_target = readlink($path);
583 die "Can't resolve link $path: $!" unless defined $link_target;
584
585 $link_target = File::Spec->catpath($vol, $dir, $link_target)
586 unless File::Spec->file_name_is_absolute($link_target);
587
588 return fast_abs_path($link_target);
589 }
590
591 return $dir eq File::Spec->rootdir
592 ? File::Spec->catpath($vol, $dir, $file)
593 : fast_abs_path(File::Spec->catpath($vol, $dir, '')) . '/' . $file;
594 }
595
596 if (!CORE::chdir($path)) {
597 _croak("Cannot chdir to $path: $!");
598 }
599 my $realpath = getcwd();
600 if (! ((-d $cwd) && (CORE::chdir($cwd)))) {
601 _croak("Cannot chdir back to $cwd: $!");
602 }
603 $realpath;
604}
605
606# added function alias to follow principle of least surprise
607# based on previous aliasing. --tchrist 27-Jan-00
608*fast_realpath = \&fast_abs_path;
609
610
611# --- PORTING SECTION ---
612
613# VMS: $ENV{'DEFAULT'} points to default directory at all times
614# 06-Mar-1996 Charles Bailey [email protected]
615# Note: Use of Cwd::chdir() causes the logical name PWD to be defined
616# in the process logical name table as the default device and directory
617# seen by Perl. This may not be the same as the default device
618# and directory seen by DCL after Perl exits, since the effects
619# the CRTL chdir() function persist only until Perl exits.
620
621sub _vms_cwd {
622 return $ENV{'DEFAULT'};
623}
624
625sub _vms_abs_path {
626 return $ENV{'DEFAULT'} unless @_;
627
628 # may need to turn foo.dir into [.foo]
629 my $path = VMS::Filespec::pathify($_[0]);
630 $path = $_[0] unless defined $path;
631
632 return VMS::Filespec::rmsexpand($path);
633}
634
635sub _os2_cwd {
636 $ENV{'PWD'} = `cmd /c cd`;
637 chomp $ENV{'PWD'};
638 $ENV{'PWD'} =~ s:\\:/:g ;
639 return $ENV{'PWD'};
640}
641
642sub _win32_cwd {
643 $ENV{'PWD'} = Win32::GetCwd();
644 $ENV{'PWD'} =~ s:\\:/:g ;
645 return $ENV{'PWD'};
646}
647
648*_NT_cwd = defined &Win32::GetCwd ? \&_win32_cwd : \&_os2_cwd;
649
650sub _dos_cwd {
651 if (!defined &Dos::GetCwd) {
652 $ENV{'PWD'} = `command /c cd`;
653 chomp $ENV{'PWD'};
654 $ENV{'PWD'} =~ s:\\:/:g ;
655 } else {
656 $ENV{'PWD'} = Dos::GetCwd();
657 }
658 return $ENV{'PWD'};
659}
660
661sub _qnx_cwd {
662 local $ENV{PATH} = '';
663 local $ENV{CDPATH} = '';
664 local $ENV{ENV} = '';
665 $ENV{'PWD'} = `/usr/bin/fullpath -t`;
666 chomp $ENV{'PWD'};
667 return $ENV{'PWD'};
668}
669
670sub _qnx_abs_path {
671 local $ENV{PATH} = '';
672 local $ENV{CDPATH} = '';
673 local $ENV{ENV} = '';
674 my $path = @_ ? shift : '.';
675 local *REALPATH;
676
677 defined( open(REALPATH, '-|') || exec '/usr/bin/fullpath', '-t', $path ) or
678 die "Can't open /usr/bin/fullpath: $!";
679 my $realpath = <REALPATH>;
680 close REALPATH;
681 chomp $realpath;
682 return $realpath;
683}
684
685sub _epoc_cwd {
686 $ENV{'PWD'} = EPOC::getcwd();
687 return $ENV{'PWD'};
688}
689
690
691# Now that all the base-level functions are set up, alias the
692# user-level functions to the right places
693
694if (exists $METHOD_MAP{$^O}) {
695 my $map = $METHOD_MAP{$^O};
696 foreach my $name (keys %$map) {
697 local $^W = 0; # assignments trigger 'subroutine redefined' warning
698 no strict 'refs';
699 *{$name} = \&{$map->{$name}};
700 }
701}
702
703# In case the XS version doesn't load.
704*abs_path = \&_perl_abs_path unless defined &abs_path;
705
706# added function alias for those of us more
707# used to the libc function. --tchrist 27-Jan-00
708*realpath = \&abs_path;
709
7101;
Note: See TracBrowser for help on using the repository browser.