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

commit 9deb0bc3b53956154d788988808bb0150385d0ba
Author: Jeremy Drake <cyg...@jdrake.com>
Date:   Wed Jun 25 22:51:05 2025 -0700

    Cygwin: testsuite: test posix_spawn of a non-Cygwin executable.
    
    Test CWD and redirection of standard handles.
    
    Signed-off-by: Jeremy Drake <cyg...@jdrake.com>

Diff:
---
 winsup/testsuite/Makefile.am                    |   1 +
 winsup/testsuite/winsup.api/posix_spawn/win32.c | 170 ++++++++++++++++++++++++
 2 files changed, 171 insertions(+)

diff --git a/winsup/testsuite/Makefile.am b/winsup/testsuite/Makefile.am
index 03f65d818..20e06b9c5 100644
--- a/winsup/testsuite/Makefile.am
+++ b/winsup/testsuite/Makefile.am
@@ -316,6 +316,7 @@ check_PROGRAMS = \
        winsup.api/posix_spawn/fds \
        winsup.api/posix_spawn/signals \
        winsup.api/posix_spawn/spawnp \
+       winsup.api/posix_spawn/win32 \
        winsup.api/samples/sample-fail \
        winsup.api/samples/sample-pass
 # winsup.api/ltp/ulimit01 is omitted as we don't have <ulimit.h>
diff --git a/winsup/testsuite/winsup.api/posix_spawn/win32.c 
b/winsup/testsuite/winsup.api/posix_spawn/win32.c
new file mode 100644
index 000000000..cd2bedcd9
--- /dev/null
+++ b/winsup/testsuite/winsup.api/posix_spawn/win32.c
@@ -0,0 +1,170 @@
+#include "test.h"
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <spawn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/cygwin.h>
+#include <unistd.h>
+
+char * find_winchild (void)
+{
+  static const char winchild[] = "/winchild";
+  char *mingwtestdir = getenv ("mingwtestdir");
+  if (!mingwtestdir)
+    {
+      Dl_info dli;
+      if (dladdr (&find_winchild, &dli))
+        {
+         ssize_t i = strlen (dli.dli_fname) - 1;
+         for (int slashes = 0; i >= 0 && slashes < 3; --i)
+           if (dli.dli_fname[i] == '/')
+             slashes++;
+         stpcpy (stpcpy (dli.dli_fname + i + 1, "/mingw"), winchild);
+         return realpath (dli.dli_fname, NULL);
+       }
+      else
+        {
+         return realpath ("../../mingw/winchild", NULL);
+       }
+    }
+  else
+    {
+      char *ret, *tmp = malloc (strlen (mingwtestdir) + sizeof (winchild));
+      stpcpy (stpcpy (tmp, mingwtestdir), winchild);
+      ret = realpath (tmp, NULL);
+      free (tmp);
+      return ret;
+    }
+}
+
+static char tmppath[] = "pspawn.XXXXXX";
+static char tmpcwd[] = "tmpcwd.XXXXXX";
+static char tmppath2[sizeof (tmpcwd) + 9] = {0};
+
+static void cleanup_tmpfiles (void)
+{
+  if (tmppath2[0])
+    unlink (tmppath2);
+  rmdir (tmpcwd);
+  unlink (tmppath);
+}
+
+int main (void)
+{
+  posix_spawn_file_actions_t fa;
+  pid_t pid;
+  int status;
+  int fd, fdcloexec, cwdfd;
+  char *childargv[] = {"winchild", NULL, NULL, NULL};
+  char *winchild = find_winchild ();
+
+  /* unbuffer stdout */
+  setvbuf(stdout, NULL, _IONBF, 0);
+
+  /* temp regular file */
+  negError (fd = mkstemp (tmppath));
+  atexit (cleanup_tmpfiles);
+  negError (close (fd));
+
+  /* temp directory */
+  nullError (mkdtemp (tmpcwd));
+
+  /* temp file within temp directory */
+  stpcpy (stpcpy (stpcpy (tmppath2, tmpcwd), "/"), "tmpfile2");
+  negError (fd = open (tmppath2, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR));
+  negError (close (fd));
+
+  /* open file descriptors to test inheritance */
+  negError (fd = open ("/dev/null", O_RDONLY, 0644));
+  negError (fdcloexec = open ("/dev/full", O_RDONLY|O_CLOEXEC, 0644));
+
+  /* test posix_spawn_file_actions_addopen */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addopen (&fa, 0, "/dev/zero", O_RDONLY,
+                                            0644));
+  childargv[1] = "0";
+  childargv[2] = "\\Device\\Null";
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_adddup2 */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_adddup2 (&fa, fd, 0));
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_adddup2 with CLOEXEC fd */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_adddup2 (&fa, fdcloexec, 0));
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_adddup2 with out to err */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addopen (&fa, 1, "/dev/zero", O_WRONLY,
+                                            0644));
+  errCode (posix_spawn_file_actions_adddup2 (&fa, 1, 2));
+  childargv[1] = "2";
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_addopen with real file */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addopen (&fa, 1, tmppath, O_WRONLY, 0644));
+  childargv[1] = "1";
+  childargv[2] = cygwin_create_path (CCP_POSIX_TO_WIN_A|CCP_ABSOLUTE, tmppath);
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+  free (childargv[2]);
+
+  /* test posix_spawn_file_actions_addchdir */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addchdir (&fa, tmpcwd));
+  childargv[1] = "CWD";
+  childargv[2] = cygwin_create_path (CCP_POSIX_TO_WIN_A|CCP_ABSOLUTE, tmpcwd);
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_addfchdir */
+  negError (cwdfd = open (tmpcwd, O_SEARCH|O_DIRECTORY|O_CLOEXEC, 0755));
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addfchdir (&fa, cwdfd));
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+  free (childargv[2]);
+
+  /* test posix_spawn_file_actions_addfchdir followed by addopen */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addfchdir (&fa, cwdfd));
+  errCode (posix_spawn_file_actions_addopen (&fa, 1, "tmpfile2", O_WRONLY, 
0644));
+  childargv[1] = "1";
+  childargv[2] = cygwin_create_path (CCP_POSIX_TO_WIN_A|CCP_ABSOLUTE, 
tmppath2);
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+  free (childargv[2]);
+
+  negError (close (cwdfd));
+  negError (close (fd));
+  negError (close (fdcloexec));
+
+  return 0;
+}

Reply via email to