Module Name:    src
Committed By:   christos
Date:           Sun Nov  7 15:46:20 UTC 2021

Modified Files:
        src/tests/lib/libc/gen/posix_spawn: Makefile h_fileactions.c h_spawn.c
            h_spawnattr.c t_fileactions.c t_spawn.c t_spawnattr.c
Added Files:
        src/tests/lib/libc/gen/posix_spawn: fa_spawn_utils.c fa_spawn_utils.h

Log Message:
new tests for posix_spawn_chdir from Piyush Sachdeva


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/tests/lib/libc/gen/posix_spawn/Makefile \
    src/tests/lib/libc/gen/posix_spawn/h_spawn.c \
    src/tests/lib/libc/gen/posix_spawn/h_spawnattr.c
cvs rdiff -u -r0 -r1.1 src/tests/lib/libc/gen/posix_spawn/fa_spawn_utils.c \
    src/tests/lib/libc/gen/posix_spawn/fa_spawn_utils.h
cvs rdiff -u -r1.1 -r1.2 src/tests/lib/libc/gen/posix_spawn/h_fileactions.c
cvs rdiff -u -r1.6 -r1.7 src/tests/lib/libc/gen/posix_spawn/t_fileactions.c
cvs rdiff -u -r1.3 -r1.4 src/tests/lib/libc/gen/posix_spawn/t_spawn.c
cvs rdiff -u -r1.4 -r1.5 src/tests/lib/libc/gen/posix_spawn/t_spawnattr.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/tests/lib/libc/gen/posix_spawn/Makefile
diff -u src/tests/lib/libc/gen/posix_spawn/Makefile:1.2 src/tests/lib/libc/gen/posix_spawn/Makefile:1.3
--- src/tests/lib/libc/gen/posix_spawn/Makefile:1.2	Mon Feb 13 19:13:54 2012
+++ src/tests/lib/libc/gen/posix_spawn/Makefile	Sun Nov  7 10:46:20 2021
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.2 2012/02/14 00:13:54 martin Exp $
+# $NetBSD: Makefile,v 1.3 2021/11/07 15:46:20 christos Exp $
 
 NOMAN=		# defined
 WARNS=4
@@ -11,6 +11,9 @@ TESTS_C=	t_spawn
 TESTS_C+=	t_fileactions
 TESTS_C+=	t_spawnattr
 
+SRCS.t_spawn += t_spawn fa_spawn_utils
+SRCS.t_fileactions += t_fileactions fa_spawn_utils
+
 BINDIR=		${TESTSDIR}
 SCRIPTSDIR=	${TESTSDIR}
 
Index: src/tests/lib/libc/gen/posix_spawn/h_spawn.c
diff -u src/tests/lib/libc/gen/posix_spawn/h_spawn.c:1.2 src/tests/lib/libc/gen/posix_spawn/h_spawn.c:1.3
--- src/tests/lib/libc/gen/posix_spawn/h_spawn.c:1.2	Sun May  2 07:18:11 2021
+++ src/tests/lib/libc/gen/posix_spawn/h_spawn.c	Sun Nov  7 10:46:20 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: h_spawn.c,v 1.2 2021/05/02 11:18:11 martin Exp $ */
+/* $NetBSD: h_spawn.c,v 1.3 2021/11/07 15:46:20 christos Exp $ */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -29,6 +29,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: h_spawn.c,v 1.3 2021/11/07 15:46:20 christos Exp $");
 
 #include <stdio.h>
 #include <stdlib.h>
