[newlib-cygwin] Cygwin: testsuite: test posix_spawn_file_actions.

Jeremy Drake via Cygwin-cvs <[email protected]>
Newsgroups gmane.os.cygwin.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=908e644b7ddf9aeb00bfb75a5998bc40df27c0be

commit 908e644b7ddf9aeb00bfb75a5998bc40df27c0be
Author: Jeremy Drake <[email protected]>
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 <[email protected]>

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;
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.