A cleaner abs_path().
Jeff Pinyan [Sun, 23 Jul 2000 17:43:02 +0000 (13:43 -0400)]
Subject: Re: unix alternative to Cwd.pm
Message-ID: <Pine.GSO.4.21.0007231739120.4304-100000@crusoe.crusoe.net>

p4raw-id: //depot/perl@6419

lib/Cwd.pm

index 9a92829..d86428c 100644 (file)
@@ -70,7 +70,7 @@ kept up to date if all packages which use chdir import it from Cwd.
 
 use Carp;
 
-$VERSION = '2.02';
+$VERSION = '2.03';
 
 require Exporter;
 @ISA = qw(Exporter);
@@ -200,63 +200,39 @@ sub chdir {
     1;
 }
 
-# Taken from Cwd.pm It is really getcwd with an optional
-# parameter instead of '.'
-#
 
-sub abs_path
-{
-    my $start = @_ ? shift : '.';
-    my($dotdots, $cwd, @pst, @cst, $dir, @tst);
+# By Jeff "japhy" Pinyan (07/23/2000)
+#   usage:  abs_path(PATHNAME)
+# see the docs
+
+sub abs_path {
+  my $base = @_ ? $_[0] : ".";
+  my $path = "";
+  my $file;
+
+  do {
+    my @devino = (stat($base))[0,1] or
+      carp("stat($base): $!"), return;
 
-    unless (@cst = stat( $start ))
-    {
-       carp "stat($start): $!";
-       return '';
+    $base .= "/..";
+
+    opendir PREV, $base or carp("opendir($base): $!"), return;
+    while (defined($file = readdir PREV)) {
+      next if $file eq "." or $file eq "..";
+      my @entry = (lstat("$base/$file"))[0,1] or
+        carp("lstat($base/$file): $!"), return;
+      last if $devino[0] == $entry[0] and $devino[1] == $entry[1];
     }
-    $cwd = '';
-    $dotdots = $start;
-    do
-    {
-       $dotdots .= '/..';
-       @pst = @cst;
-       unless (opendir(PARENT, $dotdots))
-       {
-           carp "opendir($dotdots): $!";
-           return '';
-       }
-       unless (@cst = stat($dotdots))
-       {
-           carp "stat($dotdots): $!";
-           closedir(PARENT);
-           return '';
-       }
-       if ($pst[0] == $cst[0] && $pst[1] == $cst[1])
-       {
-           $dir = undef;
-       }
-       else
-       {
-           do
-           {
-               unless (defined ($dir = readdir(PARENT)))
-               {
-                   carp "readdir($dotdots): $!";
-                   closedir(PARENT);
-                   return '';
-               }
-               $tst[0] = $pst[0]+1 unless (@tst = lstat("$dotdots/$dir"))
-           }
-           while ($dir eq '.' || $dir eq '..' || $tst[0] != $pst[0] ||
-                  $tst[1] != $pst[1]);
-       }
-       $cwd = (defined $dir ? "$dir" : "" ) . "/$cwd" ;
-       closedir(PARENT);
-    } while (defined $dir);
-    chop($cwd) unless $cwd eq '/'; # drop the trailing /
-    $cwd;
+    closedir PREV;
+
+    $path = (defined $file and $file) . "/$path";
+  } while defined $file;
+
+  length($path) > 1 and chop $path;
+  return $path;
 }
 
+
 # added function alias for those of us more
 # used to the libc function.  --tchrist 27-Jan-00
 *realpath = \&abs_path;