https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=2af1914b6ad673a2041cf94cc8e78e1bdec57a27

commit 2af1914b6ad673a2041cf94cc8e78e1bdec57a27
Author: Jeremy Drake <cyg...@jdrake.com>
Date:   Wed Jun 25 16:42:08 2025 -0700

    Cygwin: testsuite: add a mingw test program to spawn
    
    This program is currently meant to test standard file handles and
    current working directory (since these are settable via posix_spawn),
    but could be extended to add additional checks if other cygwin-to-win32
    process properties need to be tested.
    
    Signed-off-by: Jeremy Drake <cyg...@jdrake.com>

Diff:
---
 winsup/testsuite/Makefile.am                       |   2 +-
 winsup/testsuite/cygrun.sh                         |   4 +-
 winsup/testsuite/mingw/Makefile.am                 |   7 +-
 winsup/testsuite/winsup.api/posix_spawn/winchild.c | 130 +++++++++++++++++++++
 4 files changed, 139 insertions(+), 4 deletions(-)

diff --git a/winsup/testsuite/Makefile.am b/winsup/testsuite/Makefile.am
index 957554a82..03f65d818 100644
--- a/winsup/testsuite/Makefile.am
+++ b/winsup/testsuite/Makefile.am
@@ -349,7 +349,7 @@ XFAIL_TESTS = \
 LOG_COMPILER = $(srcdir)/cygrun.sh
 
 export runtime_root=$(abs_builddir)/testinst/bin
-export cygrun=$(builddir)/mingw/cygrun
+export mingwtestdir=$(builddir)/mingw
 
 # Set up things in the Cygwin 'installation' at testsuite/testinst/ to provide
 # things which tests need to work
diff --git a/winsup/testsuite/cygrun.sh b/winsup/testsuite/cygrun.sh
index bf1d5cc6b..f1673e4db 100755
--- a/winsup/testsuite/cygrun.sh
+++ b/winsup/testsuite/cygrun.sh
@@ -11,7 +11,7 @@ export PATH="$runtime_root:${PATH}"
 if [ "$1" = "./mingw/cygload" ]
 then
     windows_runtime_root=$(cygpath -m $runtime_root)
-    $cygrun "$exe -v -cygwin $windows_runtime_root/cygwin1.dll"
+    $mingwtestdir/cygrun "$exe -v -cygwin $windows_runtime_root/cygwin1.dll"
 else
-    cygdrop $cygrun $exe
+    cygdrop $mingwtestdir/cygrun $exe
 fi
diff --git a/winsup/testsuite/mingw/Makefile.am 
b/winsup/testsuite/mingw/Makefile.am
index 772e73405..25300a15d 100644
--- a/winsup/testsuite/mingw/Makefile.am
+++ b/winsup/testsuite/mingw/Makefile.am
@@ -16,7 +16,7 @@ override CC = @MINGW_CC@
 override CXX = @MINGW_CXX@
 AM_CPPFLAGS =
 
-noinst_PROGRAMS = cygrun cygload
+noinst_PROGRAMS = cygrun cygload winchild
 
 cygrun_SOURCES = \
        ../cygrun.c
@@ -24,3 +24,8 @@ cygrun_SOURCES = \
 cygload_SOURCES = \
        ../winsup.api/cygload.cc
 cygload_LDFLAGS=-static -Wl,-e,cygloadCRTStartup
