After the commit f74dc93c6359, WSL cannot start by distribution name
such as debian.exe, which has '.exe' extention but actually is a symlink.
This is because is_console_app () returns false for that symlink due
to open-failure. This patch fixes the issue using PC_SYM_FOLLOW option
in path_conv.
Fixes: f74dc93c6359 ("fix native symlink spawn passing wrong arg0")
Reviewed-by:
Signed-off-by: Takashi Yano <[email protected]>
---
winsup/cygwin/fhandler/termios.cc | 19 ++++++++++++++-----
winsup/cygwin/local_includes/fhandler.h | 2 +-
winsup/cygwin/spawn.cc | 2 +-
3 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/winsup/cygwin/fhandler/termios.cc
b/winsup/cygwin/fhandler/termios.cc
index 19d6220bc..ff6c06015 100644
--- a/winsup/cygwin/fhandler/termios.cc
+++ b/winsup/cygwin/fhandler/termios.cc
@@ -702,10 +702,19 @@ fhandler_termios::fstat (struct stat *buf)
}
static bool
-is_console_app (const WCHAR *filename)
+is_console_app (path_conv *pc)
{
+ const WCHAR *native_path = pc->get_nt_native_path ()->Buffer;
+ if (pc->issymlink ())
+ {
+ UNICODE_STRING upath;
+ RtlInitUnicodeString (&upath, native_path);
+ path_conv target (&upath, PC_SYM_FOLLOW);
+ native_path = target.get_nt_native_path ()->Buffer;
+ }
+
HANDLE h;
- h = CreateFileW (filename, GENERIC_READ, FILE_SHARE_READ,
+ h = CreateFileW (native_path, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
char buf[1024];
DWORD n;
@@ -716,7 +725,7 @@ is_console_app (const WCHAR *filename)
IMAGE_NT_HEADERS32 *p = (IMAGE_NT_HEADERS32 *) memmem (buf, n, "PE\0\0", 4);
if (p && (char *) &p->OptionalHeader.DllCharacteristics <= buf + n)
return p->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI;
- wchar_t *e = wcsrchr (filename, L'.');
+ wchar_t *e = wcsrchr (native_path, L'.');
if (e && (wcscasecmp (e, L".bat") == 0 || wcscasecmp (e, L".cmd") == 0))
return true;
return false;
@@ -755,7 +764,7 @@ fhandler_termios::ioctl (unsigned int cmd, void *varg)
void
fhandler_termios::spawn_worker::setup (bool iscygwin, HANDLE h_stdin,
- const WCHAR *runpath, bool nopcon,
+ path_conv *pc, bool nopcon,
bool reset_sendsig,
const WCHAR *envblock)
{
@@ -794,7 +803,7 @@ fhandler_termios::spawn_worker::setup (bool iscygwin,
HANDLE h_stdin,
ptys->setup_locale ();
}
}
- if (!iscygwin && ptys_primary && is_console_app (runpath))
+ if (!iscygwin && ptys_primary && is_console_app (pc))
{
if (h_stdin == ptys_primary->get_handle_nat ())
stdin_is_ptys = true;
diff --git a/winsup/cygwin/local_includes/fhandler.h
b/winsup/cygwin/local_includes/fhandler.h
index 0de82163e..d2d724fb7 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -2036,7 +2036,7 @@ class fhandler_termios: public fhandler_base
spawn_worker () :
ptys_need_cleanup (false), cons_need_cleanup (false),
stdin_is_ptys (false), ptys_ttyp (NULL) {}
- void setup (bool iscygwin, HANDLE h_stdin, const WCHAR *runpath,
+ void setup (bool iscygwin, HANDLE h_stdin, path_conv *pc,
bool nopcon, bool reset_sendsig, const WCHAR *envblock);
bool need_cleanup () { return ptys_need_cleanup || cons_need_cleanup; }
void cleanup ();
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 71add8755..9c062d58f 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -579,7 +579,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
bool no_pcon = mode != _P_OVERLAY && mode != _P_WAIT;
term_spawn_worker.setup (iscygwin (), handle (fileno_stdin, false),
- runpath, no_pcon, reset_sendsig, envblock);
+ &real_path, no_pcon, reset_sendsig, envblock);
/* Set up needed handles for stdio */
si.dwFlags = STARTF_USESTDHANDLES;
--
2.51.0