{
if (component == 0
&& (!(opt & PC_SYM_FOLLOW)
- || (is_known_reparse_point ()
+ || (is_winapi_reparse_point ()
&& (opt & PC_SYM_NOFOLLOW_REP))))
{
/* Usually a trailing slash requires to follow a symlink,
}
RtlInitCountedUnicodeString (psymbuf, utf16_buf,
utf16_bufsize * sizeof (WCHAR));
- return PATH_SYMLINK | PATH_REP;
+ return PATH_SYMLINK | PATH_REP | PATH_REP_NOAPI;
}
return -EIO;
}
if (memcmp (CYGWIN_SOCKET_GUID, &rgp->ReparseGuid, sizeof (GUID)) == 0)
#ifdef __WITH_AF_UNIX
- return PATH_SOCKET | PATH_REP;
+ return PATH_SOCKET | PATH_REP | PATH_REP_NOAPI;
#else
/* Recognize this as a reparse point but not as a socket. */
- return PATH_REP;
+ return PATH_REP | PATH_REP_NOAPI;
#endif
}
return 0;
PATH_SYMLINK = _BIT ( 4), /* symlink understood by Cygwin */
PATH_SOCKET = _BIT ( 5), /* AF_UNIX socket file */
PATH_RESOLVE_PROCFD = _BIT ( 6), /* fd symlink via /proc */
+ PATH_REP_NOAPI = _BIT ( 7), /* rep. point unknown to WinAPI */
PATH_DONT_USE = _BIT (31) /* conversion to signed happens. */
};
}
int issymlink () const {return path_flags & PATH_SYMLINK;}
int is_lnk_symlink () const {return path_flags & PATH_LNK;}
+ /* This indicates any known reparse point */
int is_known_reparse_point () const {return path_flags & PATH_REP;}
+ /* This indicates any known reparse point, handled sanely by WinAPI.
+ The difference is crucial: WSL symlinks, for instance, are known
+ reparse points, so we want to open them as reparse points usually.
+ However they are foreign to WinAPI and not handled sanely. If one
+ is part of $PATH, WinAPI functions may fail under the hood with
+ STATUS_IO_REPARSE_TAG_NOT_HANDLED. */
+ int is_winapi_reparse_point () const
+ {
+ return (path_flags & (PATH_REP | PATH_REP_NOAPI)) == PATH_REP;
+ }
int isdevice () const {return dev.not_device (FH_FS) && dev.not_device (FH_FIFO);}
int isfifo () const {return dev.is_device (FH_FIFO);}
int isspecial () const {return dev.not_device (FH_FS);}