php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77639 realpath resolves NTFS junctions which are not symlinks
Submitted: 2019-02-19 11:34 UTC Modified: 2021-09-22 09:45 UTC
Votes:3
Avg. Score:3.7 ± 0.9
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: mesaverde228 at gmail dot com Assigned: cmb (profile)
Status: Duplicate Package: *Directory/Filesystem functions
PHP Version: 7.1.26 OS: Windows/Linux
Private report: No CVE-ID: None
 [2019-02-19 11:34 UTC] mesaverde228 at gmail dot com
Description:
------------
There is some difference in interpretation symlinked folder on different platforms




Test script:
---------------
https://gist.github.com/inri13666/4f7484af32ac7eba81b0d1bf8a5a5111

Expected result:
----------------
I assume that result for `index.php` should be almost the same.
Also possibly __DIR__ should point to the symlink(junction) path instead of a physical path.

Actual result:
--------------
https://gist.github.com/inri13666/4f7484af32ac7eba81b0d1bf8a5a5111

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-02-19 16:55 UTC] cmb@php.net
Junctions are not symlinks.
 [2019-02-19 18:53 UTC] mesaverde228 at gmail dot com
Is that means that windows "junctions" not supported by PHP?
 [2019-02-19 18:55 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2019-02-19 18:55 UTC] requinix@php.net
The only bug I can see here is that realpath() on a junction is resolving it

D:\test\symlinkedcachefolder>php -r "var_dump(realpath('D:/test/symlinkedcachefolder'));"
string(23) "D:\test\realcachefolder"

when last I knew PHP deliberately did not - only symlinks. Do you agree?
 [2019-02-19 18:57 UTC] requinix@php.net
> Is that means that windows "junctions" not supported by PHP?
Depends what "support" you are expecting.
 [2019-02-19 19:00 UTC] mesaverde228 at gmail dot com
if I change 
mklink /J D:\test\symlinkedcachefolder D:\test\realcachefolder
to
mklink /d D:\test\symlinkedcachefolder D:\test\realcachefolder
I got following response from CMD
symbolic link created for D:\test\symlinkedcachefolder <<===>> D:\test\realcachefolder

But the script "index.php" works the same as for "junction"

D:\test\symlinkedcachefolder>php index.php
array(4) {
  ["realpath(__DIR__)"]=>
  string(23) "D:\test\realcachefolder"
  ["realpath("D:\test\symlinkedcachefolder\gretta")"]=>
  bool(false)
  ["dirname(__DIR__)"]=>
  string(7) "D:\test"
  ["dirname(__DIR__ . "\gretta")"]=>
  string(23) "D:\test\realcachefolder"
}
 [2019-02-19 19:13 UTC] requinix@php.net
Right. And the bug is that the junction should not be resolved. Right?
 [2019-02-19 19:26 UTC] mesaverde228 at gmail dot com
I'm not sure what is the bug, but for me is very ambiguous that on different platforms for the same functionality I got different results, when I use "soft" or "hard" links on both OS Linux and Windows.
 [2019-02-19 19:46 UTC] requinix@php.net
-Status: Feedback +Status: Open
 [2019-02-19 19:46 UTC] requinix@php.net
You cannot compare a Linux symlink with an NTFS junction. They are two different filesystem features.
 [2019-02-19 20:23 UTC] mesaverde228 at gmail dot com
Ok, install git and use "ln" from distribution to create symbolik link like on Linux system

rm -rf D:\test\symlinkedcachefolder
ln -s D:\test\realcachefolder D:\test\symlinkedcachefolder
dir

output

D:\test>dir
 Volume in drive D is dev
 Volume Serial Number is ECD3-824B

 Directory of D:\test

02/19/2019  11:14 PM    <DIR>          .
02/19/2019  11:14 PM    <DIR>          ..
02/19/2019  09:51 PM    <DIR>          realcachefolder
02/19/2019  11:14 PM    <DIR>          symlinkedcachefolder
               0 File(s)              0 bytes
               4 Dir(s)  34,891,960,320 bytes free


Next use steps from previous STR

php -r "var_dump(realpath('D:/test/symlinkedcachefolder'));"
php -r "var_dump(__DIR__);"

Will output