Index: src/tests/lib/libc/gen/posix_spawn/h_spawnattr.c
diff -u src/tests/lib/libc/gen/posix_spawn/h_spawnattr.c:1.2 src/tests/lib/libc/gen/posix_spawn/h_spawnattr.c:1.3
--- src/tests/lib/libc/gen/posix_spawn/h_spawnattr.c:1.2	Sat Aug 21 19:00:32 2021
+++ src/tests/lib/libc/gen/posix_spawn/h_spawnattr.c	Sun Nov  7 10:46:20 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: h_spawnattr.c,v 1.2 2021/08/21 23:00:32 andvar Exp $ */
+/* $NetBSD: h_spawnattr.c,v 1.3 2021/11/07 15:46:20 christos Exp $ */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -29,6 +29,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: h_spawnattr.c,v 1.3 2021/11/07 15:46:20 christos Exp $");
 
 #include <errno.h>
 #include <stdio.h>

Index: src/tests/lib/libc/gen/posix_spawn/h_fileactions.c
diff -u src/tests/lib/libc/gen/posix_spawn/h_fileactions.c:1.1 src/tests/lib/libc/gen/posix_spawn/h_fileactions.c:1.2
--- src/tests/lib/libc/gen/posix_spawn/h_fileactions.c:1.1	Mon Feb 13 16:03:08 2012
+++ src/tests/lib/libc/gen/posix_spawn/h_fileactions.c	Sun Nov  7 10:46:20 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: h_fileactions.c,v 1.1 2012/02/13 21:03:08 martin Exp $ */
+/* $NetBSD: h_fileactions.c,v 1.2 2021/11/07 15:46:20 christos Exp $ */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -29,6 +29,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: h_fileactions.c,v 1.2 2021/11/07 15:46:20 christos Exp $");
 
 #include <stdio.h>
 #include <stdlib.h>

Index: src/tests/lib/libc/gen/posix_spawn/t_fileactions.c
diff -u src/tests/lib/libc/gen/posix_spawn/t_fileactions.c:1.6 src/tests/lib/libc/gen/posix_spawn/t_fileactions.c:1.7
--- src/tests/lib/libc/gen/posix_spawn/t_fileactions.c:1.6	Tue Jan 10 17:36:29 2017
+++ src/tests/lib/libc/gen/posix_spawn/t_fileactions.c	Sun Nov  7 10:46:20 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: t_fileactions.c,v 1.6 2017/01/10 22:36:29 christos Exp $ */
+/* $NetBSD: t_fileactions.c,v 1.7 2021/11/07 15:46:20 christos Exp $ */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -29,6 +29,8 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_fileactions.c,v 1.7 2021/11/07 15:46:20 christos Exp $");
 
 
 #include <atf-c.h>
@@ -44,6 +46,8 @@
 #include <spawn.h>
 #include <unistd.h>
 
+#include "fa_spawn_utils.h"
+
 
 ATF_TC(t_spawn_openmode);
 
@@ -54,17 +58,6 @@ ATF_TC_HEAD(t_spawn_openmode, tc)
 	atf_tc_set_md_var(tc, "require.progs", "/bin/cat");
 }
 
-static off_t
-filesize(const char * restrict fname)
-{
-	struct stat st;
-	int err;
-
-	err = stat(fname, &st);
-	ATF_REQUIRE(err == 0);
-	return st.st_size;
-}
-
 #define TESTFILE	"./the_input_data"
 #define CHECKFILE	"./the_output_data"
 #define TESTCONTENT	"marry has a little lamb"
@@ -82,16 +75,6 @@ make_testfile(const char *restrict file)
 	ATF_REQUIRE(written == strlen(TESTCONTENT));
 }
 
