home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / perl502b.zip / lib / Cwd.pm < prev    next >
Text File  |  1996-01-02  |  7KB  |  279 lines

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