Subject: | Two discrepancies with realpath() utility |
Date: | Sun, 24 Jun 2007 08:24:42 -0400 |
To: | bug-Cwd [...] rt.cpan.org |
From: | Emmet Caulfield <emmet [...] netrogen.com> |
I discovered two discrepancies between Cwd::realpath() and the
realpath utility. IMHO, the behaviour of the utility is correct and
that of Cwd::realpath() wrong in both cases.
The inclusion of 'use strict;' etc. in the examples below is to make
the point that the returned value is 'undef', not merely the empty
string, which would be at least as bad, of course.
Versions of perl and Cwd:
-------------------------
$ uname -a
Linux scrat 2.6.20-16-generic #2 SMP Thu Jun 7 19:00:28 UTC 2007 x86_64 GNU/Linux
$ perl --version | grep ^This
This is perl, v5.8.8 built for x86_64-linux-gnu-thread-multi
$ perl -MCwd -e 'print "$Cwd::VERSION\n"'
3.12
$ # END
Discrepancies:
--------------
1. If Cwd::realpath() is invoked with an argument which is an
unsearchable (execute bit clear) directory, it returns undef.
This is contrary to expectation and the behaviour of the realpath
utility which (correctly IMO) returns the full path of the
directory. The full path of a directory has nothing to do with the
searchability of that directory itself, so Cwd is wrong and the
utility is right in this case.
Reproduce with:
$ cd /tmp
$ mkdir foo
$ chmod u-x foo
$ realpath ./foo
/tmp/foo
$ perl -MCwd -we 'use strict; my $p=Cwd::realpath("./foo"); print "$p\n";'
Use of uninitialized value in concatenation (.) or string at -e line 1.
$ # END
2. If Cwd::realpath is invoked on a dangling symlink where the
directory name of the target exists, it returns the (non-existant)
target of the symlink.
This is contrary to the behaviour of the realpath utility, which
returns an error for all dangling symlinks, and is inconsistent with
Cwd::realpath()'s own behaviour when the "dirname" of the target does
not exist. IMHO, Cwd::realpath() should return 'undef' or the
(non-existant) target consistently for all dangling symlinks and not
return different results depending on whether the directory-part of
the symlink target exists or not.
Reproduce with:
$ cd /tmp
$ rm -f bar
$ ln -s bar foo
$ realpath ./foo
./foo: No such file or directory
$ perl -MCwd -we "use strict; my \$p=Cwd::realpath('./foo'); print \"\$p\n\";"
/tmp/bar
$ # END
However, when the "dirname" of the target does not exist, the
behaviour is different:
$ ln -sf /this/does/not/exist foo
$ realpath ./foo
./foo: No such file or directory
$ perl -MCwd -we "use strict; my \$p=Cwd::realpath('./foo'); print \"\$p\n\";"
Use of uninitialized value in concatenation (.) or string at -e line 1.
$ # END