PHP realpath on Windows Case Issue

天大地大妈咪最大 提交于 2019-12-07 19:26:43

问题


I have a symlink on my Windows server which was made like this:

F:\>mkdir link-target
F:\>mklink /D link f:\link-target 

(Note the lower case f: in the symlink target)

In PHP I run this:

$dir = realpath('f:\link');
var_dump($dir);

$dir = realpath($dir);
var_dump($dir);

Which outputs:

string 'f:\link-target' (length=14)
string 'F:\link-target' (length=14)

Notice the change in case on the second realpath.

Is this a bug, or intended? And whats the best way to work around it?

It is breaking a case like this:

function check_link($to, $from) {
    if (realpath($to) !== realpath($from)) {
        ...
    }
}

Which is used to check $to exists, and is linked to $from.

  • PHP 5.4
  • Windows 7

Edit:

I need consistent behavior on both Windows and Linux, and have the following work around be its pretty nasty:

if (realpath($from) === false) {
} elseif (realpath($to) === false) {
} else {
    do {
        $to = realpath($to);
    } while (realpath($to) !== false && $to !== realpath($to));
    do {
        $from = realpath($from);
    } while (realpath($from) !== false && $from !== realpath($from));
    if ($to !== $from) {
        ...
    }
}

Edit 2:

On furter investigation I have noticed that on Windows symlinks are only followed 1 level deep:

// F:\>mkdir link-target
// F:\>mklink /D link f:\link-target 
// F:\>mklink /D link2 f:\link

$dir = realpath('f:\link2');
var_dump($dir);

$dir = realpath($dir);
var_dump($dir);

$dir = realpath($dir);
var_dump($dir);

// string 'f:\link' (length=7)
// string 'f:\link-target' (length=14)
// string 'F:\link-target' (length=14)

回答1:


Turns out

do {
    $to = realpath($to);
} while (realpath($to) !== false && $to !== realpath($to));

is the only way.

https://bugs.php.net/bug.php?id=61933




回答2:


This makes sense, if you think it through. For the first path resolution, it is finding what was defined as the link target. For the second, you end up with the same path, but one with the proper upper-case for the drive letter.

Under Windows file systems, paths/file names are case insensitive. To compare them, just convert both to upper or lower case before testing.

if (strtoupper(realpath($to)) !== strtotupper(realpath($from))) {


来源:https://stackoverflow.com/questions/10418590/php-realpath-on-windows-case-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!