php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #50366 realpath() doesn't correctly resolve symlink
Submitted: 2009-12-02 22:07 UTC Modified: 2010-12-20 09:12 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: jerico dot dev at gmail dot com Assigned:
Status: Open Package: Filesystem function related
PHP Version: 5.2.11 OS: Linux
Private report: No CVE-ID: None
 [2009-12-02 22:07 UTC] jerico dot dev at gmail dot com
Description:
------------
realpath() doesn't resolve symlinks correctly when followed by /..

Reproduce code:
---------------
echo realpath('/home/user/test/app/lib/symlink/tests/../../..');

where "symlink" points to /home/user/test/something

Expected result:
----------------
/home/user/test/app

Actual result:
--------------
/home/user

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-12-03 08:13 UTC] jani@php.net
"realpath() expands all symbolic links and resolves references to '/./', '/../' and extra '/' characters in the input path . and return the canonicalized absolute pathname. "

And since it first resolves to /home/user/test/something/tests from where you go down 3 levels, of course you get /home/user/ ?

See this:

# php -r  'echo realpath("/home/jani/test/app/lib/symlink/tests/"), "\n";'
/home/jani/test/something/tests

# php -r  'echo realpath("/home/jani/test/app/lib/symlink/tests/../../.."), "\n";'
/home/jani


 [2009-12-03 18:28 UTC] jerico dot dev at gmail dot com
Hi Jani,

thanks a lot for looking into this.

I think the problem is that what is "logical" depends on what your use case is. There are two different approaches to resolving paths to canonical (physical) locations with symlinks:
1) Resolving .. first, then symlinks. This is AFAIK the default for the *nix command line (try cd'ing or ls'ing the example location and you'll see what I mean).
2) Resolving symlinks first, then .. There is one tool on Linux (that I know of) that behaves like this: readlink -e

I agree with you that there ARE use cases where you want 2). I've changed the bug category to "feature request" to reflect this. Sorry for filing a bug in the first place. :-(

There are many use cases, though, where realpath()/chdir() behavior is NOT useful (otherwise the OS would probably have chosen realpath/chdir logic as it's default ;-) ). The problem is that AFAIK PHP currently has no way of doing 1). Try

chdir('/home/user/test/app/lib/symlink/tests/../../..');
echo getcwd()."\n";

To see what I mean.

Also see 
http://bugs.php.net/bug.php?id=37603 and
http://bugs.php.net/bug.php?id=46260
which request very similar features.

The only way I know to achieve 1) would be going to OS-level (e.g. using `cd ...` or s.th. like that) which is awkward and not portable.

If you know a portable way to map a relative or absolute path with symlinks to it's physical location "OS style" in PHP then it would be extremely useful for me (and probably others) if you could share your knowledge. It's entirely possible that I miss something.

If you feel extremely helpful ;-) then you also might extend the PHP documentation of realpath()/chdir() and make it clear that both treat symlinks the same way as readlink -e does. There already is a user comment for chdir() saying that but I think it'd be worth mentioning at a more prominent location.
 [2010-12-20 09:12 UTC] jani@php.net
-Package: Feature/Change Request +Package: Filesystem function related
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Oct 08 13:01:26 2024 UTC