Skip to content

directory functions doesn't support IO_REPARSE_TAG_LX_SYMLINK reparse points (Unix/WSL symlinks) #15588

Open
@llde

Description

@llde

Description

builtin (extension "standard") function is_file and is_dir doesn't work properly if the path I'm trying to use these files on contains a unix symlink (IO_REPARSE_TAG_LX_SYMLINK reparse points).

These functions, before trying to detect if the path point to a file or directory try to get the real path of the path using the function
tsrm_realpath_r inside zend_vritual_cwd.c where t traverse all path component backwards, opening all encountered paths.
If one of these paths get a FILE_ATTRIBUTE_REPARSE_POINT attribute, the function try to resolve the reparse point using FSCTL_GET_REPARSE_POINT DeviceIOControl. It breaks here as the returned type IO_REPARSE_TAG_LX_SYMLINK isn't handled, exiting the function.

This is a serious issue with "wine" as all native symlinks are treated as IO_REPARSE_TAG_LX_SYMLINK, and I confirmed that treating the resulting symlink as IO_REPARSE_TAG_SYMLINK is correcting the issue. It's however a risky change on wine side, as both symlinks can have a different implementation on filesystem, and I'm not sure if is always transparent to the application.

tsrm_realpath_r should support IO_REPARSE_TAG_LX_SYMLINK (support should be more trivial then IO_REPARSE_TAG_SYMLINK, but I'm also finding strange that these functions do traverse the path in this way. It doesn't seem to add some value at first glance, at least for paths that contains symlinks, but don't end in symlinks themselves.

I'm bound to using wine here, as I'm using an application Windows only, and it use php for various operations. But the way the application is starting php don't allow me to replace the windows version with a native linux version.

Resulted in this output (call done inside the interactive shell):

php > $path = "C:\\users\\lorenzo\\Scrivania\\Fanbox";
php > $ret =  is_dir($path);
php > var_dump($ret);
bool(false)

Scrivania is a symlink to Z:\home\lorenzo\Desktop

But I expected this output instead:

php > $path = "C:\\users\\lorenzo\\Scrivania\\Fanbox";
php > $ret =  is_dir($path);
php > var_dump($ret);
bool(true)

PHP Version

PHP 8.2.7

Operating System

ArchLinux (WINE Staging 9.15)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions