|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2016-12-16 11:01 UTC] steve dot baldwin at publisure dot com
Description:
------------
If you call is_dir("D:MyFolder") when both the drive (D) and the folder (MyFolder) exists it will return true. However windows will not resolve D:MyFolder as a valid path because a forward/or back slash is omitted after the root drive.
The correct path is D:\MyFolder or D:/MyFolder and PHP should be returning false instead of true.
Test script:
---------------
//change this below to a valid drive and folder but omit the \\
$path = "C:PHP";
assert(is_dir($path) == false);
Actual result:
--------------
Warning: assert(): Assertion failed
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 07:00:01 2025 UTC |
Actually I'm not sure that's correct. In the blog you linked to, in the test script an environment variable is set; // A hidden environment variable will be kept for each drive where a current directory is set // (need to set via P/Invoke as .NET blocks this) SetEnvironmentVariableW(@"=C:", @"C:\Program Files"); I believe this is what allows 'C:Foo' to resolve to C:\Program Files\Foo. If you use dirname("C:PHP") it returns C:. however if you use dirname("C:PHP\Test") it will return C:PHP. Either way it does look like PHP is actually correct regarding is_dir but windows has some odd functionality regarding how this resolves.Given that I have a copy of PHP runnable at E:\php56, from the command line: C:\Windows>E:\php56 -r "var_dump(is_dir('C:Windows'));" bool(false) C:\Windows>E: E:\>E:\php56 -r "var_dump(is_dir('C:Windows'));" bool(false) E:\>cd /d C:\ C:\>E:\php56 -r "var_dump(is_dir('C:Windows'));" bool(true) C:\>E: E:\>E:\php56 -r "var_dump(is_dir('C:Windows'));" bool(true) Additionally, E:\>E:\php56 -r "chdir('C:/Windows'); var_dump(is_dir('C:Windows'));" bool(false) E:\>E:\php56 -r "chdir('C:/'); var_dump(is_dir('C:Windows'));" bool(true) E:\>E:\php56 -r "chdir('C:/Windows'); chdir('E:/'); var_dump(is_dir('C:Windows'));" bool(false) E:\>E:\php56 -r "chdir('C:/'); chdir('E:/'); var_dump(is_dir('C:Windows'));" bool(true) All of those outputs are correct. I can't easily test is what happens from with IIS or Apache, but the only change in behavior that I would expect is that C: is always interpreted to be the root of the drive - "or the drive alone if none is set" clause from that link. But whatever happens, it is Windows making the decision. At least as far as this code is concerned... @ab: "Documented scenario"? Where? That's probably related to this: realpath isn't aware of drive-relative paths. C:\Windows>E: E:\>E:\php56 -r "var_dump(is_dir('C:System32')); var_dump(realpath('C:System32'));" bool(true) bool(false) The bug is the inconsistency. Whether PHP enforces that C:foo is strictly equal to C:\foo or whether it obeys the rules of the operating system, all of the filesystem functions should work the same way. https://github.com/php/php-src/blob/PHP-5.6.29/Zend/zend_virtual_cwd.c#L1260ab@php.net; Regardless of the escape sequence it will not resolve to the correct path. var_dump(dirname("C:PHP\Welcome")); #C:PHP var_dump(dirname("C:PHP\\Welcome")); #C:PHP var_dump(dirname("C:PHP\\Help\\Me")); #C:PHP\Help If anything, the escape \ should resolve it to C:PHPelcome. I am running this directly using CLI so IIS and Apache has no influence on how this is resolved.