-static void
-empty_outfile(const char *restrict filename)
-{
-	FILE *f;
-
-	f = fopen(filename, "w");
-	ATF_REQUIRE(f != NULL);
-	fclose(f);
-}
-
 ATF_TC_BODY(t_spawn_openmode, tc)
 {
 	int status, err;

Index: src/tests/lib/libc/gen/posix_spawn/t_spawn.c
diff -u src/tests/lib/libc/gen/posix_spawn/t_spawn.c:1.3 src/tests/lib/libc/gen/posix_spawn/t_spawn.c:1.4
--- src/tests/lib/libc/gen/posix_spawn/t_spawn.c:1.3	Fri Sep  3 18:33:18 2021
+++ src/tests/lib/libc/gen/posix_spawn/t_spawn.c	Sun Nov  7 10:46:20 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: t_spawn.c,v 1.3 2021/09/03 22:33:18 andvar Exp $ */
+/* $NetBSD: t_spawn.c,v 1.4 2021/11/07 15:46:20 christos Exp $ */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -29,15 +29,29 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
-
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_spawn.c,v 1.4 2021/11/07 15:46:20 christos Exp $");
 
 #include <atf-c.h>
+
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+
 #include <spawn.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
-#include <sys/wait.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "fa_spawn_utils.h"
+
+
+static void check_success(const char *, int, ...);
 
 ATF_TC(t_spawn_ls);
 
@@ -97,7 +111,7 @@ ATF_TC(t_spawn_missing);
 ATF_TC_HEAD(t_spawn_missing, tc)
 {
 	atf_tc_set_md_var(tc, "descr",
-	    "posix_spawn a non-existent binary");
+	    "posix_spawn a non existant binary");
 }
 
 ATF_TC_BODY(t_spawn_missing, tc)
@@ -117,7 +131,7 @@ ATF_TC(t_spawn_nonexec);
 ATF_TC_HEAD(t_spawn_nonexec, tc)
 {
 	atf_tc_set_md_var(tc, "descr",
-	    "posix_spawn a script with non-existent interpreter");
+	    "posix_spawn a script with non existing interpreter");
 }
 
 ATF_TC_BODY(t_spawn_nonexec, tc)
@@ -171,6 +185,493 @@ ATF_TC_BODY(t_spawn_child, tc)
 	ATF_REQUIRE(WIFEXITED(status) && WEXITSTATUS(status) == 7);
 }
 
+#define CHDIRPATH "/tmp"
+#define FILENAME "output"
+#define FILEPATH "/tmp/output"
+
+static void
+check_success(const char *file, int argc, ...)
+{
+	va_list ap;
+	int bytesRead, fd;
+	size_t sizeOfFile = (size_t)filesize(file);
+	size_t sizeOfStr;
+	char *contents;
+	const char *dir;
+
+	contents = malloc(sizeOfFile);
+	ATF_REQUIRE(contents != NULL);
+
+	/*
+	 * for now only 1 variadic argument expected
+	 * only from t_spawn_chdir_rel
+	 */
+	if (argc != 0) {
+		va_start(ap, argc);
+		dir = va_arg(ap, char *);
+		ATF_REQUIRE(dir != NULL);
+		va_end(ap);
+	} else
+		dir = CHDIRPATH;
+
+	fd = open(file, O_RDONLY);
+	ATF_REQUIRE_MSG(fd != -1, "Can't open `%s' (%s)", file, strerror(errno));
+
+	/*
+	 * file contains form feed i.e ASCII - 10 at the end.
+	 * Therefore sizeOfFile - 1
+	 */
+	sizeOfStr = strlen(dir);
+	ATF_CHECK_MSG(sizeOfStr == sizeOfFile - 1, "%zu (%s) != %zu (%s)", 
+	    sizeOfStr, dir, sizeOfFile - 1, file);
+
+	bytesRead = read(fd, contents, sizeOfFile - 1);
+	contents[sizeOfFile - 1] = '\0';
+	ATF_REQUIRE_MSG(strcmp(dir, contents) == 0,
+	    "[%s] != [%s] Directories dont match", dir, contents);
+
+	fd = close(fd);
+	ATF_REQUIRE(fd == 0);
+
+	unlink(file);
+	free(contents);
+
+	/* XXX not really required */
+	ATF_REQUIRE(bytesRead = sizeOfStr);
+}
+
+ATF_TC(t_spawn_chdir_abs);
+
+ATF_TC_HEAD(t_spawn_chdir_abs, tc)
+{
+	atf_tc_set_md_var(tc, "descr",
+	    "Test posix_spawn_fa_addchdir for absolute path");
+	atf_tc_set_md_var(tc, "require.progs", "/bin/pwd");
+}
+
+ATF_TC_BODY(t_spawn_chdir_abs, tc)
+{
+	char * const args[2] = { __UNCONST("pwd"), NULL };
+	int error, status;
+	pid_t pid;
+	posix_spawn_file_actions_t fa;
+
+	empty_outfile(FILEPATH);
+
+	error = posix_spawn_file_actions_init(&fa);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addchdir(&fa, CHDIRPATH);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addopen(&fa, STDOUT_FILENO, FILENAME,
+			O_WRONLY, 0);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn(&pid, "/bin/pwd", &fa, NULL, args, NULL);
+	ATF_REQUIRE(error == 0);
+
+	/* wait for the child to finish */
+	waitpid(pid, &status, 0);
+	ATF_REQUIRE_MSG(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS,
+	    "%s", "chdir failed");
+	posix_spawn_file_actions_destroy(&fa);
+
+	/* finally cross check the output of "pwd" directory */
+	check_success(FILEPATH, 0);
+}
+
+ATF_TC(t_spawn_chdir_rel);
+
+ATF_TC_HEAD(t_spawn_chdir_rel, tc)
+{
+	atf_tc_set_md_var(tc, "descr",
+	    "Test posix_spawn_fa_addchdir for relative path");
+	atf_tc_set_md_var(tc, "require.progs", "/bin/pwd");
+}
+
+
+ATF_TC_BODY(t_spawn_chdir_rel, tc)
+{
+	const char *relative_dir = "ch-dir";
+	const char *testdir = getcwd(NULL, 0);
+	char * const args[2] = { __UNCONST("pwd"), NULL };
+	char *chdirwd, *filepath;
+	int error, status;
+	pid_t pid;
+	posix_spawn_file_actions_t fa;
+
+	/* cleanup previous */
+	error = asprintf(&filepath, "%s/%s", relative_dir, FILENAME);
+	ATF_CHECK(error != -1);
+	unlink(filepath);
+	free(filepath);
+	rmdir(relative_dir);
+
+	error = mkdir(relative_dir, 0777);
+	ATF_REQUIRE_MSG(error == 0, "mkdir `%s' (%s)", relative_dir,
+	    strerror(errno));
+
+	error = asprintf(&chdirwd, "%s/%s", testdir, relative_dir);
+	ATF_CHECK(error != -1);
+
+	error = asprintf(&filepath, "%s/%s", chdirwd, FILENAME);
+	ATF_CHECK(error != -1);
+
+#ifdef DEBUG
+	printf("cwd: %s\n", testdir);
+	printf("chdirwd: %s\n", chdirwd);
+	printf("filepath: %s\n", filepath);
+#endif
+
+	empty_outfile(filepath);
+
+	error = posix_spawn_file_actions_init(&fa);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addchdir(&fa, relative_dir);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addopen(&fa, STDOUT_FILENO, FILENAME,
+			O_WRONLY, 0);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn(&pid, "/bin/pwd", &fa, NULL, args, NULL);
+	ATF_REQUIRE(error == 0);
+
+	/* wait for the child to finish */
+	waitpid(pid, &status, 0);
+	ATF_REQUIRE_MSG(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS,
+	    "%s", "chdir failed");
+	posix_spawn_file_actions_destroy(&fa);
+
+	/* finally cross check the directory */
+	check_success(filepath, 1, chdirwd);
+	free(chdirwd);
+	free(filepath);
+
+	rmdir(relative_dir);
+}
+
+ATF_TC(t_spawn_chdir_file);
+
+ATF_TC_HEAD(t_spawn_chdir_file, tc)
+{
+	atf_tc_set_md_var(tc, "descr",
+	    "Test posix_spawn_fa_addchdir on plain file (not a directory)");
+	atf_tc_set_md_var(tc, "require.progs", "/bin/pwd");
+}
+
+ATF_TC_BODY(t_spawn_chdir_file, tc)
+{
+	int error;
+	pid_t pid;
+	char * const args[2] = { __UNCONST("pwd"), NULL };
+	posix_spawnattr_t attr;
+	posix_spawn_file_actions_t fa;
+
+	empty_outfile(FILEPATH);
+
+	error = posix_spawnattr_init(&attr);
+	ATF_REQUIRE(error == 0);
+	/*
+	 * POSIX_SPAWN_RETURNERROR is a NetBSD specific flag that
+	 * will cause a "proper" return value from posix_spawn(2)
+	 * instead of a (potential) success there and a 127 exit
+	 * status from the child process (c.f. the non-diag variant
+	 * of this test).
+	 */
+	error = posix_spawnattr_setflags(&attr, POSIX_SPAWN_RETURNERROR);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_init(&fa);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addchdir(&fa, FILEPATH);
+	ATF_REQUIRE(error == 0);
+	
+	error = posix_spawn(&pid, "/bin/pwd", &fa, &attr, args, NULL);
+	ATF_REQUIRE(error == ENOTDIR);
+
+	posix_spawn_file_actions_destroy(&fa);
+	posix_spawnattr_destroy(&attr);
+
+	unlink(FILEPATH);
+}
+
+ATF_TC(t_spawn_chdir_invalid);
+
+ATF_TC_HEAD(t_spawn_chdir_invalid, tc)
+{
+	atf_tc_set_md_var(tc, "descr",
+	    "Test posix_spawn_fa_addchdir for an invalid dir");
+	atf_tc_set_md_var(tc, "require.progs", "/bin/pwd");
+}
+
+ATF_TC_BODY(t_spawn_chdir_invalid, tc)
+{
+	int error;
+	pid_t pid;
+	const char *dirpath = "/not/a/valid/dir";
+	char * const args[2] = { __UNCONST("pwd"), NULL };
+	posix_spawnattr_t attr;
+	posix_spawn_file_actions_t fa;
+
+	error = posix_spawnattr_init(&attr);
+	ATF_REQUIRE(error == 0);
+	/*
+	 * POSIX_SPAWN_RETURNERROR is a NetBSD specific flag that
+	 * will cause a "proper" return value from posix_spawn(2)
+	 * instead of a (potential) success there and a 127 exit
+	 * status from the child process (c.f. the non-diag variant
+	 * of this test).
+	 */
+	error = posix_spawnattr_setflags(&attr, POSIX_SPAWN_RETURNERROR);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_init(&fa);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addchdir(&fa, dirpath);
+	ATF_REQUIRE(error == 0);
+	
+	error = posix_spawn(&pid, "/bin/pwd", &fa, &attr, args, NULL);
+	ATF_REQUIRE(error == ENOENT);
+
+	posix_spawn_file_actions_destroy(&fa);
+	posix_spawnattr_destroy(&attr);
+}
+
+ATF_TC(t_spawn_chdir_permissions);
+
+ATF_TC_HEAD(t_spawn_chdir_permissions, tc)
+{
+	atf_tc_set_md_var(tc, "descr",
+	    "Test posix_spawn_file_actions_addchdir for prohibited directory");
+	atf_tc_set_md_var(tc, "require.progs", "/bin/pwd");
+	atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(t_spawn_chdir_permissions, tc)
+{
+	int error;
+	pid_t pid;
+	const char *restrRelDir = "prohibited";
+	char * const args[2] = { __UNCONST("pwd"), NULL };
+	posix_spawnattr_t attr;
+	posix_spawn_file_actions_t fa;
+
+	error = mkdir(restrRelDir, 0055);
+	ATF_REQUIRE(error == 0);
+
+	posix_spawnattr_init(&attr);
+	ATF_REQUIRE(error == 0);
+	/*
+	 * POSIX_SPAWN_RETURNERROR is a NetBSD specific flag that
+	 * will cause a "proper" return value from posix_spawn(2)
+	 * instead of a (potential) success there and a 127 exit
+	 * status from the child process (c.f. the non-diag variant
+	 * of this test).
+	 */
+	error = posix_spawnattr_setflags(&attr, POSIX_SPAWN_RETURNERROR);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_init(&fa);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addchdir(&fa, restrRelDir);
+	ATF_REQUIRE(error == 0);
+	
+	error = posix_spawn(&pid, "/bin/pwd", &fa, &attr, args, NULL);
+	ATF_CHECK(error == EACCES);
+
+	posix_spawn_file_actions_destroy(&fa);
+	posix_spawnattr_destroy(&attr);
+
+	rmdir(restrRelDir);
+}
+
+	
+ATF_TC(t_spawn_fchdir);
+
+ATF_TC_HEAD(t_spawn_fchdir, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "Test posix_spawn_fa_fchdir");
+	atf_tc_set_md_var(tc, "require.progs", "/bin/pwd");
+}
+
+ATF_TC_BODY(t_spawn_fchdir, tc)
+{
+	int error, fd, status;
+	pid_t pid;
+	char * const args[2] = { __UNCONST("pwd"), NULL };
+	posix_spawn_file_actions_t fa;
+
+	empty_outfile(FILEPATH);
+
+	fd = open(CHDIRPATH, O_RDONLY);
+	ATF_REQUIRE(fd >= 0);
+
+	error = posix_spawn_file_actions_init(&fa);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addfchdir(&fa, fd);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addopen(&fa, STDOUT_FILENO, FILENAME,
+	    O_WRONLY, 0);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn(&pid, "/bin/pwd", &fa, NULL, args, NULL);
+	ATF_REQUIRE(error == 0);
+
+	/* wait for the child to finish */
+	waitpid(pid, &status, 0);
+	ATF_REQUIRE_MSG(WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS,
+	    "%s", "chdir failed");
+	posix_spawn_file_actions_destroy(&fa);
+
+	/* The file should be closed before reopening in 'check_success' */
+	error = close(fd);
+	ATF_REQUIRE(error == 0);
+
+	/* finally cross check the directory */
+	check_success(FILEPATH, 0);
+}
+
+ATF_TC(t_spawn_fchdir_neg_fd);
+
+ATF_TC_HEAD(t_spawn_fchdir_neg_fd, tc)
+{
+	atf_tc_set_md_var(tc, "descr",
+	    "Testing posix_spawn_file_actions_addfchdir on a negative file "
+	    "descriptor");
+	atf_tc_set_md_var(tc, "require.progs", "/bin/pwd");
+}
+
+ATF_TC_BODY(t_spawn_fchdir_neg_fd, tc)
+{
+	int error, fd;
+	posix_spawn_file_actions_t fa;
+
+	fd = -1;
+
+	error = posix_spawn_file_actions_init(&fa);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addfchdir(&fa, fd);
+	ATF_REQUIRE(error == EBADF);
+
+	posix_spawn_file_actions_destroy(&fa);
+}
+
+ATF_TC(t_spawn_fchdir_closed);
+
+ATF_TC_HEAD(t_spawn_fchdir_closed, tc)
+{
+	atf_tc_set_md_var(tc, "descr",
+	    "Testing posix_spawn_file_actions_addfchdir for a closed fd");
+	atf_tc_set_md_var(tc, "require.progs", "/bin/pwd");
+}
+
+ATF_TC_BODY(t_spawn_fchdir_closed, tc)
+{
+	int error, fd;
+	pid_t pid;
+	char * const args[2] = { __UNCONST("pwd"), NULL };
+	posix_spawnattr_t attr;
+	posix_spawn_file_actions_t fa;
+
+	/*
+	 * fd = open(CHDIRPATH, O_RDONLY);
+	 * ATF_REQUIRE(fd >= 0);
+	 * error = close(fd);
+	 * ATF_REQUIRE(error == 0);
+	 */
+	fd = 3;
+
+	error = posix_spawnattr_init(&attr);
+	ATF_CHECK(error == 0);
+	/*
+	 * POSIX_SPAWN_RETURNERROR is a NetBSD specific flag that
+	 * will cause a "proper" return value from posix_spawn(2)
+	 * instead of a (potential) success there and a 127 exit
+	 * status from the child process (c.f. the non-diag variant
+	 * of this test).
+	 */
+	error = posix_spawnattr_setflags(&attr, POSIX_SPAWN_RETURNERROR);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_init(&fa);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addfchdir(&fa, fd);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn(&pid, "/bin/pwd", &fa, &attr, args, NULL);
+	ATF_REQUIRE(error == EBADF);
+
+	posix_spawn_file_actions_destroy(&fa);
+	posix_spawnattr_destroy(&attr);
+}
+
+ATF_TC(t_spawn_fchdir_file);
+
+ATF_TC_HEAD(t_spawn_fchdir_file, tc)
+{
+	atf_tc_set_md_var(tc, "descr",
+	    "Testing posix_spawn_file_actions_addfchdir on a "
+	    "regular file (not a directory)");
+	atf_tc_set_md_var(tc, "require.progs", "/bin/pwd");
+}
+
+ATF_TC_BODY(t_spawn_fchdir_file, tc)
+{
+	int error, fd; 
+	pid_t pid;
+	char * const args[2] = { __UNCONST("pwd"), NULL };
+	posix_spawnattr_t attr;
+	posix_spawn_file_actions_t fa;
+
+	fd = open(FILEPATH, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+	ATF_REQUIRE_MSG(fd != -1, "Can't open `%s' (%s)", FILEPATH,
+	    strerror(errno));
+
+	error = posix_spawnattr_init(&attr);
+	ATF_REQUIRE(error == 0);
+	/*
+	 * POSIX_SPAWN_RETURNERROR is a NetBSD specific flag that
+	 * will cause a "proper" return value from posix_spawn(2)
+	 * instead of a (potential) success there and a 127 exit
+	 * status from the child process (c.f. the non-diag variant
+	 * of this test).
+	 */
+	error = posix_spawnattr_setflags(&attr, POSIX_SPAWN_RETURNERROR);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_init(&fa);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn_file_actions_addfchdir(&fa, fd);
+	ATF_REQUIRE(error == 0);
+
+	error = posix_spawn(&pid, "/bin/pwd", &fa, &attr, args, NULL);
+	ATF_CHECK(error == ENOTDIR);
+
+	posix_spawn_file_actions_destroy(&fa);
+	posix_spawnattr_destroy(&attr);
+
+	error = close(fd);
+	ATF_REQUIRE(error == 0);
+
+	unlink(FILEPATH);
+
+}
+
+#undef CHDIRPATH
+#undef FILENAME
+#undef FILEPATH
+
 ATF_TP_ADD_TCS(tp)
 {
 	ATF_TP_ADD_TC(tp, t_spawn_ls);
@@ -179,6 +680,15 @@ ATF_TP_ADD_TCS(tp)
 	ATF_TP_ADD_TC(tp, t_spawn_missing);
 	ATF_TP_ADD_TC(tp, t_spawn_nonexec);
 	ATF_TP_ADD_TC(tp, t_spawn_child);
+	ATF_TP_ADD_TC(tp, t_spawn_chdir_abs);
+	ATF_TP_ADD_TC(tp, t_spawn_chdir_rel);
+	ATF_TP_ADD_TC(tp, t_spawn_chdir_file);
+	ATF_TP_ADD_TC(tp, t_spawn_chdir_invalid);
+	ATF_TP_ADD_TC(tp, t_spawn_chdir_permissions);
+	ATF_TP_ADD_TC(tp, t_spawn_fchdir);
+	ATF_TP_ADD_TC(tp, t_spawn_fchdir_neg_fd);
+	ATF_TP_ADD_TC(tp, t_spawn_fchdir_closed);
+	ATF_TP_ADD_TC(tp, t_spawn_fchdir_file);
 
 	return atf_no_error();
 }

Index: src/tests/lib/libc/gen/posix_spawn/t_spawnattr.c
diff -u src/tests/lib/libc/gen/posix_spawn/t_spawnattr.c:1.4 src/tests/lib/libc/gen/posix_spawn/t_spawnattr.c:1.5
--- src/tests/lib/libc/gen/posix_spawn/t_spawnattr.c:1.4	Sun May  2 07:18:11 2021
+++ src/tests/lib/libc/gen/posix_spawn/t_spawnattr.c	Sun Nov  7 10:46:20 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: t_spawnattr.c,v 1.4 2021/05/02 11:18:11 martin Exp $ */
+/* $NetBSD: t_spawnattr.c,v 1.5 2021/11/07 15:46:20 christos Exp $ */
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -29,7 +29,10 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_spawnattr.c,v 1.5 2021/11/07 15:46:20 christos Exp $");
 
+#include <sys/param.h>
 #include <atf-c.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -42,9 +45,6 @@
 #include <unistd.h>
 #include <sys/wait.h>
 
-#define MAX(a, b)	(a) > (b) ? (a) : (b)
-#define MIN(a, b)	(a) > (b) ? (b) : (a)
-
 static int
 get_different_scheduler(void)
 {

Added files:

Index: src/tests/lib/libc/gen/posix_spawn/fa_spawn_utils.c
diff -u /dev/null src/tests/lib/libc/gen/posix_spawn/fa_spawn_utils.c:1.1
--- /dev/null	Sun Nov  7 10:46:20 2021
+++ src/tests/lib/libc/gen/posix_spawn/fa_spawn_utils.c	Sun Nov  7 10:46:20 2021
@@ -0,0 +1,62 @@
+/*	$NetBSD: fa_spawn_utils.c,v 1.1 2021/11/07 15:46:20 christos Exp $	*/
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles Zhang <char...@netbsd.org> and
+ * Martin Husemann <mar...@netbsd.org>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: fa_spawn_utils.c,v 1.1 2021/11/07 15:46:20 christos Exp $");
+
+#include <atf-c.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "fa_spawn_utils.h"
+
+off_t
+filesize(const char * restrict fname)
+{
+	struct stat st;
+	int err;
+
+	err = stat(fname, &st);
+	ATF_REQUIRE_MSG(err == 0, "Can't stat %s (%s)", fname, strerror(errno));
+	return st.st_size;
+}
+
+void
+empty_outfile(const char * restrict fname)
+{
+	FILE *f;
+
+	f = fopen(fname, "w");
+	ATF_REQUIRE_MSG(f != NULL, "Can't open %s (%s)", fname, strerror(errno));
+	fclose(f);
+}
Index: src/tests/lib/libc/gen/posix_spawn/fa_spawn_utils.h
diff -u /dev/null src/tests/lib/libc/gen/posix_spawn/fa_spawn_utils.h:1.1
--- /dev/null	Sun Nov  7 10:46:20 2021
+++ src/tests/lib/libc/gen/posix_spawn/fa_spawn_utils.h	Sun Nov  7 10:46:20 2021
@@ -0,0 +1,31 @@
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles Zhang <char...@netbsd.org> and
+ * Martin Husemann <mar...@netbsd.org>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+off_t filesize(const char * restrict);
+void empty_outfile(const char * restrict);

Reply via email to