Bug #69473 [Opn]: bug in symlink() prevents relative symlinks on Windows

From: Date: Sat, 18 Apr 2015 08:43:07 +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-192181@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 User updated by: email at spikx dot 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: 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'). Previous Comments: ------------------------------------------------------------------------ [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? ------------------------------------------------------------------------ [2015-04-17 07:08:16] email at spikx dot net The issue with the CWD is even more problematic than expected. Assume you have a local XAMPP installation on your Windows system and the aforementioned script is under C:\xampp\htdocs\symlinktest\index.php Now, if you execute this script via Apache (e.g. by opening it via your Browser), the CWD (for the Win32API functions) will actually be C:\xampp (!) At least it was in my case. If you execute the script via the command line directly within C:\xampp\htdocs\symlinktest, then the CWD for the Win32API functions will also be C:\xampp\htdocs\symlinktest as expected. Calling chdir(…) before the symlink(…) call did not change the CWD for the Win32API function as well. In my opinion, the if ((attr = GetFileAttributes(topath)) == INVALID_FILE_ATTRIBUTES) { ... } should simply be removed - or only applied, if topath is not a relative path. It's then the responsibility of the user to make sure the relative path provided in $target is valid/meaningful. As it is currently, PHP's symlink function only allows you to generate invalid relative symlinks anyway. ------------------------------------------------------------------------ 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

« previous php.bugs (#192181) next »