[perl #111510] File::Spec::UNIX->abs2rel() gets it wrong with ".." components
authorVolker Schatz <perldoc@volkerschatz.com>
Sat, 26 May 2012 19:32:25 +0000 (12:32 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sat, 26 May 2012 19:32:25 +0000 (12:32 -0700)
commit70b6afc16df4c7a694abcf12330e74113a1b3cee
tree7563ad56f2afaeed187ff8735c53e4eb05c66048
parent83c03aa3e02c6caf08cbd40cd0ac1f82ce181d81
[perl #111510] File::Spec::UNIX->abs2rel() gets it wrong with ".." components

File::Spec::UNIX->abs2rel() returns wrong results in a few cases, most
of which involve ".." path components.

To reproduce, paste the following test cases into:
perl -MFile::Spec::Unix -n -e 'print File::Spec::Unix->abs2rel(split),"\n";'

../foo bar/bat
bar/bat ../foo
foo bar/../bat
. .
/ /

Correct results when run at /home/me and no symlinks in base path:
../../../foo
../me/bar/bat
../foo
.
.

Results for File::Spec::Unix from PathTols 3.33:
../../foo
../bar/bat
../../../foo
/
/

The error in the first test case is due to an optimisation applied when
both arguments are relative paths, which prepends "/" instead of the
current directory.  "/../" is then converted to "/" by canonpath().

I have replaced this optimisation by a single call to _cwd() in the
following patch.  This also fixes the fourth test case.  Besides, I have
moved checks which make sense only for absolute path arguments to the
first branch of the if.

(hunk @@ -366,28 +367,32 @@)

The error in the last test case arises because a root dir $base is
treated specially, and catdir() does not work well for fewer than two
path components. The first added line in the following patch catches that.

As regards the second and third test case, they can be solved without
consulting the filesystem only if no symlinks are involved.  Whereever
$path contains .. components, the corresponding directory has to be
descended into. The following patch does this.

(hunk @@ -395,19 +400,39 @@)

It can be impossible for abs2rel() to work correctly without looking at
the filesystem if $base contains symlinks.  I understand from the
documentation that the File::Spec modules are not meant to consult the
filesystem.  Even though the docs state that abs2rel() does not consult
the filesystem, the implications could perhaps be made clearer, for
example like this:

(hunk @@ -352,9 +352,10 @@)
dist/Cwd/lib/File/Spec/Unix.pm