Bug #73884 [Com]: is_dir() returns false for junction / symlinkd

From: Date: Thu, 12 Jan 2017 15:15:39 +0000
Subject: Bug #73884 [Com]: is_dir() returns false for junction / symlinkd
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-206561@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=73884&edit=1 ID: 73884 Comment by: kulakov74 at yandex dot ru Reported by: kulakov74 at yandex dot ru Summary: is_dir() returns false for junction / symlinkd Status: Open Type: Bug Package: Filesystem function related Operating System: Windows 8.1 PHP Version: 7.1.0 Block user comment: N Private report: N New Comment: >>please retry putting the code into a file As I wrote I did so. I tested with Windows 7 x64 - the bug is still there for both "c:\Users\All Users" and junctions to cyrillic directories. Note that for me is_dir() gives true if the junction itself is cyrillic but the target is latin. The bug shows only if the target is cyrillic, no matter what charset of the link is. I also tried the old PHP 5.5 and it gave me correct result with jun2ru (target is rus), but not for All Users. I compared phpinfo() output of both versions and found a difference: in 5.5 default_charset="" while in 7.1 it's UTF-8. I tried using different values for default_charset and finally got correct result with Windows-1251 (Cyrillic): ini_set('default_charset', 'Windows-1251'); echo(ini_get('default_charset')."\n"); $p='c:\temp\рус2рус'; var_dump(is_dir($p), readlink($p)); This way PHP 7.1 was correct, at the same time when I used UTF-8 / no value / iso-8859-1 it was not. With PHP 5.5 it seems you can use any default_charset. It may be that is_dir() depends on what language is installed in the system, I have Russian installed and for me Windows-1251 worked with PHP 7. "c:\Users\All Users\" doesn't work at all in both versions. Previous Comments: ------------------------------------------------------------------------ [2017-01-11 22:51:12] ab@php.net Hmm, but again, $ x64\Release\php.exe -n -r "$p = 'c:\\users\\all users'; var_dump(is_dir($p), readlink($p));" bool(true) string(14) "C:\ProgramData" $ x64\Release\php.exe -n -r "$p = 'c:\\users\\default user'; var_dump(is_dir($p), readlink($p));" Warning: readlink(): readlink failed to read the symbolic link (c:\users\default user), error 5) in Command line code on line 1 bool(true) bool(false) Seems I simply come to the start. is_dir() works where i test, and readlink() seems correct according to the ACLs. Please, lets leave the multibyte path aside yet - if there's an issue, it should be handled in a different ticket. So far 7.0 shows same behavior. Need first to reproduce what you've on your side, which seems to be tricky as i've no machine behaving like that. If someone could produce a synthetic reproduce case, that would give a base to move forward on this. No status for this situation :/ Thanks. ------------------------------------------------------------------------ [2017-01-11 21:49:16] ab@php.net ACK, so i misunderstood the part about the username. There are indeed several places, where the username is relevant, but not this one. is_dir() is a simple stat() call on the given path. There's no step in between, so at the very bottom it's really the internal API. Maybe it'd be different if CreateFile and accompanying non POSIX compatible APIs were used, need to experiment with that. I'm leaving this open for now, so someone with a similar issue could possibly deliver more input or better repro way. With the other issue you've mentioned - please retry putting the code into a file. It is possibly, that the console blows the encoding. Thanks. ------------------------------------------------------------------------ [2017-01-10 20:57:15] kulakov74 at yandex dot ru Hm. I'm surprised links to cyrillic dirs worked for you. I thought I found the reason. Well, I can't help now. >>The points 3. and 4. are intended to work, otherwise the whole UTF-8 thing were useful. I know, and readlink() and is_dir() (when applied directly to a cyrillic dir) work fine. But when is_dir() meets a link it has to do an extra step and it may have a bug with buffer length, like the one readlink() had. Yeah, I agree Dir seems to go there but it can't show the files there. But it doesn't really matter - is_dir() only has to find out the target dir and "dir /a:l" shows it. So, PHP could get it and check whether it is a dir. But I can't say what Windows API function would return the target like dir does. Anyway, that's a different issue. As for cd'ing to the dir, this is what Total Commander does: if I go to "All Users" (it's a symlink), it goes there and the current path is "c:\Users\All Users\", as if it was a folder, although we really get to "C:\ProgramData". And if I go to "Default User" (it's a junction) I get to "c:\Users\Default" - I guess because TC first sniffs the target and then goes to it directly. This is what PHP could do with is_dir(), but without going (cd) there. I didn't mean my non-ASCII username was the problem, only non-ASCII dir names, and they could have my name in the path. Privileges/ACLs are not the reason here, if only for "Default User" that has a Deny rule, but that's a different issue. I use Win 8.1 (x64), the snapshot from 01/07/17. I'll also try the latest PHP at office, where I have Win 7 x64. Codepage (437) should not matter, as I run the tests from a php script that uses UTF-8. Codepage only matters for cmd.exe, I had 866 and now I have 1251, but that shouldn't matter. ------------------------------------------------------------------------ [2017-01-09 22:50:36] ab@php.net Typo, 3. and 4. are intended to work, otherwise UTF-8 were USELESS :) Thanks. ------------------------------------------------------------------------ [2017-01-09 22:48:17] ab@php.net Thanks for the further investigation. I still not reproduce the cases 3. and 4. from your post. Here $ mkdir bugs\bug73884\Кат $ icacls bugs\bug73884\Кат bugs\bug73884\Кат BUILTIN\Administrators:(I)(OI)(CI)(F) NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F) BUILTIN\Users:(I)(OI)(CI)(RX) NT AUTHORITY\Authenticated Users:(I)(M) NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M) $ mklink /j bugs\bug73884\linktorus bugs\bug73884\Кат Junction created for bugs\bug73884\linktorus <<===>> bugs\bug73884\Кат $ icacls bugs\bug73884\linktorus /L bugs\bug73884\linktorus BUILTIN\Administrators:(I)(OI)(CI)(F) NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F) BUILTIN\Users:(I)(OI)(CI)(RX) NT AUTHORITY\Authenticated Users:(I)(M) NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M) $ x64\Release\php.exe -n -r "$p = 'bugs\bug73884\linktorus'; var_dump(is_dir($p), readlink($p));" bool(true) string(54) "C:\php-sdk\php71\vc14\x64\php-src\bugs\bug73884\Кат" $ mklink /j bugs\bug73884\рус-ссылка bugs\bug73884\Кат Junction created for bugs\bug73884\рус-ссылка <<===>> bugs\bug73884\Кат $ icacls bugs\bug73884\рус-ссылка /L bugs\bug73884\рус-ссылка BUILTIN\Administrators:(I)(OI)(CI)(F) NT AUTHORITY\SYSTEM:(I)(OI)(CI)(F) BUILTIN\Users:(I)(OI)(CI)(RX) NT AUTHORITY\Authenticated Users:(I)(M) NT AUTHORITY\Authenticated Users:(I)(OI)(CI)(IO)(M) $ x64\Release\php.exe -n -r "$p = 'bugs\bug73884\рус-ссылка'; var_dump(is_dir($p), readlink($p));" bool(true) string(54) "C:\php-sdk\php71\vc14\x64\php-src\bugs\bug73884\Кат" Used the current dev tree, of course. Hopefully you used some snapshot after the readlink() fix, too. I'm on win10 however, but not sure it is of importance in this case. Also I don't think the username being not ASCII is relevant. Now see, cmd indeed looks like going into c:\users\default user, doing same as you $ cd "Default User" c:\Users\Default User $ dir Volume in drive C is SYSTEM Volume Serial Number is AE0A-76BD Directory of c:\Users\Default User File Not Found But the dir command shows - it cannot read it. Even the dir were empty, it should have shown periods. IMO, what the cd command does, is weird. It in no case looks, like the access no "c:\users\default user" is granted. The points 3. and 4. are intended to work, otherwise the whole UTF-8 thing were useful. You don't have to explain the russian words to me, anyway ;) The fact is - everything path related is converted to UTF-16 internally, and the corresponding W API is used. Also, PHP doesn't automatically elevate any privileges, it always runs with the default security descriptor, so the one corresponding to the current user. An exception from this the impersonation, in that case the impersonated user identity is used. Thereby, if such an issue is real - it doesn't concern only one particular codepage or language, it is most likely present in any other. For some reason, on machines i've tried this particular case doesn't produce issues you have. Used win 10 and server 2012 both with the cp 437. I'd wonder, whether you maybe have some group policies, that force to create files with particular ACLs, etc. Otherwise, it's an awkward situation, as i can't reproduce the issue from your side :( If you're sure, the non ASCII username could be an issue, please try some user with ASCII symbols only. Otherwise, there has to be another factor that we didn't determine yet, causing different behavior. Thanks. ------------------------------------------------------------------------ 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=73884 -- Edit this bug report at https://bugs.php.net/bug.php?id=73884&edit=1

« previous php.bugs (#206561) next »