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);