Bug #69473 [Opn]: bug in symlink() prevents relative symlinks on Windows
| From: | cmb@php.net | Date: | Sat, 18 Apr 2015 10:16:22 +0000 |
| Subject: | Bug #69473 [Opn]: bug in symlink() prevents relative symlinks on Windows | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-192182@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=69473&edit=1
ID: 69473
Updated by: cmb@php.net
Reported by: email at spikx dot net
Summary: bug in symlink() prevents relative symlinks on
Windows
Status: Open
Type: Bug
Package: Win32API related
Operating System: Windows 7
PHP Version: 5.6.8
Block user comment: N
Private report: N
New Comment:
From the symlink(2) man page[1]:
| Symbolic links may contain .. path components, which (if used at
| the start of the link) refer to the parent directories of that in
| which the link resides.
This is even acknowledged by a comment in the code[2]:
| The target is relative to the link itself, not to the CWD.
However, it doesn't behave that way.
[1] <http://man7.org/linux/man-pages/man2/symlink.2.html>
[2] <https://github.com/php/php-src/blob/master/ext/standard/link_win32.c#L176>
Previous Comments:
------------------------------------------------------------------------
[2015-04-18 08:43:06] email at spikx dot net
No, relative symbolic links do not need to be CWD relative. See the first point in your linked
documentation:
Relative links are specified using the following conventions:
* Dot (. and ..) conventionsâfor example, "..\" resolves the path relative to the
parent directory.
[...]
As already said: relative symbolic links work the same way in Windows as they do under Linux. The
script works under Linux and it would work under Windows as well, if the symlink function of PHP did
not use GetFileAttributes to check if the $target exists - since it checks a completely wrong path.
Just try it yourself under Windows. As already said, this will not work:
<?php
mkdir('foo1');
mkdir('foo2');
symlink( '../foo2', 'foo1/foo3' );
However, THIS will work:
<?php
mkdir('foo1');
mkdir('foo2');
symlink( '../symlinktest/foo2', 'foo1/foo3' );
This works, because now the GetFileAttributes receives the path '../symlinktest/foo2',
which is a valid path relative to the CWD. However it creates an invalid symlink, since it is a
relative symlnk, which resides under /symlinktest/foo1, and will now point to
'../symlinktest/foo2', which does not exist (the full expanded path is
'C:\xampp\htdocs\symlinktest\symlinktest\foo2').
------------------------------------------------------------------------
[2015-04-18 03:22:26] pajoye@php.net
Your cwd is not foo1, so it won't work
See https://msdn.microsoft.com/en-us/library/windows/desktop/aa363878%28v=vs.85%29.aspx
------------------------------------------------------------------------
[2015-04-17 16:13:34] email at spikx dot net
Sorry, I mixed up the foo1 and foo2 folders in this test (I created a symlink to ../foo1 within foo2
instead of a symlink to ../foo2 within foo1, like in the original example), but you get the idea,
doesn't matter anyway :)
------------------------------------------------------------------------
[2015-04-17 16:09:28] email at spikx dot net
No, the symlink, which is called "foo3" in this case is located in the folder foo2
($source is 'foo2/foo3') and points to '../foo1' ($target), i.e. the foo1 folder
in the root directory (which is the parent directory of foo2). Look at this console output from
Linux, where it works, I think it will get more clear then:
[...]/symlinktest # vi index.php (create the aformentioned script)
[...]/symlinktest # php index.php (execute script via php binary)
[...]/symlinktest # ls -la (list root directory)
4.0K Apr 17 18:02 .
4.0K Apr 17 18:01 ..
4.0K Apr 17 18:02 foo1
4.0K Apr 17 18:02 foo2
71 Apr 17 18:02 index.php
[...]/symlinktest # cd foo2
[...]/symlinktest/foo2 # ls -la
4.0K Apr 17 18:02 .
4.0K Apr 17 18:02 ..
7 Apr 17 18:02 foo3 -> ../foo1
Just to mention it again: relative symlinks work on Windows too. However, PHP's implementation
of the symlink function prevents relative symlinks, due to the GetFileAttributes call on the target
path.
------------------------------------------------------------------------
[2015-04-17 13:49:24] pajoye@php.net
Your script creates a link to a non existing directory (../foo2) instead of the one you created
(./foo2).
Or am I missing something?
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=69473
--
Edit this bug report at https://bugs.php.net/bug.php?id=69473&edit=1