D:\test\symlinkedcachefolder>php -r "var_dump(realpath('D:/test/symlinkedcachefolder'));"
string(28) "D:\test\symlinkedcachefolder"

D:\test\symlinkedcachefolder>php -r "var_dump(__DIR__);"
string(28) "D:\test\symlinkedcachefolder"

and script will return following

D:\test\symlinkedcachefolder>php index.php
array(4) {
  ["realpath(__DIR__)"]=>
  string(28) "D:\test\symlinkedcachefolder"
  ["realpath("D:\test\symlinkedcachefolder\gretta")"]=>
  bool(false)
  ["dirname(__DIR__)"]=>
  string(7) "D:\test"
  ["dirname(__DIR__ . "\gretta")"]=>
  string(28) "D:\test\symlinkedcachefolder"
}

Totally different result comparing to junctions or native soft links in windows and not the same as on Linux fo links created using "ln" tool
 [2019-02-19 21:06 UTC] requinix@php.net
ln is not creating a symlink. Rather, it appears to be creating a copy.

1. If it were a symlink then dir would have shown it as such.
2. By default Windows requires admin privileges to create symlinks.
3. Create a file in one directory and it will not appear in the other.
4. If I create a large file in the original and try to ln -s to it, ln takes time when the operation should be instant.
 [2019-02-19 21:21 UTC] mesaverde228 at gmail dot com
yes, you are right.

"ln" tool is not a solution for me :(

and as I can see there is no cross-platform solution to create sym-link that can be later recognized by PHP the same on different OS :(
 [2019-02-19 21:29 UTC] mesaverde228 at gmail dot com
-Status: Open +Status: Closed
 [2019-02-19 21:29 UTC] mesaverde228 at gmail dot com
I assume issue can be closed because for subfolders within "linked" directory exists another separate ticket
 [2019-02-19 21:40 UTC] requinix@php.net
-Summary: Wrong behavior of getting paths for symlink +Summary: realpath resolves NTFS junctions which are not symlinks -Status: Closed +Status: Re-Opened
 [2019-02-19 21:40 UTC] requinix@php.net
There is still a bug here, even if it wasn't the one you were expecting.

> there is no cross-platform solution to create sym-link that can be later
> recognized by PHP the same on different OS :(
The problems come from Windows and NTFS restrictions. Specifically, Windows requires the SeCreateSymbolicLinkPrivilege privilege, which Administrator has but it can also be granted to other accounts. Windows also does not support symlinked directories. But it can do symlinked files and hardlinked/junctioned directories.

Besides that, PHP is as cross-platform as it can be.
 [2019-08-16 18:38 UTC] jbelli at pobox dot com
Windows does support symlinked directories. They can even be symlinks to UNC paths. Symlinked directories can be relative or absolute.

C:\>mklink /?
Creates a symbolic link.

MKLINK [[/D] | [/H] | [/J]] Link Target

        /D      Creates a directory symbolic link.  Default is a file
                symbolic link.
        /H      Creates a hard link instead of a symbolic link.
        /J      Creates a Directory Junction.
        Link    Specifies the new symbolic link name.
        Target  Specifies the path (relative or absolute) that the new link
                refers to.
 [2019-08-16 18:50 UTC] requinix@php.net
@jbelli: There was a specific reason why I said you can't symlink a directory... but I don't remember what it was. Some sort of quirk, maybe? Regardless, right now the symlinked directory I just created is behaving as I expect, and mklink's /D isn't something new to Windows 10.
 [2021-09-22 09:45 UTC] cmb@php.net
-Status: Re-Opened +Status: Duplicate -Assigned To: +Assigned To: cmb
 [2021-09-22 09:45 UTC] cmb@php.net
> The only bug I can see here is that realpath() on a junction is
> resolving it
> […]
> when last I knew PHP deliberately did not - only symlinks. Do
> you agree?

I just checked with PHP 5.3.29, and that already did resolve
junctions.

Anyhow, this ticket is actually a duplicate of bug #72738; I don't
think it makes much sense to change this long standing behavior.

> There was a specific reason why I said you can't symlink a
> directory... but I don't remember what it was. Some sort of quirk,
> maybe?

Perhaps that you can't unlink() a directory symlink on Windows
(you need to rmdir() there).
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Mar 19 07:01:29 2024 UTC