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

commit 908e644b7ddf9aeb00bfb75a5998bc40df27c0be
Author: Jeremy Drake <cyg...@jdrake.com>
Date:   Thu Jun 19 22:21:44 2025 -0700

    Cygwin: testsuite: test posix_spawn_file_actions.
    
    There are still more that could be tested, such as (f)chdir.
    
    Signed-off-by: Jeremy Drake <cyg...@jdrake.com>

Diff:
---
 winsup/testsuite/Makefile.am                  |   1 +
 winsup/testsuite/winsup.api/posix_spawn/fds.c | 124 ++++++++++++++++++++++++++
 2 files changed, 125 insertions(+)

diff --git a/winsup/testsuite/Makefile.am b/winsup/testsuite/Makefile.am
index b92532e4f..4b056bd5b 100644
--- a/winsup/testsuite/Makefile.am
+++ b/winsup/testsuite/Makefile.am
@@ -312,6 +312,7 @@ check_PROGRAMS = \
        winsup.api/pthread/threadidafterfork \
        winsup.api/pthread/tsd1 \
        winsup.api/posix_spawn/errors \
+       winsup.api/posix_spawn/fds \
        winsup.api/posix_spawn/signals \
        winsup.api/posix_spawn/spawnp \
        winsup.api/samples/sample-fail \
diff --git a/winsup/testsuite/winsup.api/posix_spawn/fds.c 
b/winsup/testsuite/winsup.api/posix_spawn/fds.c
new file mode 100644
index 000000000..6e6e8c635
--- /dev/null
+++ b/winsup/testsuite/winsup.api/posix_spawn/fds.c
@@ -0,0 +1,124 @@
+#include "test.h"
+#include <fcntl.h>
+#include <limits.h>
+#include <spawn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int handle_child (char *devfd, char *target)
+{
+  char buf[PATH_MAX];
+  ssize_t ret;
+
+  ret = readlink (devfd, buf, PATH_MAX);
+  if (ret < 0)
+    {
+      int err = errno;
+      if (err == ENOENT && !strcmp (target, "<ENOENT>"))
+       return 0;
+      error_at_line (1, err, __FILE__, __LINE__ - 6,
+                    "ret = readlink (devfd, buf, PATH_MAX)");
+    }
+  testAssertMsg (ret < PATH_MAX, "Path too long for PATH_MAX buffer");
+  buf[ret] = '\0';
+  if (strcmp (target, buf))
+      error_at_line (1, 0, __FILE__, __LINE__ - 12,
+                    "Target '%s' != expected '%s'", buf, target);
+
+  return 0;
+}
+
+int main (int argc, char **argv)
+{
+  posix_spawn_file_actions_t fa;
+  pid_t pid;
+  int status;
+  int fd, fdcloexec;
+  char buf[16];
+  char *childargv[] = {"fds", "--child", buf, "", NULL};
+
+  /* unbuffer stdout */
+  setvbuf(stdout, NULL, _IONBF, 0);
+
+  if (argc == 4 && !strcmp (argv[1], "--child"))
+    return handle_child (argv[2], argv[3]);
+
+  /* open file descriptors to test inheritance */
+  negError (fd = open ("/dev/null", O_RDONLY, 0644));
+  negError (fdcloexec = open ("/dev/full", O_RDONLY|O_CLOEXEC, 0644));
+
+  /* ensure fd is inherited by default */
+  sprintf (buf, "/dev/fd/%d", fd);
+  childargv[3] = "/dev/null";
+  errCode (posix_spawn (&pid, MYSELF, NULL, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+
+  /* ensure CLOEXEC fd is closed */
+  sprintf (buf, "/dev/fd/%d", fdcloexec);
+  childargv[3] = "<ENOENT>";
+  errCode (posix_spawn (&pid, MYSELF, NULL, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+
+  /* 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));
+  strcpy (buf, "/dev/fd/0");
+  childargv[3] = "/dev/zero";
+  errCode (posix_spawn (&pid, MYSELF, &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));
+  childargv[3] = "/dev/null";
+  errCode (posix_spawn (&pid, MYSELF, &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));
+  childargv[3] = "/dev/full";
+  errCode (posix_spawn (&pid, MYSELF, &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));
+  strcpy (buf, "/dev/fd/2");
+  childargv[3] = "/dev/zero";
+  errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_addclose */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addclose (&fa, fd));
+  sprintf (buf, "/dev/fd/%d", fd);
+  childargv[3] = "<ENOENT>";
+  errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* TODO: test new fds (open or dup2) not 0 through 2 */
+  /* TODO: test posix_spawn_file_actions_add(f)chdir */
+
+  negError (close (fd));
+  negError (close (fdcloexec));
+
+  return 0;
+}

Reply via email to