https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=922719ba36e097f6d0d7ff454d95ca5f9e8104f7
commit 922719ba36e097f6d0d7ff454d95ca5f9e8104f7 Author: Jeremy Drake <cyg...@jdrake.com> Date: Tue Jun 24 11:18:42 2025 -0700 Cygwin: testsuite: test posix_file_actions_add(f)chdir Also test their interaction with addopen, as opens added subsequent to a chdir need to be relative to that new cwd. In order for the tests to compile on Linux, define O_SEARCH to O_PATH if O_SEARCH is not defined, and use the *chdir_np names instead of the now-standardized *chdir. Signed-off-by: Jeremy Drake <cyg...@jdrake.com> Diff: --- winsup/testsuite/Makefile.am | 1 + winsup/testsuite/winsup.api/posix_spawn/chdir.c | 146 ++++++++++++++++++++++++ winsup/testsuite/winsup.api/posix_spawn/fds.c | 2 +- winsup/testsuite/winsup.api/posix_spawn/test.h | 5 + 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/winsup/testsuite/Makefile.am b/winsup/testsuite/Makefile.am index 4b056bd5b..957554a82 100644 --- a/winsup/testsuite/Makefile.am +++ b/winsup/testsuite/Makefile.am @@ -311,6 +311,7 @@ check_PROGRAMS = \ winsup.api/pthread/self2 \ winsup.api/pthread/threadidafterfork \ winsup.api/pthread/tsd1 \ + winsup.api/posix_spawn/chdir \ winsup.api/posix_spawn/errors \ winsup.api/posix_spawn/fds \ winsup.api/posix_spawn/signals \ diff --git a/winsup/testsuite/winsup.api/posix_spawn/chdir.c b/winsup/testsuite/winsup.api/posix_spawn/chdir.c new file mode 100644 index 000000000..c6ccc45fb --- /dev/null +++ b/winsup/testsuite/winsup.api/posix_spawn/chdir.c @@ -0,0 +1,146 @@ +#include "test.h" +#include <fcntl.h> +#include <limits.h> +#include <spawn.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* Linux is behind the times a bit (also needs the *chdir_np functions) */ +#ifndef O_SEARCH +# define O_SEARCH O_PATH +#endif + +int handle_child (char *expected) +{ + char buf[PATH_MAX + 1]; + + nullError (getcwd (buf, sizeof (buf))); + testAssertMsg (!strcmp (buf, expected), "cwd '%s' != expected '%s'", + buf, expected); + + return 0; +} + +int handle_childfds (char *expectedcwd, char *expectedfd0, char *expectedfd1) +{ + char buf[PATH_MAX + 1]; + ssize_t ret; + + testAssert (handle_child (expectedcwd) == 0); + + negError (ret = readlink ("/dev/fd/0", buf, PATH_MAX)); + testAssertMsg (ret < PATH_MAX, "Path too long for PATH_MAX buffer"); + buf[ret] = '\0'; + testAssertMsg (!strcmp (buf, expectedfd0), "fd 0 '%s' != expected '%s'", + buf, expectedfd0); + + negError (ret = readlink ("/dev/fd/1", buf, PATH_MAX)); + testAssertMsg (ret < PATH_MAX, "Path too long for PATH_MAX buffer"); + buf[ret] = '\0'; + testAssertMsg (!strcmp (buf, expectedfd1), "fd 1 '%s' != expected '%s'", + buf, expectedfd1); + + return 0; +} + +static char tmpcwd[] = "tmpcwd.XXXXXX"; +static char tmppath[] = "tmpfile.XXXXXX"; +static char tmppath2[sizeof (tmpcwd) + 9] = {0}; + +static void cleanup_tmpfiles (void) +{ + if (tmppath2[0]) + unlink (tmppath2); + rmdir (tmpcwd); + unlink (tmppath); +} + +int main (int argc, char **argv) +{ + posix_spawn_file_actions_t fa; + pid_t pid; + int status; + int fd; + char buf[PATH_MAX + 1]; + char buffd0[PATH_MAX + 1]; + char buffd1[PATH_MAX + 1]; + char *childargv[] = {"chdir", "--child", buf, NULL, NULL, NULL}; + + /* unbuffer stdout */ + setvbuf(stdout, NULL, _IONBF, 0); + + if (argc == 3 && !strcmp (argv[1], "--child")) + return handle_child (argv[2]); + else if (argc == 5 && !strcmp (argv[1], "--child")) + return handle_childfds (argv[2], argv[3], argv[4]); + + /* make a directory and a couple of files for testing */ + nullError (mkdtemp (tmpcwd)); + atexit (cleanup_tmpfiles); + + negError (fd = mkstemp (tmppath)); + negError (close (fd)); + + stpcpy (stpcpy (stpcpy (tmppath2, tmpcwd), "/"), "tmpfile2"); + negError (fd = open (tmppath2, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)); + negError (close (fd)); + + + /* ensure cwd is inherited by default */ + nullError (getcwd (buf, sizeof (buf))); + stpcpy (stpcpy (stpcpy (buffd0, buf), "/"), tmppath); + errCode (posix_spawn (&pid, MYSELF, NULL, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + + /* test posix_spawn_file_actions_addchdir */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addchdir_np (&fa, tmpcwd)); + + strcat (buf, "/"); + strcat (buf, tmpcwd); + stpcpy (stpcpy (stpcpy (buffd1, buf), "/"), "tmpfile2"); + + 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_addfchdir */ + negError (fd = open (tmpcwd, O_SEARCH|O_DIRECTORY|O_CLOEXEC, 0755)); + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addfchdir_np (&fa, fd)); + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + negError (close (fd)); + + /* test posix_spawn_file_actions_addchdir + addopen */ + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addopen (&fa, 0, tmppath, O_RDONLY, 0644)); + errCode (posix_spawn_file_actions_addchdir_np (&fa, tmpcwd)); + errCode (posix_spawn_file_actions_addopen (&fa, 1, "tmpfile2", O_WRONLY, 0644)); + childargv[3] = buffd0; + childargv[4] = buffd1; + 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_addfchdir + addopen */ + negError (fd = open (tmpcwd, O_SEARCH|O_DIRECTORY|O_CLOEXEC, 0755)); + errCode (posix_spawn_file_actions_init (&fa)); + errCode (posix_spawn_file_actions_addopen (&fa, 0, tmppath, O_RDONLY, 0644)); + errCode (posix_spawn_file_actions_addfchdir_np (&fa, fd)); + errCode (posix_spawn_file_actions_addopen (&fa, 1, "tmpfile2", O_WRONLY, 0644)); + errCode (posix_spawn (&pid, MYSELF, &fa, NULL, childargv, environ)); + negError (waitpid (pid, &status, 0)); + exitStatus (status, 0); + errCode (posix_spawn_file_actions_destroy (&fa)); + negError (close (fd)); + + return 0; +} diff --git a/winsup/testsuite/winsup.api/posix_spawn/fds.c b/winsup/testsuite/winsup.api/posix_spawn/fds.c index 6e6e8c635..98ce36ff3 100644 --- a/winsup/testsuite/winsup.api/posix_spawn/fds.c +++ b/winsup/testsuite/winsup.api/posix_spawn/fds.c @@ -115,7 +115,7 @@ int main (int argc, char **argv) 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 */ + /* TODO: test error cases */ negError (close (fd)); negError (close (fdcloexec)); diff --git a/winsup/testsuite/winsup.api/posix_spawn/test.h b/winsup/testsuite/winsup.api/posix_spawn/test.h index 531d11c4d..5c56ed10f 100644 --- a/winsup/testsuite/winsup.api/posix_spawn/test.h +++ b/winsup/testsuite/winsup.api/posix_spawn/test.h @@ -12,6 +12,11 @@ error_at_line(1, errno, __FILE__, __LINE__, "%s", #x); \ } while (0) +#define nullError(x) do { \ + if (!(x)) \ + error_at_line(1, errno, __FILE__, __LINE__, "%s", #x); \ +} while (0) + #define sigError(x) do { \ if ((x) == SIG_ERR) \ error_at_line(1, errno, __FILE__, __LINE__, "%s", #x); \