+
+winchild_SOURCES = \
+       ../winsup.api/posix_spawn/winchild.c
+winchild_LDFLAGS=-municode
+winchild_LDADD=-lntdll
diff --git a/winsup/testsuite/winsup.api/posix_spawn/winchild.c 
b/winsup/testsuite/winsup.api/posix_spawn/winchild.c
new file mode 100644
index 000000000..6fdfa002c
--- /dev/null
+++ b/winsup/testsuite/winsup.api/posix_spawn/winchild.c
@@ -0,0 +1,130 @@
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winternl.h>
+#include <ctype.h>
+#include <stdio.h>
+
+
+int wmain (int argc, wchar_t **argv)
+{
+  if (argc != 3)
+    {
+      fwprintf (stderr, L"Usage: %ls handle expected\n", argv[0]);
+      return 1;
+    }
+
+  if (!wcscmp (argv[1], L"CWD"))
+    {
+      LPWSTR buffer;
+      DWORD len = GetCurrentDirectoryW (0, NULL);
+      if (len == 0)
+        {
+         fwprintf (stderr, L"%ls: GetCurrentDirectory failed with error %lu\n",
+                   argv[0], GetLastError ());
+         return 2;
+       }
+      buffer = malloc (len * sizeof (WCHAR));
+      if (GetCurrentDirectoryW (len, buffer) != len - 1)
+        {
+         fwprintf (stderr, L"%ls: GetCurrentDirectory failed with error %lu\n",
+                   argv[0], GetLastError ());
+         return 2;
+       }
+      if (wcscmp (argv[2], buffer))
+        {
+         fwprintf (stderr, L"%ls: CWD '%ls' != expected '%ls'\n",
+                   argv[0], buffer, argv[2]);
+         free (buffer);
+         return 4;
+       }
+      free (buffer);
+    }
+  else if (iswdigit (argv[1][0]) && !argv[1][1])
+    {
+      HANDLE stdhandle;
+      DWORD nStdHandle;
+      switch (argv[1][0])
+      {
+       case L'0':
+         nStdHandle = STD_INPUT_HANDLE;
+         break;
+       case L'1':
+         nStdHandle = STD_OUTPUT_HANDLE;
+         break;
+       case L'2':
+         nStdHandle = STD_ERROR_HANDLE;
+         break;
+       default:
+         fwprintf (stderr, L"%ls: Unknown handle '%ls'\n", argv[0], argv[1]);
+         return 1;
+      }
+
+      stdhandle = GetStdHandle (nStdHandle);
+      if (stdhandle == INVALID_HANDLE_VALUE)
+        {
+         fwprintf (stderr, L"%ls: Failed getting standard handle %ls: %lu\n",
+             argv[0], argv[1], GetLastError ());
+         return 2;
+       }
+      else if (stdhandle == NULL)
+       {
+         if (wcscmp (argv[2], L"<CLOSED>"))
+           {
+             fwprintf (stderr,
+                       L"%ls: Handle %ls name '%ls' != expected '%ls'\n",
+                       argv[0], argv[1], L"<CLOSED>", argv[2]);
+             return 4;
+           }
+       }
+      else
+        {
+         LPWSTR buf, win32path;
+         buf = malloc (65536);
+         if (!GetFinalPathNameByHandleW (stdhandle, buf,
+                                         65536 / sizeof (WCHAR),
+                                         FILE_NAME_OPENED|VOLUME_NAME_DOS))
+           {
+             POBJECT_NAME_INFORMATION pinfo = (POBJECT_NAME_INFORMATION) buf;
+             DWORD err = GetLastError ();
+             ULONG len;
+             NTSTATUS status = NtQueryObject (stdhandle, ObjectNameInformation,
+                                              pinfo, 65536, &len);
+             if (!NT_SUCCESS (status))
+               {
+                 fwprintf (stderr,
+                     L"%ls: NtQueryObject for handle %ls failed: 0x%08x\n",
+                     argv[0], argv[1], status);
+                 free (buf);
+                 return 3;
+               }
+
+             pinfo->Name.Buffer[pinfo->Name.Length / sizeof (WCHAR)] = L'\0';
+             win32path = pinfo->Name.Buffer;
+           }
+         else
+           {
+             static const WCHAR prefix[] = L"\\\\?\\";
+             win32path = buf;
+             if (!wcsncmp (win32path, prefix,
+                           sizeof (prefix) / sizeof (WCHAR) - 1))
+               win32path += sizeof (prefix) / sizeof (WCHAR) - 1;
+           }
+
+         if (wcscmp (win32path, argv[2]))
+           {
+             fwprintf (stderr,
+                       L"%ls: Handle %ls name '%ls' != expected '%ls'\n",
+                       argv[0], argv[1], win32path, argv[2]);
+             free (buf);
+             return 4;
+           }
+         free (buf);
+       }
+    }
+  else
+    {
+      fwprintf (stderr, L"%ls: Unknown handle '%ls'\n", argv[0], argv[1]);
+      return 1;
+    }
+  return 0;
+}

Reply via email to