|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2015-04-16 20:29 UTC] email at spikx dot net
Description: ------------ As far as I checked, the following applies to any PHP version since the symlink function was introduced (in PHP 5.3). Currently it is impossible under Windows to create relative symbolic links with PHP's symlink function. It will always fail with the message "Could not fetch file information". The reason is the following: At line #169 ( https://github.com/php/php-src/blob/master/ext/standard/link_win32.c#L169 ) the function checks, if the $target ("topath" in the C function) actually exists: if ((attr = GetFileAttributes(topath)) == INVALID_FILE_ATTRIBUTES) { ... } However, the Win32API function "GetFileAttributes" expects the path to be either absolute or relative **to the CWD**! This means that this check will always fail, if you want to use a relative symlink, since the relative path of the symlink is relative to the $source's directory, not relative to the CWD. Test script: --------------- <?php mkdir('foo1'); mkdir('foo2'); symlink( '../foo2', 'foo1/foo3' ); Expected result: ---------------- /foo1 should contain a directory symlink to ../foo2 (i.e. the /foo2 directory in the root folder) Actual result: -------------- Under Windows: Warning: symlink(): Could not fetch file information(error 2) in index.php on line 6 Under Linux: foo1 contains a directory symlink to ../foo2 (i.e. the foo2 directory in CWD) PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Nov 04 21:00:01 2025 UTC |
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.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').