summaryrefslogtreecommitdiffstats
path: root/contrib/netbsd-tests/lib/libc/sys
diff options
context:
space:
mode:
authorgjb <gjb@FreeBSD.org>2014-10-14 15:37:19 +0000
committergjb <gjb@FreeBSD.org>2014-10-14 15:37:19 +0000
commit49bc9d1f7ffccd05cb04d7cb7b41a1ee2f39b46d (patch)
treeacfa7870dec8e734f823d6db57d1b0799de03ad1 /contrib/netbsd-tests/lib/libc/sys
parent8521a45a5518d0da7ec2b53f2abb0f433d612a61 (diff)
parent594c54630f7d35d5f8feece66ae5ef818703cd18 (diff)
downloadFreeBSD-src-49bc9d1f7ffccd05cb04d7cb7b41a1ee2f39b46d.zip
FreeBSD-src-49bc9d1f7ffccd05cb04d7cb7b41a1ee2f39b46d.tar.gz
Reintegrate head@r273095
Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'contrib/netbsd-tests/lib/libc/sys')
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_access.c210
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_chroot.c313
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_clock_gettime.c212
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_clone.c252
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_connect.c99
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_dup.c385
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_fsync.c120
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_getcontext.c129
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_getgroups.c171
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_getitimer.c211
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_getlogin.c237
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_getpid.c134
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_getrusage.c197
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_getsid.c119
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_gettimeofday.c86
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_issetugid.c148
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_kevent.c180
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_kill.c312
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_link.c229
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_listen.c134
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_lwp_create.c247
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_lwp_ctl.c74
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_mincore.c318
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_minherit.c200
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_mkdir.c210
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_mkfifo.c276
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_mknod.c192
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_mlock.c244
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_mmap.c505
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_mprotect.c359
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_msgctl.c358
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_msgget.c292
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_msgrcv.c342
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_msgsnd.c338
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_msync.c237
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_nanosleep.c187
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_pipe.c163
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_pipe2.c188
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_poll.c392
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_posix_fadvise.c165
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_recvmmsg.c161
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_revoke.c186
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_select.c215
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_setrlimit.c522
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_setuid.c122
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_sigaction.c154
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_sigqueue.c103
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_sigtimedwait.c126
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_socketpair.c137
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_stat.c417
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_swapcontext.c133
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_timer_create.c207
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_truncate.c175
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_ucontext.c76
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_umask.c205
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_unlink.c158
-rw-r--r--contrib/netbsd-tests/lib/libc/sys/t_write.c226
57 files changed, 12488 insertions, 0 deletions
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_access.c b/contrib/netbsd-tests/lib/libc/sys/t_access.c
new file mode 100644
index 0000000..f15afc2
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_access.c
@@ -0,0 +1,210 @@
+/* $NetBSD: t_access.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_access.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+static const char path[] = "access";
+static const int mode[4] = { R_OK, W_OK, X_OK, F_OK };
+
+ATF_TC_WITH_CLEANUP(access_access);
+ATF_TC_HEAD(access_access, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test access(2) for EACCES");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(access_access, tc)
+{
+ const int perm[3] = { 0200, 0400, 0000 };
+ size_t i;
+ int fd;
+
+ fd = open(path, O_RDONLY | O_CREAT);
+
+ if (fd < 0)
+ return;
+
+ for (i = 0; i < __arraycount(mode) - 1; i++) {
+
+ ATF_REQUIRE(fchmod(fd, perm[i]) == 0);
+
+ errno = 0;
+
+ ATF_REQUIRE(access(path, mode[i]) != 0);
+ ATF_REQUIRE(errno == EACCES);
+ }
+
+ ATF_REQUIRE(close(fd) == 0);
+}
+
+ATF_TC_CLEANUP(access_access, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(access_fault);
+ATF_TC_HEAD(access_fault, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test access(2) for EFAULT");
+}
+
+ATF_TC_BODY(access_fault, tc)
+{
+ size_t i;
+
+ for (i = 0; i < __arraycount(mode); i++) {
+
+ errno = 0;
+
+ ATF_REQUIRE(access(NULL, mode[i]) != 0);
+ ATF_REQUIRE(errno == EFAULT);
+
+ errno = 0;
+
+ ATF_REQUIRE(access((char *)-1, mode[i]) != 0);
+ ATF_REQUIRE(errno == EFAULT);
+ }
+}
+
+ATF_TC(access_inval);
+ATF_TC_HEAD(access_inval, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test access(2) for EINVAL");
+}
+
+ATF_TC_BODY(access_inval, tc)
+{
+
+ errno = 0;
+
+ ATF_REQUIRE(access("/usr", -1) != 0);
+ ATF_REQUIRE(errno == EINVAL);
+}
+
+ATF_TC(access_notdir);
+ATF_TC_HEAD(access_notdir, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test access(2) for ENOTDIR");
+}
+
+ATF_TC_BODY(access_notdir, tc)
+{
+ size_t i;
+
+ for (i = 0; i < __arraycount(mode); i++) {
+
+ errno = 0;
+
+ /*
+ * IEEE Std 1003.1-2008 about ENOTDIR:
+ *
+ * "A component of the path prefix is not a directory,
+ * or the path argument contains at least one non-<slash>
+ * character and ends with one or more trailing <slash>
+ * characters and the last pathname component names an
+ * existing file that is neither a directory nor a symbolic
+ * link to a directory."
+ */
+ ATF_REQUIRE(access("/etc/passwd//", mode[i]) != 0);
+ ATF_REQUIRE(errno == ENOTDIR);
+ }
+}
+
+ATF_TC(access_notexist);
+ATF_TC_HEAD(access_notexist, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test access(2) for ENOENT");
+}
+
+ATF_TC_BODY(access_notexist, tc)
+{
+ size_t i;
+
+ for (i = 0; i < __arraycount(mode); i++) {
+
+ errno = 0;
+
+ ATF_REQUIRE(access("", mode[i]) != 0);
+ ATF_REQUIRE(errno == ENOENT);
+ }
+}
+
+ATF_TC(access_toolong);
+ATF_TC_HEAD(access_toolong, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test access(2) for ENAMETOOLONG");
+}
+
+ATF_TC_BODY(access_toolong, tc)
+{
+ char *buf;
+ size_t i;
+
+ buf = malloc(PATH_MAX);
+
+ if (buf == NULL)
+ return;
+
+ for (i = 0; i < PATH_MAX; i++)
+ buf[i] = 'x';
+
+ for (i = 0; i < __arraycount(mode); i++) {
+
+ errno = 0;
+
+ ATF_REQUIRE(access(buf, mode[i]) != 0);
+ ATF_REQUIRE(errno == ENAMETOOLONG);
+ }
+
+ free(buf);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, access_access);
+ ATF_TP_ADD_TC(tp, access_fault);
+ ATF_TP_ADD_TC(tp, access_inval);
+ ATF_TP_ADD_TC(tp, access_notdir);
+ ATF_TP_ADD_TC(tp, access_notexist);
+ ATF_TP_ADD_TC(tp, access_toolong);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_chroot.c b/contrib/netbsd-tests/lib/libc/sys/t_chroot.c
new file mode 100644
index 0000000..ce71708
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_chroot.c
@@ -0,0 +1,313 @@
+/* $NetBSD: t_chroot.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_chroot.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
+
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+ATF_TC(chroot_basic);
+ATF_TC_HEAD(chroot_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of chroot(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(chroot_basic, tc)
+{
+ char buf[PATH_MAX];
+ int fd, sta;
+ pid_t pid;
+
+ (void)memset(buf, '\0', sizeof(buf));
+ (void)getcwd(buf, sizeof(buf));
+ (void)strlcat(buf, "/dir", sizeof(buf));
+
+ ATF_REQUIRE(mkdir(buf, 0500) == 0);
+ ATF_REQUIRE(chdir(buf) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ if (chroot(buf) != 0)
+ _exit(EXIT_FAILURE);
+
+ errno = 0;
+
+ if (chroot("/root") != -1)
+ _exit(EXIT_FAILURE);
+
+ if (errno != ENOENT)
+ _exit(EXIT_FAILURE);
+
+ fd = open("file", O_RDONLY | O_CREAT, 0600);
+
+ if (fd < 0)
+ _exit(EXIT_FAILURE);
+
+ if (close(fd) != 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("chroot(2) failed");
+
+ (void)chdir("/");
+ (void)strlcat(buf, "/file", sizeof(buf));
+
+ fd = open(buf, O_RDONLY);
+
+ if (fd < 0)
+ atf_tc_fail("chroot(2) did not change the root directory");
+
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(unlink(buf) == 0);
+}
+
+ATF_TC(chroot_err);
+ATF_TC_HEAD(chroot_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions of chroot(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(chroot_err, tc)
+{
+ char buf[PATH_MAX + 1];
+
+ (void)memset(buf, 'x', sizeof(buf));
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENAMETOOLONG, chroot(buf) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, chroot((void *)-1) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, chroot("/a/b/c/d/e/f/g/h/i/j") == -1);
+}
+
+ATF_TC(chroot_perm);
+ATF_TC_HEAD(chroot_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test permissions with chroot(2)");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(chroot_perm, tc)
+{
+ static char buf[LINE_MAX];
+ pid_t pid;
+ int sta;
+
+ (void)memset(buf, '\0', sizeof(buf));
+ ATF_REQUIRE(getcwd(buf, sizeof(buf)) != NULL);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ errno = 0;
+
+ if (chroot(buf) != -1)
+ _exit(EXIT_FAILURE);
+
+ if (errno != EPERM)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("chroot(2) succeeded as unprivileged user");
+}
+
+ATF_TC(fchroot_basic);
+ATF_TC_HEAD(fchroot_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of fchroot(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(fchroot_basic, tc)
+{
+ char buf[PATH_MAX];
+ int fd, sta;
+ pid_t pid;
+
+ (void)memset(buf, '\0', sizeof(buf));
+ (void)getcwd(buf, sizeof(buf));
+ (void)strlcat(buf, "/dir", sizeof(buf));
+
+ ATF_REQUIRE(mkdir(buf, 0500) == 0);
+ ATF_REQUIRE(chdir(buf) == 0);
+
+ fd = open(buf, O_RDONLY);
+ ATF_REQUIRE(fd >= 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ if (fchroot(fd) != 0)
+ _exit(EXIT_FAILURE);
+
+ if (close(fd) != 0)
+ _exit(EXIT_FAILURE);
+
+ fd = open("file", O_RDONLY | O_CREAT, 0600);
+
+ if (fd < 0)
+ _exit(EXIT_FAILURE);
+
+ if (close(fd) != 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("fchroot(2) failed");
+
+ (void)chdir("/");
+ (void)strlcat(buf, "/file", sizeof(buf));
+
+ fd = open(buf, O_RDONLY);
+
+ if (fd < 0)
+ atf_tc_fail("fchroot(2) did not change the root directory");
+
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(unlink(buf) == 0);
+}
+
+ATF_TC(fchroot_err);
+ATF_TC_HEAD(fchroot_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions of fchroot(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(fchroot_err, tc)
+{
+ int fd;
+
+ fd = open("/etc/passwd", O_RDONLY);
+ ATF_REQUIRE(fd >= 0);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, fchroot(-1) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOTDIR, fchroot(fd) == -1);
+
+ ATF_REQUIRE(close(fd) == 0);
+}
+
+ATF_TC(fchroot_perm);
+ATF_TC_HEAD(fchroot_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test permissions with fchroot(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(fchroot_perm, tc)
+{
+ static char buf[LINE_MAX];
+ struct passwd *pw;
+ int fd, sta;
+ pid_t pid;
+
+ (void)memset(buf, '\0', sizeof(buf));
+ ATF_REQUIRE(getcwd(buf, sizeof(buf)) != NULL);
+
+ pw = getpwnam("nobody");
+ fd = open(buf, O_RDONLY);
+
+ ATF_REQUIRE(fd >= 0);
+ ATF_REQUIRE(pw != NULL);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ (void)setuid(pw->pw_uid);
+
+ errno = 0;
+
+ if (fchroot(fd) != -1)
+ _exit(EXIT_FAILURE);
+
+ if (errno != EPERM)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("fchroot(2) succeeded as unprivileged user");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, chroot_basic);
+ ATF_TP_ADD_TC(tp, chroot_err);
+ ATF_TP_ADD_TC(tp, chroot_perm);
+ ATF_TP_ADD_TC(tp, fchroot_basic);
+ ATF_TP_ADD_TC(tp, fchroot_err);
+ ATF_TP_ADD_TC(tp, fchroot_perm);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_clock_gettime.c b/contrib/netbsd-tests/lib/libc/sys/t_clock_gettime.c
new file mode 100644
index 0000000..69890fd
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_clock_gettime.c
@@ -0,0 +1,212 @@
+/* $NetBSD: t_clock_gettime.c,v 1.1 2011/10/15 06:42:16 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Frank Kardel.
+ *
+ * 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.
+ */
+
+/*-
+ * Copyright (c) 2006 Frank Kardel
+ * All rights reserved.
+ *
+ * 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>
+__COPYRIGHT("@(#) Copyright (c) 2008\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_clock_gettime.c,v 1.1 2011/10/15 06:42:16 jruoho Exp $");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <machine/int_limits.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "../../../h_macros.h"
+
+#define MINPOSDIFF 15000000 /* 15 ms for now */
+#define TIMEOUT 5
+
+#define TC_HARDWARE "kern.timecounter.hardware"
+#define TC_CHOICE "kern.timecounter.choice"
+
+static void
+check_timecounter(void)
+{
+ struct timespec tsa, tsb, tsl, res;
+ long long mindiff = INTMAX_MAX;
+ time_t endlimit;
+
+#define CL(x) \
+ do { \
+ if ((x) != -1) \
+ break; \
+ atf_tc_fail_nonfatal("%s: %s", #x, strerror(errno)); \
+ return; \
+ } while (0)
+
+ CL(clock_gettime(CLOCK_REALTIME, &tsa));
+ tsl = tsa;
+
+ CL(time(&endlimit));
+ endlimit += TIMEOUT + 1;
+
+ while ((time_t)tsa.tv_sec < endlimit) {
+ long long diff;
+
+ CL(clock_gettime(CLOCK_REALTIME, &tsb));
+ diff = 1000000000LL * (tsb.tv_sec - tsa.tv_sec)
+ + tsb.tv_nsec - tsa.tv_nsec;
+
+ if (diff > 0 && mindiff > diff)
+ mindiff = diff;
+
+ if (diff < 0 || diff > MINPOSDIFF) {
+ long long elapsed;
+ (void)printf("%stime TSA: 0x%jx.%08jx, TSB: 0x%jx.%08jx, "
+ "diff = %lld nsec, ", (diff < 0) ? "BAD " : "",
+ (uintmax_t)tsa.tv_sec, (uintmax_t)tsa.tv_nsec,
+ (uintmax_t)tsb.tv_sec, (uintmax_t)tsb.tv_nsec, diff);
+
+ elapsed = 1000000000LL * (tsb.tv_sec - tsl.tv_sec)
+ + tsb.tv_nsec - tsl.tv_nsec;
+
+
+ (void)printf("%lld nsec\n", elapsed);
+ tsl = tsb;
+
+ ATF_CHECK(diff >= 0);
+ if (diff < 0)
+ return;
+ }
+
+ tsa.tv_sec = tsb.tv_sec;
+ tsa.tv_nsec = tsb.tv_nsec;
+ }
+
+ if (clock_getres(CLOCK_REALTIME, &res) == 0) {
+ long long r = res.tv_sec * 1000000000 + res.tv_nsec;
+
+ (void)printf("Claimed resolution: %lld nsec (%f Hz) or "
+ "better\n", r, 1.0 / r * 1e9);
+ (void)printf("Observed minimum non zero delta: %lld "
+ "nsec\n", mindiff);
+ }
+
+#undef CL
+}
+
+ATF_TC(clock_gettime_real);
+ATF_TC_HEAD(clock_gettime_real, tc)
+{
+ atf_tc_set_md_var(tc, "require.user", "root");
+ atf_tc_set_md_var(tc, "descr",
+ "Checks the monotonicity of the CLOCK_REALTIME implementation");
+ atf_tc_set_md_var(tc, "timeout", "300");
+}
+
+ATF_TC_BODY(clock_gettime_real, tc)
+{
+ char name[128], cbuf[512], ctrbuf[10240];
+ size_t cbufsiz = sizeof(cbuf);
+ size_t ctrbufsiz = sizeof(ctrbuf);
+ const char *p;
+ char *save;
+ int quality, n;
+
+ if (sysctlbyname(TC_HARDWARE, cbuf, &cbufsiz, NULL, 0) != 0) {
+ (void)printf("\nChecking legacy time implementation "
+ "for %d seconds\n", TIMEOUT);
+ check_timecounter();
+ return;
+ /* NOTREACHED */
+ }
+ (void)printf("%s = %s\n", TC_HARDWARE, cbuf);
+ REQUIRE_LIBC(save = strdup(cbuf), NULL);
+
+ RL(sysctlbyname(TC_CHOICE, ctrbuf, &ctrbufsiz, NULL, 0));
+ (void)printf("%s = %s\n", TC_CHOICE, ctrbuf);
+
+ for (p = ctrbuf, n = 0; sscanf(p, "%127[^(](q=%d, f=%*u Hz)%*[ ]%n",
+ name, &quality, &n) == 2; p += n) {
+ struct timespec ts;
+ int ret;
+
+ if (quality < 0)
+ continue;
+
+ (void)printf("\nChecking %s for %d seconds\n", name, TIMEOUT);
+ CHECK_LIBC(ret = sysctlbyname(TC_HARDWARE, NULL, 0,
+ name, strlen(name)), -1);
+ if (ret == -1)
+ continue;
+
+ /* wait a bit to select new counter in clockinterrupt */
+ ts.tv_sec = 0;
+ ts.tv_nsec = 100000000;
+ (void)nanosleep(&ts, NULL);
+
+ check_timecounter();
+ }
+
+ RL(sysctlbyname(TC_HARDWARE, NULL, 0, save, strlen(save)));
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, clock_gettime_real);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_clone.c b/contrib/netbsd-tests/lib/libc/sys/t_clone.c
new file mode 100644
index 0000000..ea33f32
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_clone.c
@@ -0,0 +1,252 @@
+/* $NetBSD: t_clone.c,v 1.3 2011/12/12 20:55:44 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * 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>
+__COPYRIGHT("@(#) Copyright (c) 2008\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_clone.c,v 1.3 2011/12/12 20:55:44 joerg Exp $");
+
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+#define STACKSIZE (8 * 1024)
+#define FROBVAL 41973
+#define CHILDEXIT 0xa5
+
+static int
+dummy(void *arg)
+{
+
+ return 0;
+}
+
+static int
+clone_func(void *arg)
+{
+ long *frobp = arg, diff;
+
+ printf("child: stack ~= %p, frobme = %p\n", &frobp, frobp);
+ fflush(stdout);
+
+ if (frobp[0] != getppid())
+ return 1;
+
+ if (frobp[0] == getpid())
+ return 2;
+
+ diff = labs(frobp[1] - (long) &frobp);
+
+ if (diff > 1024)
+ return 3;
+
+ frobp[1] = FROBVAL;
+
+ return (CHILDEXIT);
+}
+
+ATF_TC(clone_basic);
+ATF_TC_HEAD(clone_basic, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr", "Checks clone(2)");
+}
+
+ATF_TC_BODY(clone_basic, tc)
+{
+ sigset_t mask;
+ void *allocstack, *stack;
+ pid_t pid;
+ volatile long frobme[2];
+ int stat;
+
+ allocstack = mmap(NULL, STACKSIZE, PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_PRIVATE|MAP_ANON, -1, (off_t) 0);
+
+ ATF_REQUIRE_ERRNO(errno, allocstack != MAP_FAILED);
+
+ stack = allocstack;
+#ifndef __MACHINE_STACK_GROWS_UP
+ stack = (char *)stack + STACKSIZE;
+#endif
+
+ printf("parent: stack = %p, frobme = %p\n", stack, frobme);
+ fflush(stdout);
+
+ frobme[0] = (long)getpid();
+ frobme[1] = (long)stack;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGUSR1);
+
+ ATF_REQUIRE_ERRNO(errno, sigprocmask(SIG_BLOCK, &mask, NULL) != -1);
+
+ switch (pid = __clone(clone_func, stack,
+ CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGUSR1,
+ __UNVOLATILE(frobme))) {
+ case 0:
+ atf_tc_fail("clone() returned 0");
+ /*NOTREACHED*/
+ case -1:
+ atf_tc_fail("clone() failed: %s", strerror(errno));
+ /*NOTREACHED*/
+ default:
+ while (waitpid(pid, &stat, __WCLONE) != pid)
+ continue;
+ }
+
+ ATF_REQUIRE_MSG(WIFEXITED(stat) != 0, "child didn't exit");
+
+ printf("parent: childexit = 0x%x, frobme = %ld\n",
+ WEXITSTATUS(stat), frobme[1]);
+
+ switch (WEXITSTATUS(stat)) {
+ case CHILDEXIT:
+ ATF_REQUIRE_EQ(frobme[1], FROBVAL);
+ break;
+ case 1:
+ atf_tc_fail("child: argument does not contain parent's pid");
+ /*NOTREACHED*/
+ case 2:
+ atf_tc_fail("child: called in parent's pid");
+ /*NOTREACHED*/
+ case 3:
+ atf_tc_fail("child: called with bad stack");
+ /*NOTREACHED*/
+ default:
+ atf_tc_fail("child returned unknown code: %d",
+ WEXITSTATUS(stat));
+ /*NOTREACHED*/
+ }
+
+ ATF_REQUIRE_ERRNO(errno, munmap(allocstack, STACKSIZE) != -1);
+}
+
+ATF_TC(clone_null_stack);
+ATF_TC_HEAD(clone_null_stack, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr",
+ "Checks that clone(2) fails when stack pointer is NULL");
+}
+
+ATF_TC_BODY(clone_null_stack, tc)
+{
+ int rv;
+
+ rv = __clone(dummy, NULL,
+ CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD, NULL);
+
+ ATF_REQUIRE_EQ(rv, -1);
+ ATF_REQUIRE_EQ(errno, EINVAL);
+}
+
+ATF_TC(clone_null_func);
+ATF_TC_HEAD(clone_null_func, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr",
+ "Checks that clone(2) fails when function pointer is NULL");
+}
+
+ATF_TC_BODY(clone_null_func, tc)
+{
+ void *allocstack, *stack;
+ int rv;
+
+ allocstack = mmap(NULL, STACKSIZE, PROT_READ|PROT_WRITE|PROT_EXEC,
+ MAP_PRIVATE|MAP_ANON, -1, (off_t) 0);
+ ATF_REQUIRE_ERRNO(errno, allocstack != MAP_FAILED);
+ stack = allocstack;
+#ifndef __MACHINE_STACK_GROWS_UP
+ stack = (char *)stack + STACKSIZE;
+#endif
+
+ errno = 0;
+ rv = __clone(0, stack,
+ CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD, NULL);
+
+ ATF_REQUIRE_EQ(rv, -1);
+ ATF_REQUIRE_EQ(errno, EINVAL);
+
+ ATF_REQUIRE_ERRNO(errno, munmap(allocstack, STACKSIZE) != -1);
+}
+
+ATF_TC(clone_out_of_proc);
+ATF_TC_HEAD(clone_out_of_proc, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr",
+ "Checks that clone(2) fails when running out of processes");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(clone_out_of_proc, tc)
+{
+ struct rlimit rl;
+ int rv;
+
+ ATF_REQUIRE_ERRNO(errno, getrlimit(RLIMIT_NPROC, &rl) != -1);
+
+ rl.rlim_cur = 0;
+ rl.rlim_max = 0;
+
+ ATF_REQUIRE_ERRNO(errno, setrlimit(RLIMIT_NPROC, &rl) != -1);
+
+ errno = 0;
+ rv = __clone(dummy, malloc(10240),
+ CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGCHLD, (void *)&rl);
+
+ ATF_REQUIRE_EQ(rv, -1);
+ ATF_REQUIRE_EQ(errno, EAGAIN);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, clone_basic);
+ ATF_TP_ADD_TC(tp, clone_null_stack);
+ ATF_TP_ADD_TC(tp, clone_null_func);
+ ATF_TP_ADD_TC(tp, clone_out_of_proc);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_connect.c b/contrib/netbsd-tests/lib/libc/sys/t_connect.c
new file mode 100644
index 0000000..d161ee3
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_connect.c
@@ -0,0 +1,99 @@
+/* $NetBSD: t_connect.c,v 1.1 2011/11/05 18:19:02 jruoho Exp $ */
+/*
+ * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 <err.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <atf-c.h>
+
+ATF_TC(connect_low_port);
+ATF_TC_HEAD(connect_low_port, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that low-port allocation "
+ "works");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+ATF_TC_BODY(connect_low_port, tc)
+{
+ struct sockaddr_in sin, sinlist;
+ int sd, val, slist;
+ socklen_t slen;
+
+ slist = socket(AF_INET, SOCK_STREAM, 0);
+ sd = socket(AF_INET, SOCK_STREAM, 0);
+
+ /* bind listening socket */
+ memset(&sinlist, 0, sizeof(sinlist));
+ sinlist.sin_family = AF_INET;
+ sinlist.sin_port = htons(31522);
+ sinlist.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+ ATF_REQUIRE_EQ(bind(slist,
+ (struct sockaddr *)&sinlist, sizeof(sinlist)), 0);
+ ATF_REQUIRE_EQ(listen(slist, 1), 0);
+
+ val = IP_PORTRANGE_LOW;
+ if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, &val,
+ sizeof(val)) == -1)
+ atf_tc_fail("setsockopt failed: %s", strerror(errno));
+
+ memset(&sin, 0, sizeof(sin));
+
+ sin.sin_port = htons(31522);
+ sin.sin_addr.s_addr = inet_addr("127.0.0.1");
+ sin.sin_family = AF_INET;
+
+ if (connect(sd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+ int serrno = errno;
+ atf_tc_fail("connect failed: %s%s",
+ strerror(serrno),
+ serrno != EACCES ? "" :
+ " (see http://mail-index.netbsd.org/"
+ "source-changes/2007/12/16/0011.html)");
+ }
+
+ slen = sizeof(sin);
+ ATF_REQUIRE_EQ(getsockname(sd, (struct sockaddr *)&sin, &slen), 0);
+ ATF_REQUIRE_EQ(slen, sizeof(sin));
+ ATF_REQUIRE(ntohs(sin.sin_port) <= IPPORT_RESERVEDMAX);
+
+ close(sd);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, connect_low_port);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_dup.c b/contrib/netbsd-tests/lib/libc/sys/t_dup.c
new file mode 100644
index 0000000..a2623c0
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_dup.c
@@ -0,0 +1,385 @@
+/* $NetBSD: t_dup.c,v 1.8 2012/03/18 07:00:51 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_dup.c,v 1.8 2012/03/18 07:00:51 jruoho Exp $");
+
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sysexits.h>
+
+static char path[] = "dup";
+static void check_mode(bool, bool, bool);
+
+static void
+check_mode(bool _dup, bool _dup2, bool _dup3)
+{
+ int mode[3] = { O_RDONLY, O_WRONLY, O_RDWR };
+ int perm[5] = { 0700, 0400, 0600, 0444, 0666 };
+ struct stat st, st1;
+ int fd, fd1, fd2;
+ size_t i, j;
+
+ /*
+ * Check that a duplicated descriptor
+ * retains the mode of the original file.
+ */
+ for (i = 0; i < __arraycount(mode); i++) {
+
+ for (j = 0; j < __arraycount(perm); j++) {
+
+ fd1 = open(path, mode[i] | O_CREAT, perm[j]);
+ fd2 = open("/etc/passwd", O_RDONLY);
+
+ ATF_REQUIRE(fd1 >= 0);
+ ATF_REQUIRE(fd2 >= 0);
+
+ if (_dup != false)
+ fd = dup(fd1);
+ else if (_dup2 != false)
+ fd = dup2(fd1, fd2);
+ else if (_dup3 != false)
+ fd = dup3(fd1, fd2, O_CLOEXEC);
+ else {
+ fd = -1;
+ }
+
+ ATF_REQUIRE(fd >= 0);
+
+ (void)memset(&st, 0, sizeof(struct stat));
+ (void)memset(&st1, 0, sizeof(struct stat));
+
+ ATF_REQUIRE(fstat(fd, &st) == 0);
+ ATF_REQUIRE(fstat(fd1, &st1) == 0);
+
+ if (st.st_mode != st1.st_mode)
+ atf_tc_fail("invalid mode");
+
+ (void)close(fd);
+ (void)close(fd1);
+ (void)close(fd2);
+ (void)unlink(path);
+ }
+ }
+}
+
+ATF_TC(dup2_basic);
+ATF_TC_HEAD(dup2_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of dup2(2)");
+}
+
+ATF_TC_BODY(dup2_basic, tc)
+{
+ int fd, fd1, fd2;
+
+ fd1 = open("/etc/passwd", O_RDONLY);
+ fd2 = open("/etc/passwd", O_RDONLY);
+
+ ATF_REQUIRE(fd1 >= 0);
+ ATF_REQUIRE(fd2 >= 0);
+
+ fd = dup2(fd1, fd2);
+ ATF_REQUIRE(fd >= 0);
+
+ if (fd != fd2)
+ atf_tc_fail("invalid descriptor");
+
+ (void)close(fd);
+ (void)close(fd1);
+
+ ATF_REQUIRE(close(fd2) != 0);
+}
+
+ATF_TC(dup2_err);
+ATF_TC_HEAD(dup2_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions of dup2(2)");
+}
+
+ATF_TC_BODY(dup2_err, tc)
+{
+ int fd;
+
+ fd = open("/etc/passwd", O_RDONLY);
+ ATF_REQUIRE(fd >= 0);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, dup2(-1, -1) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, dup2(fd, -1) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, dup2(-1, fd) == -1);
+
+ /*
+ * Note that this should not fail with EINVAL.
+ */
+ ATF_REQUIRE(dup2(fd, fd) != -1);
+
+ (void)close(fd);
+}
+
+ATF_TC(dup2_max);
+ATF_TC_HEAD(dup2_max, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test dup2(2) against limits");
+}
+
+ATF_TC_BODY(dup2_max, tc)
+{
+ struct rlimit res;
+
+ (void)memset(&res, 0, sizeof(struct rlimit));
+ (void)getrlimit(RLIMIT_NOFILE, &res);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, dup2(STDERR_FILENO, res.rlim_cur + 1) == -1);
+}
+
+ATF_TC_WITH_CLEANUP(dup2_mode);
+ATF_TC_HEAD(dup2_mode, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of dup2(2)");
+}
+
+ATF_TC_BODY(dup2_mode, tc)
+{
+ check_mode(false, true, false);
+}
+
+ATF_TC_CLEANUP(dup2_mode, tc)
+{
+ (void)unlink(path);
+}
+
+
+ATF_TC(dup3_err);
+ATF_TC_HEAD(dup3_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test error conditions of dup3(2) (PR lib/45148)");
+}
+
+ATF_TC_BODY(dup3_err, tc)
+{
+ int fd;
+
+ fd = open("/etc/passwd", O_RDONLY);
+ ATF_REQUIRE(fd >= 0);
+
+ errno = 0;
+ ATF_REQUIRE(dup3(fd, fd, O_CLOEXEC) != -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, dup3(-1, -1, O_CLOEXEC) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, dup3(fd, -1, O_CLOEXEC) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, dup3(-1, fd, O_CLOEXEC) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, dup3(fd, 1, O_NOFOLLOW) == -1);
+
+ (void)close(fd);
+}
+
+ATF_TC(dup3_max);
+ATF_TC_HEAD(dup3_max, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test dup3(2) against limits");
+}
+
+ATF_TC_BODY(dup3_max, tc)
+{
+ struct rlimit res;
+
+ (void)memset(&res, 0, sizeof(struct rlimit));
+ (void)getrlimit(RLIMIT_NOFILE, &res);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, dup3(STDERR_FILENO,
+ res.rlim_cur + 1, O_CLOEXEC) == -1);
+}
+
+ATF_TC_WITH_CLEANUP(dup3_mode);
+ATF_TC_HEAD(dup3_mode, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of dup3(2)");
+}
+
+ATF_TC_BODY(dup3_mode, tc)
+{
+ check_mode(false, false, true);
+}
+
+ATF_TC_CLEANUP(dup3_mode, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(dup_err);
+ATF_TC_HEAD(dup_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions of dup(2)");
+}
+
+ATF_TC_BODY(dup_err, tc)
+{
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, dup(-1) == -1);
+}
+
+ATF_TC_WITH_CLEANUP(dup_max);
+ATF_TC_HEAD(dup_max, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test dup(2) against limits");
+}
+
+ATF_TC_BODY(dup_max, tc)
+{
+ struct rlimit res;
+ int *buf, fd, sta;
+ size_t i, n;
+ pid_t pid;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ /*
+ * Open a temporary file until the
+ * maximum number of open files is
+ * reached. Ater that dup(2) family
+ * should fail with EMFILE.
+ */
+ (void)closefrom(0);
+ (void)memset(&res, 0, sizeof(struct rlimit));
+
+ n = 10;
+ res.rlim_cur = res.rlim_max = n;
+ if (setrlimit(RLIMIT_NOFILE, &res) != 0)
+ _exit(EX_OSERR);
+
+ buf = calloc(n, sizeof(int));
+
+ if (buf == NULL)
+ _exit(EX_OSERR);
+
+ buf[0] = mkstemp(path);
+
+ if (buf[0] < 0)
+ _exit(EX_OSERR);
+
+ for (i = 1; i < n; i++) {
+
+ buf[i] = open(path, O_RDONLY);
+
+ if (buf[i] < 0)
+ _exit(EX_OSERR);
+ }
+
+ errno = 0;
+ fd = dup(buf[0]);
+
+ if (fd != -1 || errno != EMFILE)
+ _exit(EX_DATAERR);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) {
+
+ if (WEXITSTATUS(sta) == EX_OSERR)
+ atf_tc_fail("system call error");
+
+ if (WEXITSTATUS(sta) == EX_DATAERR)
+ atf_tc_fail("dup(2) dupped more than RLIMIT_NOFILE");
+
+ atf_tc_fail("unknown error");
+ }
+
+ (void)unlink(path);
+}
+
+ATF_TC_CLEANUP(dup_max, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(dup_mode);
+ATF_TC_HEAD(dup_mode, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of dup(2)");
+}
+
+ATF_TC_BODY(dup_mode, tc)
+{
+ check_mode(true, false, false);
+}
+
+ATF_TC_CLEANUP(dup_mode, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, dup2_basic);
+ ATF_TP_ADD_TC(tp, dup2_err);
+ ATF_TP_ADD_TC(tp, dup2_max);
+ ATF_TP_ADD_TC(tp, dup2_mode);
+ ATF_TP_ADD_TC(tp, dup3_err);
+ ATF_TP_ADD_TC(tp, dup3_max);
+ ATF_TP_ADD_TC(tp, dup3_mode);
+ ATF_TP_ADD_TC(tp, dup_err);
+ ATF_TP_ADD_TC(tp, dup_max);
+ ATF_TP_ADD_TC(tp, dup_mode);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_fsync.c b/contrib/netbsd-tests/lib/libc/sys/t_fsync.c
new file mode 100644
index 0000000..e61ea7e
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_fsync.c
@@ -0,0 +1,120 @@
+/* $NetBSD: t_fsync.c,v 1.2 2012/03/18 07:00:52 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_fsync.c,v 1.2 2012/03/18 07:00:52 jruoho Exp $");
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+ATF_TC(fsync_err);
+ATF_TC_HEAD(fsync_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test error conditions of fsync(2) (PR kern/30)");
+}
+
+ATF_TC_BODY(fsync_err, tc)
+{
+ int i, fd[2];
+
+ /*
+ * The fsync(2) call should fail with EBADF
+ * when the 'fd' is not a valid descriptor.
+ */
+ for (i = 1; i < 1024; i = i + 128) {
+
+ errno = 0;
+
+ ATF_REQUIRE(fsync(-i) == -1);
+ ATF_REQUIRE(errno == EBADF);
+ }
+
+ /*
+ * On the other hand, EINVAL should follow
+ * if the operation is not possible with
+ * the file descriptor.
+ */
+ ATF_REQUIRE(pipe(fd) == 0);
+
+ errno = 0;
+
+ ATF_REQUIRE(fsync(fd[0]) == -1);
+ ATF_REQUIRE(errno == EINVAL);
+
+ errno = 0;
+
+ ATF_REQUIRE(fsync(fd[1]) == -1);
+ ATF_REQUIRE(errno == EINVAL);
+
+ ATF_REQUIRE(close(fd[0]) == 0);
+ ATF_REQUIRE(close(fd[1]) == 0);
+}
+
+ATF_TC(fsync_sync);
+ATF_TC_HEAD(fsync_sync, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of fsync(2)");
+}
+
+ATF_TC_BODY(fsync_sync, tc)
+{
+ char buf[128];
+ int fd, i;
+
+ for (i = 0; i < 10; i++) {
+
+ (void)snprintf(buf, sizeof(buf), "t_fsync-%d", i);
+
+ fd = mkstemp(buf);
+
+ ATF_REQUIRE(fd != -1);
+ ATF_REQUIRE(write(fd, "0", 1) == 1);
+ ATF_REQUIRE(fsync(fd) == 0);
+
+ ATF_REQUIRE(unlink(buf) == 0);
+ ATF_REQUIRE(close(fd) == 0);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, fsync_err);
+ ATF_TP_ADD_TC(tp, fsync_sync);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_getcontext.c b/contrib/netbsd-tests/lib/libc/sys/t_getcontext.c
new file mode 100644
index 0000000..3a2d9f7
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_getcontext.c
@@ -0,0 +1,129 @@
+/* $NetBSD: t_getcontext.c,v 1.3 2011/07/14 04:59:14 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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>
+__COPYRIGHT("@(#) Copyright (c) 2008\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_getcontext.c,v 1.3 2011/07/14 04:59:14 jruoho Exp $");
+
+#include <atf-c.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ucontext.h>
+
+#define STACKSZ (10*1024)
+#define DEPTH 3
+
+static int calls;
+
+static void
+run(int n, ...)
+{
+ va_list va;
+ int i, ia;
+
+ ATF_REQUIRE_EQ(n, DEPTH - calls - 1);
+
+ va_start(va, n);
+ for (i = 0; i < 9; i++) {
+ ia = va_arg(va, int);
+ ATF_REQUIRE_EQ(i, ia);
+ }
+ va_end(va);
+
+ calls++;
+}
+
+ATF_TC(getcontext_err);
+ATF_TC_HEAD(getcontext_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from getcontext(2)");
+}
+
+ATF_TC_BODY(getcontext_err, tc)
+{
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, getcontext((void *)-1) == -1);
+}
+
+ATF_TC(setcontext_err);
+ATF_TC_HEAD(setcontext_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from setcontext(2)");
+}
+
+ATF_TC_BODY(setcontext_err, tc)
+{
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, setcontext((void *)-1) == -1);
+}
+
+ATF_TC(setcontext_link);
+ATF_TC_HEAD(setcontext_link, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr",
+ "Checks get/make/setcontext(), context linking via uc_link(), "
+ "and argument passing to the new context");
+}
+
+ATF_TC_BODY(setcontext_link, tc)
+{
+ ucontext_t uc[DEPTH];
+ ucontext_t save;
+ volatile int i = 0; /* avoid longjmp clobbering */
+
+ for (i = 0; i < DEPTH; ++i) {
+ ATF_REQUIRE_EQ(getcontext(&uc[i]), 0);
+
+ uc[i].uc_stack.ss_sp = malloc(STACKSZ);
+ uc[i].uc_stack.ss_size = STACKSZ;
+ uc[i].uc_link = (i > 0) ? &uc[i - 1] : &save;
+
+ makecontext(&uc[i], (void *)run, 10, i,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8);
+ }
+
+ ATF_REQUIRE_EQ(getcontext(&save), 0);
+
+ if (calls == 0)
+ ATF_REQUIRE_EQ(setcontext(&uc[DEPTH-1]), 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getcontext_err);
+ ATF_TP_ADD_TC(tp, setcontext_err);
+ ATF_TP_ADD_TC(tp, setcontext_link);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_getgroups.c b/contrib/netbsd-tests/lib/libc/sys/t_getgroups.c
new file mode 100644
index 0000000..9a8ec8e
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_getgroups.c
@@ -0,0 +1,171 @@
+/* $NetBSD: t_getgroups.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_getgroups.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
+
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+ATF_TC(getgroups_err);
+ATF_TC_HEAD(getgroups_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors in getgroups(2)");
+}
+
+ATF_TC_BODY(getgroups_err, tc)
+{
+ gid_t gidset[NGROUPS_MAX];
+
+ errno = 0;
+
+ ATF_REQUIRE(getgroups(10, (gid_t *)-1) == -1);
+ ATF_REQUIRE(errno == EFAULT);
+
+ errno = 0;
+
+ ATF_REQUIRE(getgroups(-1, gidset) == -1);
+ ATF_REQUIRE(errno == EINVAL);
+}
+
+ATF_TC(getgroups_getgid);
+ATF_TC_HEAD(getgroups_getgid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test getgid(2) from getgroups(2)");
+}
+
+ATF_TC_BODY(getgroups_getgid, tc)
+{
+ gid_t gidset[NGROUPS_MAX];
+ gid_t gid = getgid();
+ int i, n;
+
+ /*
+ * Check that getgid(2) is found from
+ * the GIDs returned by getgroups(2).
+ */
+ n = getgroups(NGROUPS_MAX, gidset);
+
+ for (i = 0; i < n; i++) {
+
+ if (gidset[i] == gid)
+ return;
+ }
+
+ atf_tc_fail("getgid(2) not found from getgroups(2)");
+}
+
+ATF_TC(getgroups_setgid);
+ATF_TC_HEAD(getgroups_setgid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setgid(2) from getgroups(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(getgroups_setgid, tc)
+{
+ gid_t gidset[NGROUPS_MAX];
+ int i, n, rv, sta;
+ pid_t pid;
+
+ /*
+ * Check that we can setgid(2)
+ * to the returned group IDs.
+ */
+ n = getgroups(NGROUPS_MAX, gidset);
+ ATF_REQUIRE(n >= 0);
+
+ for (i = 0; i < n; i++) {
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ rv = setgid(gidset[i]);
+
+ if (rv != 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("getgroups(2) is inconsistent");
+ }
+}
+
+ATF_TC(getgroups_zero);
+ATF_TC_HEAD(getgroups_zero, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test getgroups(2) with zero param");
+}
+
+ATF_TC_BODY(getgroups_zero, tc)
+{
+ const gid_t val = 123456789;
+ gid_t gidset[NGROUPS_MAX];
+ size_t i;
+
+ /*
+ * If the first parameter is zero, the number
+ * of groups should be returned but the supplied
+ * buffer should remain intact.
+ */
+ for (i = 0; i < __arraycount(gidset); i++)
+ gidset[i] = val;
+
+ ATF_REQUIRE(getgroups(0, gidset) >= 0);
+
+ for (i = 0; i < __arraycount(gidset); i++) {
+
+ if (gidset[i] != val)
+ atf_tc_fail("getgroups(2) modified the buffer");
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getgroups_err);
+ ATF_TP_ADD_TC(tp, getgroups_getgid);
+ ATF_TP_ADD_TC(tp, getgroups_setgid);
+ ATF_TP_ADD_TC(tp, getgroups_zero);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_getitimer.c b/contrib/netbsd-tests/lib/libc/sys/t_getitimer.c
new file mode 100644
index 0000000..b384541
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_getitimer.c
@@ -0,0 +1,211 @@
+/* $NetBSD: t_getitimer.c,v 1.2 2012/03/22 18:20:46 christos Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_getitimer.c,v 1.2 2012/03/22 18:20:46 christos Exp $");
+
+#include <sys/time.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+static bool fail;
+static void sighandler(int);
+
+static void
+sighandler(int signo)
+{
+
+ if (signo == SIGALRM || signo == SIGVTALRM)
+ fail = false;
+}
+
+ATF_TC(getitimer_empty);
+ATF_TC_HEAD(getitimer_empty, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "getitimer(2) before setitimer(2)");
+}
+
+ATF_TC_BODY(getitimer_empty, tc)
+{
+ struct itimerval it;
+
+ /*
+ * Verify that the passed structure remains
+ * empty after calling getitimer(2) but before
+ * actually arming the timer with setitimer(2).
+ */
+ (void)memset(&it, 0, sizeof(struct itimerval));
+
+ ATF_REQUIRE(getitimer(ITIMER_REAL, &it) == 0);
+
+ if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0)
+ goto fail;
+
+ ATF_REQUIRE(getitimer(ITIMER_VIRTUAL, &it) == 0);
+
+ if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0)
+ goto fail;
+
+ ATF_REQUIRE(getitimer(ITIMER_PROF, &it) == 0);
+
+ if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0)
+ goto fail;
+
+ return;
+
+fail:
+ atf_tc_fail("getitimer(2) modfied the timer before it was armed");
+}
+
+ATF_TC(getitimer_err);
+ATF_TC_HEAD(getitimer_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from getitimer(2)");
+}
+
+ATF_TC_BODY(getitimer_err, tc)
+{
+ struct itimerval it;
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, getitimer(-1, &it) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, getitimer(INT_MAX, &it) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, getitimer(ITIMER_REAL, (void *)-1) == -1);
+}
+
+ATF_TC(setitimer_basic);
+ATF_TC_HEAD(setitimer_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of setitimer(2)");
+}
+
+ATF_TC_BODY(setitimer_basic, tc)
+{
+ struct itimerval it;
+
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 100;
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+
+ fail = true;
+
+ ATF_REQUIRE(signal(SIGALRM, sighandler) != SIG_ERR);
+ ATF_REQUIRE(setitimer(ITIMER_REAL, &it, NULL) == 0);
+
+ /*
+ * Although the interaction between
+ * setitimer(2) and sleep(3) can be
+ * unspecified, it is assumed that one
+ * second suspension will be enough for
+ * the timer to fire.
+ */
+ (void)sleep(1);
+
+ if (fail != false)
+ atf_tc_fail("timer did not fire");
+}
+
+ATF_TC(setitimer_err);
+ATF_TC_HEAD(setitimer_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from setitimer(2)"
+ " (PR standards/44927)");
+}
+
+ATF_TC_BODY(setitimer_err, tc)
+{
+ struct itimerval it, ot;
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, setitimer(-1, &it, &ot) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, setitimer(INT_MAX, &it, &ot) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, setitimer(ITIMER_REAL,(void*)-1, &ot) == -1);
+}
+
+ATF_TC(setitimer_old);
+ATF_TC_HEAD(setitimer_old, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test old values from setitimer(2)");
+}
+
+ATF_TC_BODY(setitimer_old, tc)
+{
+ struct itimerval it, ot;
+
+ /*
+ * Make two calls; the second one
+ * should store the old values.
+ */
+ it.it_value.tv_sec = 4;
+ it.it_value.tv_usec = 3;
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+
+ ATF_REQUIRE(setitimer(ITIMER_REAL, &it, &ot) == 0);
+
+ it.it_value.tv_sec = 2;
+ it.it_value.tv_usec = 1;
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+
+ ATF_REQUIRE(setitimer(ITIMER_REAL, &it, &ot) == 0);
+
+ if (ot.it_value.tv_sec != 4 || ot.it_value.tv_usec != 3)
+ atf_tc_fail("setitimer(2) did not store old values");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getitimer_empty);
+ ATF_TP_ADD_TC(tp, getitimer_err);
+ ATF_TP_ADD_TC(tp, setitimer_basic);
+ ATF_TP_ADD_TC(tp, setitimer_err);
+ ATF_TP_ADD_TC(tp, setitimer_old);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_getlogin.c b/contrib/netbsd-tests/lib/libc/sys/t_getlogin.c
new file mode 100644
index 0000000..8c2b199
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_getlogin.c
@@ -0,0 +1,237 @@
+/* $NetBSD: t_getlogin.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_getlogin.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
+
+#include <sys/param.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+ATF_TC(getlogin_r_err);
+ATF_TC_HEAD(getlogin_r_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from getlogin_r(2)");
+}
+
+ATF_TC_BODY(getlogin_r_err, tc)
+{
+ char small[0];
+
+ ATF_REQUIRE(getlogin_r(small, sizeof(small)) == ERANGE);
+}
+
+ATF_TC(getlogin_same);
+ATF_TC_HEAD(getlogin_same, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "getlogin(2) vs. getlogin_r(2)");
+}
+
+ATF_TC_BODY(getlogin_same, tc)
+{
+ char buf[MAXLOGNAME];
+ char *str;
+
+ str = getlogin();
+
+ if (str == NULL)
+ return;
+
+ ATF_REQUIRE(getlogin_r(buf, sizeof(buf)) == 0);
+
+ if (strcmp(str, buf) != 0)
+ atf_tc_fail("getlogin(2) and getlogin_r(2) differ");
+}
+
+ATF_TC(setlogin_basic);
+ATF_TC_HEAD(setlogin_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test that setlogin(2) works");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(setlogin_basic, tc)
+{
+ char *name;
+ pid_t pid;
+ int sta;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ (void)setsid();
+
+ if (setlogin("foobar") != 0)
+ _exit(EXIT_FAILURE);
+
+ name = getlogin();
+
+ if (name == NULL)
+ _exit(EXIT_FAILURE);
+
+ if (strcmp(name, "foobar") != 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("setlogin(2) failed to set login name");
+}
+
+ATF_TC(setlogin_err);
+ATF_TC_HEAD(setlogin_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from setlogin(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(setlogin_err, tc)
+{
+ char buf[MAXLOGNAME + 1];
+ char *name;
+ pid_t pid;
+ int sta;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ (void)memset(buf, 'x', sizeof(buf));
+
+ if (pid == 0) {
+
+ (void)setsid();
+
+ errno = 0;
+
+ if (setlogin(buf) != -1)
+ _exit(EINVAL);
+
+ if (errno != EINVAL)
+ _exit(EINVAL);
+
+ errno = 0;
+
+ if (setlogin((void *)-1) != -1)
+ _exit(EFAULT);
+
+ if (errno != EFAULT)
+ _exit(EFAULT);
+
+ name = getlogin();
+
+ if (name == NULL)
+ _exit(EXIT_FAILURE);
+
+ if (strcmp(name, "foobar") == 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) {
+
+ if (WEXITSTATUS(sta) == EFAULT)
+ atf_tc_fail("expected EFAULT, but the call succeeded");
+
+ if (WEXITSTATUS(sta) == EINVAL)
+ atf_tc_fail("expected EINVAL, but the call succeeded");
+
+ atf_tc_fail("setlogin(2) failed, but login name was set");
+ }
+}
+
+ATF_TC(setlogin_perm);
+ATF_TC_HEAD(setlogin_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setlogin(2) as normal user");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(setlogin_perm, tc)
+{
+ char *name;
+ pid_t pid;
+ int sta;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ (void)setsid();
+
+ errno = 0;
+
+ if (setlogin("foobar") != -1)
+ _exit(EXIT_FAILURE);
+
+ if (errno != EPERM)
+ _exit(EXIT_FAILURE);
+
+ name = getlogin();
+
+ if (name == NULL)
+ _exit(EXIT_FAILURE);
+
+ if (strcmp(name, "foobar") == 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("login name was set as an unprivileged user");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getlogin_r_err);
+ ATF_TP_ADD_TC(tp, getlogin_same);
+ ATF_TP_ADD_TC(tp, setlogin_basic);
+ ATF_TP_ADD_TC(tp, setlogin_err);
+ ATF_TP_ADD_TC(tp, setlogin_perm);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_getpid.c b/contrib/netbsd-tests/lib/libc/sys/t_getpid.c
new file mode 100644
index 0000000..b3ed393
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_getpid.c
@@ -0,0 +1,134 @@
+/* $NetBSD: t_getpid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_getpid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
+
+#include <sys/wait.h>
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+static int maxiter = 10;
+static void *threadfunc(void *);
+
+static void *
+threadfunc(void *arg)
+{
+ *(pid_t *)arg = getpid();
+
+ return NULL;
+}
+
+ATF_TC(getpid_process);
+ATF_TC_HEAD(getpid_process, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test getpid(2) with processes");
+}
+
+ATF_TC_BODY(getpid_process, tc)
+{
+ pid_t ppid, fpid, cpid, tpid, wpid;
+ int i, sta;
+
+ for (i = 0; i < maxiter; i++) {
+
+ tpid = getpid();
+ fpid = fork();
+
+ ATF_REQUIRE(fpid >= 0);
+
+ if (fpid == 0) {
+
+ cpid = getpid();
+ ppid = getppid();
+
+ if (tpid != ppid)
+ _exit(EXIT_FAILURE);
+
+ if (cpid == ppid)
+ _exit(EXIT_FAILURE);
+
+ if (tpid == fpid)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ wpid = wait(&sta);
+
+ if (wpid != fpid)
+ atf_tc_fail("PID mismatch");
+
+ ATF_REQUIRE(WIFEXITED(sta) != 0);
+
+ if (WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("PID mismatch");
+ }
+}
+
+ATF_TC(getpid_thread);
+ATF_TC_HEAD(getpid_thread, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test getpid(2) with threads");
+}
+
+ATF_TC_BODY(getpid_thread, tc)
+{
+ pid_t pid, tpid;
+ pthread_t tid;
+ int i, rv;
+
+ for (i = 0; i < maxiter; i++) {
+
+ pid = getpid();
+
+ rv = pthread_create(&tid, NULL, threadfunc, &tpid);
+ ATF_REQUIRE(rv == 0);
+
+ rv = pthread_join(tid, NULL);
+ ATF_REQUIRE(rv == 0);
+
+ if (pid != tpid)
+ atf_tc_fail("Unequal PIDs");
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getpid_process);
+ ATF_TP_ADD_TC(tp, getpid_thread);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_getrusage.c b/contrib/netbsd-tests/lib/libc/sys/t_getrusage.c
new file mode 100644
index 0000000..6c4218a
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_getrusage.c
@@ -0,0 +1,197 @@
+/* $NetBSD: t_getrusage.c,v 1.3 2014/09/03 19:24:12 matt Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_getrusage.c,v 1.3 2014/09/03 19:24:12 matt Exp $");
+
+#include <sys/resource.h>
+#include <sys/time.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdint.h>
+#include <string.h>
+
+static void work(void);
+static void sighandler(int);
+
+static const size_t maxiter = 2000;
+
+static void
+sighandler(int signo)
+{
+ /* Nothing. */
+}
+
+static void
+work(void)
+{
+ size_t n = UINT16_MAX * 10;
+
+ while (n > 0) {
+#ifdef __or1k__
+ asm volatile("l.nop"); /* Do something. */
+#else
+ asm volatile("nop"); /* Do something. */
+#endif
+ n--;
+ }
+}
+
+ATF_TC(getrusage_err);
+ATF_TC_HEAD(getrusage_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions");
+}
+
+ATF_TC_BODY(getrusage_err, tc)
+{
+ struct rusage ru;
+
+ errno = 0;
+
+ ATF_REQUIRE(getrusage(INT_MAX, &ru) != 0);
+ ATF_REQUIRE(errno == EINVAL);
+
+ errno = 0;
+
+ ATF_REQUIRE(getrusage(RUSAGE_SELF, (void *)0) != 0);
+ ATF_REQUIRE(errno == EFAULT);
+}
+
+ATF_TC(getrusage_sig);
+ATF_TC_HEAD(getrusage_sig, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test signal count with getrusage(2)");
+}
+
+ATF_TC_BODY(getrusage_sig, tc)
+{
+ struct rusage ru;
+ const long n = 5;
+ int i;
+
+ /*
+ * Test that signals are recorded.
+ */
+ ATF_REQUIRE(signal(SIGUSR1, sighandler) != SIG_ERR);
+
+ for (i = 0; i < n; i++)
+ ATF_REQUIRE(raise(SIGUSR1) == 0);
+
+ (void)memset(&ru, 0, sizeof(struct rusage));
+ ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0);
+
+ if (n != ru.ru_nsignals)
+ atf_tc_fail("getrusage(2) did not record signals");
+}
+
+ATF_TC(getrusage_utime_back);
+ATF_TC_HEAD(getrusage_utime_back, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test bogus values from getrusage(2)");
+}
+
+ATF_TC_BODY(getrusage_utime_back, tc)
+{
+ struct rusage ru1, ru2;
+ size_t i;
+
+ /*
+ * Test that two consecutive calls are sane.
+ */
+ atf_tc_expect_fail("PR kern/30115");
+
+ for (i = 0; i < maxiter; i++) {
+
+ (void)memset(&ru1, 0, sizeof(struct rusage));
+ (void)memset(&ru2, 0, sizeof(struct rusage));
+
+ work();
+
+ ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru1) == 0);
+
+ work();
+
+ ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru2) == 0);
+
+ if (timercmp(&ru2.ru_utime, &ru1.ru_utime, <) != 0)
+ atf_tc_fail("user time went backwards");
+ }
+
+ atf_tc_fail("anticipated error did not occur");
+}
+
+ATF_TC(getrusage_utime_zero);
+ATF_TC_HEAD(getrusage_utime_zero, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test zero utime from getrusage(2)");
+}
+
+ATF_TC_BODY(getrusage_utime_zero, tc)
+{
+ struct rusage ru;
+ size_t i;
+
+ /*
+ * Test that getrusage(2) does not return
+ * zero user time for the calling process.
+ *
+ * See also (duplicate) PR port-amd64/41734.
+ */
+ atf_tc_expect_fail("PR kern/30115");
+
+ for (i = 0; i < maxiter; i++) {
+
+ work();
+
+ (void)memset(&ru, 0, sizeof(struct rusage));
+
+ ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0);
+
+ if (ru.ru_utime.tv_sec == 0 && ru.ru_utime.tv_usec == 0)
+ atf_tc_fail("zero user time from getrusage(2)");
+ }
+
+ atf_tc_fail("anticipated error did not occur");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getrusage_err);
+ ATF_TP_ADD_TC(tp, getrusage_sig);
+ ATF_TP_ADD_TC(tp, getrusage_utime_back);
+ ATF_TP_ADD_TC(tp, getrusage_utime_zero);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_getsid.c b/contrib/netbsd-tests/lib/libc/sys/t_getsid.c
new file mode 100644
index 0000000..76b54ab
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_getsid.c
@@ -0,0 +1,119 @@
+/* $NetBSD: t_getsid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_getsid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
+
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+ATF_TC(getsid_current);
+ATF_TC_HEAD(getsid_current, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test getsid(0)");
+}
+
+ATF_TC_BODY(getsid_current, tc)
+{
+ pid_t sid;
+
+ sid = getsid(0);
+ ATF_REQUIRE(sid != -1);
+
+ if (sid != getsid(getpid()))
+ atf_tc_fail("getsid(0) did not match the calling process");
+}
+
+ATF_TC(getsid_err);
+ATF_TC_HEAD(getsid_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions in getsid(2)");
+}
+
+ATF_TC_BODY(getsid_err, tc)
+{
+
+ errno = 0;
+
+ ATF_REQUIRE(getsid(-1) == -1);
+ ATF_REQUIRE(errno == ESRCH);
+}
+
+ATF_TC(getsid_process);
+ATF_TC_HEAD(getsid_process, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test getsid(2) with processes");
+}
+
+ATF_TC_BODY(getsid_process, tc)
+{
+ pid_t csid, pid, ppid, sid;
+ int sta;
+
+ sid = getsid(0);
+ pid = fork();
+
+ ATF_REQUIRE(pid >= 0);
+ ATF_REQUIRE(sid != -1);
+
+ if (pid == 0) {
+
+ csid = getsid(0);
+ ppid = getppid();
+
+ if (sid != csid)
+ _exit(EXIT_FAILURE);
+
+ if (getsid(ppid) != csid)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("invalid session ID");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, getsid_current);
+ ATF_TP_ADD_TC(tp, getsid_err);
+ ATF_TP_ADD_TC(tp, getsid_process);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_gettimeofday.c b/contrib/netbsd-tests/lib/libc/sys/t_gettimeofday.c
new file mode 100644
index 0000000..1cf303b
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_gettimeofday.c
@@ -0,0 +1,86 @@
+/* $NetBSD: t_gettimeofday.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_gettimeofday.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
+
+#include <sys/time.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <string.h>
+
+ATF_TC(gettimeofday_err);
+ATF_TC_HEAD(gettimeofday_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from gettimeofday(2)");
+}
+
+ATF_TC_BODY(gettimeofday_err, tc)
+{
+
+ errno = 0;
+
+ ATF_REQUIRE_ERRNO(EFAULT, gettimeofday((void *)-1, NULL) != 0);
+}
+
+ATF_TC(gettimeofday_mono);
+ATF_TC_HEAD(gettimeofday_mono, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test monotonicity of gettimeofday(2)");
+}
+
+ATF_TC_BODY(gettimeofday_mono, tc)
+{
+ static const size_t maxiter = 100;
+ struct timeval tv1, tv2;
+ size_t i;
+
+ for (i = 0; i < maxiter; i++) {
+
+ (void)memset(&tv1, 0, sizeof(struct timeval));
+ (void)memset(&tv2, 0, sizeof(struct timeval));
+
+ ATF_REQUIRE(gettimeofday(&tv1, NULL) == 0);
+ ATF_REQUIRE(gettimeofday(&tv2, NULL) == 0);
+
+ if (timercmp(&tv2, &tv1, <) != 0)
+ atf_tc_fail("time went backwards");
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, gettimeofday_err);
+ ATF_TP_ADD_TC(tp, gettimeofday_mono);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_issetugid.c b/contrib/netbsd-tests/lib/libc/sys/t_issetugid.c
new file mode 100644
index 0000000..b76ba39
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_issetugid.c
@@ -0,0 +1,148 @@
+/* $NetBSD: t_issetugid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_issetugid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
+
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static bool check(int (*fuid)(uid_t), int (*fgid)(gid_t));
+
+static bool
+check(int (*fuid)(uid_t), int (*fgid)(gid_t))
+{
+ struct passwd *pw;
+ pid_t pid;
+ int sta;
+
+ pw = getpwnam("nobody");
+
+ if (pw == NULL)
+ return false;
+
+ pid = fork();
+
+ if (pid < 0)
+ return false;
+
+ if (pid == 0) {
+
+ if (fuid != NULL && (*fuid)(pw->pw_uid) != 0)
+ _exit(EXIT_FAILURE);
+
+ if (fgid != NULL && (*fgid)(pw->pw_gid) != 0)
+ _exit(EXIT_FAILURE);
+
+ if (issetugid() != 1)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ return false;
+
+ return true;
+}
+
+ATF_TC(issetugid_egid);
+ATF_TC_HEAD(issetugid_egid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A test of issetugid(2), eff. GID");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(issetugid_egid, tc)
+{
+
+ if (check(NULL, setegid) != true)
+ atf_tc_fail("issetugid(2) failed with effective GID");
+}
+
+ATF_TC(issetugid_euid);
+ATF_TC_HEAD(issetugid_euid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A test of issetugid(2), eff. UID");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(issetugid_euid, tc)
+{
+
+ if (check(seteuid, NULL) != true)
+ atf_tc_fail("issetugid(2) failed with effective UID");
+}
+
+ATF_TC(issetugid_rgid);
+ATF_TC_HEAD(issetugid_rgid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A test of issetugid(2), real GID");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(issetugid_rgid, tc)
+{
+
+ if (check(NULL, setgid) != true)
+ atf_tc_fail("issetugid(2) failed with real GID");
+}
+
+ATF_TC(issetugid_ruid);
+ATF_TC_HEAD(issetugid_ruid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A test of issetugid(2), real UID");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(issetugid_ruid, tc)
+{
+
+ if (check(setuid, NULL) != true)
+ atf_tc_fail("issetugid(2) failed with real UID");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, issetugid_egid);
+ ATF_TP_ADD_TC(tp, issetugid_euid);
+ ATF_TP_ADD_TC(tp, issetugid_rgid);
+ ATF_TP_ADD_TC(tp, issetugid_ruid);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_kevent.c b/contrib/netbsd-tests/lib/libc/sys/t_kevent.c
new file mode 100644
index 0000000..73ffbf8
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_kevent.c
@@ -0,0 +1,180 @@
+/* $NetBSD: t_kevent.c,v 1.6 2012/11/29 09:13:44 martin Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundatiom
+ * by Christos Zoulas.
+ *
+ * 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: t_kevent.c,v 1.6 2012/11/29 09:13:44 martin Exp $");
+
+#include <sys/types.h>
+#include <sys/event.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#include <sys/drvctlio.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+ATF_TC(kevent_zerotimer);
+ATF_TC_HEAD(kevent_zerotimer, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that kevent with a 0 timer "
+ "does not crash the system (PR lib/45618)");
+}
+
+ATF_TC_BODY(kevent_zerotimer, tc)
+{
+ struct kevent ev;
+ int kq;
+
+ ATF_REQUIRE((kq = kqueue()) != -1);
+ EV_SET(&ev, 1, EVFILT_TIMER, EV_ADD|EV_ENABLE, 0, 1, 0);
+ ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) != -1);
+ ATF_REQUIRE(kevent(kq, NULL, 0, &ev, 1, NULL) == 1);
+}
+
+ATF_TC(kqueue_desc_passing);
+ATF_TC_HEAD(kqueue_desc_passing, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that passing a kqueue to "
+ "another process does not crash the kernel (PR 46463)");
+}
+
+ATF_TC_BODY(kqueue_desc_passing, tc)
+{
+ pid_t child;
+ int s[2], storage, status, kq;
+ struct cmsghdr *msg;
+ struct iovec iov;
+ struct msghdr m;
+ struct kevent ev;
+
+ ATF_REQUIRE((kq = kqueue()) != -1);
+
+ // atf_tc_skip("crashes kernel (PR 46463)");
+
+ ATF_REQUIRE(socketpair(AF_LOCAL, SOCK_STREAM, 0, s) != -1);
+ msg = malloc(CMSG_SPACE(sizeof(int)));
+ m.msg_iov = &iov;
+ m.msg_iovlen = 1;
+ m.msg_name = NULL;
+ m.msg_namelen = 0;
+ m.msg_control = msg;
+ m.msg_controllen = CMSG_SPACE(sizeof(int));
+
+ child = fork();
+ if (child == 0) {
+ close(s[0]);
+
+ iov.iov_base = &storage;
+ iov.iov_len = sizeof(int);
+ m.msg_iov = &iov;
+ m.msg_iovlen = 1;
+
+ if (recvmsg(s[1], &m, 0) == -1)
+ err(1, "child: could not recvmsg");
+
+ kq = *(int *)CMSG_DATA(msg);
+ printf("child (pid %d): received kq fd %d\n", getpid(), kq);
+ exit(0);
+ }
+
+ close(s[1]);
+
+ iov.iov_base = &storage;
+ iov.iov_len = sizeof(int);
+
+ msg->cmsg_level = SOL_SOCKET;
+ msg->cmsg_type = SCM_RIGHTS;
+ msg->cmsg_len = CMSG_LEN(sizeof(int));
+
+ *(int *)CMSG_DATA(msg) = kq;
+
+ EV_SET(&ev, 1, EVFILT_TIMER, EV_ADD|EV_ENABLE, 0, 1, 0);
+ ATF_CHECK(kevent(kq, &ev, 1, NULL, 0, NULL) != -1);
+
+ printf("parent (pid %d): sending kq fd %d\n", getpid(), kq);
+ if (sendmsg(s[0], &m, 0) == -1) {
+ ATF_REQUIRE_EQ_MSG(errno, EBADF, "errno is %d", errno);
+ atf_tc_skip("PR kern/46523");
+ }
+
+ close(kq);
+
+ waitpid(child, &status, 0);
+ ATF_CHECK(WIFEXITED(status) && WEXITSTATUS(status)==0);
+}
+
+ATF_TC(kqueue_unsupported_fd);
+ATF_TC_HEAD(kqueue_unsupported_fd, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that watching an fd whose"
+ " type is not supported does not crash the kernel");
+}
+
+ATF_TC_BODY(kqueue_unsupported_fd, tc)
+{
+ /* mqueue and semaphore use fnullop_kqueue also */
+ int fd, kq;
+ struct kevent ev;
+
+ fd = open(DRVCTLDEV, O_RDONLY);
+ if (fd == -1 && errno == ENOENT)
+ atf_tc_skip("no " DRVCTLDEV " available for testing");
+ ATF_REQUIRE(fd != -1);
+ ATF_REQUIRE((kq = kqueue()) != -1);
+
+ EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
+ NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|
+ NOTE_RENAME|NOTE_REVOKE, 0, 0);
+
+ ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == -1);
+ ATF_REQUIRE_ERRNO(EOPNOTSUPP, true);
+
+ (void)close(fd);
+}
+
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, kevent_zerotimer);
+ ATF_TP_ADD_TC(tp, kqueue_desc_passing);
+ ATF_TP_ADD_TC(tp, kqueue_unsupported_fd);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_kill.c b/contrib/netbsd-tests/lib/libc/sys/t_kill.c
new file mode 100644
index 0000000..2f42862
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_kill.c
@@ -0,0 +1,312 @@
+/* $NetBSD: t_kill.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_kill.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
+
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+ATF_TC(kill_basic);
+ATF_TC_HEAD(kill_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test that kill(2) works");
+}
+
+ATF_TC_BODY(kill_basic, tc)
+{
+ const int sig[] = { SIGHUP, SIGINT, SIGKILL, SIGTERM };
+ pid_t pid;
+ size_t i;
+ int sta;
+
+ for (i = 0; i < __arraycount(sig); i++) {
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ switch (pid) {
+
+ case 0:
+ pause();
+ break;
+
+ default:
+ ATF_REQUIRE(kill(pid, sig[i]) == 0);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != sig[i])
+ atf_tc_fail("kill(2) failed to kill child");
+ }
+}
+
+ATF_TC(kill_err);
+ATF_TC_HEAD(kill_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions of kill(2)");
+}
+
+ATF_TC_BODY(kill_err, tc)
+{
+ int rv, sta;
+ pid_t pid;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ errno = 0;
+ rv = kill(getpid(), -1);
+
+ if (rv == 0 || errno != EINVAL)
+ _exit(EINVAL);
+
+ errno = 0;
+ rv = kill(INT_MAX, SIGUSR1);
+
+ if (rv == 0 || errno != ESRCH)
+ _exit(ESRCH);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) {
+
+ if (WEXITSTATUS(sta) == EINVAL)
+ atf_tc_fail("expected EINVAL, but kill(2) succeeded");
+
+ if (WEXITSTATUS(sta) == ESRCH)
+ atf_tc_fail("expected ESRCH, but kill(2) succeeded");
+
+ atf_tc_fail("unknown error from kill(2)");
+ }
+}
+
+ATF_TC(kill_perm);
+ATF_TC_HEAD(kill_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test kill(2) permissions");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(kill_perm, tc)
+{
+ struct passwd *pw;
+ pid_t cpid, ppid;
+ uid_t cuid = 0;
+ uid_t puid = 0;
+ int sta;
+
+ /*
+ * Test that kill(2) fails when called
+ * for a PID owned by another user.
+ */
+ pw = getpwnam("operator");
+
+ if (pw != NULL)
+ cuid = pw->pw_uid;
+
+ pw = getpwnam("nobody");
+
+ if (pw != NULL)
+ puid = pw->pw_uid;
+
+ if (cuid == 0 || puid == 0 || cuid == puid)
+ atf_tc_fail("getpwnam(3) failed");
+
+ ppid = fork();
+
+ if (ppid < 0)
+ _exit(EXIT_FAILURE);
+
+ if (ppid == 0) {
+
+ cpid = fork();
+
+ if (cpid < 0)
+ _exit(EXIT_FAILURE);
+
+ if (cpid == 0) {
+
+ if (setuid(cuid) < 0)
+ _exit(EXIT_FAILURE);
+ else {
+ (void)sleep(1);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ /*
+ * Try to kill the child after having
+ * set the real and effective UID.
+ */
+ if (setuid(puid) != 0)
+ _exit(EXIT_FAILURE);
+
+ errno = 0;
+
+ if (kill(cpid, SIGKILL) == 0)
+ _exit(EPERM);
+
+ if (errno != EPERM)
+ _exit(EPERM);
+
+ (void)waitpid(cpid, &sta, 0);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)waitpid(ppid, &sta, 0);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) == EPERM)
+ atf_tc_fail("killed a process of another user");
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("unknown error from kill(2)");
+}
+
+ATF_TC(kill_pgrp_neg);
+ATF_TC_HEAD(kill_pgrp_neg, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test kill(2) with process group, #2");
+}
+
+ATF_TC_BODY(kill_pgrp_neg, tc)
+{
+ const int maxiter = 3;
+ pid_t cpid, ppid;
+ int i, sta;
+
+ ppid = fork();
+ ATF_REQUIRE(ppid >= 0);
+
+ if (ppid == 0) {
+
+ ATF_REQUIRE(setpgid(0, 0) == 0);
+
+ for (i = 0; i < maxiter; i++) {
+
+ cpid = fork();
+ ATF_REQUIRE(cpid >= 0);
+
+ if (cpid == 0)
+ pause();
+ }
+
+ /*
+ * Test the variant of killpg(3); if the process number
+ * is negative but not -1, the signal should be sent to
+ * all processes whose process group ID is equal to the
+ * absolute value of the process number.
+ */
+ ATF_REQUIRE(kill(-getpgrp(), SIGKILL) == 0);
+
+ (void)sleep(1);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)waitpid(ppid, &sta, 0);
+
+ if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != SIGKILL)
+ atf_tc_fail("failed to kill(2) a process group");
+}
+
+ATF_TC(kill_pgrp_zero);
+ATF_TC_HEAD(kill_pgrp_zero, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test kill(2) with process group, #1");
+}
+
+ATF_TC_BODY(kill_pgrp_zero, tc)
+{
+ const int maxiter = 3;
+ pid_t cpid, ppid;
+ int i, sta;
+
+ ppid = fork();
+ ATF_REQUIRE(ppid >= 0);
+
+ if (ppid == 0) {
+
+ ATF_REQUIRE(setpgid(0, 0) == 0);
+
+ for (i = 0; i < maxiter; i++) {
+
+ cpid = fork();
+ ATF_REQUIRE(cpid >= 0);
+
+ if (cpid == 0)
+ pause();
+ }
+
+ /*
+ * If the supplied process number is zero,
+ * the signal should be sent to all processes
+ * under the current process group.
+ */
+ ATF_REQUIRE(kill(0, SIGKILL) == 0);
+
+ (void)sleep(1);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)waitpid(ppid, &sta, 0);
+
+ if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != SIGKILL)
+ atf_tc_fail("failed to kill(2) a process group");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, kill_basic);
+ ATF_TP_ADD_TC(tp, kill_err);
+ ATF_TP_ADD_TC(tp, kill_perm);
+ ATF_TP_ADD_TC(tp, kill_pgrp_neg);
+ ATF_TP_ADD_TC(tp, kill_pgrp_zero);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_link.c b/contrib/netbsd-tests/lib/libc/sys/t_link.c
new file mode 100644
index 0000000..b58c4c9
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_link.c
@@ -0,0 +1,229 @@
+/* $NetBSD: t_link.c,v 1.2 2014/04/21 14:39:36 martin Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_link.c,v 1.2 2014/04/21 14:39:36 martin Exp $");
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static const char *getpath(void);
+static char path[] = "link";
+static const char *pathl;
+
+static const char *
+getpath(void)
+{
+ static char buf[LINE_MAX];
+
+ (void)memset(buf, '\0', sizeof(buf));
+
+ if (getcwd(buf, sizeof(buf)) == NULL)
+ return NULL;
+
+ (void)strlcat(buf, path, sizeof(buf));
+ (void)strlcat(buf, ".link", sizeof(buf));
+
+ return buf;
+}
+
+ATF_TC_WITH_CLEANUP(link_count);
+ATF_TC_HEAD(link_count, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "link(2) counts are incremented?");
+}
+
+ATF_TC_BODY(link_count, tc)
+{
+ struct stat sa, sb;
+ int fd;
+
+ (void)memset(&sa, 0, sizeof(struct stat));
+ (void)memset(&sb, 0, sizeof(struct stat));
+
+ pathl = getpath();
+ fd = open(path, O_RDWR | O_CREAT, 0600);
+
+ ATF_REQUIRE(fd >= 0);
+ ATF_REQUIRE(pathl != NULL);
+
+ ATF_REQUIRE(stat(path, &sa) == 0);
+ ATF_REQUIRE(link(path, pathl) == 0);
+ ATF_REQUIRE(stat(path, &sb) == 0);
+
+ if (sa.st_nlink != sb.st_nlink - 1)
+ atf_tc_fail("incorrect link(2) count");
+
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(unlink(path) == 0);
+ ATF_REQUIRE(unlink(pathl) == 0);
+}
+
+ATF_TC_CLEANUP(link_count, tc)
+{
+ (void)unlink(path);
+ (void)unlink(pathl);
+}
+
+ATF_TC_WITH_CLEANUP(link_err);
+ATF_TC_HEAD(link_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions of link(2)");
+}
+
+ATF_TC_BODY(link_err, tc)
+{
+ char buf[MAXPATHLEN + 1];
+ int fd;
+
+ (void)memset(buf, 'x', sizeof(buf));
+
+ pathl = getpath();
+ fd = open(path, O_RDWR | O_CREAT, 0600);
+
+ ATF_REQUIRE(fd >= 0);
+ ATF_REQUIRE(pathl != NULL);
+
+ errno = 0;
+ ATF_REQUIRE(link(path, pathl) == 0);
+ ATF_REQUIRE_ERRNO(EEXIST, link(path, pathl) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENAMETOOLONG, link(buf, "xxx") == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, link(path, "/d/c/b/a") == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, link("/a/b/c/d", path) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, link("/a/b/c/d", "/d/c/b/a") == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, link(path, (const char *)-1) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, link((const char *)-1, "xxx") == -1);
+
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(unlink(path) == 0);
+ ATF_REQUIRE(unlink(pathl) == 0);
+}
+
+ATF_TC_CLEANUP(link_err, tc)
+{
+ (void)unlink(path);
+ (void)unlink(pathl);
+}
+
+ATF_TC(link_perm);
+ATF_TC_HEAD(link_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test permissions with link(2)");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(link_perm, tc)
+{
+ int rv;
+
+ errno = 0;
+ rv = link("/root", "/root.link");
+ ATF_REQUIRE_MSG(rv == -1 && (errno == EACCES || errno == EPERM),
+ "link to a directory did not fail with EPERM or EACCESS; link() "
+ "returned %d, errno %d", rv, errno);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EACCES,
+ link("/root/.profile", "/root/.profile.link") == -1);
+}
+
+ATF_TC_WITH_CLEANUP(link_stat);
+ATF_TC_HEAD(link_stat, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Check stat(2) of a linked file");
+}
+
+ATF_TC_BODY(link_stat, tc)
+{
+ struct stat sa, sb;
+ int fd;
+
+ (void)memset(&sa, 0, sizeof(struct stat));
+ (void)memset(&sb, 0, sizeof(struct stat));
+
+ pathl = getpath();
+ fd = open(path, O_RDWR | O_CREAT, 0600);
+
+ ATF_REQUIRE(fd >= 0);
+ ATF_REQUIRE(pathl != NULL);
+
+ ATF_REQUIRE(link(path, pathl) == 0);
+ ATF_REQUIRE(stat(path, &sa) == 0);
+ ATF_REQUIRE(lstat(pathl, &sb) == 0);
+
+ if (sa.st_uid != sb.st_uid)
+ atf_tc_fail("unequal UIDs");
+
+ if (sa.st_mode != sb.st_mode)
+ atf_tc_fail("unequal modes");
+
+ if (sa.st_ino != sb.st_ino)
+ atf_tc_fail("unequal inodes");
+
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(unlink(path) == 0);
+ ATF_REQUIRE(unlink(pathl) == 0);
+}
+
+ATF_TC_CLEANUP(link_stat, tc)
+{
+ (void)unlink(path);
+ (void)unlink(pathl);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, link_count);
+ ATF_TP_ADD_TC(tp, link_err);
+ ATF_TP_ADD_TC(tp, link_perm);
+ ATF_TP_ADD_TC(tp, link_stat);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_listen.c b/contrib/netbsd-tests/lib/libc/sys/t_listen.c
new file mode 100644
index 0000000..71201d3
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_listen.c
@@ -0,0 +1,134 @@
+/* $NetBSD: t_listen.c,v 1.4 2012/03/18 07:00:52 jruoho Exp $ */
+/*
+ * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 <atf-c.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+static const char *path = "listen";
+
+ATF_TC_WITH_CLEANUP(listen_err);
+ATF_TC_HEAD(listen_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Checks errors from listen(2) (PR standards/46150)");
+}
+
+ATF_TC_BODY(listen_err, tc)
+{
+ static const size_t siz = sizeof(struct sockaddr_in);
+ struct sockaddr_in sina, sinb;
+ int fda, fdb, fdc;
+
+ (void)memset(&sina, 0, sizeof(struct sockaddr_in));
+ (void)memset(&sinb, 0, sizeof(struct sockaddr_in));
+
+ sina.sin_family = AF_INET;
+ sina.sin_port = htons(31522);
+ sina.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+ sinb.sin_family = AF_INET;
+ sinb.sin_port = htons(31522);
+ sinb.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+ fda = socket(AF_INET, SOCK_STREAM, 0);
+ fdb = socket(AF_INET, SOCK_STREAM, 0);
+ fdc = open("listen", O_RDWR | O_CREAT, 0600);
+
+ ATF_REQUIRE(fda >= 0 && fdb >= 0 && fdc >= 0);
+ ATF_REQUIRE_ERRNO(ENOTSOCK, listen(fdc, 1) == -1);
+
+ (void)close(fdc);
+ (void)unlink(path);
+
+ ATF_REQUIRE(bind(fda, (struct sockaddr *)&sina, siz) == 0);
+ ATF_REQUIRE(listen(fda, 1) == 0);
+
+ /*
+ * According to IEEE Std 1003.1-2008: if the socket is
+ * already connected, the call should fail with EINVAL.
+ */
+ ATF_REQUIRE(connect(fdb, (struct sockaddr *)&sinb, siz) == 0);
+ ATF_REQUIRE_ERRNO(EINVAL, listen(fdb, 1) == -1);
+
+ (void)close(fda);
+ (void)close(fdb);
+
+ ATF_REQUIRE_ERRNO(EBADF, connect(fdb,
+ (struct sockaddr *)&sinb, siz) == -1);
+}
+
+ATF_TC_CLEANUP(listen_err, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(listen_low_port);
+ATF_TC_HEAD(listen_low_port, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Does low-port allocation work?");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(listen_low_port, tc)
+{
+ int sd, val;
+
+ sd = socket(AF_INET, SOCK_STREAM, 0);
+
+ val = IP_PORTRANGE_LOW;
+ if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, &val,
+ sizeof(val)) == -1)
+ atf_tc_fail("setsockopt failed: %s", strerror(errno));
+
+ if (listen(sd, 5) == -1) {
+ int serrno = errno;
+ atf_tc_fail("listen failed: %s%s",
+ strerror(serrno),
+ serrno != EACCES ? "" :
+ " (see http://mail-index.netbsd.org/"
+ "source-changes/2007/12/16/0011.html)");
+ }
+
+ close(sd);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, listen_err);
+ ATF_TP_ADD_TC(tp, listen_low_port);
+
+ return 0;
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_lwp_create.c b/contrib/netbsd-tests/lib/libc/sys/t_lwp_create.c
new file mode 100644
index 0000000..02545fe
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_lwp_create.c
@@ -0,0 +1,247 @@
+/* $NetBSD: t_lwp_create.c,v 1.2 2012/05/22 09:23:39 martin Exp $ */
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+/*
+ * This code is partly based on code by Joel Sing <joel at sing.id.au>
+ */
+
+#include <atf-c.h>
+#include <lwp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ucontext.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#ifdef __alpha__
+#include <machine/alpha_cpu.h>
+#endif
+#ifdef __amd64__
+#include <machine/vmparam.h>
+#include <machine/psl.h>
+#endif
+#ifdef __hppa__
+#include <machine/psl.h>
+#endif
+#ifdef __i386__
+#include <machine/segments.h>
+#include <machine/psl.h>
+#endif
+#if defined(__m68k__) || defined(__sh3__) || defined __vax__
+#include <machine/psl.h>
+#endif
+
+volatile lwpid_t the_lwp_id = 0;
+
+static void lwp_main_func(void* arg)
+{
+ the_lwp_id = _lwp_self();
+ _lwp_exit();
+}
+
+/*
+ * Hard to document - see usage examples below.
+ */
+#define INVALID_UCONTEXT(ARCH,NAME,DESC) \
+static void ARCH##_##NAME(ucontext_t *); \
+ATF_TC(lwp_create_##ARCH##_fail_##NAME); \
+ATF_TC_HEAD(lwp_create_##ARCH##_fail_##NAME, tc) \
+{ \
+ atf_tc_set_md_var(tc, "descr", "verify rejection of invalid ucontext " \
+ "on " #ARCH " due to " DESC); \
+} \
+ \
+ATF_TC_BODY(lwp_create_##ARCH##_fail_##NAME, tc) \
+{ \
+ ucontext_t uc; \
+ lwpid_t lid; \
+ int error; \
+ \
+ getcontext(&uc); \
+ uc.uc_flags = _UC_CPU; \
+ ARCH##_##NAME(&uc); \
+ \
+ error = _lwp_create(&uc, 0, &lid); \
+ ATF_REQUIRE(error != 0 && errno == EINVAL); \
+} \
+static void ARCH##_##NAME(ucontext_t *uc) \
+{
+
+
+ATF_TC(lwp_create_works);
+ATF_TC_HEAD(lwp_create_works, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Verify creation of a lwp and waiting"
+ " for it to finish");
+}
+
+ATF_TC_BODY(lwp_create_works, tc)
+{
+ ucontext_t uc;
+ lwpid_t lid;
+ int error;
+ void *stack;
+ static const size_t ssize = 16*1024;
+
+ stack = malloc(ssize);
+ _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize);
+
+ error = _lwp_create(&uc, 0, &lid);
+ ATF_REQUIRE(error == 0);
+
+ error = _lwp_wait(lid, NULL);
+ ATF_REQUIRE(error == 0);
+ ATF_REQUIRE(lid == the_lwp_id);
+}
+
+INVALID_UCONTEXT(generic, no_uc_cpu, "not setting cpu registers")
+ uc->uc_flags &= ~_UC_CPU;
+}
+
+#ifdef __alpha__
+INVALID_UCONTEXT(alpha, pslset, "trying to clear the USERMODE flag")
+ uc->uc_mcontext.__gregs[_REG_PS] &= ~ALPHA_PSL_USERMODE;
+}
+INVALID_UCONTEXT(alpha, pslclr, "trying to set a 'must be zero' flag")
+ uc->uc_mcontext.__gregs[_REG_PS] |= ALPHA_PSL_IPL_HIGH;
+}
+#endif
+#ifdef __amd64__
+INVALID_UCONTEXT(amd64, untouchable_rflags, "forbidden rflags changed")
+ uc->uc_mcontext.__gregs[_REG_RFLAGS] |= PSL_MBZ;
+}
+/*
+ * XXX: add invalid GS/DS selector tests
+ */
+INVALID_UCONTEXT(amd64, pc_too_high,
+ "instruction pointer outside userland address space")
+ uc->uc_mcontext.__gregs[_REG_RIP] = VM_MAXUSER_ADDRESS;
+}
+#endif
+#ifdef __arm__
+INVALID_UCONTEXT(arm, invalid_mode, "psr or r15 set to non-user-mode")
+ uc->uc_mcontext.__gregs[_REG_PC] |= 0x1f /*PSR_SYS32_MODE*/;
+ uc->uc_mcontext.__gregs[_REG_CPSR] |= 0x03 /*R15_MODE_SVC*/;
+}
+#endif
+#ifdef __hppa__
+INVALID_UCONTEXT(hppa, invalid_1, "set illegal bits in psw")
+ uc->uc_mcontext.__gregs[_REG_PSW] |= PSW_MBZ;
+}
+INVALID_UCONTEXT(hppa, invalid_0, "clear illegal bits in psw")
+ uc->uc_mcontext.__gregs[_REG_PSW] &= ~PSW_MBS;
+}
+#endif
+#ifdef __i386__
+INVALID_UCONTEXT(i386, untouchable_eflags, "changing forbidden eflags")
+ uc->uc_mcontext.__gregs[_REG_EFL] |= PSL_IOPL;
+}
+INVALID_UCONTEXT(i386, priv_escalation, "modifying priviledge level")
+ uc->uc_mcontext.__gregs[_REG_CS] &= ~SEL_RPL;
+}
+#endif
+#ifdef __m68k__
+INVALID_UCONTEXT(m68k, invalid_ps_bits,
+ "setting forbidden bits in the ps register")
+ uc->uc_mcontext.__gregs[_REG_PS] |= (PSL_MBZ|PSL_IPL|PSL_S);
+}
+#endif
+#ifdef __sh3__
+INVALID_UCONTEXT(sh3, modify_userstatic,
+ "modifying illegal bits in the status register")
+ uc->uc_mcontext.__gregs[_REG_SR] |= PSL_MD;
+}
+#endif
+#ifdef __sparc__
+INVALID_UCONTEXT(sparc, pc_odd, "mis-aligned instruction pointer")
+ uc->uc_mcontext.__gregs[_REG_PC] = 0x100002;
+}
+INVALID_UCONTEXT(sparc, npc_odd, "mis-aligned next instruction pointer")
+ uc->uc_mcontext.__gregs[_REG_nPC] = 0x100002;
+}
+INVALID_UCONTEXT(sparc, pc_null, "NULL instruction pointer")
+ uc->uc_mcontext.__gregs[_REG_PC] = 0;
+}
+INVALID_UCONTEXT(sparc, npc_null, "NULL next instruction pointer")
+ uc->uc_mcontext.__gregs[_REG_nPC] = 0;
+}
+#endif
+#ifdef __vax__
+INVALID_UCONTEXT(vax, psl_0, "clearing forbidden bits in psl")
+ uc->uc_mcontext.__gregs[_REG_PSL] &= ~(PSL_U | PSL_PREVU);
+}
+INVALID_UCONTEXT(vax, psl_1, "setting forbidden bits in psl")
+ uc->uc_mcontext.__gregs[_REG_PSL] |= PSL_IPL | PSL_IS;
+}
+INVALID_UCONTEXT(vax, psl_cm, "setting CM bit in psl")
+ uc->uc_mcontext.__gregs[_REG_PSL] |= PSL_CM;
+}
+#endif
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, lwp_create_works);
+ ATF_TP_ADD_TC(tp, lwp_create_generic_fail_no_uc_cpu);
+#ifdef __alpha__
+ ATF_TP_ADD_TC(tp, lwp_create_alpha_fail_pslset);
+ ATF_TP_ADD_TC(tp, lwp_create_alpha_fail_pslclr);
+#endif
+#ifdef __amd64__
+ ATF_TP_ADD_TC(tp, lwp_create_amd64_fail_untouchable_rflags);
+ ATF_TP_ADD_TC(tp, lwp_create_amd64_fail_pc_too_high);
+#endif
+#ifdef __arm__
+ ATF_TP_ADD_TC(tp, lwp_create_arm_fail_invalid_mode);
+#endif
+#ifdef __hppa__
+ ATF_TP_ADD_TC(tp, lwp_create_hppa_fail_invalid_1);
+ ATF_TP_ADD_TC(tp, lwp_create_hppa_fail_invalid_0);
+#endif
+#ifdef __i386__
+ ATF_TP_ADD_TC(tp, lwp_create_i386_fail_untouchable_eflags);
+ ATF_TP_ADD_TC(tp, lwp_create_i386_fail_priv_escalation);
+#endif
+#ifdef __m68k__
+ ATF_TP_ADD_TC(tp, lwp_create_m68k_fail_invalid_ps_bits);
+#endif
+#ifdef __sh3__
+ ATF_TP_ADD_TC(tp, lwp_create_sh3_fail_modify_userstatic);
+#endif
+#ifdef __sparc__
+ ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_pc_odd);
+ ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_npc_odd);
+ ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_pc_null);
+ ATF_TP_ADD_TC(tp, lwp_create_sparc_fail_npc_null);
+#endif
+#ifdef __vax__
+ ATF_TP_ADD_TC(tp, lwp_create_vax_fail_psl_0);
+ ATF_TP_ADD_TC(tp, lwp_create_vax_fail_psl_1);
+ ATF_TP_ADD_TC(tp, lwp_create_vax_fail_psl_cm);
+#endif
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_lwp_ctl.c b/contrib/netbsd-tests/lib/libc/sys/t_lwp_ctl.c
new file mode 100644
index 0000000..1b28f75
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_lwp_ctl.c
@@ -0,0 +1,74 @@
+/* $NetBSD: t_lwp_ctl.c,v 1.2 2012/03/18 06:20:51 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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>
+__COPYRIGHT("@(#) Copyright (c) 2008\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_lwp_ctl.c,v 1.2 2012/03/18 06:20:51 jruoho Exp $");
+
+#include <sys/lwpctl.h>
+
+#include <atf-c.h>
+#include <lwp.h>
+#include <stdio.h>
+#include <time.h>
+
+ATF_TC(lwpctl_counter);
+ATF_TC_HEAD(lwpctl_counter, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks lwpctl preemption counter");
+}
+
+ATF_TC_BODY(lwpctl_counter, tc)
+{
+ lwpctl_t *lc;
+ struct timespec ts;
+ int ctr1, ctr2;
+
+ ATF_REQUIRE(_lwp_ctl(LWPCTL_FEATURE_PCTR, &lc) == 0);
+
+ /* Ensure that preemption is reported. */
+ ctr1 = lc->lc_pctr;
+ (void)printf("pctr = %d\n", ctr1);
+ ts.tv_nsec = 10*1000000;
+ ts.tv_sec = 0;
+
+ ATF_REQUIRE(nanosleep(&ts, 0) != -1);
+
+ ctr2 = lc->lc_pctr;
+ (void)printf("pctr = %d\n", ctr2);
+
+ ATF_REQUIRE_MSG(ctr1 != ctr2, "counters match");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, lwpctl_counter);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_mincore.c b/contrib/netbsd-tests/lib/libc/sys/t_mincore.c
new file mode 100644
index 0000000..553207a
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_mincore.c
@@ -0,0 +1,318 @@
+/* $NetBSD: t_mincore.c,v 1.8 2012/06/08 07:18:58 martin Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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.
+ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * 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: t_mincore.c,v 1.8 2012/06/08 07:18:58 martin Exp $");
+
+#include <sys/mman.h>
+#include <sys/shm.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/resource.h>
+
+static long page = 0;
+static const char path[] = "mincore";
+static size_t check_residency(void *, size_t);
+
+static size_t
+check_residency(void *addr, size_t npgs)
+{
+ size_t i, resident;
+ char *vec;
+
+ vec = malloc(npgs);
+
+ ATF_REQUIRE(vec != NULL);
+ ATF_REQUIRE(mincore(addr, npgs * page, vec) == 0);
+
+ for (i = resident = 0; i < npgs; i++) {
+
+ if (vec[i] != 0)
+ resident++;
+
+#if 0
+ (void)fprintf(stderr, "page 0x%p is %sresident\n",
+ (char *)addr + (i * page), vec[i] ? "" : "not ");
+#endif
+ }
+
+ free(vec);
+
+ return resident;
+}
+
+ATF_TC(mincore_err);
+ATF_TC_HEAD(mincore_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from mincore(2)");
+}
+
+ATF_TC_BODY(mincore_err, tc)
+{
+ char *map, *vec;
+
+ map = mmap(NULL, page, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
+ vec = malloc(page);
+
+ ATF_REQUIRE(vec != NULL);
+ ATF_REQUIRE(map != MAP_FAILED);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, mincore(map, 0, vec) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOMEM, mincore(0, page, vec) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, mincore(map, page, (void *)-1) == -1);
+
+ free(vec);
+ ATF_REQUIRE(munmap(map, page) == 0);
+}
+
+ATF_TC_WITH_CLEANUP(mincore_resid);
+ATF_TC_HEAD(mincore_resid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test page residency with mincore(2)");
+}
+
+ATF_TC_BODY(mincore_resid, tc)
+{
+ void *addr, *addr2, *addr3, *buf;
+ size_t npgs = 0, resident;
+ struct stat st;
+ int fd, rv;
+ struct rlimit rlim;
+
+ ATF_REQUIRE(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
+ rlim.rlim_cur = rlim.rlim_max;
+ ATF_REQUIRE(setrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
+
+ (void)memset(&st, 0, sizeof(struct stat));
+
+ fd = open(path, O_RDWR | O_CREAT, 0700);
+ buf = malloc(page * 5);
+
+ ATF_REQUIRE(fd >= 0);
+ ATF_REQUIRE(buf != NULL);
+
+ rv = write(fd, buf, page * 5);
+ ATF_REQUIRE(rv >= 0);
+
+ ATF_REQUIRE(fd >= 0);
+ ATF_REQUIRE(fstat(fd, &st) == 0);
+
+ addr = mmap(NULL, (size_t)st.st_size, PROT_READ,
+ MAP_FILE | MAP_SHARED, fd, (off_t) 0);
+
+ ATF_REQUIRE(addr != MAP_FAILED);
+
+ (void)close(fd);
+
+ npgs = st.st_size / page;
+
+ if (st.st_size % page != 0)
+ npgs++;
+
+ (void)check_residency(addr, npgs);
+
+ rv = mlock(addr, npgs * page);
+ if (rv == -1 && errno == EAGAIN)
+ atf_tc_skip("hit process resource limits");
+ ATF_REQUIRE(munmap(addr, st.st_size) == 0);
+
+ npgs = 128;
+
+ addr = mmap(NULL, npgs * page, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE | MAP_WIRED, -1, (off_t)0);
+
+ if (addr == MAP_FAILED)
+ atf_tc_skip("could not mmap wired anonymous test area, system "
+ "might be low on memory");
+
+ ATF_REQUIRE(check_residency(addr, npgs) == npgs);
+ ATF_REQUIRE(munmap(addr, npgs * page) == 0);
+
+ npgs = 128;
+
+ addr = mmap(NULL, npgs * page, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, (off_t)0);
+
+ ATF_REQUIRE(addr != MAP_FAILED);
+
+ /*
+ * Check that the in-core pages match the locked pages.
+ */
+ ATF_REQUIRE(check_residency(addr, npgs) == 0);
+
+ errno = 0;
+ if (mlockall(MCL_CURRENT|MCL_FUTURE) != 0 && errno != ENOMEM)
+ atf_tc_fail("mlockall(2) failed");
+ if (errno == ENOMEM)
+ atf_tc_skip("mlockall() exceeded process resource limits");
+
+ resident = check_residency(addr, npgs);
+ if (resident < npgs)
+ atf_tc_fail("mlockall(MCL_FUTURE) succeeded, still only "
+ "%zu pages of the newly mapped %zu pages are resident",
+ resident, npgs);
+
+ addr2 = mmap(NULL, npgs * page, PROT_READ, MAP_ANON, -1, (off_t)0);
+ addr3 = mmap(NULL, npgs * page, PROT_NONE, MAP_ANON, -1, (off_t)0);
+
+ if (addr2 == MAP_FAILED || addr3 == MAP_FAILED)
+ atf_tc_skip("could not mmap more anonymous test pages with "
+ "mlockall(MCL_FUTURE) in effect, system "
+ "might be low on memory");
+
+ ATF_REQUIRE(check_residency(addr2, npgs) == npgs);
+ ATF_REQUIRE(check_residency(addr3, npgs) == 0);
+ ATF_REQUIRE(mprotect(addr3, npgs * page, PROT_READ) == 0);
+ ATF_REQUIRE(check_residency(addr, npgs) == npgs);
+ ATF_REQUIRE(check_residency(addr2, npgs) == npgs);
+
+ (void)munlockall();
+
+ ATF_REQUIRE(madvise(addr2, npgs * page, MADV_FREE) == 0);
+ ATF_REQUIRE(check_residency(addr2, npgs) == 0);
+
+ (void)memset(addr, 0, npgs * page);
+
+ ATF_REQUIRE(madvise(addr, npgs * page, MADV_FREE) == 0);
+ ATF_REQUIRE(check_residency(addr, npgs) == 0);
+
+ (void)munmap(addr, npgs * page);
+ (void)munmap(addr2, npgs * page);
+ (void)munmap(addr3, npgs * page);
+ (void)unlink(path);
+}
+
+ATF_TC_CLEANUP(mincore_resid, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(mincore_shmseg);
+ATF_TC_HEAD(mincore_shmseg, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "residency of shared memory");
+}
+
+ATF_TC_BODY(mincore_shmseg, tc)
+{
+ size_t npgs = 128;
+ void *addr = NULL;
+ int shmid;
+
+ shmid = shmget(IPC_PRIVATE, npgs * page,
+ IPC_CREAT | S_IRUSR | S_IWUSR);
+
+ ATF_REQUIRE(shmid != -1);
+
+ addr = shmat(shmid, NULL, 0);
+
+ ATF_REQUIRE(addr != NULL);
+ ATF_REQUIRE(check_residency(addr, npgs) == 0);
+
+ (void)memset(addr, 0xff, npgs * page);
+
+ ATF_REQUIRE(check_residency(addr, npgs) == npgs);
+ ATF_REQUIRE(madvise(addr, npgs * page, MADV_FREE) == 0);
+
+ /*
+ * NOTE! Even though we have MADV_FREE'd the range,
+ * there is another reference (the kernel's) to the
+ * object which owns the pages. In this case, the
+ * kernel does not simply free the pages, as haphazardly
+ * freeing pages when there are still references to
+ * an object can cause data corruption (say, the other
+ * referencer doesn't expect the pages to be freed,
+ * and is surprised by the subsequent ZFOD).
+ *
+ * Because of this, we simply report the number of
+ * pages still resident, for information only.
+ */
+ npgs = check_residency(addr, npgs);
+
+ (void)fprintf(stderr, "%zu pages still resident\n", npgs);
+
+ ATF_REQUIRE(shmdt(addr) == 0);
+ ATF_REQUIRE(shmctl(shmid, IPC_RMID, NULL) == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ page = sysconf(_SC_PAGESIZE);
+ ATF_REQUIRE(page >= 0);
+
+ ATF_TP_ADD_TC(tp, mincore_err);
+ ATF_TP_ADD_TC(tp, mincore_resid);
+ ATF_TP_ADD_TC(tp, mincore_shmseg);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_minherit.c b/contrib/netbsd-tests/lib/libc/sys/t_minherit.c
new file mode 100644
index 0000000..0bdf6bc
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_minherit.c
@@ -0,0 +1,200 @@
+/* $NetBSD: t_minherit.c,v 1.1 2014/07/18 12:34:52 christos Exp $ */
+
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas
+ *
+ * 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: t_minherit.c,v 1.1 2014/07/18 12:34:52 christos Exp $");
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+static long page;
+
+static void *
+makemap(int v, int f) {
+ void *map = mmap(NULL, page, PROT_READ|PROT_WRITE,
+ MAP_SHARED|MAP_ANON, -1, 0);
+ ATF_REQUIRE(map != MAP_FAILED);
+ memset(map, v, page);
+ if (f != 666)
+ ATF_REQUIRE(minherit(map, page, f) == 0);
+ else
+ ATF_REQUIRE(minherit(map, page, f) == -1);
+ return map;
+}
+
+ATF_TC(minherit_copy);
+ATF_TC_HEAD(minherit_copy, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test for MAP_INHERIT_COPY from minherit(2)");
+}
+
+ATF_TC_BODY(minherit_copy, tc)
+{
+ void *map1 = makemap(1, MAP_INHERIT_COPY);
+ void *map2 = makemap(1, MAP_INHERIT_COPY);
+ switch (fork()) {
+ default:
+ ATF_REQUIRE(wait(NULL) != -1);
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ break;
+ case -1:
+ ATF_REQUIRE(0);
+ break;
+ case 0:
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ memset(map1, 0, page);
+ exit(0);
+ }
+}
+
+ATF_TC(minherit_share);
+ATF_TC_HEAD(minherit_share, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test for MAP_INHERIT_SHARE from minherit(2)");
+}
+
+ATF_TC_BODY(minherit_share, tc)
+{
+ void *map1 = makemap(1, MAP_INHERIT_SHARE);
+ void *map2 = makemap(1, MAP_INHERIT_SHARE);
+
+ switch (fork()) {
+ default:
+ ATF_REQUIRE(wait(NULL) != -1);
+ memset(map2, 0, page);
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ break;
+ case -1:
+ ATF_REQUIRE(0);
+ break;
+ case 0:
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ memset(map1, 0, page);
+ exit(0);
+ }
+}
+
+static void
+segv(int n) {
+ _exit(n);
+}
+
+ATF_TC(minherit_none);
+ATF_TC_HEAD(minherit_none, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test for MAP_INHERIT_NONE from minherit(2)");
+}
+
+ATF_TC_BODY(minherit_none, tc)
+{
+ void *map1 = makemap(0, MAP_INHERIT_NONE);
+ int status;
+
+ switch (fork()) {
+ default:
+ ATF_REQUIRE(wait(&status) != -1);
+ ATF_REQUIRE(WEXITSTATUS(status) == SIGSEGV);
+ break;
+ case -1:
+ ATF_REQUIRE(0);
+ break;
+ case 0:
+ ATF_REQUIRE(signal(SIGSEGV, segv) != SIG_ERR);
+ memset(map1, 0, page);
+ exit(0);
+ }
+}
+
+ATF_TC(minherit_zero);
+ATF_TC_HEAD(minherit_zero, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test for MAP_INHERIT_ZERO from minherit(2)");
+}
+
+ATF_TC_BODY(minherit_zero, tc)
+{
+ void *map1 = makemap(1, MAP_INHERIT_ZERO);
+ void *map2 = makemap(0, MAP_INHERIT_SHARE);
+
+ switch (fork()) {
+ default:
+ ATF_REQUIRE(wait(NULL) != -1);
+ memset(map2, 1, page);
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ break;
+ case -1:
+ ATF_REQUIRE(0);
+ break;
+ case 0:
+ ATF_REQUIRE(memcmp(map1, map2, page) == 0);
+ memset(map1, 2, page);
+ exit(0);
+ }
+}
+
+ATF_TC(minherit_bad);
+ATF_TC_HEAD(minherit_bad, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test for bad minherit(2)");
+}
+
+ATF_TC_BODY(minherit_bad, tc)
+{
+ (void)makemap(0, 666);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ page = sysconf(_SC_PAGESIZE);
+ ATF_REQUIRE(page >= 0);
+
+ ATF_TP_ADD_TC(tp, minherit_copy);
+ ATF_TP_ADD_TC(tp, minherit_share);
+ ATF_TP_ADD_TC(tp, minherit_none);
+ ATF_TP_ADD_TC(tp, minherit_zero);
+ ATF_TP_ADD_TC(tp, minherit_bad);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_mkdir.c b/contrib/netbsd-tests/lib/libc/sys/t_mkdir.c
new file mode 100644
index 0000000..d97a20b
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_mkdir.c
@@ -0,0 +1,210 @@
+/* $NetBSD: t_mkdir.c,v 1.2 2011/10/15 07:38:31 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2008, 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe and Jukka Ruohonen.
+ *
+ * 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>
+__COPYRIGHT("@(#) Copyright (c) 2008\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_mkdir.c,v 1.2 2011/10/15 07:38:31 jruoho Exp $");
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+ATF_TC(mkdir_err);
+ATF_TC_HEAD(mkdir_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks errors from mkdir(2)");
+}
+
+ATF_TC_BODY(mkdir_err, tc)
+{
+ char buf[PATH_MAX + 1];
+ int fd;
+
+ (void)memset(buf, 'x', sizeof(buf));
+
+ fd = open("/etc", O_RDONLY);
+
+ if (fd >= 0) {
+
+ (void)close(fd);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EEXIST, mkdir("/etc", 0500) == -1);
+ }
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, mkdir((void *)-1, 0500) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENAMETOOLONG, mkdir(buf, 0500) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, mkdir("/a/b/c/d/e/f/g/h/i/j/k", 0500) == -1);
+}
+
+ATF_TC_WITH_CLEANUP(mkdir_perm);
+ATF_TC_HEAD(mkdir_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks permissions with mkdir(2)");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(mkdir_perm, tc)
+{
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EACCES, mkdir("/usr/__nonexistent__", 0500) == -1);
+}
+
+ATF_TC_CLEANUP(mkdir_perm, tc)
+{
+ (void)rmdir("/usr/__nonexistent__");
+}
+
+ATF_TC_WITH_CLEANUP(mkdir_mode);
+ATF_TC_HEAD(mkdir_mode, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test that UIDs and GIDs are right "
+ "for a directory created with mkdir(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(mkdir_mode, tc)
+{
+ static const char *path = "/tmp/mkdir";
+ struct stat st_a, st_b;
+ struct passwd *pw;
+ pid_t pid;
+ int sta;
+
+ (void)memset(&st_a, 0, sizeof(struct stat));
+ (void)memset(&st_b, 0, sizeof(struct stat));
+
+ pw = getpwnam("nobody");
+
+ ATF_REQUIRE(pw != NULL);
+ ATF_REQUIRE(stat("/tmp", &st_a) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ if (setuid(pw->pw_uid) != 0)
+ _exit(EXIT_FAILURE);
+
+ if (mkdir(path, 0500) != 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)sleep(1);
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("failed to create '%s'", path);
+
+ ATF_REQUIRE(stat(path, &st_b) == 0);
+ ATF_REQUIRE(rmdir(path) == 0);
+
+ /*
+ * The directory's owner ID should be set to the
+ * effective UID, whereas the group ID should be
+ * set to that of the parent directory.
+ */
+ if (st_b.st_uid != pw->pw_uid)
+ atf_tc_fail("invalid UID for '%s'", path);
+
+ if (st_b.st_gid != st_a.st_gid)
+ atf_tc_fail("GID did not follow the parent directory");
+}
+
+ATF_TC_CLEANUP(mkdir_mode, tc)
+{
+ (void)rmdir("/tmp/mkdir");
+}
+
+ATF_TC(mkdir_trail);
+ATF_TC_HEAD(mkdir_trail, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks mkdir(2) for trailing slashes");
+}
+
+ATF_TC_BODY(mkdir_trail, tc)
+{
+ const char *tests[] = {
+ /*
+ * IEEE 1003.1 second ed. 2.2.2.78:
+ *
+ * If the pathname refers to a directory, it may also have
+ * one or more trailing slashes. Multiple successive slashes
+ * are considered to be the same as one slash.
+ */
+ "dir1/",
+ "dir2//",
+
+ NULL,
+ };
+
+ const char **test;
+
+ for (test = &tests[0]; *test != NULL; ++test) {
+
+ (void)printf("Checking \"%s\"\n", *test);
+ (void)rmdir(*test);
+
+ ATF_REQUIRE(mkdir(*test, 0777) == 0);
+ ATF_REQUIRE(rename(*test, "foo") == 0);
+ ATF_REQUIRE(rename("foo/", *test) == 0);
+ ATF_REQUIRE(rmdir(*test) == 0);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mkdir_err);
+ ATF_TP_ADD_TC(tp, mkdir_perm);
+ ATF_TP_ADD_TC(tp, mkdir_mode);
+ ATF_TP_ADD_TC(tp, mkdir_trail);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_mkfifo.c b/contrib/netbsd-tests/lib/libc/sys/t_mkfifo.c
new file mode 100644
index 0000000..56bc4c8
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_mkfifo.c
@@ -0,0 +1,276 @@
+/* $NetBSD: t_mkfifo.c,v 1.2 2011/11/02 06:04:48 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_mkfifo.c,v 1.2 2011/11/02 06:04:48 jruoho Exp $");
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+static const char path[] = "fifo";
+static void support(void);
+
+static void
+support(void)
+{
+
+ errno = 0;
+
+ if (mkfifo(path, 0600) == 0) {
+ ATF_REQUIRE(unlink(path) == 0);
+ return;
+ }
+
+ if (errno == EOPNOTSUPP)
+ atf_tc_skip("the kernel does not support FIFOs");
+ else {
+ atf_tc_fail("mkfifo(2) failed");
+ }
+}
+
+ATF_TC_WITH_CLEANUP(mkfifo_block);
+ATF_TC_HEAD(mkfifo_block, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test that FIFOs block");
+}
+
+ATF_TC_BODY(mkfifo_block, tc)
+{
+ int sta, fd = -1;
+ pid_t pid;
+
+ support();
+
+ ATF_REQUIRE(mkfifo(path, 0600) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ /*
+ * If we open the FIFO as read-only (write-only),
+ * the call should block until another process
+ * opens the FIFO for writing (reading).
+ */
+ fd = open(path, O_RDONLY);
+
+ _exit(EXIT_FAILURE); /* NOTREACHED */
+ }
+
+ (void)sleep(1);
+
+ ATF_REQUIRE(kill(pid, SIGKILL) == 0);
+
+ (void)wait(&sta);
+
+ if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != SIGKILL)
+ atf_tc_fail("FIFO did not block");
+
+ (void)close(fd);
+ (void)unlink(path);
+}
+
+ATF_TC_CLEANUP(mkfifo_block, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(mkfifo_err);
+ATF_TC_HEAD(mkfifo_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test erros from mkfifo(2)");
+}
+
+ATF_TC_BODY(mkfifo_err, tc)
+{
+ char buf[PATH_MAX + 1];
+
+ support();
+
+ (void)memset(buf, 'x', sizeof(buf));
+ ATF_REQUIRE(mkfifo(path, 0600) == 0);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, mkfifo((char *)-1, 0600) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EEXIST, mkfifo("/etc/passwd", 0600) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EEXIST, mkfifo(path, 0600) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENAMETOOLONG, mkfifo(buf, 0600) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, mkfifo("/a/b/c/d/e/f/g", 0600) == -1);
+
+ ATF_REQUIRE(unlink(path) == 0);
+}
+
+ATF_TC_CLEANUP(mkfifo_err, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(mkfifo_nonblock);
+ATF_TC_HEAD(mkfifo_nonblock, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test O_NONBLOCK with FIFOs");
+}
+
+ATF_TC_BODY(mkfifo_nonblock, tc)
+{
+ int fd, sta;
+ pid_t pid;
+
+ support();
+
+ fd = -1;
+ ATF_REQUIRE(mkfifo(path, 0600) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ /*
+ * If we open the FIFO as O_NONBLOCK, the O_RDONLY
+ * call should return immediately, whereas the call
+ * for write-only should fail with ENXIO.
+ */
+ fd = open(path, O_RDONLY | O_NONBLOCK);
+
+ if (fd >= 0)
+ _exit(EXIT_SUCCESS);
+
+ (void)pause(); /* NOTREACHED */
+ }
+
+ (void)sleep(1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENXIO, open(path, O_WRONLY | O_NONBLOCK) == -1);
+
+ (void)kill(pid, SIGKILL);
+ (void)wait(&sta);
+
+ if (WIFSIGNALED(sta) != 0 || WTERMSIG(sta) == SIGKILL)
+ atf_tc_fail("FIFO blocked for O_NONBLOCK open(2)");
+
+ (void)close(fd);
+ (void)unlink(path);
+}
+
+ATF_TC_CLEANUP(mkfifo_nonblock, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(mkfifo_perm);
+ATF_TC_HEAD(mkfifo_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test permissions with mkfifo(2)");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(mkfifo_perm, tc)
+{
+
+ support();
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EACCES, mkfifo("/root/fifo", 0600) == -1);
+
+ ATF_REQUIRE(mkfifo(path, 0600) == 0);
+
+ /*
+ * For some reason this fails with EFTYPE...
+ */
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFTYPE, chmod(path, 1777) == -1);
+
+ ATF_REQUIRE(unlink(path) == 0);
+}
+
+ATF_TC_CLEANUP(mkfifo_perm, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(mkfifo_stat);
+ATF_TC_HEAD(mkfifo_stat, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test mkfifo(2) with stat");
+}
+
+ATF_TC_BODY(mkfifo_stat, tc)
+{
+ struct stat st;
+
+ support();
+
+ (void)memset(&st, 0, sizeof(struct stat));
+
+ ATF_REQUIRE(mkfifo(path, 0600) == 0);
+ ATF_REQUIRE(stat(path, &st) == 0);
+
+ if (S_ISFIFO(st.st_mode) == 0)
+ atf_tc_fail("invalid mode from mkfifo(2)");
+
+ ATF_REQUIRE(unlink(path) == 0);
+}
+
+ATF_TC_CLEANUP(mkfifo_stat, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mkfifo_block);
+ ATF_TP_ADD_TC(tp, mkfifo_err);
+ ATF_TP_ADD_TC(tp, mkfifo_nonblock);
+ ATF_TP_ADD_TC(tp, mkfifo_perm);
+ ATF_TP_ADD_TC(tp, mkfifo_stat);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_mknod.c b/contrib/netbsd-tests/lib/libc/sys/t_mknod.c
new file mode 100644
index 0000000..b394b31
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_mknod.c
@@ -0,0 +1,192 @@
+/* $NetBSD: t_mknod.c,v 1.2 2012/03/18 07:00:52 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_mknod.c,v 1.2 2012/03/18 07:00:52 jruoho Exp $");
+
+#include <sys/stat.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static char path[] = "node";
+
+ATF_TC_WITH_CLEANUP(mknod_err);
+ATF_TC_HEAD(mknod_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test error conditions of mknod(2) (PR kern/45111)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(mknod_err, tc)
+{
+ char buf[PATH_MAX + 1];
+
+ (void)memset(buf, 'x', sizeof(buf));
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, mknod(path, S_IFCHR, -1) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENAMETOOLONG, mknod(buf, S_IFCHR, 0) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, mknod((char *)-1, S_IFCHR, 0) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, mknod("/a/b/c/d/e/f/g", S_IFCHR, 0) == -1);
+}
+
+ATF_TC_CLEANUP(mknod_err, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(mknod_exist);
+ATF_TC_HEAD(mknod_exist, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test EEXIST from mknod(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(mknod_exist, tc)
+{
+ int fd;
+
+ fd = open("/etc/passwd", O_RDONLY);
+
+ if (fd >= 0) {
+
+ (void)close(fd);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EEXIST,
+ mknod("/etc/passwd", S_IFCHR, 0) == -1);
+ }
+
+ ATF_REQUIRE(mknod(path, S_IFCHR, 0) == 0);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EEXIST, mknod(path, S_IFCHR, 0) == -1);
+
+ ATF_REQUIRE(unlink(path) == 0);
+}
+
+ATF_TC_CLEANUP(mknod_exist, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(mknod_perm);
+ATF_TC_HEAD(mknod_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test permissions of mknod(2)");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(mknod_perm, tc)
+{
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EPERM, mknod(path, S_IFCHR, 0) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EPERM, mknod(path, S_IFBLK, 0) == -1);
+}
+
+ATF_TC_CLEANUP(mknod_perm, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(mknod_stat);
+ATF_TC_HEAD(mknod_stat, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of mknod(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(mknod_stat, tc)
+{
+ struct stat st;
+
+ (void)memset(&st, 0, sizeof(struct stat));
+
+ ATF_REQUIRE(mknod(path, S_IFCHR, 0) == 0);
+ ATF_REQUIRE(stat(path, &st) == 0);
+
+ if (S_ISCHR(st.st_mode) == 0)
+ atf_tc_fail_nonfatal("invalid mode from mknod(2) (S_IFCHR)");
+
+ ATF_REQUIRE(unlink(path) == 0);
+
+ (void)memset(&st, 0, sizeof(struct stat));
+
+ ATF_REQUIRE(mknod(path, S_IFBLK, 0) == 0);
+ ATF_REQUIRE(stat(path, &st) == 0);
+
+ if (S_ISBLK(st.st_mode) == 0)
+ atf_tc_fail_nonfatal("invalid mode from mknod(2) (S_IFBLK)");
+
+ ATF_REQUIRE(unlink(path) == 0);
+
+ (void)memset(&st, 0, sizeof(struct stat));
+
+ ATF_REQUIRE(mknod(path, S_IFREG, 0) == 0);
+ ATF_REQUIRE(stat(path, &st) == 0);
+
+ if (S_ISREG(st.st_mode) == 0)
+ atf_tc_fail_nonfatal("invalid mode from mknod(2) (S_IFREG)");
+
+ ATF_REQUIRE(unlink(path) == 0);
+}
+
+ATF_TC_CLEANUP(mknod_stat, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, mknod_err);
+ ATF_TP_ADD_TC(tp, mknod_exist);
+ ATF_TP_ADD_TC(tp, mknod_perm);
+ ATF_TP_ADD_TC(tp, mknod_stat);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_mlock.c b/contrib/netbsd-tests/lib/libc/sys/t_mlock.c
new file mode 100644
index 0000000..52576f7
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_mlock.c
@@ -0,0 +1,244 @@
+/* $NetBSD: t_mlock.c,v 1.5 2014/02/26 20:49:26 martin Exp $ */
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_mlock.c,v 1.5 2014/02/26 20:49:26 martin Exp $");
+
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <atf-c.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static long page = 0;
+
+ATF_TC(mlock_clip);
+ATF_TC_HEAD(mlock_clip, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test with mlock(2) that UVM only "
+ "clips if the clip address is within the entry (PR kern/44788)");
+}
+
+ATF_TC_BODY(mlock_clip, tc)
+{
+ void *buf;
+
+ buf = malloc(page);
+ ATF_REQUIRE(buf != NULL);
+
+ if (page < 1024)
+ atf_tc_skip("page size too small");
+
+ for (size_t i = page; i >= 1; i = i - 1024) {
+ (void)mlock(buf, page - i);
+ (void)munlock(buf, page - i);
+ }
+
+ free(buf);
+}
+
+ATF_TC(mlock_err);
+ATF_TC_HEAD(mlock_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test error conditions in mlock(2) and munlock(2)");
+}
+
+ATF_TC_BODY(mlock_err, tc)
+{
+ unsigned long vmin = 0;
+ size_t len = sizeof(vmin);
+ void *invalid_ptr;
+ int null_errno = ENOMEM; /* error expected for NULL */
+
+ if (sysctlbyname("vm.minaddress", &vmin, &len, NULL, 0) != 0)
+ atf_tc_fail("failed to read vm.minaddress");
+
+ if (vmin > 0)
+ null_errno = EINVAL; /* NULL is not inside user VM */
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(null_errno, mlock(NULL, page) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(null_errno, mlock((char *)0, page) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, mlock((char *)-1, page) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(null_errno, munlock(NULL, page) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(null_errno, munlock((char *)0, page) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, munlock((char *)-1, page) == -1);
+
+ /*
+ * Try to create a pointer to an unmapped page - first after current
+ * brk will likely do.
+ */
+ invalid_ptr = (void*)(((uintptr_t)sbrk(0)+page) & ~(page-1));
+ printf("testing with (hopefully) invalid pointer %p\n", invalid_ptr);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOMEM, mlock(invalid_ptr, page) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOMEM, munlock(invalid_ptr, page) == -1);
+}
+
+ATF_TC(mlock_limits);
+ATF_TC_HEAD(mlock_limits, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test system limits with mlock(2)");
+}
+
+ATF_TC_BODY(mlock_limits, tc)
+{
+ struct rlimit res;
+ void *buf;
+ pid_t pid;
+ int sta;
+
+ buf = malloc(page);
+ ATF_REQUIRE(buf != NULL);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ for (ssize_t i = page; i >= 2; i -= 100) {
+
+ res.rlim_cur = i - 1;
+ res.rlim_max = i - 1;
+
+ (void)fprintf(stderr, "trying to lock %zd bytes "
+ "with %zu byte limit\n", i, (size_t)res.rlim_cur);
+
+ if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
+ _exit(EXIT_FAILURE);
+
+ errno = 0;
+
+ if (mlock(buf, i) != -1 || errno != EAGAIN) {
+ (void)munlock(buf, i);
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("mlock(2) locked beyond system limits");
+
+ free(buf);
+}
+
+ATF_TC(mlock_mmap);
+ATF_TC_HEAD(mlock_mmap, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test mlock(2)-mmap(2) interaction");
+}
+
+ATF_TC_BODY(mlock_mmap, tc)
+{
+ static const int flags = MAP_ANON | MAP_PRIVATE | MAP_WIRED;
+ void *buf;
+
+ /*
+ * Make a wired RW mapping and check that mlock(2)
+ * does not fail for the (already locked) mapping.
+ */
+ buf = mmap(NULL, page, PROT_READ | PROT_WRITE, flags, -1, 0);
+
+ ATF_REQUIRE(buf != MAP_FAILED);
+ ATF_REQUIRE(mlock(buf, page) == 0);
+ ATF_REQUIRE(munlock(buf, page) == 0);
+ ATF_REQUIRE(munmap(buf, page) == 0);
+ ATF_REQUIRE(munlock(buf, page) != 0);
+
+ /*
+ * But it should be impossible to mlock(2) a PROT_NONE mapping.
+ */
+ buf = mmap(NULL, page, PROT_NONE, flags, -1, 0);
+
+ ATF_REQUIRE(buf != MAP_FAILED);
+ ATF_REQUIRE(mlock(buf, page) != 0);
+ ATF_REQUIRE(munmap(buf, page) == 0);
+}
+
+ATF_TC(mlock_nested);
+ATF_TC_HEAD(mlock_nested, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that consecutive mlock(2) calls succeed");
+}
+
+ATF_TC_BODY(mlock_nested, tc)
+{
+ const size_t maxiter = 100;
+ void *buf;
+
+ buf = malloc(page);
+ ATF_REQUIRE(buf != NULL);
+
+ for (size_t i = 0; i < maxiter; i++)
+ ATF_REQUIRE(mlock(buf, page) == 0);
+
+ ATF_REQUIRE(munlock(buf, page) == 0);
+ free(buf);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ page = sysconf(_SC_PAGESIZE);
+ ATF_REQUIRE(page >= 0);
+
+ ATF_TP_ADD_TC(tp, mlock_clip);
+ ATF_TP_ADD_TC(tp, mlock_err);
+ ATF_TP_ADD_TC(tp, mlock_limits);
+ ATF_TP_ADD_TC(tp, mlock_mmap);
+ ATF_TP_ADD_TC(tp, mlock_nested);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_mmap.c b/contrib/netbsd-tests/lib/libc/sys/t_mmap.c
new file mode 100644
index 0000000..c6b97b1
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_mmap.c
@@ -0,0 +1,505 @@
+/* $NetBSD: t_mmap.c,v 1.7 2012/06/14 17:47:58 bouyer Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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.
+ */
+
+/*-
+ * Copyright (c)2004 YAMAMOTO Takashi,
+ * All rights reserved.
+ *
+ * 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 AUTHOR 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 AUTHOR 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: t_mmap.c,v 1.7 2012/06/14 17:47:58 bouyer Exp $");
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <paths.h>
+#include <machine/disklabel.h>
+
+static long page = 0;
+static char path[] = "mmap";
+static void map_check(void *, int);
+static void map_sighandler(int);
+static void testloan(void *, void *, char, int);
+
+#define BUFSIZE (32 * 1024) /* enough size to trigger sosend_loan */
+
+static void
+map_check(void *map, int flag)
+{
+
+ if (flag != 0) {
+ ATF_REQUIRE(map == MAP_FAILED);
+ return;
+ }
+
+ ATF_REQUIRE(map != MAP_FAILED);
+ ATF_REQUIRE(munmap(map, page) == 0);
+}
+
+void
+testloan(void *vp, void *vp2, char pat, int docheck)
+{
+ char buf[BUFSIZE];
+ char backup[BUFSIZE];
+ ssize_t nwritten;
+ ssize_t nread;
+ int fds[2];
+ int val;
+
+ val = BUFSIZE;
+
+ if (docheck != 0)
+ (void)memcpy(backup, vp, BUFSIZE);
+
+ if (socketpair(AF_LOCAL, SOCK_STREAM, PF_UNSPEC, fds) != 0)
+ atf_tc_fail("socketpair() failed");
+
+ val = BUFSIZE;
+
+ if (setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) != 0)
+ atf_tc_fail("setsockopt() failed, SO_RCVBUF");
+
+ val = BUFSIZE;
+
+ if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) != 0)
+ atf_tc_fail("setsockopt() failed, SO_SNDBUF");
+
+ if (fcntl(fds[0], F_SETFL, O_NONBLOCK) != 0)
+ atf_tc_fail("fcntl() failed");
+
+ nwritten = write(fds[0], (char *)vp + page, BUFSIZE - page);
+
+ if (nwritten == -1)
+ atf_tc_fail("write() failed");
+
+ /* Break loan. */
+ (void)memset(vp2, pat, BUFSIZE);
+
+ nread = read(fds[1], buf + page, BUFSIZE - page);
+
+ if (nread == -1)
+ atf_tc_fail("read() failed");
+
+ if (nread != nwritten)
+ atf_tc_fail("too short read");
+
+ if (docheck != 0 && memcmp(backup, buf + page, nread) != 0)
+ atf_tc_fail("data mismatch");
+
+ ATF_REQUIRE(close(fds[0]) == 0);
+ ATF_REQUIRE(close(fds[1]) == 0);
+}
+
+static void
+map_sighandler(int signo)
+{
+ _exit(signo);
+}
+
+ATF_TC(mmap_block);
+ATF_TC_HEAD(mmap_block, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test mmap(2) with a block device");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(mmap_block, tc)
+{
+ static const int mib[] = { CTL_HW, HW_DISKNAMES };
+ static const unsigned int miblen = __arraycount(mib);
+ char *map, *dk, *drives, dev[PATH_MAX];
+ size_t len;
+ int fd = -1;
+
+ atf_tc_skip("The test case causes a panic (PR kern/38889, kern/46592)");
+
+ ATF_REQUIRE(sysctl(mib, miblen, NULL, &len, NULL, 0) == 0);
+ drives = malloc(len);
+ ATF_REQUIRE(drives != NULL);
+ ATF_REQUIRE(sysctl(mib, miblen, drives, &len, NULL, 0) == 0);
+ for (dk = strtok(drives, " "); dk != NULL; dk = strtok(NULL, " ")) {
+ sprintf(dev, _PATH_DEV "%s%c", dk, 'a'+RAW_PART);
+ fprintf(stderr, "trying: %s\n", dev);
+
+ if ((fd = open(dev, O_RDONLY)) >= 0) {
+ (void)fprintf(stderr, "using %s\n", dev);
+ break;
+ }
+ }
+ free(drives);
+
+ if (fd < 0)
+ atf_tc_skip("failed to find suitable block device");
+
+ map = mmap(NULL, 4096, PROT_READ, MAP_FILE, fd, 0);
+ ATF_REQUIRE(map != MAP_FAILED);
+
+ (void)fprintf(stderr, "first byte %x\n", *map);
+ ATF_REQUIRE(close(fd) == 0);
+ (void)fprintf(stderr, "first byte %x\n", *map);
+
+ ATF_REQUIRE(munmap(map, 4096) == 0);
+}
+
+ATF_TC(mmap_err);
+ATF_TC_HEAD(mmap_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions of mmap(2)");
+}
+
+ATF_TC_BODY(mmap_err, tc)
+{
+ size_t addr = SIZE_MAX;
+ void *map;
+
+ errno = 0;
+ map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, -1, 0);
+
+ ATF_REQUIRE(map == MAP_FAILED);
+ ATF_REQUIRE(errno == EBADF);
+
+ errno = 0;
+ map = mmap(&addr, page, PROT_READ, MAP_FIXED|MAP_PRIVATE, -1, 0);
+
+ ATF_REQUIRE(map == MAP_FAILED);
+ ATF_REQUIRE(errno == EINVAL);
+
+ errno = 0;
+ map = mmap(NULL, page, PROT_READ, MAP_ANON|MAP_PRIVATE, INT_MAX, 0);
+
+ ATF_REQUIRE(map == MAP_FAILED);
+ ATF_REQUIRE(errno == EINVAL);
+}
+
+ATF_TC_WITH_CLEANUP(mmap_loan);
+ATF_TC_HEAD(mmap_loan, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test uvm page loanout with mmap(2)");
+}
+
+ATF_TC_BODY(mmap_loan, tc)
+{
+ char buf[BUFSIZE];
+ char *vp, *vp2;
+ int fd;
+
+ fd = open(path, O_RDWR | O_CREAT, 0600);
+ ATF_REQUIRE(fd >= 0);
+
+ (void)memset(buf, 'x', sizeof(buf));
+ (void)write(fd, buf, sizeof(buf));
+
+ vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
+ MAP_FILE | MAP_PRIVATE, fd, 0);
+
+ ATF_REQUIRE(vp != MAP_FAILED);
+
+ vp2 = vp;
+
+ testloan(vp, vp2, 'A', 0);
+ testloan(vp, vp2, 'B', 1);
+
+ ATF_REQUIRE(munmap(vp, BUFSIZE) == 0);
+
+ vp = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
+ MAP_FILE | MAP_SHARED, fd, 0);
+
+ vp2 = mmap(NULL, BUFSIZE, PROT_READ | PROT_WRITE,
+ MAP_FILE | MAP_SHARED, fd, 0);
+
+ ATF_REQUIRE(vp != MAP_FAILED);
+ ATF_REQUIRE(vp2 != MAP_FAILED);
+
+ testloan(vp, vp2, 'E', 1);
+
+ ATF_REQUIRE(munmap(vp, BUFSIZE) == 0);
+ ATF_REQUIRE(munmap(vp2, BUFSIZE) == 0);
+}
+
+ATF_TC_CLEANUP(mmap_loan, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(mmap_prot_1);
+ATF_TC_HEAD(mmap_prot_1, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #1");
+}
+
+ATF_TC_BODY(mmap_prot_1, tc)
+{
+ void *map;
+ int fd;
+
+ /*
+ * Open a file write-only and try to
+ * map it read-only. This should fail.
+ */
+ fd = open(path, O_WRONLY | O_CREAT, 0700);
+
+ if (fd < 0)
+ return;
+
+ ATF_REQUIRE(write(fd, "XXX", 3) == 3);
+
+ map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
+ map_check(map, 1);
+
+ map = mmap(NULL, 3, PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);
+ map_check(map, 0);
+
+ ATF_REQUIRE(close(fd) == 0);
+}
+
+ATF_TC_CLEANUP(mmap_prot_1, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(mmap_prot_2);
+ATF_TC_HEAD(mmap_prot_2, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #2");
+}
+
+ATF_TC_BODY(mmap_prot_2, tc)
+{
+ char buf[2];
+ void *map;
+ pid_t pid;
+ int sta;
+
+ /*
+ * Make a PROT_NONE mapping and try to access it.
+ * If we catch a SIGSEGV, all works as expected.
+ */
+ map = mmap(NULL, page, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
+ ATF_REQUIRE(map != MAP_FAILED);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+ ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
+ ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
+ }
+
+ (void)wait(&sta);
+
+ ATF_REQUIRE(WIFEXITED(sta) != 0);
+ ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
+ ATF_REQUIRE(munmap(map, page) == 0);
+}
+
+ATF_TC_WITH_CLEANUP(mmap_prot_3);
+ATF_TC_HEAD(mmap_prot_3, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #3");
+}
+
+ATF_TC_BODY(mmap_prot_3, tc)
+{
+ char buf[2];
+ int fd, sta;
+ void *map;
+ pid_t pid;
+
+ /*
+ * Open a file, change the permissions
+ * to read-only, and try to map it as
+ * PROT_NONE. This should succeed, but
+ * the access should generate SIGSEGV.
+ */
+ fd = open(path, O_RDWR | O_CREAT, 0700);
+
+ if (fd < 0)
+ return;
+
+ ATF_REQUIRE(write(fd, "XXX", 3) == 3);
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(chmod(path, 0444) == 0);
+
+ fd = open(path, O_RDONLY);
+ ATF_REQUIRE(fd != -1);
+
+ map = mmap(NULL, 3, PROT_NONE, MAP_FILE | MAP_SHARED, fd, 0);
+ ATF_REQUIRE(map != MAP_FAILED);
+
+ pid = fork();
+
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+ ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
+ ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
+ }
+
+ (void)wait(&sta);
+
+ ATF_REQUIRE(WIFEXITED(sta) != 0);
+ ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
+ ATF_REQUIRE(munmap(map, 3) == 0);
+}
+
+ATF_TC_CLEANUP(mmap_prot_3, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(mmap_truncate);
+ATF_TC_HEAD(mmap_truncate, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test mmap(2) and ftruncate(2)");
+}
+
+ATF_TC_BODY(mmap_truncate, tc)
+{
+ char *map;
+ long i;
+ int fd;
+
+ fd = open(path, O_RDWR | O_CREAT, 0700);
+
+ if (fd < 0)
+ return;
+
+ /*
+ * See that ftruncate(2) works
+ * while the file is mapped.
+ */
+ ATF_REQUIRE(ftruncate(fd, page) == 0);
+
+ map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE,
+ fd, 0);
+ ATF_REQUIRE(map != MAP_FAILED);
+
+ for (i = 0; i < page; i++)
+ map[i] = 'x';
+
+ ATF_REQUIRE(ftruncate(fd, 0) == 0);
+ ATF_REQUIRE(ftruncate(fd, page / 8) == 0);
+ ATF_REQUIRE(ftruncate(fd, page / 4) == 0);
+ ATF_REQUIRE(ftruncate(fd, page / 2) == 0);
+ ATF_REQUIRE(ftruncate(fd, page / 12) == 0);
+ ATF_REQUIRE(ftruncate(fd, page / 64) == 0);
+
+ ATF_REQUIRE(close(fd) == 0);
+}
+
+ATF_TC_CLEANUP(mmap_truncate, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(mmap_va0);
+ATF_TC_HEAD(mmap_va0, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test mmap(2) and vm.user_va0_disable");
+}
+
+ATF_TC_BODY(mmap_va0, tc)
+{
+ int flags = MAP_ANON | MAP_FIXED | MAP_PRIVATE;
+ size_t len = sizeof(int);
+ void *map;
+ int val;
+
+ /*
+ * Make an anonymous fixed mapping at zero address. If the address
+ * is restricted as noted in security(7), the syscall should fail.
+ */
+ if (sysctlbyname("vm.user_va0_disable", &val, &len, NULL, 0) != 0)
+ atf_tc_fail("failed to read vm.user_va0_disable");
+
+ map = mmap(NULL, page, PROT_EXEC, flags, -1, 0);
+ map_check(map, val);
+
+ map = mmap(NULL, page, PROT_READ, flags, -1, 0);
+ map_check(map, val);
+
+ map = mmap(NULL, page, PROT_WRITE, flags, -1, 0);
+ map_check(map, val);
+
+ map = mmap(NULL, page, PROT_READ|PROT_WRITE, flags, -1, 0);
+ map_check(map, val);
+
+ map = mmap(NULL, page, PROT_EXEC|PROT_READ|PROT_WRITE, flags, -1, 0);
+ map_check(map, val);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ page = sysconf(_SC_PAGESIZE);
+ ATF_REQUIRE(page >= 0);
+
+ ATF_TP_ADD_TC(tp, mmap_block);
+ ATF_TP_ADD_TC(tp, mmap_err);
+ ATF_TP_ADD_TC(tp, mmap_loan);
+ ATF_TP_ADD_TC(tp, mmap_prot_1);
+ ATF_TP_ADD_TC(tp, mmap_prot_2);
+ ATF_TP_ADD_TC(tp, mmap_prot_3);
+ ATF_TP_ADD_TC(tp, mmap_truncate);
+ ATF_TP_ADD_TC(tp, mmap_va0);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_mprotect.c b/contrib/netbsd-tests/lib/libc/sys/t_mprotect.c
new file mode 100644
index 0000000..c534e11
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_mprotect.c
@@ -0,0 +1,359 @@
+/* $NetBSD: t_mprotect.c,v 1.3 2011/07/20 22:53:44 jym Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_mprotect.c,v 1.3 2011/07/20 22:53:44 jym Exp $");
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+#include "../common/exec_prot.h"
+
+static long page = 0;
+static int pax_global = -1;
+static int pax_enabled = -1;
+static char path[] = "mmap";
+
+static void sighandler(int);
+static bool paxinit(void);
+static bool paxset(int, int);
+
+static void
+sighandler(int signo)
+{
+ _exit(signo);
+}
+
+static bool
+paxinit(void)
+{
+ size_t len = sizeof(int);
+ int rv;
+
+ rv = sysctlbyname("security.pax.mprotect.global",
+ &pax_global, &len, NULL, 0);
+
+ if (rv != 0)
+ return false;
+
+ rv = sysctlbyname("security.pax.mprotect.enabled",
+ &pax_enabled, &len, NULL, 0);
+
+ if (rv != 0)
+ return false;
+
+ return paxset(1, 1);
+}
+
+static bool
+paxset(int global, int enabled)
+{
+ size_t len = sizeof(int);
+ int rv;
+
+ rv = sysctlbyname("security.pax.mprotect.global",
+ NULL, NULL, &global, len);
+
+ if (rv != 0)
+ return false;
+
+ rv = sysctlbyname("security.pax.mprotect.enabled",
+ NULL, NULL, &enabled, len);
+
+ if (rv != 0)
+ return false;
+
+ return true;
+}
+
+
+ATF_TC_WITH_CLEANUP(mprotect_access);
+ATF_TC_HEAD(mprotect_access, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test for EACCES from mprotect(2)");
+}
+
+ATF_TC_BODY(mprotect_access, tc)
+{
+ int prot[2] = { PROT_NONE, PROT_READ };
+ void *map;
+ size_t i;
+ int fd;
+
+ fd = open(path, O_RDONLY | O_CREAT);
+ ATF_REQUIRE(fd >= 0);
+
+ /*
+ * The call should fail with EACCES if we try to mark
+ * a PROT_NONE or PROT_READ file/section as PROT_WRITE.
+ */
+ for (i = 0; i < __arraycount(prot); i++) {
+
+ map = mmap(NULL, page, prot[i], MAP_SHARED, fd, 0);
+
+ if (map == MAP_FAILED)
+ continue;
+
+ errno = 0;
+
+ ATF_REQUIRE(mprotect(map, page, PROT_WRITE) != 0);
+ ATF_REQUIRE(errno == EACCES);
+ ATF_REQUIRE(munmap(map, page) == 0);
+ }
+
+ ATF_REQUIRE(close(fd) == 0);
+}
+
+ATF_TC_CLEANUP(mprotect_access, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(mprotect_err);
+ATF_TC_HEAD(mprotect_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions of mprotect(2)");
+}
+
+ATF_TC_BODY(mprotect_err, tc)
+{
+ errno = 0;
+
+ ATF_REQUIRE(mprotect((char *)-1, 1, PROT_READ) != 0);
+ ATF_REQUIRE(errno == EINVAL);
+}
+
+ATF_TC(mprotect_exec);
+ATF_TC_HEAD(mprotect_exec, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test mprotect(2) executable space protections");
+}
+
+/*
+ * Trivial function -- should fit into a page
+ */
+ATF_TC_BODY(mprotect_exec, tc)
+{
+ pid_t pid;
+ void *map;
+ int sta, xp_support;
+
+ xp_support = exec_prot_support();
+
+ switch (xp_support) {
+ case NOTIMPL:
+ atf_tc_skip(
+ "Execute protection callback check not implemented");
+ break;
+ case NO_XP:
+ atf_tc_skip(
+ "Host does not support executable space protection");
+ break;
+ case PARTIAL_XP: case PERPAGE_XP: default:
+ break;
+ }
+
+ /*
+ * Map a page read/write and copy a trivial assembly function inside.
+ * We will then change the mapping rights:
+ * - first by setting the execution right, and check that we can
+ * call the code found in the allocated page.
+ * - second by removing the execution right. This should generate
+ * a SIGSEGV on architectures that can enforce --x permissions.
+ */
+
+ map = mmap(NULL, page, PROT_WRITE|PROT_READ, MAP_ANON, -1, 0);
+ ATF_REQUIRE(map != MAP_FAILED);
+
+ memcpy(map, (void *)return_one,
+ (uintptr_t)return_one_end - (uintptr_t)return_one);
+
+ /* give r-x rights then call code in page */
+ ATF_REQUIRE(mprotect(map, page, PROT_EXEC|PROT_READ) == 0);
+ ATF_REQUIRE(((int (*)(void))map)() == 1);
+
+ /* remove --x right */
+ ATF_REQUIRE(mprotect(map, page, PROT_READ) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+ ATF_REQUIRE(signal(SIGSEGV, sighandler) != SIG_ERR);
+ ATF_CHECK(((int (*)(void))map)() == 1);
+ _exit(0);
+ }
+
+ (void)wait(&sta);
+
+ ATF_REQUIRE(munmap(map, page) == 0);
+
+ ATF_REQUIRE(WIFEXITED(sta) != 0);
+
+ switch (xp_support) {
+ case PARTIAL_XP:
+ /* Partial protection might fail; skip the test when it does */
+ if (WEXITSTATUS(sta) != SIGSEGV) {
+ atf_tc_skip("Host only supports "
+ "partial executable space protection");
+ }
+ break;
+ case PERPAGE_XP: default:
+ /* Per-page --x protection should not fail */
+ ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
+ break;
+ }
+}
+
+ATF_TC(mprotect_pax);
+ATF_TC_HEAD(mprotect_pax, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "PaX restrictions and mprotect(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(mprotect_pax, tc)
+{
+ const int prot[4] = { PROT_NONE, PROT_READ, PROT_WRITE };
+ const char *str = NULL;
+ void *map;
+ size_t i;
+ int rv;
+
+ if (paxinit() != true)
+ return;
+
+ /*
+ * As noted in the original PaX documentation [1],
+ * the following restrictions should apply:
+ *
+ * (1) creating executable anonymous mappings
+ *
+ * (2) creating executable/writable file mappings
+ *
+ * (3) making a non-executable mapping executable
+ *
+ * (4) making an executable/read-only file mapping
+ * writable except for performing relocations
+ * on an ET_DYN ELF file (non-PIC shared library)
+ *
+ * The following will test only the case (3).
+ *
+ * [1] http://pax.grsecurity.net/docs/mprotect.txt
+ *
+ * (Sun Apr 3 11:06:53 EEST 2011.)
+ */
+ for (i = 0; i < __arraycount(prot); i++) {
+
+ map = mmap(NULL, page, prot[i], MAP_ANON, -1, 0);
+
+ if (map == MAP_FAILED)
+ continue;
+
+ rv = mprotect(map, 1, prot[i] | PROT_EXEC);
+
+ (void)munmap(map, page);
+
+ if (rv == 0) {
+ str = "non-executable mapping made executable";
+ goto out;
+ }
+ }
+
+out:
+ if (pax_global != -1 && pax_enabled != -1)
+ (void)paxset(pax_global, pax_enabled);
+
+ if (str != NULL)
+ atf_tc_fail("%s", str);
+}
+
+ATF_TC(mprotect_write);
+ATF_TC_HEAD(mprotect_write, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test mprotect(2) write protections");
+}
+
+ATF_TC_BODY(mprotect_write, tc)
+{
+ pid_t pid;
+ void *map;
+ int sta;
+
+ /*
+ * Map a page read/write, change the protection
+ * to read-only with mprotect(2), and try to write
+ * to the page. This should generate a SIGSEGV.
+ */
+ map = mmap(NULL, page, PROT_WRITE|PROT_READ, MAP_ANON, -1, 0);
+ ATF_REQUIRE(map != MAP_FAILED);
+
+ ATF_REQUIRE(strlcpy(map, "XXX", 3) == 3);
+ ATF_REQUIRE(mprotect(map, page, PROT_READ) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+ ATF_REQUIRE(signal(SIGSEGV, sighandler) != SIG_ERR);
+ ATF_REQUIRE(strlcpy(map, "XXX", 3) == 0);
+ }
+
+ (void)wait(&sta);
+
+ ATF_REQUIRE(WIFEXITED(sta) != 0);
+ ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
+ ATF_REQUIRE(munmap(map, page) == 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ page = sysconf(_SC_PAGESIZE);
+ ATF_REQUIRE(page >= 0);
+
+ ATF_TP_ADD_TC(tp, mprotect_access);
+ ATF_TP_ADD_TC(tp, mprotect_err);
+ ATF_TP_ADD_TC(tp, mprotect_exec);
+ ATF_TP_ADD_TC(tp, mprotect_pax);
+ ATF_TP_ADD_TC(tp, mprotect_write);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_msgctl.c b/contrib/netbsd-tests/lib/libc/sys/t_msgctl.c
new file mode 100644
index 0000000..1e74d60
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_msgctl.c
@@ -0,0 +1,358 @@
+/* $NetBSD: t_msgctl.c,v 1.4 2014/02/27 00:59:50 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_msgctl.c,v 1.4 2014/02/27 00:59:50 joerg Exp $");
+
+#include <sys/msg.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+#define MSG_KEY 12345689
+#define MSG_MTYPE_1 0x41
+
+struct msg {
+ long mtype;
+ char buf[3];
+};
+
+static void clean(void);
+
+static void
+clean(void)
+{
+ int id;
+
+ if ((id = msgget(MSG_KEY, 0)) != -1)
+ (void)msgctl(id, IPC_RMID, 0);
+}
+
+ATF_TC_WITH_CLEANUP(msgctl_err);
+ATF_TC_HEAD(msgctl_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from msgctl(2)");
+}
+
+ATF_TC_BODY(msgctl_err, tc)
+{
+ const int cmd[] = { IPC_STAT, IPC_SET, IPC_RMID };
+ struct msqid_ds msgds;
+ size_t i;
+ int id;
+
+ (void)memset(&msgds, 0, sizeof(struct msqid_ds));
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, msgctl(id, INT_MAX, &msgds) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, msgctl(id, IPC_STAT, (void *)-1) == -1);
+
+ for (i = 0; i < __arraycount(cmd); i++) {
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, msgctl(-1, cmd[i], &msgds) == -1);
+ }
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgctl_err, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgctl_perm);
+ATF_TC_HEAD(msgctl_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test permissions with msgctl(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(msgctl_perm, tc)
+{
+ struct msqid_ds msgds;
+ struct passwd *pw;
+ pid_t pid;
+ int sta;
+ int id;
+
+ (void)memset(&msgds, 0, sizeof(struct msqid_ds));
+
+ pw = getpwnam("nobody");
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+
+ ATF_REQUIRE(id != -1);
+ ATF_REQUIRE(pw != NULL);
+ ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ if (setuid(pw->pw_uid) != 0)
+ _exit(EX_OSERR);
+
+ msgds.msg_perm.uid = getuid();
+ msgds.msg_perm.gid = getgid();
+
+ errno = 0;
+
+ if (msgctl(id, IPC_SET, &msgds) == 0)
+ _exit(EXIT_FAILURE);
+
+ if (errno != EPERM)
+ _exit(EXIT_FAILURE);
+
+ (void)memset(&msgds, 0, sizeof(struct msqid_ds));
+
+ if (msgctl(id, IPC_STAT, &msgds) != 0)
+ _exit(EX_OSERR);
+
+ msgds.msg_qbytes = 1;
+
+ if (msgctl(id, IPC_SET, &msgds) == 0)
+ _exit(EXIT_FAILURE);
+
+ if (errno != EPERM)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0) {
+
+ if (WEXITSTATUS(sta) == EX_OSERR)
+ atf_tc_fail("system call failed");
+
+ if (WEXITSTATUS(sta) == EXIT_FAILURE)
+ atf_tc_fail("UID %u manipulated root's "
+ "message queue", pw->pw_uid);
+ }
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgctl_perm, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgctl_pid);
+ATF_TC_HEAD(msgctl_pid, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test that PIDs are updated");
+}
+
+ATF_TC_BODY(msgctl_pid, tc)
+{
+ struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ struct msqid_ds msgds;
+ int id, sta;
+ pid_t pid;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ (void)msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)sleep(1);
+ (void)wait(&sta);
+ (void)memset(&msgds, 0, sizeof(struct msqid_ds));
+
+ ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
+
+ if (pid != msgds.msg_lspid)
+ atf_tc_fail("the PID of last msgsnd(2) was not updated");
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ (void)msgrcv(id, &msg,
+ sizeof(struct msg), MSG_MTYPE_1, IPC_NOWAIT);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)sleep(1);
+ (void)wait(&sta);
+ (void)memset(&msgds, 0, sizeof(struct msqid_ds));
+
+ ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
+
+ if (pid != msgds.msg_lrpid)
+ atf_tc_fail("the PID of last msgrcv(2) was not updated");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgctl_pid, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgctl_set);
+ATF_TC_HEAD(msgctl_set, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test msgctl(2) with IPC_SET");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(msgctl_set, tc)
+{
+ struct msqid_ds msgds;
+ struct passwd *pw;
+ int id;
+
+ (void)memset(&msgds, 0, sizeof(struct msqid_ds));
+
+ pw = getpwnam("nobody");
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+
+ ATF_REQUIRE(id != -1);
+ ATF_REQUIRE(pw != NULL);
+ ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
+
+ msgds.msg_perm.uid = pw->pw_uid;
+
+ if (msgctl(id, IPC_SET, &msgds) != 0)
+ atf_tc_fail("root failed to change the UID of message queue");
+
+ msgds.msg_perm.uid = getuid();
+ msgds.msg_perm.gid = pw->pw_gid;
+
+ if (msgctl(id, IPC_SET, &msgds) != 0)
+ atf_tc_fail("root failed to change the GID of message queue");
+
+ /*
+ * Note: setting the qbytes to zero fails even as root.
+ */
+ msgds.msg_qbytes = 1;
+ msgds.msg_perm.gid = getgid();
+
+ if (msgctl(id, IPC_SET, &msgds) != 0)
+ atf_tc_fail("root failed to change qbytes of message queue");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgctl_set, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgctl_time);
+ATF_TC_HEAD(msgctl_time, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test that access times are updated");
+}
+
+ATF_TC_BODY(msgctl_time, tc)
+{
+ struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ struct msqid_ds msgds;
+ time_t t;
+ int id;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ t = time(NULL);
+
+ (void)memset(&msgds, 0, sizeof(struct msqid_ds));
+ (void)msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT);
+ (void)msgctl(id, IPC_STAT, &msgds);
+
+ if (llabs(t - msgds.msg_stime) > 1)
+ atf_tc_fail("time of last msgsnd(2) was not updated");
+
+ if (msgds.msg_rtime != 0)
+ atf_tc_fail("time of last msgrcv(2) was updated incorrectly");
+
+ t = time(NULL);
+
+ (void)memset(&msgds, 0, sizeof(struct msqid_ds));
+ (void)msgrcv(id, &msg, sizeof(struct msg), MSG_MTYPE_1, IPC_NOWAIT);
+ (void)msgctl(id, IPC_STAT, &msgds);
+
+ if (llabs(t - msgds.msg_rtime) > 1)
+ atf_tc_fail("time of last msgrcv(2) was not updated");
+
+ /*
+ * Note: this is non-zero even after the memset(3).
+ */
+ if (msgds.msg_stime == 0)
+ atf_tc_fail("time of last msgsnd(2) was updated incorrectly");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgctl_time, tc)
+{
+ clean();
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, msgctl_err);
+ ATF_TP_ADD_TC(tp, msgctl_perm);
+ ATF_TP_ADD_TC(tp, msgctl_pid);
+ ATF_TP_ADD_TC(tp, msgctl_set);
+ ATF_TP_ADD_TC(tp, msgctl_time);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_msgget.c b/contrib/netbsd-tests/lib/libc/sys/t_msgget.c
new file mode 100644
index 0000000..e26cde2
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_msgget.c
@@ -0,0 +1,292 @@
+/* $NetBSD: t_msgget.c,v 1.2 2014/02/27 00:59:50 joerg Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_msgget.c,v 1.2 2014/02/27 00:59:50 joerg Exp $");
+
+#include <sys/msg.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+#define MSG_KEY 12345689
+
+static void clean(void);
+
+static void
+clean(void)
+{
+ int id;
+
+ if ((id = msgget(MSG_KEY, 0)) != -1)
+ (void)msgctl(id, IPC_RMID, 0);
+}
+
+ATF_TC_WITH_CLEANUP(msgget_excl);
+ATF_TC_HEAD(msgget_excl, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test msgget(2) with IPC_EXCL");
+}
+
+ATF_TC_BODY(msgget_excl, tc)
+{
+ int id;
+
+ /*
+ * Create a message queue and re-open it with
+ * O_CREAT and IPC_EXCL set. This should fail.
+ */
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+
+ if (id < 0)
+ atf_tc_fail("failed to create message queue");
+
+ errno = 0;
+
+ if (msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | 0600) != -1)
+ atf_tc_fail("msgget(2) failed for IPC_EXCL");
+
+ ATF_REQUIRE(errno == EEXIST);
+
+ /*
+ * However, the same call should succeed
+ * when IPC_EXCL is not set in the flags.
+ */
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+
+ if (id < 0)
+ atf_tc_fail("msgget(2) failed to re-open");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgget_excl, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgget_exit);
+ATF_TC_HEAD(msgget_exit, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that XSI message queues are "
+ "not removed when the process exits");
+}
+
+ATF_TC_BODY(msgget_exit, tc)
+{
+ int id, sta;
+ pid_t pid;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ if (msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | 0600) == -1)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("failed to create message queue");
+
+ id = msgget(MSG_KEY, 0);
+
+ if (id == -1)
+ atf_tc_fail("message queue was removed on process exit");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgget_exit, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgget_init);
+ATF_TC_HEAD(msgget_init, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that msgget(2) initializes data structures properly");
+}
+
+ATF_TC_BODY(msgget_init, tc)
+{
+ const uid_t uid = geteuid();
+ const gid_t gid = getegid();
+ struct msqid_ds msgds;
+ time_t t;
+ int id;
+
+ (void)memset(&msgds, 0x9, sizeof(struct msqid_ds));
+
+ t = time(NULL);
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+
+ ATF_REQUIRE(id !=-1);
+ ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
+
+ ATF_CHECK(msgds.msg_qnum == 0);
+ ATF_CHECK(msgds.msg_lspid == 0);
+ ATF_CHECK(msgds.msg_lrpid == 0);
+ ATF_CHECK(msgds.msg_rtime == 0);
+ ATF_CHECK(msgds.msg_stime == 0);
+ ATF_CHECK(msgds.msg_perm.uid == uid);
+ ATF_CHECK(msgds.msg_perm.gid == gid);
+ ATF_CHECK(msgds.msg_perm.cuid == uid);
+ ATF_CHECK(msgds.msg_perm.cgid == gid);
+ ATF_CHECK(msgds.msg_perm.mode == 0600);
+
+ if (llabs(t - msgds.msg_ctime) > 5)
+ atf_tc_fail("msgget(2) initialized current time incorrectly");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgget_init, tc)
+{
+ clean();
+}
+
+ATF_TC(msgget_limit);
+ATF_TC_HEAD(msgget_limit, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test msgget(2) against system limits");
+}
+
+ATF_TC_BODY(msgget_limit, tc)
+{
+ size_t len = sizeof(int);
+ bool fail = false;
+ int i, lim = 0;
+ int *buf;
+
+ if (sysctlbyname("kern.ipc.msgmni", &lim, &len, NULL, 0) != 0)
+ atf_tc_skip("failed to read kern.ipc.msgmni sysctl");
+
+ buf = calloc(lim + 1, sizeof(*buf));
+ ATF_REQUIRE(buf != NULL);
+
+ for (i = 0; i < lim; i++) {
+
+ buf[i] = msgget(MSG_KEY + i, IPC_CREAT | IPC_EXCL | 0600);
+
+ (void)fprintf(stderr, "key[%d] = %d\n", i, buf[i]);
+
+ /*
+ * This test only works when there are zero existing
+ * message queues. Thus, bypass the unit test when
+ * this precondition is not met, for reason or another.
+ */
+ if (buf[i] == -1)
+ goto out;
+ }
+
+ i++;
+ errno = 0;
+
+ buf[i] = msgget(MSG_KEY + i, IPC_CREAT | IPC_EXCL | 0600);
+
+ if (buf[i] != -1 || errno != ENOSPC)
+ fail = true;
+
+out: /* Remember to clean-up. */
+ for (i = 0; i < lim; i++)
+ (void)msgctl(buf[i], IPC_RMID, 0);
+
+ free(buf);
+
+ if (fail != false)
+ atf_tc_fail("msgget(2) opened more than %d queues", lim);
+}
+
+ATF_TC_WITH_CLEANUP(msgget_mode);
+ATF_TC_HEAD(msgget_mode, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test different modes with msgget(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(msgget_mode, tc)
+{
+ static const mode_t mode[] = {
+ S_IRWXU, S_IRUSR, S_IWUSR, S_IXUSR, S_IRWXG, S_IRGRP,
+ S_IWGRP, S_IXGRP, S_IRWXO, S_IROTH, S_IWOTH, S_IXOTH
+ };
+
+ struct msqid_ds msgds;
+ size_t i;
+ int id;
+
+ for (i = 0; i < __arraycount(mode); i++) {
+
+ (void)fprintf(stderr, "testing mode %d\n", mode[i]);
+ (void)memset(&msgds, 0, sizeof(struct msqid_ds));
+
+ id = msgget(MSG_KEY, IPC_CREAT | IPC_EXCL | (int)mode[i]);
+
+ ATF_REQUIRE(id != -1);
+ ATF_REQUIRE(msgctl(id, IPC_STAT, &msgds) == 0);
+ ATF_REQUIRE(msgds.msg_perm.mode == mode[i]);
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+ }
+}
+
+ATF_TC_CLEANUP(msgget_mode, tc)
+{
+ clean();
+}
+
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, msgget_excl);
+ ATF_TP_ADD_TC(tp, msgget_exit);
+ ATF_TP_ADD_TC(tp, msgget_init);
+ ATF_TP_ADD_TC(tp, msgget_limit);
+ ATF_TP_ADD_TC(tp, msgget_mode);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_msgrcv.c b/contrib/netbsd-tests/lib/libc/sys/t_msgrcv.c
new file mode 100644
index 0000000..e32be26
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_msgrcv.c
@@ -0,0 +1,342 @@
+/* $NetBSD: t_msgrcv.c,v 1.3 2013/07/24 11:44:10 skrll Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_msgrcv.c,v 1.3 2013/07/24 11:44:10 skrll Exp $");
+
+#include <sys/msg.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+#define MSG_KEY 1234
+#define MSG_MTYPE_1 0x41
+#define MSG_MTYPE_2 0x42
+#define MSG_MTYPE_3 0x43
+#define MSG_LEN 3
+
+struct msg {
+ long mtype;
+ char buf[MSG_LEN];
+};
+
+static void clean(void);
+
+static void
+clean(void)
+{
+ int id;
+
+ if ((id = msgget(MSG_KEY, 0)) != -1)
+ (void)msgctl(id, IPC_RMID, 0);
+}
+
+ATF_TC_WITH_CLEANUP(msgrcv_basic);
+ATF_TC_HEAD(msgrcv_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of msgrcv(2)");
+}
+
+ATF_TC_BODY(msgrcv_basic, tc)
+{
+ struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ struct msg msg2 = { MSG_MTYPE_1, { 'x', 'y', 'z' } };
+ int id;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
+ (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT);
+
+ ATF_CHECK(msg1.buf[0] == msg2.buf[0]);
+ ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
+ ATF_CHECK(msg1.buf[2] == msg2.buf[2]);
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgrcv_basic, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgrcv_block);
+ATF_TC_HEAD(msgrcv_block, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test that msgrcv(2) blocks");
+}
+
+ATF_TC_BODY(msgrcv_block, tc)
+{
+ struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ int id, sta;
+ pid_t pid;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ if (msgrcv(id, &msg, MSG_LEN, MSG_MTYPE_1, 0) < 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ /*
+ * Below msgsnd(2) should unblock the child,
+ * and hence kill(2) should fail with ESRCH.
+ */
+ (void)sleep(1);
+ (void)msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT);
+ (void)sleep(1);
+ (void)kill(pid, SIGKILL);
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WIFSIGNALED(sta) != 0)
+ atf_tc_fail("msgrcv(2) did not block");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgrcv_block, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgrcv_err);
+ATF_TC_HEAD(msgrcv_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from msgrcv(2)");
+}
+
+ATF_TC_BODY(msgrcv_err, tc)
+{
+ struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ int id, r = 0;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ errno = 0;
+
+ ATF_REQUIRE_ERRNO(ENOMSG, msgrcv(id, &msg,
+ MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
+
+ ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
+
+ errno = 0;
+
+ ATF_REQUIRE_ERRNO(EFAULT, msgrcv(id, (void *)-1,
+ MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
+
+ errno = 0;
+
+ ATF_REQUIRE_ERRNO(EINVAL, msgrcv(-1, &msg,
+ MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
+
+ errno = 0;
+
+ ATF_REQUIRE_ERRNO(EINVAL, msgrcv(-1, &msg,
+ SSIZE_MAX, MSG_MTYPE_1, IPC_NOWAIT) == -1);
+
+ ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
+
+ errno = 0;
+
+ ATF_REQUIRE_ERRNO(E2BIG, msgrcv(id, &r,
+ MSG_LEN - 1, MSG_MTYPE_1, IPC_NOWAIT) == -1);
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgrcv_err, tc)
+{
+ clean();
+}
+
+
+ATF_TC_WITH_CLEANUP(msgrcv_mtype);
+ATF_TC_HEAD(msgrcv_mtype, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test message types with msgrcv(2)");
+}
+
+ATF_TC_BODY(msgrcv_mtype, tc)
+{
+ struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ struct msg msg2 = { MSG_MTYPE_3, { 'x', 'y', 'z' } };
+ int id;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
+ (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_2, IPC_NOWAIT);
+
+ ATF_CHECK(msg1.buf[0] != msg2.buf[0]); /* Different mtype. */
+ ATF_CHECK(msg1.buf[1] != msg2.buf[1]);
+ ATF_CHECK(msg1.buf[2] != msg2.buf[2]);
+
+ (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT);
+
+ ATF_CHECK(msg1.buf[0] == msg2.buf[0]); /* Same mtype. */
+ ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
+ ATF_CHECK(msg1.buf[2] == msg2.buf[2]);
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgrcv_mtype, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgrcv_nonblock);
+ATF_TC_HEAD(msgrcv_nonblock, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test msgrcv(2) with IPC_NOWAIT");
+ atf_tc_set_md_var(tc, "timeout", "10");
+}
+
+ATF_TC_BODY(msgrcv_nonblock, tc)
+{
+ struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ const ssize_t n = 10;
+ int id, sta;
+ ssize_t i;
+ pid_t pid;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ for (i = 0; i < n; i++) {
+
+ ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
+ }
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ while (i != 0) {
+
+ if (msgrcv(id, &msg, MSG_LEN, MSG_MTYPE_1,
+ IPC_NOWAIT) == -1)
+ _exit(EXIT_FAILURE);
+
+ i--;
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)sleep(2);
+ (void)kill(pid, SIGKILL);
+ (void)wait(&sta);
+
+ if (WIFSIGNALED(sta) != 0 || WTERMSIG(sta) == SIGKILL)
+ atf_tc_fail("msgrcv(2) blocked with IPC_NOWAIT");
+
+ if (WIFEXITED(sta) == 0 && WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("msgrcv(2) failed");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgrcv_nonblock, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgrcv_truncate);
+ATF_TC_HEAD(msgrcv_truncate, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test msgrcv(2) with MSG_NOERROR");
+}
+
+ATF_TC_BODY(msgrcv_truncate, tc)
+{
+#define MSG_SMALLLEN 2
+ struct msgsmall {
+ long mtype;
+ char buf[MSG_SMALLLEN];
+ };
+
+ struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ struct msgsmall msg2 = { MSG_MTYPE_1, { 'x', 'y' } };
+ int id;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
+ (void)msgrcv(id, &msg2, MSG_SMALLLEN,
+ MSG_MTYPE_1, IPC_NOWAIT | MSG_NOERROR);
+
+ ATF_CHECK(msg1.buf[0] == msg2.buf[0]);
+ ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgrcv_truncate, tc)
+{
+ clean();
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, msgrcv_basic);
+ ATF_TP_ADD_TC(tp, msgrcv_block);
+ ATF_TP_ADD_TC(tp, msgrcv_err);
+ ATF_TP_ADD_TC(tp, msgrcv_mtype);
+ ATF_TP_ADD_TC(tp, msgrcv_nonblock);
+ ATF_TP_ADD_TC(tp, msgrcv_truncate);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_msgsnd.c b/contrib/netbsd-tests/lib/libc/sys/t_msgsnd.c
new file mode 100644
index 0000000..5493789
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_msgsnd.c
@@ -0,0 +1,338 @@
+/* $NetBSD: t_msgsnd.c,v 1.2 2011/11/05 08:47:54 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_msgsnd.c,v 1.2 2011/11/05 08:47:54 jruoho Exp $");
+
+#include <sys/msg.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <time.h>
+#include <unistd.h>
+
+#define MSG_KEY 1234
+#define MSG_MTYPE_1 0x41
+#define MSG_MTYPE_2 0x42
+#define MSG_MTYPE_3 0x43
+
+struct msg {
+ long mtype;
+ char buf[3];
+};
+
+static void clean(void);
+
+static void
+clean(void)
+{
+ int id;
+
+ if ((id = msgget(MSG_KEY, 0)) != -1)
+ (void)msgctl(id, IPC_RMID, 0);
+}
+
+ATF_TC_WITH_CLEANUP(msgsnd_block);
+ATF_TC_HEAD(msgsnd_block, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test that msgsnd(2) blocks");
+ atf_tc_set_md_var(tc, "timeout", "10");
+}
+
+ATF_TC_BODY(msgsnd_block, tc)
+{
+ struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ int id, sta;
+ pid_t pid;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ /*
+ * Enqueue messages until some limit (e.g. the maximum
+ * number of messages in the queue or the maximum number
+ * of bytes in the queue) is reached. After this the call
+ * should block when the IPC_NOWAIT is not set.
+ */
+ for (;;) {
+
+ if (msgsnd(id, &msg, sizeof(struct msg), 0) < 0)
+ _exit(EXIT_FAILURE);
+ }
+ }
+
+ (void)sleep(2);
+ (void)kill(pid, SIGKILL);
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) != 0 || WIFSIGNALED(sta) == 0)
+ atf_tc_fail("msgsnd(2) did not block");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgsnd_block, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgsnd_count);
+ATF_TC_HEAD(msgsnd_count, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test that msgsnd(2) increments the amount of "
+ "message in the queue, as given by msgctl(2)");
+ atf_tc_set_md_var(tc, "timeout", "10");
+}
+
+ATF_TC_BODY(msgsnd_count, tc)
+{
+ struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ struct msqid_ds ds;
+ size_t i = 0;
+ int id, rv;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ for (;;) {
+
+ errno = 0;
+ rv = msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT);
+
+ if (rv == 0) {
+ i++;
+ continue;
+ }
+
+ if (rv == -1 && errno == EAGAIN)
+ break;
+
+ atf_tc_fail("failed to enqueue a message");
+ }
+
+ (void)memset(&ds, 0, sizeof(struct msqid_ds));
+ (void)msgctl(id, IPC_STAT, &ds);
+
+ if (ds.msg_qnum != i)
+ atf_tc_fail("incorrect message count");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgsnd_count, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgsnd_err);
+ATF_TC_HEAD(msgsnd_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from msgsnd(2)");
+}
+
+ATF_TC_BODY(msgsnd_err, tc)
+{
+ struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ int id;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ errno = 0;
+
+ ATF_REQUIRE_ERRNO(EFAULT, msgsnd(id, (void *)-1,
+ sizeof(struct msg), IPC_NOWAIT) == -1);
+
+ errno = 0;
+
+ ATF_REQUIRE_ERRNO(EINVAL, msgsnd(-1, &msg,
+ sizeof(struct msg), IPC_NOWAIT) == -1);
+
+ errno = 0;
+
+ ATF_REQUIRE_ERRNO(EINVAL, msgsnd(-1, &msg,
+ SSIZE_MAX, IPC_NOWAIT) == -1);
+
+ errno = 0;
+ msg.mtype = 0;
+
+ ATF_REQUIRE_ERRNO(EINVAL, msgsnd(id, &msg,
+ sizeof(struct msg), IPC_NOWAIT) == -1);
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgsnd_err, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgsnd_nonblock);
+ATF_TC_HEAD(msgsnd_nonblock, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test msgsnd(2) with IPC_NOWAIT");
+ atf_tc_set_md_var(tc, "timeout", "10");
+}
+
+ATF_TC_BODY(msgsnd_nonblock, tc)
+{
+ struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ int id, rv, sta;
+ pid_t pid;
+
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+ ATF_REQUIRE(id != -1);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ for (;;) {
+
+ errno = 0;
+ rv = msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT);
+
+ if (rv == -1 && errno == EAGAIN)
+ _exit(EXIT_SUCCESS);
+ }
+ }
+
+ (void)sleep(2);
+ (void)kill(pid, SIGKILL);
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WIFSIGNALED(sta) != 0)
+ atf_tc_fail("msgsnd(2) blocked with IPC_NOWAIT");
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgsnd_nonblock, tc)
+{
+ clean();
+}
+
+ATF_TC_WITH_CLEANUP(msgsnd_perm);
+ATF_TC_HEAD(msgsnd_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test permissions with msgsnd(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(msgsnd_perm, tc)
+{
+ struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
+ struct passwd *pw;
+ int id, sta;
+ pid_t pid;
+ uid_t uid;
+
+ pw = getpwnam("nobody");
+ id = msgget(MSG_KEY, IPC_CREAT | 0600);
+
+ ATF_REQUIRE(id != -1);
+ ATF_REQUIRE(pw != NULL);
+
+ uid = pw->pw_uid;
+ ATF_REQUIRE(uid != 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ /*
+ * Try to enqueue a message to the queue
+ * created by root as RW for owner only.
+ */
+ if (setuid(uid) != 0)
+ _exit(EX_OSERR);
+
+ id = msgget(MSG_KEY, 0);
+
+ if (id == -1)
+ _exit(EX_OSERR);
+
+ errno = 0;
+
+ if (msgsnd(id, &msg, sizeof(struct msg), IPC_NOWAIT) == 0)
+ _exit(EXIT_FAILURE);
+
+ if (errno != EACCES)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) {
+
+ if (errno == EX_OSERR)
+ atf_tc_fail("system call failed");
+
+ atf_tc_fail("UID %u enqueued message to root's queue", uid);
+ }
+
+ ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
+}
+
+ATF_TC_CLEANUP(msgsnd_perm, tc)
+{
+ clean();
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, msgsnd_block);
+ ATF_TP_ADD_TC(tp, msgsnd_count);
+ ATF_TP_ADD_TC(tp, msgsnd_err);
+ ATF_TP_ADD_TC(tp, msgsnd_nonblock);
+ ATF_TP_ADD_TC(tp, msgsnd_perm);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_msync.c b/contrib/netbsd-tests/lib/libc/sys/t_msync.c
new file mode 100644
index 0000000..9743300
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_msync.c
@@ -0,0 +1,237 @@
+/* $NetBSD: t_msync.c,v 1.2 2012/03/16 06:15:17 matt Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_msync.c,v 1.2 2012/03/16 06:15:17 matt Exp $");
+
+#include <sys/mman.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static long page = 0;
+static const off_t off = 512;
+static const char path[] = "msync";
+
+static const char *msync_sync(const char *, int);
+
+static const char *
+msync_sync(const char *garbage, int flags)
+{
+ char *buf, *map = MAP_FAILED;
+ const char *str = NULL;
+ size_t i, len;
+ ssize_t tot;
+ int fd, rv;
+
+ /*
+ * Create a temporary file, write
+ * one page to it, and map the file.
+ */
+ buf = malloc(page);
+
+ if (buf == NULL)
+ return NULL;
+
+ for (i = 0; i < (size_t)page; i++)
+ buf[i] = 'x';
+
+ fd = open(path, O_RDWR | O_CREAT, 0700);
+
+ if (fd < 0) {
+ str = "failed to open";
+ goto out;
+ }
+
+ tot = 0;
+
+ while (tot < page) {
+
+ rv = write(fd, buf, sizeof(buf));
+
+ if (rv < 0) {
+ str = "failed to write";
+ goto out;
+ }
+
+ tot += rv;
+ }
+
+ map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE,
+ fd, 0);
+
+ if (map == MAP_FAILED) {
+ str = "failed to map";
+ goto out;
+ }
+
+ /*
+ * Seek to an arbitrary offset and
+ * write garbage to this position.
+ */
+ if (lseek(fd, off, SEEK_SET) != off) {
+ str = "failed to seek";
+ goto out;
+ }
+
+ len = strlen(garbage);
+ rv = write(fd, garbage, len);
+
+ if (rv != (ssize_t)len) {
+ str = "failed to write garbage";
+ goto out;
+ }
+
+ /*
+ * Synchronize the mapping and verify
+ * that garbage is at the given offset.
+ */
+ if (msync(map, page, flags) != 0) {
+ str = "failed to msync";
+ goto out;
+ }
+
+ if (memcmp(map + off, garbage, len) != 0) {
+ str = "msync did not synchronize";
+ goto out;
+ }
+
+out:
+ free(buf);
+
+ (void)close(fd);
+ (void)unlink(path);
+
+ if (map != MAP_FAILED)
+ (void)munmap(map, page);
+
+ return str;
+}
+
+ATF_TC(msync_async);
+ATF_TC_HEAD(msync_async, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_ASYNC");
+}
+
+ATF_TC_BODY(msync_async, tc)
+{
+ const char *str;
+
+ str = msync_sync("garbage", MS_ASYNC);
+
+ if (str != NULL)
+ atf_tc_fail("%s", str);
+}
+
+ATF_TC(msync_err);
+ATF_TC_HEAD(msync_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions in msync(2)");
+}
+
+ATF_TC_BODY(msync_err, tc)
+{
+
+ char *map = MAP_FAILED;
+
+ /*
+ * Test that invalid flags error out.
+ */
+ ATF_REQUIRE(msync_sync("error", -1) != NULL);
+ ATF_REQUIRE(msync_sync("error", INT_MAX) != NULL);
+
+ errno = 0;
+
+ /*
+ * Map a page and then unmap to get an unmapped address.
+ */
+ map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,
+ -1, 0);
+ ATF_REQUIRE(map != MAP_FAILED);
+
+ (void)munmap(map, page);
+
+ ATF_REQUIRE(msync(map, page, MS_SYNC) != 0);
+ ATF_REQUIRE(errno == EFAULT);
+}
+
+ATF_TC(msync_invalidate);
+ATF_TC_HEAD(msync_invalidate, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_INVALIDATE");
+}
+
+ATF_TC_BODY(msync_invalidate, tc)
+{
+ const char *str;
+
+ str = msync_sync("garbage", MS_INVALIDATE);
+
+ if (str != NULL)
+ atf_tc_fail("%s", str);
+}
+
+ATF_TC(msync_sync);
+ATF_TC_HEAD(msync_sync, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_SYNC");
+}
+
+ATF_TC_BODY(msync_sync, tc)
+{
+ const char *str;
+
+ str = msync_sync("garbage", MS_SYNC);
+
+ if (str != NULL)
+ atf_tc_fail("%s", str);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ page = sysconf(_SC_PAGESIZE);
+
+ ATF_REQUIRE(page >= 0);
+ ATF_REQUIRE(page > off);
+
+ ATF_TP_ADD_TC(tp, msync_async);
+ ATF_TP_ADD_TC(tp, msync_err);
+ ATF_TP_ADD_TC(tp, msync_invalidate);
+ ATF_TP_ADD_TC(tp, msync_sync);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_nanosleep.c b/contrib/netbsd-tests/lib/libc/sys/t_nanosleep.c
new file mode 100644
index 0000000..317d667
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_nanosleep.c
@@ -0,0 +1,187 @@
+/* $NetBSD: t_nanosleep.c,v 1.3 2013/03/31 16:47:16 christos Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_nanosleep.c,v 1.3 2013/03/31 16:47:16 christos Exp $");
+
+#include <sys/time.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <time.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+static void
+handler(int signo)
+{
+ /* Nothing. */
+}
+
+ATF_TC(nanosleep_basic);
+ATF_TC_HEAD(nanosleep_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test that nanosleep(2) works");
+}
+
+ATF_TC_BODY(nanosleep_basic, tc)
+{
+ static const size_t maxiter = 10;
+ struct timespec ts1, ts2, tsn;
+ size_t i;
+
+ for (i = 1; i < maxiter; i++) {
+
+ tsn.tv_sec = 0;
+ tsn.tv_nsec = i;
+
+ (void)memset(&ts1, 0, sizeof(struct timespec));
+ (void)memset(&ts2, 0, sizeof(struct timespec));
+
+ ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts1) == 0);
+ ATF_REQUIRE(nanosleep(&tsn, NULL) == 0);
+ ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts2) == 0);
+
+ /*
+ * Verify that we slept at least one nanosecond.
+ */
+ if (timespeccmp(&ts2, &ts1, <=) != 0) {
+
+ (void)fprintf(stderr,
+ "sleep time:: sec %llu, nsec %lu\n\t\t"
+ "ts1: sec %llu, nsec %lu\n\t\t"
+ "ts2: sec %llu, nsec %lu\n",
+ (unsigned long long)tsn.tv_sec, tsn.tv_nsec,
+ (unsigned long long)ts1.tv_sec, ts1.tv_nsec,
+ (unsigned long long)ts2.tv_sec, ts2.tv_nsec);
+
+ atf_tc_fail_nonfatal("inaccuracies in sleep time "
+ "(resolution = %lu nsec)", tsn.tv_nsec);
+ }
+ }
+}
+
+ATF_TC(nanosleep_err);
+ATF_TC_HEAD(nanosleep_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test errors from nanosleep(2) (PR bin/14558)");
+}
+
+ATF_TC_BODY(nanosleep_err, tc)
+{
+ struct timespec ts;
+
+ ts.tv_sec = 1;
+ ts.tv_nsec = -1;
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, nanosleep(&ts, NULL) == -1);
+
+ ts.tv_sec = 1;
+ ts.tv_nsec = 1000000000;
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, nanosleep(&ts, NULL) == -1);
+
+ ts.tv_sec = -1;
+ ts.tv_nsec = 0;
+ errno = 0;
+ ATF_REQUIRE_ERRNO(0, nanosleep(&ts, NULL) == 0);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, nanosleep((void *)-1, NULL) == -1);
+}
+
+ATF_TC(nanosleep_sig);
+ATF_TC_HEAD(nanosleep_sig, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test signal for nanosleep(2)");
+}
+
+ATF_TC_BODY(nanosleep_sig, tc)
+{
+ struct timespec tsn, tsr;
+ pid_t pid;
+ int sta;
+
+ /*
+ * Test that a signal interrupts nanosleep(2).
+ *
+ * (In which case the return value should be -1 and the
+ * second parameter should contain the unslept time.)
+ */
+ pid = fork();
+
+ ATF_REQUIRE(pid >= 0);
+ ATF_REQUIRE(signal(SIGINT, handler) == 0);
+
+ if (pid == 0) {
+
+ tsn.tv_sec = 10;
+ tsn.tv_nsec = 0;
+
+ tsr.tv_sec = 0;
+ tsr.tv_nsec = 0;
+
+ errno = 0;
+
+ if (nanosleep(&tsn, &tsr) != -1)
+ _exit(EXIT_FAILURE);
+
+ if (errno != EINTR)
+ _exit(EXIT_FAILURE);
+
+ if (tsr.tv_sec == 0 && tsr.tv_nsec == 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)sleep(1);
+ (void)kill(pid, SIGINT);
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("signal did not interrupt nanosleep(2)");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, nanosleep_basic);
+ ATF_TP_ADD_TC(tp, nanosleep_err);
+ ATF_TP_ADD_TC(tp, nanosleep_sig);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_pipe.c b/contrib/netbsd-tests/lib/libc/sys/t_pipe.c
new file mode 100644
index 0000000..b30b94d
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_pipe.c
@@ -0,0 +1,163 @@
+/* $NetBSD: t_pipe.c,v 1.3 2011/10/31 15:41:31 christos Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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>
+__COPYRIGHT("@(#) Copyright (c) 2008\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_pipe.c,v 1.3 2011/10/31 15:41:31 christos Exp $");
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+#include "../../../h_macros.h"
+
+static pid_t pid;
+static int nsiginfo = 0;
+
+/*
+ * This is used for both parent and child. Handle parent's SIGALRM,
+ * the childs SIGINFO doesn't need anything.
+ */
+static void
+sighand(int sig)
+{
+ if (sig == SIGALRM) {
+ kill(pid, SIGINFO);
+ }
+ if (sig == SIGINFO) {
+ nsiginfo++;
+ }
+}
+
+ATF_TC(pipe_restart);
+ATF_TC_HEAD(pipe_restart, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that writing to pipe "
+ "works correctly after being interrupted and restarted "
+ "(kern/14087)");
+}
+
+ATF_TC_BODY(pipe_restart, tc)
+{
+ int pp[2], st;
+ ssize_t sz, todo, done;
+ char *f;
+ sigset_t asigset, osigset, emptysigset;
+
+ /* Initialise signal masks */
+ RL(sigemptyset(&emptysigset));
+ RL(sigemptyset(&asigset));
+ RL(sigaddset(&asigset, SIGINFO));
+
+ /* Register signal handlers for both read and writer */
+ REQUIRE_LIBC(signal(SIGINFO, sighand), SIG_ERR);
+ REQUIRE_LIBC(signal(SIGALRM, sighand), SIG_ERR);
+
+ todo = 2 * 1024 * 1024;
+ REQUIRE_LIBC(f = malloc(todo), NULL);
+
+ RL(pipe(pp));
+
+ RL(pid = fork());
+ if (pid == 0) {
+ /* child */
+ RL(close(pp[1]));
+
+ /* Do inital write. This should succeed, make
+ * the other side do partial write and wait for us to pick
+ * rest up.
+ */
+ RL(done = read(pp[0], f, 128 * 1024));
+
+ /* Wait until parent is alarmed and awakens us */
+ RL(sigprocmask(SIG_BLOCK, &asigset, &osigset));
+ while (nsiginfo == 0) {
+ if (sigsuspend(&emptysigset) != -1 || errno != EINTR)
+ atf_tc_fail("sigsuspend(&emptysigset): %s",
+ strerror(errno));
+ }
+ RL(sigprocmask(SIG_SETMASK, &osigset, NULL));
+
+ /* Read all what parent wants to give us */
+ while((sz = read(pp[0], f, 1024 * 1024)) > 0)
+ done += sz;
+
+ /*
+ * Exit with 1 if number of bytes read doesn't match
+ * number of expected bytes
+ */
+ printf("Read: %#zx\n", (size_t)done);
+ printf("Expected: %#zx\n", (size_t)todo);
+
+ exit(done != todo);
+
+ /* NOTREACHED */
+ } else {
+ RL(close(pp[0]));
+
+ /*
+ * Arrange for alarm after two seconds. Since we have
+ * handler setup for SIGARLM, the write(2) call should
+ * be restarted internally by kernel.
+ */
+ (void)alarm(2);
+
+ /* We write exactly 'todo' bytes. The very first write(2)
+ * should partially succeed, block and eventually
+ * be restarted by kernel
+ */
+ while(todo > 0 && ((sz = write(pp[1], f, todo)) > 0))
+ todo -= sz;
+
+ /* Close the pipe, so that child would stop reading */
+ RL(close(pp[1]));
+
+ /* And pickup child's exit status */
+ RL(waitpid(pid, &st, 0));
+
+ ATF_REQUIRE_EQ(WEXITSTATUS(st), 0);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, pipe_restart);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_pipe2.c b/contrib/netbsd-tests/lib/libc/sys/t_pipe2.c
new file mode 100644
index 0000000..51f2240
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_pipe2.c
@@ -0,0 +1,188 @@
+/* $NetBSD: t_pipe2.c,v 1.8 2012/05/16 13:54:28 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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: t_pipe2.c,v 1.8 2012/05/16 13:54:28 jruoho Exp $");
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/resource.h>
+
+static void
+run(int flags)
+{
+ int fd[2], i;
+
+ while ((i = open("/", O_RDONLY)) < 3)
+ ATF_REQUIRE(i != -1);
+
+ ATF_REQUIRE(fcntl(3, F_CLOSEM) != -1);
+
+ ATF_REQUIRE(pipe2(fd, flags) == 0);
+
+ ATF_REQUIRE(fd[0] == 3);
+ ATF_REQUIRE(fd[1] == 4);
+
+ if (flags & O_CLOEXEC) {
+ ATF_REQUIRE((fcntl(fd[0], F_GETFD) & FD_CLOEXEC) != 0);
+ ATF_REQUIRE((fcntl(fd[1], F_GETFD) & FD_CLOEXEC) != 0);
+ } else {
+ ATF_REQUIRE((fcntl(fd[0], F_GETFD) & FD_CLOEXEC) == 0);
+ ATF_REQUIRE((fcntl(fd[1], F_GETFD) & FD_CLOEXEC) == 0);
+ }
+
+ if (flags & O_NONBLOCK) {
+ ATF_REQUIRE((fcntl(fd[0], F_GETFL) & O_NONBLOCK) != 0);
+ ATF_REQUIRE((fcntl(fd[1], F_GETFL) & O_NONBLOCK) != 0);
+ } else {
+ ATF_REQUIRE((fcntl(fd[0], F_GETFL) & O_NONBLOCK) == 0);
+ ATF_REQUIRE((fcntl(fd[1], F_GETFL) & O_NONBLOCK) == 0);
+ }
+
+ if (flags & O_NOSIGPIPE) {
+ ATF_REQUIRE(fcntl(fd[0], F_GETNOSIGPIPE) != 0);
+ ATF_REQUIRE(fcntl(fd[1], F_GETNOSIGPIPE) != 0);
+ } else {
+ ATF_REQUIRE(fcntl(fd[0], F_GETNOSIGPIPE) == 0);
+ ATF_REQUIRE(fcntl(fd[1], F_GETNOSIGPIPE) == 0);
+ }
+
+ ATF_REQUIRE(close(fd[0]) != -1);
+ ATF_REQUIRE(close(fd[1]) != -1);
+}
+
+ATF_TC(pipe2_basic);
+ATF_TC_HEAD(pipe2_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of pipe2(2)");
+}
+
+ATF_TC_BODY(pipe2_basic, tc)
+{
+ run(0);
+}
+
+ATF_TC(pipe2_consume);
+ATF_TC_HEAD(pipe2_consume, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test that consuming file descriptors "
+ "with pipe2(2) does not crash the system (PR kern/46457)");
+}
+
+ATF_TC_BODY(pipe2_consume, tc)
+{
+ struct rlimit rl;
+ int err, filedes[2];
+
+ err = fcntl(4, F_CLOSEM);
+ ATF_REQUIRE(err == 0);
+
+ err = getrlimit(RLIMIT_NOFILE, &rl);
+ ATF_REQUIRE(err == 0);
+ /*
+ * The heart of this test is to run against the number of open
+ * file descriptor limit in the middle of a pipe2() call - i.e.
+ * before the call only a single descriptor may be openend.
+ */
+ rl.rlim_cur = 4;
+ err = setrlimit(RLIMIT_NOFILE, &rl);
+ ATF_REQUIRE(err == 0);
+
+ err = pipe2(filedes, O_CLOEXEC);
+ ATF_REQUIRE(err == -1);
+}
+
+ATF_TC(pipe2_nonblock);
+ATF_TC_HEAD(pipe2_nonblock, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A non-blocking test of pipe2(2)");
+}
+
+ATF_TC_BODY(pipe2_nonblock, tc)
+{
+ run(O_NONBLOCK);
+}
+
+ATF_TC(pipe2_cloexec);
+ATF_TC_HEAD(pipe2_cloexec, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A close-on-exec test of pipe2(2)");
+}
+
+ATF_TC_BODY(pipe2_cloexec, tc)
+{
+ run(O_CLOEXEC);
+}
+
+ATF_TC(pipe2_nosigpipe);
+ATF_TC_HEAD(pipe2_nosigpipe, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A no sigpipe test of pipe2(2)");
+}
+
+ATF_TC_BODY(pipe2_nosigpipe, tc)
+{
+ run(O_NOSIGPIPE);
+}
+
+ATF_TC(pipe2_einval);
+ATF_TC_HEAD(pipe2_einval, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A error check of pipe2(2)");
+}
+
+ATF_TC_BODY(pipe2_einval, tc)
+{
+ int fd[2];
+ ATF_REQUIRE_ERRNO(EINVAL, pipe2(fd, O_ASYNC) == -1);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, pipe2_basic);
+ ATF_TP_ADD_TC(tp, pipe2_consume);
+ ATF_TP_ADD_TC(tp, pipe2_nonblock);
+ ATF_TP_ADD_TC(tp, pipe2_cloexec);
+ ATF_TP_ADD_TC(tp, pipe2_nosigpipe);
+ ATF_TP_ADD_TC(tp, pipe2_einval);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_poll.c b/contrib/netbsd-tests/lib/libc/sys/t_poll.c
new file mode 100644
index 0000000..7a786d2
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_poll.c
@@ -0,0 +1,392 @@
+/* $NetBSD: t_poll.c,v 1.3 2012/03/18 07:00:52 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthias Scheler.
+ *
+ * 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/time.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <poll.h>
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+
+static int desc;
+
+static void
+child1(void)
+{
+ struct pollfd pfd;
+
+ pfd.fd = desc;
+ pfd.events = POLLIN | POLLHUP | POLLOUT;
+
+ (void)poll(&pfd, 1, 2000);
+ (void)printf("child1 exit\n");
+}
+
+static void
+child2(void)
+{
+ struct pollfd pfd;
+
+ pfd.fd = desc;
+ pfd.events = POLLIN | POLLHUP | POLLOUT;
+
+ (void)sleep(1);
+ (void)poll(&pfd, 1, INFTIM);
+ (void)printf("child2 exit\n");
+}
+
+static void
+child3(void)
+{
+ struct pollfd pfd;
+
+ (void)sleep(5);
+
+ pfd.fd = desc;
+ pfd.events = POLLIN | POLLHUP | POLLOUT;
+
+ (void)poll(&pfd, 1, INFTIM);
+ (void)printf("child3 exit\n");
+}
+
+ATF_TC(poll_3way);
+ATF_TC_HEAD(poll_3way, tc)
+{
+ atf_tc_set_md_var(tc, "timeout", "15");
+ atf_tc_set_md_var(tc, "descr",
+ "Check for 3-way collision for descriptor. First child comes "
+ "and polls on descriptor, second child comes and polls, first "
+ "child times out and exits, third child comes and polls. When "
+ "the wakeup event happens, the two remaining children should "
+ "both be awaken. (kern/17517)");
+}
+
+ATF_TC_BODY(poll_3way, tc)
+{
+ int pf[2];
+ int status, i;
+ pid_t pid;
+
+ pipe(pf);
+ desc = pf[0];
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+ (void)close(pf[1]);
+ child1();
+ _exit(0);
+ /* NOTREACHED */
+ }
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+ (void)close(pf[1]);
+ child2();
+ _exit(0);
+ /* NOTREACHED */
+ }
+
+ pid = fork();
+ ATF_REQUIRE( pid >= 0);
+
+ if (pid == 0) {
+ (void)close(pf[1]);
+ child3();
+ _exit(0);
+ /* NOTREACHED */
+ }
+
+ (void)sleep(10);
+
+ (void)printf("parent write\n");
+
+ ATF_REQUIRE(write(pf[1], "konec\n", 6) == 6);
+
+ for(i = 0; i < 3; ++i)
+ (void)wait(&status);
+
+ (void)printf("parent terminated\n");
+}
+
+ATF_TC(poll_basic);
+ATF_TC_HEAD(poll_basic, tc)
+{
+ atf_tc_set_md_var(tc, "timeout", "10");
+ atf_tc_set_md_var(tc, "descr",
+ "Basis functionality test for poll(2)");
+}
+
+ATF_TC_BODY(poll_basic, tc)
+{
+ int fds[2];
+ struct pollfd pfds[2];
+ int ret;
+
+ ATF_REQUIRE_EQ(pipe(fds), 0);
+
+ pfds[0].fd = fds[0];
+ pfds[0].events = POLLIN;
+ pfds[1].fd = fds[1];
+ pfds[1].events = POLLOUT;
+
+ /*
+ * Check that we get a timeout waiting for data on the read end
+ * of our pipe.
+ */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
+
+ /* Check that the write end of the pipe as reported as ready. */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
+ pfds[1].revents);
+
+ /* Check that only the write end of the pipe as reported as ready. */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
+ pfds[1].revents);
+
+ /* Write data to our pipe. */
+ ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
+
+ /* Check that both ends of our pipe are reported as ready. */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
+ pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
+ pfds[1].revents);
+
+ ATF_REQUIRE_EQ(close(fds[0]), 0);
+ ATF_REQUIRE_EQ(close(fds[1]), 0);
+}
+
+ATF_TC(poll_err);
+ATF_TC_HEAD(poll_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)");
+}
+
+ATF_TC_BODY(poll_err, tc)
+{
+ struct pollfd pfd;
+ int fd = 0;
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1);
+}
+
+ATF_TC(pollts_basic);
+ATF_TC_HEAD(pollts_basic, tc)
+{
+ atf_tc_set_md_var(tc, "timeout", "10");
+ atf_tc_set_md_var(tc, "descr",
+ "Basis functionality test for pollts(2)");
+}
+
+ATF_TC_BODY(pollts_basic, tc)
+{
+ int fds[2];
+ struct pollfd pfds[2];
+ struct timespec timeout;
+ int ret;
+
+ ATF_REQUIRE_EQ(pipe(fds), 0);
+
+ pfds[0].fd = fds[0];
+ pfds[0].events = POLLIN;
+ pfds[1].fd = fds[1];
+ pfds[1].events = POLLOUT;
+
+ /* Use a timeout of 1 second. */
+ timeout.tv_sec = 1;
+ timeout.tv_nsec = 0;
+
+ /*
+ * Check that we get a timeout waiting for data on the read end
+ * of our pipe.
+ */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[0], 1, &timeout, NULL), 0,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
+
+ /* Check that the write end of the pipe as reported as ready. */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[1], 1, &timeout, NULL), 1,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
+ pfds[1].revents);
+
+ /* Check that only the write end of the pipe as reported as ready. */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 1,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
+ pfds[1].revents);
+
+ /* Write data to our pipe. */
+ ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
+
+ /* Check that both ends of our pipe are reported as ready. */
+ pfds[0].revents = -1;
+ pfds[1].revents = -1;
+ ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 2,
+ "got: %d", ret);
+ ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
+ pfds[0].revents);
+ ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
+ pfds[1].revents);
+
+ ATF_REQUIRE_EQ(close(fds[0]), 0);
+ ATF_REQUIRE_EQ(close(fds[1]), 0);
+}
+
+ATF_TC(pollts_err);
+ATF_TC_HEAD(pollts_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Check errors from pollts(2)");
+}
+
+ATF_TC_BODY(pollts_err, tc)
+{
+ struct timespec timeout;
+ struct pollfd pfd;
+ int fd = 0;
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+
+ timeout.tv_sec = 1;
+ timeout.tv_nsec = 0;
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, pollts((void *)-1, 1, &timeout, NULL) == -1);
+
+ timeout.tv_sec = -1;
+ timeout.tv_nsec = -1;
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, pollts(&pfd, 1, &timeout, NULL) == -1);
+}
+
+ATF_TC(pollts_sigmask);
+ATF_TC_HEAD(pollts_sigmask, tc)
+{
+ atf_tc_set_md_var(tc, "timeout", "10");
+ atf_tc_set_md_var(tc, "descr",
+ "Check that pollts(2) restores the signal mask (PR kern/44986)");
+}
+
+ATF_TC_BODY(pollts_sigmask, tc)
+{
+ int fd;
+ struct pollfd pfd;
+ struct timespec timeout;
+ sigset_t mask;
+ int ret;
+
+ fd = open(_PATH_DEVNULL, O_RDONLY);
+ ATF_REQUIRE(fd >= 0);
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+
+ /* Use a timeout of 1 second. */
+ timeout.tv_sec = 1;
+ timeout.tv_nsec = 0;
+
+ /* Unblock all signals. */
+ ATF_REQUIRE_EQ(sigfillset(&mask), 0);
+ ATF_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &mask, NULL), 0);
+
+ /*
+ * Check that pollts(2) immediately returns. We block *all*
+ * signals during pollts(2).
+ */
+ ATF_REQUIRE_EQ_MSG(ret = pollts(&pfd, 1, &timeout, &mask), 1,
+ "got: %d", ret);
+
+ /* Check that signals are now longer blocked. */
+ ATF_REQUIRE_EQ(sigprocmask(SIG_SETMASK, NULL, &mask), 0);
+ ATF_REQUIRE_EQ_MSG(sigismember(&mask, SIGUSR1), 0,
+ "signal mask was changed.");
+
+ ATF_REQUIRE_EQ(close(fd), 0);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, poll_3way);
+ ATF_TP_ADD_TC(tp, poll_basic);
+ ATF_TP_ADD_TC(tp, poll_err);
+ ATF_TP_ADD_TC(tp, pollts_basic);
+ ATF_TP_ADD_TC(tp, pollts_err);
+ ATF_TP_ADD_TC(tp, pollts_sigmask);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_posix_fadvise.c b/contrib/netbsd-tests/lib/libc/sys/t_posix_fadvise.c
new file mode 100644
index 0000000..da4e746
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_posix_fadvise.c
@@ -0,0 +1,165 @@
+/* $NetBSD: t_posix_fadvise.c,v 1.1 2011/10/15 06:10:26 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by YAMAMOTO Takashi.
+ *
+ * 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.
+ */
+
+/*-
+ * Copyright (c)2005 YAMAMOTO Takashi,
+ * All rights reserved.
+ *
+ * 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 AUTHOR 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 AUTHOR 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>
+__COPYRIGHT("@(#) Copyright (c) 2008\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_posix_fadvise.c,v 1.1 2011/10/15 06:10:26 jruoho Exp $");
+
+#include <sys/fcntl.h>
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+
+#include "../../../h_macros.h"
+
+#include <rump/rump.h>
+#include <rump/rump_syscalls.h>
+
+ATF_TC(posix_fadvise);
+ATF_TC_HEAD(posix_fadvise, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks posix_fadvise(2)");
+}
+
+ATF_TC(posix_fadvise_reg);
+ATF_TC_HEAD(posix_fadvise_reg, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks posix_fadvise(2) "
+ "for regular files");
+}
+
+ATF_TC_BODY(posix_fadvise, tc)
+{
+ int fd;
+ int pipe_fds[2];
+ int badfd = 10;
+ int ret;
+
+ RL(fd = open("/dev/null", O_RDWR));
+
+ (void)close(badfd);
+ RL(pipe(pipe_fds));
+
+ /*
+ * it's hard to check if posix_fadvise is working properly.
+ * only check return values here.
+ */
+
+ /* posix_fadvise shouldn't affect errno. */
+
+#define CE(x, exp) \
+ do { \
+ int save = errno; \
+ errno = 999; \
+ ATF_CHECK_EQ_MSG(ret = (x), exp, "got: %d", ret); \
+ ATF_CHECK_EQ_MSG(errno, 999, "got: %s", strerror(errno)); \
+ errno = save; \
+ } while (0);
+
+ CE(posix_fadvise(fd, 0, 0, -1), EINVAL);
+ CE(posix_fadvise(pipe_fds[0], 0, 0, POSIX_FADV_NORMAL), ESPIPE);
+ CE(posix_fadvise(badfd, 0, 0, POSIX_FADV_NORMAL), EBADF);
+ CE(posix_fadvise(fd, 0, 0, POSIX_FADV_NORMAL), 0);
+ CE(posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL), 0);
+ CE(posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM), 0);
+ CE(posix_fadvise(fd, 0, 0, POSIX_FADV_WILLNEED), 0);
+ CE(posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED), 0);
+ CE(posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE), 0);
+}
+
+ATF_TC_BODY(posix_fadvise_reg, tc)
+{
+ int rfd, ret;
+
+ rump_init();
+ RL(rfd = rump_sys_open("/a_file", O_CREAT, 0666));
+
+ CE(rump_sys_posix_fadvise(rfd, 0, 0, POSIX_FADV_NORMAL), 0);
+ CE(rump_sys_posix_fadvise(rfd, 0, 0, POSIX_FADV_SEQUENTIAL), 0);
+ CE(rump_sys_posix_fadvise(rfd, 0, 0, POSIX_FADV_RANDOM), 0);
+ CE(rump_sys_posix_fadvise(rfd, 0, 0, POSIX_FADV_WILLNEED), 0);
+ CE(rump_sys_posix_fadvise(rfd, 0, 0, POSIX_FADV_NOREUSE), 0);
+
+ CE(rump_sys_posix_fadvise(rfd,
+ INT64_MAX-getpagesize(), getpagesize(), POSIX_FADV_NORMAL), 0);
+ CE(rump_sys_posix_fadvise(rfd,
+ INT64_MAX-getpagesize(), getpagesize(), POSIX_FADV_SEQUENTIAL), 0);
+ CE(rump_sys_posix_fadvise(rfd,
+ INT64_MAX-getpagesize(), getpagesize(), POSIX_FADV_RANDOM), 0);
+ CE(rump_sys_posix_fadvise(rfd,
+ INT64_MAX-getpagesize(), getpagesize(), POSIX_FADV_WILLNEED), 0);
+ CE(rump_sys_posix_fadvise(rfd,
+ INT64_MAX-getpagesize(), getpagesize(), POSIX_FADV_NOREUSE), 0);
+
+ //atf_tc_expect_signal(-1, "http://mail-index.netbsd.org/source-changes-d/2010/11/11/msg002508.html");
+ CE(rump_sys_posix_fadvise(rfd,
+ INT64_MAX-getpagesize(), getpagesize(), POSIX_FADV_DONTNEED), 0);
+ CE(rump_sys_posix_fadvise(rfd, 0, 0, POSIX_FADV_DONTNEED), 0);
+#undef CE
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, posix_fadvise);
+ ATF_TP_ADD_TC(tp, posix_fadvise_reg);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_recvmmsg.c b/contrib/netbsd-tests/lib/libc/sys/t_recvmmsg.c
new file mode 100644
index 0000000..76bc7dd
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_recvmmsg.c
@@ -0,0 +1,161 @@
+/* $NetBSD: t_recvmmsg.c,v 1.1 2012/06/22 18:45:23 christos Exp $ */
+
+/*-
+ * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jared McNeill and Christos Zoulas.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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: t_recvmmsg.c,v 1.1 2012/06/22 18:45:23 christos Exp $");
+
+#include <atf-c.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#include <string.h>
+#include <time.h>
+#include <stdint.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sched.h>
+
+#define BUFSIZE 65536
+#define NPKTS 50
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+static int debug;
+
+
+ATF_TC(recvmmsg_basic);
+ATF_TC_HEAD(recvmmsg_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of recvmmsg(2)");
+}
+
+ATF_TC_BODY(recvmmsg_basic, tc)
+{
+ int fd[2], error, i, cnt;
+ uint8_t *buf;
+ struct mmsghdr *mmsghdr;
+ struct iovec *iov;
+ unsigned int mmsgcnt, n;
+ int status;
+ off_t off;
+ uint8_t DGRAM[1316] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, };
+
+ error = socketpair(AF_UNIX, SOCK_DGRAM, 0, fd);
+ ATF_REQUIRE_MSG(error != -1, "socketpair failed (%s)", strerror(errno));
+
+ buf = malloc(BUFSIZE);
+ ATF_REQUIRE_MSG(buf != NULL, "malloc failed (%s)", strerror(errno));
+
+ mmsgcnt = BUFSIZE / sizeof(DGRAM);
+ mmsghdr = malloc(sizeof(*mmsghdr) * mmsgcnt);
+ ATF_REQUIRE_MSG(mmsghdr != NULL, "malloc failed (%s)", strerror(errno));
+ iov = malloc(sizeof(*iov) * mmsgcnt);
+ ATF_REQUIRE_MSG(iov != NULL, "malloc failed (%s)", strerror(errno));
+
+ for (off = 0, n = 0; n < mmsgcnt; n++) {
+ iov[n].iov_base = buf + off;
+ iov[n].iov_len = sizeof(DGRAM);
+ off += iov[n].iov_len;
+ mmsghdr[n].msg_hdr.msg_iov = &iov[n];
+ mmsghdr[n].msg_hdr.msg_iovlen = 1;
+ mmsghdr[n].msg_hdr.msg_name = NULL;
+ mmsghdr[n].msg_hdr.msg_namelen = 0;
+ }
+
+ switch (fork()) {
+ case -1:
+ ATF_REQUIRE_MSG(0, "fork failed (%s)", strerror(errno));
+ break;
+
+ case 0:
+ n = NPKTS;
+ if (debug)
+ printf("waiting for %u messages (max %u per syscall)\n", n,
+ mmsgcnt);
+ while (n > 0) {
+ struct timespec ts = { 1, 0 };
+ cnt = recvmmsg(fd[1], mmsghdr, min(mmsgcnt, n),
+ MSG_WAITALL, &ts);
+ ATF_REQUIRE_MSG(cnt != -1, "recvmmsg failed (%s)",
+ strerror(errno));
+ ATF_REQUIRE_MSG(cnt != 0, "recvmmsg timeout");
+ if (debug)
+ printf("recvmmsg: got %u messages\n", cnt);
+ for (i = 0; i < cnt; i++) {
+ ATF_CHECK_EQ_MSG(mmsghdr[i].msg_len,
+ sizeof(DGRAM), "packet length");
+ ATF_CHECK_EQ_MSG(
+ ((uint8_t *)iov[i].iov_base)[0],
+ NPKTS - n + i, "packet contents");
+ }
+ n -= cnt;
+ }
+ if (debug)
+ printf("done!\n");
+ exit(0);
+ /*NOTREACHED*/
+ default:
+ sched_yield();
+
+ for (n = 0; n < NPKTS; n++) {
+ if (debug)
+ printf("sending packet %u/%u...\n", (n+1),
+ NPKTS);
+ do {
+ DGRAM[0] = n;
+ error = send(fd[0], DGRAM, sizeof(DGRAM), 0);
+ } while (error == -1 && errno == ENOBUFS);
+ if (error == -1)
+ ATF_REQUIRE_MSG(error != -1, "send failed (%s)",
+ strerror(errno));
+ }
+ error = wait(&status);
+ ATF_REQUIRE_MSG(error != -1, "wait failed (%s)",
+ strerror(errno));
+ break;
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, recvmmsg_basic);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_revoke.c b/contrib/netbsd-tests/lib/libc/sys/t_revoke.c
new file mode 100644
index 0000000..10fd6d6
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_revoke.c
@@ -0,0 +1,186 @@
+/* $NetBSD: t_revoke.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_revoke.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
+
+#include <sys/resource.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static const char path[] = "revoke";
+
+ATF_TC_WITH_CLEANUP(revoke_basic);
+ATF_TC_HEAD(revoke_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of revoke(2)");
+}
+
+ATF_TC_BODY(revoke_basic, tc)
+{
+ struct rlimit res;
+ char tmp[10];
+ size_t i, n;
+ int *buf;
+
+ (void)memset(&res, 0, sizeof(struct rlimit));
+ (void)getrlimit(RLIMIT_NOFILE, &res);
+
+ if ((n = res.rlim_cur / 10) == 0)
+ n = 10;
+
+ buf = calloc(n, sizeof(int));
+ ATF_REQUIRE(buf != NULL);
+
+ buf[0] = open(path, O_RDWR | O_CREAT, 0600);
+ ATF_REQUIRE(buf[0] >= 0);
+
+ for (i = 1; i < n; i++) {
+ buf[i] = open(path, O_RDWR);
+ ATF_REQUIRE(buf[i] >= 0);
+ }
+
+ ATF_REQUIRE(revoke(path) == 0);
+
+ for (i = 0; i < n; i++) {
+
+ ATF_REQUIRE(read(buf[i], tmp, sizeof(tmp)) == -1);
+
+ (void)close(buf[i]);
+ }
+
+ free(buf);
+
+ (void)unlink(path);
+}
+
+ATF_TC_CLEANUP(revoke_basic, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(revoke_err);
+ATF_TC_HEAD(revoke_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from revoke(2)");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(revoke_err, tc)
+{
+ char buf[1024 + 1]; /* XXX: From the manual page... */
+
+ (void)memset(buf, 'x', sizeof(buf));
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, revoke((char *)-1) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENAMETOOLONG, revoke(buf) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EPERM, revoke("/etc/passwd") == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, revoke("/etc/xxx/yyy") == -1);
+}
+
+ATF_TC_WITH_CLEANUP(revoke_perm);
+ATF_TC_HEAD(revoke_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test permissions revoke(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(revoke_perm, tc)
+{
+ struct passwd *pw;
+ int fd, sta;
+ pid_t pid;
+
+ pw = getpwnam("nobody");
+ fd = open(path, O_RDWR | O_CREAT, 0600);
+
+ ATF_REQUIRE(fd >= 0);
+ ATF_REQUIRE(pw != NULL);
+ ATF_REQUIRE(revoke(path) == 0);
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ if (setuid(pw->pw_uid) != 0)
+ _exit(EXIT_FAILURE);
+
+ errno = 0;
+
+ if (revoke(path) == 0)
+ _exit(EXIT_FAILURE);
+
+ if (errno != EACCES)
+ _exit(EXIT_FAILURE);
+
+ if (close(fd) != 0)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("revoke(2) did not obey permissions");
+
+ ATF_REQUIRE(unlink(path) == 0);
+}
+
+ATF_TC_CLEANUP(revoke_perm, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, revoke_basic);
+ ATF_TP_ADD_TC(tp, revoke_err);
+ ATF_TP_ADD_TC(tp, revoke_perm);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_select.c b/contrib/netbsd-tests/lib/libc/sys/t_select.c
new file mode 100644
index 0000000..4316acf
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_select.c
@@ -0,0 +1,215 @@
+/* $NetBSD: t_select.c,v 1.3 2012/03/18 07:00:52 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundatiom
+ * by Christos Zoulas.
+ *
+ * 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 <assert.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/wait.h>
+#include <err.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <atf-c.h>
+
+static sig_atomic_t keep_going = 1;
+
+static void
+sig_handler(int signum)
+{
+ keep_going = 0;
+}
+
+static void
+sigchld(int signum)
+{
+}
+
+static char
+xtoa(uint8_t n)
+{
+ static const char xarray[] = "0123456789abcdef";
+ assert(n < sizeof(xarray));
+ return xarray[n];
+}
+
+static const char *
+prmask(const sigset_t *m, char *buf, size_t len)
+{
+ size_t j = 2;
+ assert(len >= 3 + sizeof(*m));
+ buf[0] = '0';
+ buf[1] = 'x';
+#define N(p, a) (((p) >> ((a) * 4)) & 0xf)
+ for (size_t i = __arraycount(m->__bits); i > 0; i--) {
+ uint32_t p = m->__bits[i - 1];
+ for (size_t k = sizeof(p); k > 0; k--)
+ buf[j++] = xtoa(N(p, k - 1));
+ }
+ buf[j] = '\0';
+ return buf;
+}
+
+static void
+child(const struct timespec *ts)
+{
+ struct sigaction sa;
+ sigset_t set, oset, nset;
+ char obuf[sizeof(oset) + 3], nbuf[sizeof(nset) + 3];
+ int fd;
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = sig_handler;
+ if ((fd = open("/dev/null", O_RDONLY)) == -1)
+ err(1, "open");
+
+ if (sigaction(SIGTERM, &sa, NULL) == -1)
+ err(1, "sigaction");
+
+ sigfillset(&set);
+ if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
+ err(1, "sigprocmask");
+
+ if (sigprocmask(SIG_BLOCK, NULL, &oset) == -1)
+ err(1, "sigprocmask");
+
+ sigemptyset(&set);
+
+ for (;;) {
+ fd_set rset;
+ FD_ZERO(&rset);
+ FD_SET(fd, &rset);
+ if (pselect(1, &rset, NULL, NULL, ts, &set) == -1) {
+ if(errno == EINTR) {
+ if (!keep_going)
+ break;
+ }
+ }
+ if (ts)
+ break;
+ }
+ if (sigprocmask(SIG_BLOCK, NULL, &nset) == -1)
+ err(1, "sigprocmask");
+ if (memcmp(&oset, &nset, sizeof(oset)) != 0)
+ atf_tc_fail("pselect() masks don't match "
+ "after timeout %s != %s",
+ prmask(&nset, nbuf, sizeof(nbuf)),
+ prmask(&oset, obuf, sizeof(obuf)));
+}
+
+ATF_TC(pselect_sigmask);
+ATF_TC_HEAD(pselect_sigmask, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks pselect's temporary mask "
+ "setting when a signal is received (PR lib/43625)");
+}
+
+ATF_TC_BODY(pselect_sigmask, tc)
+{
+ pid_t pid;
+ int status;
+
+ signal(SIGCHLD, sigchld);
+
+ switch (pid = fork()) {
+ case 0:
+ child(NULL);
+ case -1:
+ err(1, "fork");
+ default:
+ sleep(1);
+ if (kill(pid, SIGTERM) == -1)
+ err(1, "kill");
+ sleep(1);
+ switch (waitpid(pid, &status, WNOHANG)) {
+ case -1:
+ err(1, "wait");
+ case 0:
+ if (kill(pid, SIGKILL) == -1)
+ err(1, "kill");
+ atf_tc_fail("pselect() did not receive signal");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+ATF_TC(pselect_timeout);
+ATF_TC_HEAD(pselect_timeout, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr", "Checks pselect's temporary mask "
+ "setting when a timeout occurs");
+}
+
+ATF_TC_BODY(pselect_timeout, tc)
+{
+ pid_t pid;
+ int status;
+ static const struct timespec zero = { 0, 0 };
+
+ signal(SIGCHLD, sigchld);
+
+ switch (pid = fork()) {
+ case 0:
+ child(&zero);
+ break;
+ case -1:
+ err(1, "fork");
+ default:
+ sleep(1);
+ switch (waitpid(pid, &status, WNOHANG)) {
+ case -1:
+ err(1, "wait");
+ case 0:
+ if (kill(pid, SIGKILL) == -1)
+ err(1, "kill");
+ atf_tc_fail("pselect() did not receive signal");
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, pselect_sigmask);
+ ATF_TP_ADD_TC(tp, pselect_timeout);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_setrlimit.c b/contrib/netbsd-tests/lib/libc/sys/t_setrlimit.c
new file mode 100644
index 0000000..c760cfb
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_setrlimit.c
@@ -0,0 +1,522 @@
+/* $NetBSD: t_setrlimit.c,v 1.4 2012/06/12 23:56:19 christos Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_setrlimit.c,v 1.4 2012/06/12 23:56:19 christos Exp $");
+
+#include <sys/resource.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <lwp.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+static void sighandler(int);
+static const char path[] = "setrlimit";
+
+static const int rlimit[] = {
+ RLIMIT_AS,
+ RLIMIT_CORE,
+ RLIMIT_CPU,
+ RLIMIT_DATA,
+ RLIMIT_FSIZE,
+ RLIMIT_MEMLOCK,
+ RLIMIT_NOFILE,
+ RLIMIT_NPROC,
+ RLIMIT_RSS,
+ RLIMIT_SBSIZE,
+ RLIMIT_STACK
+};
+
+ATF_TC(setrlimit_basic);
+ATF_TC_HEAD(setrlimit_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic soft limit test");
+}
+
+ATF_TC_BODY(setrlimit_basic, tc)
+{
+ struct rlimit res;
+ int *buf, lim;
+ size_t i;
+
+ buf = calloc(__arraycount(rlimit), sizeof(int));
+
+ if (buf == NULL)
+ atf_tc_fail("initialization failed");
+
+ for (i = lim = 0; i < __arraycount(rlimit); i++) {
+
+ (void)memset(&res, 0, sizeof(struct rlimit));
+
+ if (getrlimit(rlimit[i], &res) != 0)
+ continue;
+
+ if (res.rlim_cur == RLIM_INFINITY || res.rlim_cur == 0)
+ continue;
+
+ if (res.rlim_cur == res.rlim_max) /* An unprivileged run. */
+ continue;
+
+ buf[i] = res.rlim_cur;
+ res.rlim_cur = res.rlim_cur - 1;
+
+ if (setrlimit(rlimit[i], &res) != 0) {
+ lim = rlimit[i];
+ goto out;
+ }
+ }
+
+out:
+ for (i = 0; i < __arraycount(rlimit); i++) {
+
+ (void)memset(&res, 0, sizeof(struct rlimit));
+
+ if (buf[i] == 0)
+ continue;
+
+ if (getrlimit(rlimit[i], &res) != 0)
+ continue;
+
+ res.rlim_cur = buf[i];
+
+ (void)setrlimit(rlimit[i], &res);
+ }
+
+ if (lim != 0)
+ atf_tc_fail("failed to set limit (%d)", lim);
+}
+
+ATF_TC(setrlimit_current);
+ATF_TC_HEAD(setrlimit_current, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "setrlimit(3) with current limits");
+}
+
+ATF_TC_BODY(setrlimit_current, tc)
+{
+ struct rlimit res;
+ size_t i;
+
+ for (i = 0; i < __arraycount(rlimit); i++) {
+
+ (void)memset(&res, 0, sizeof(struct rlimit));
+
+ ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
+ ATF_REQUIRE(setrlimit(rlimit[i], &res) == 0);
+ }
+}
+
+ATF_TC(setrlimit_err);
+ATF_TC_HEAD(setrlimit_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions");
+}
+
+ATF_TC_BODY(setrlimit_err, tc)
+{
+ struct rlimit res;
+ size_t i;
+
+ for (i = 0; i < __arraycount(rlimit); i++) {
+
+ errno = 0;
+
+ ATF_REQUIRE(getrlimit(rlimit[i], (void *)0) != 0);
+ ATF_REQUIRE(errno == EFAULT);
+ }
+
+ errno = 0;
+
+ ATF_REQUIRE(getrlimit(INT_MAX, &res) != 0);
+ ATF_REQUIRE(errno == EINVAL);
+}
+
+ATF_TC_WITH_CLEANUP(setrlimit_fsize);
+ATF_TC_HEAD(setrlimit_fsize, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_FSIZE");
+}
+
+ATF_TC_BODY(setrlimit_fsize, tc)
+{
+ struct rlimit res;
+ int fd, sta;
+ pid_t pid;
+
+ fd = open(path, O_RDWR | O_CREAT, 0700);
+
+ if (fd < 0)
+ atf_tc_fail("initialization failed");
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ res.rlim_cur = 2;
+ res.rlim_max = 2;
+
+ if (setrlimit(RLIMIT_FSIZE, &res) != 0)
+ _exit(EXIT_FAILURE);
+
+ if (signal(SIGXFSZ, sighandler) == SIG_ERR)
+ _exit(EXIT_FAILURE);
+
+ /*
+ * The third call should generate a SIGXFSZ.
+ */
+ (void)write(fd, "X", 1);
+ (void)write(fd, "X", 1);
+ (void)write(fd, "X", 1);
+
+ _exit(EXIT_FAILURE);
+ }
+
+ (void)close(fd);
+ (void)wait(&sta);
+ (void)unlink(path);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("RLIMIT_FSIZE not enforced");
+}
+
+ATF_TC_CLEANUP(setrlimit_fsize, tc)
+{
+ (void)unlink(path);
+}
+
+static void
+sighandler(int signo)
+{
+
+ if (signo != SIGXFSZ)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+}
+
+ATF_TC(setrlimit_memlock);
+ATF_TC_HEAD(setrlimit_memlock, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_MEMLOCK");
+}
+
+ATF_TC_BODY(setrlimit_memlock, tc)
+{
+ struct rlimit res;
+ void *buf;
+ long page;
+ pid_t pid;
+ int sta;
+
+ page = sysconf(_SC_PAGESIZE);
+ ATF_REQUIRE(page >= 0);
+
+ buf = malloc(page);
+ pid = fork();
+
+ if (buf == NULL || pid < 0)
+ atf_tc_fail("initialization failed");
+
+ if (pid == 0) {
+
+ /*
+ * Try to lock a page while
+ * RLIMIT_MEMLOCK is zero.
+ */
+ if (mlock(buf, page) != 0)
+ _exit(EXIT_FAILURE);
+
+ if (munlock(buf, page) != 0)
+ _exit(EXIT_FAILURE);
+
+ res.rlim_cur = 0;
+ res.rlim_max = 0;
+
+ if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
+ _exit(EXIT_FAILURE);
+
+ if (mlock(buf, page) != 0)
+ _exit(EXIT_SUCCESS);
+
+ (void)munlock(buf, page);
+
+ _exit(EXIT_FAILURE);
+ }
+
+ free(buf);
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("RLIMIT_MEMLOCK not enforced");
+}
+
+ATF_TC(setrlimit_nofile_1);
+ATF_TC_HEAD(setrlimit_nofile_1, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #1");
+}
+
+ATF_TC_BODY(setrlimit_nofile_1, tc)
+{
+ struct rlimit res;
+ int fd, i, rv, sta;
+ pid_t pid;
+
+ res.rlim_cur = 0;
+ res.rlim_max = 0;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ /*
+ * Close all descriptors, set RLIMIT_NOFILE
+ * to zero, and try to open a random file.
+ * This should fail with EMFILE.
+ */
+ for (i = 0; i < 1024; i++)
+ (void)close(i);
+
+ rv = setrlimit(RLIMIT_NOFILE, &res);
+
+ if (rv != 0)
+ _exit(EXIT_FAILURE);
+
+ errno = 0;
+ fd = open("/etc/passwd", O_RDONLY);
+
+ if (fd >= 0 || errno != EMFILE)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("RLIMIT_NOFILE not enforced");
+}
+
+ATF_TC(setrlimit_nofile_2);
+ATF_TC_HEAD(setrlimit_nofile_2, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #2");
+}
+
+ATF_TC_BODY(setrlimit_nofile_2, tc)
+{
+ static const rlim_t lim = 12;
+ struct rlimit res;
+ int fd, i, rv, sta;
+ pid_t pid;
+
+ /*
+ * See that an arbitrary limit on
+ * open files is being enforced.
+ */
+ res.rlim_cur = lim;
+ res.rlim_max = lim;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ for (i = 0; i < 1024; i++)
+ (void)close(i);
+
+ rv = setrlimit(RLIMIT_NOFILE, &res);
+
+ if (rv != 0)
+ _exit(EXIT_FAILURE);
+
+ for (i = 0; i < (int)lim; i++) {
+
+ fd = open("/etc/passwd", O_RDONLY);
+
+ if (fd < 0)
+ _exit(EXIT_FAILURE);
+ }
+
+ /*
+ * After the limit has been reached,
+ * EMFILE should again follow.
+ */
+ fd = open("/etc/passwd", O_RDONLY);
+
+ if (fd >= 0 || errno != EMFILE)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("RLIMIT_NOFILE not enforced");
+}
+
+ATF_TC(setrlimit_nproc);
+ATF_TC_HEAD(setrlimit_nproc, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NPROC");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(setrlimit_nproc, tc)
+{
+ struct rlimit res;
+ pid_t pid, cpid;
+ int sta;
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ /*
+ * Set RLIMIT_NPROC to zero and try to fork.
+ */
+ res.rlim_cur = 0;
+ res.rlim_max = 0;
+
+ if (setrlimit(RLIMIT_NPROC, &res) != 0)
+ _exit(EXIT_FAILURE);
+
+ cpid = fork();
+
+ if (cpid < 0)
+ _exit(EXIT_SUCCESS);
+
+ _exit(EXIT_FAILURE);
+ }
+
+ (void)waitpid(pid, &sta, 0);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("RLIMIT_NPROC not enforced");
+}
+
+ATF_TC(setrlimit_nthr);
+ATF_TC_HEAD(setrlimit_nthr, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NTHR");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+static void
+func(lwpid_t *id)
+{
+ printf("thread %d\n", *id);
+ fflush(stdout);
+ _lwp_exit();
+}
+
+ATF_TC_BODY(setrlimit_nthr, tc)
+{
+ struct rlimit res;
+ lwpid_t lwpid;
+ ucontext_t c;
+
+ /*
+ * Set RLIMIT_NTHR to zero and try to create a thread.
+ */
+ res.rlim_cur = 0;
+ res.rlim_max = 0;
+ ATF_REQUIRE(setrlimit(RLIMIT_NTHR, &res) == 0);
+ ATF_REQUIRE(getcontext(&c) == 0);
+ c.uc_link = NULL;
+ sigemptyset(&c.uc_sigmask);
+ c.uc_stack.ss_flags = 0;
+ c.uc_stack.ss_size = 4096;
+ ATF_REQUIRE((c.uc_stack.ss_sp = malloc(c.uc_stack.ss_size)) != NULL);
+ makecontext(&c, func, 1, &lwpid);
+ ATF_CHECK_ERRNO(EAGAIN, _lwp_create(&c, 0, &lwpid) == -1);
+}
+
+ATF_TC(setrlimit_perm);
+ATF_TC_HEAD(setrlimit_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setrlimit(2) for EPERM");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(setrlimit_perm, tc)
+{
+ struct rlimit res;
+ size_t i;
+
+ /*
+ * Try to raise the maximum limits as an user.
+ */
+ for (i = 0; i < __arraycount(rlimit); i++) {
+
+ ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
+
+ if (res.rlim_max == UINT64_MAX) /* Overflow. */
+ continue;
+
+ errno = 0;
+ res.rlim_max = res.rlim_max + 1;
+
+ ATF_CHECK_ERRNO(EPERM, setrlimit(rlimit[i], &res) != 0);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, setrlimit_basic);
+ ATF_TP_ADD_TC(tp, setrlimit_current);
+ ATF_TP_ADD_TC(tp, setrlimit_err);
+ ATF_TP_ADD_TC(tp, setrlimit_fsize);
+ ATF_TP_ADD_TC(tp, setrlimit_memlock);
+ ATF_TP_ADD_TC(tp, setrlimit_nofile_1);
+ ATF_TP_ADD_TC(tp, setrlimit_nofile_2);
+ ATF_TP_ADD_TC(tp, setrlimit_nproc);
+ ATF_TP_ADD_TC(tp, setrlimit_perm);
+ ATF_TP_ADD_TC(tp, setrlimit_nthr);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_setuid.c b/contrib/netbsd-tests/lib/libc/sys/t_setuid.c
new file mode 100644
index 0000000..d2bf523
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_setuid.c
@@ -0,0 +1,122 @@
+/* $NetBSD: t_setuid.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_setuid.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
+
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+ATF_TC(setuid_perm);
+ATF_TC_HEAD(setuid_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setuid(0) as normal user");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(setuid_perm, tc)
+{
+ errno = 0;
+
+ ATF_REQUIRE(setuid(0) == -1);
+ ATF_REQUIRE(errno == EPERM);
+}
+
+ATF_TC(setuid_real);
+ATF_TC_HEAD(setuid_real, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test setuid(2) with real UID");
+}
+
+ATF_TC_BODY(setuid_real, tc)
+{
+ uid_t uid = getuid();
+
+ ATF_REQUIRE(setuid(uid) == 0);
+
+ ATF_REQUIRE(getuid() == uid);
+ ATF_REQUIRE(geteuid() == uid);
+}
+
+ATF_TC(setuid_root);
+ATF_TC_HEAD(setuid_root, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of setuid(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(setuid_root, tc)
+{
+ struct passwd *pw;
+ int rv, sta;
+ pid_t pid;
+ uid_t uid;
+
+ while ((pw = getpwent()) != NULL) {
+
+ pid = fork();
+ ATF_REQUIRE(pid >= 0);
+
+ if (pid == 0) {
+
+ rv = setuid(pw->pw_uid);
+
+ if (rv != 0)
+ _exit(EXIT_FAILURE);
+
+ uid = getuid();
+
+ if (uid != pw->pw_uid)
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ atf_tc_fail("failed to change UID to %u", pw->pw_uid);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, setuid_perm);
+ ATF_TP_ADD_TC(tp, setuid_real);
+ ATF_TP_ADD_TC(tp, setuid_root);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_sigaction.c b/contrib/netbsd-tests/lib/libc/sys/t_sigaction.c
new file mode 100644
index 0000000..8022353
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_sigaction.c
@@ -0,0 +1,154 @@
+/* $NetBSD: t_sigaction.c,v 1.2 2012/11/07 16:51:16 pgoyette Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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>
+__COPYRIGHT("@(#) Copyright (c) 2010\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_sigaction.c,v 1.2 2012/11/07 16:51:16 pgoyette Exp $");
+
+#include <sys/wait.h>
+
+#include <signal.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <atf-c.h>
+#include <atf-c/config.h>
+
+#include "../../../h_macros.h"
+
+static bool handler_called = false;
+
+static void
+handler(int signo)
+{
+ handler_called = true;
+}
+
+static void
+sa_resethand_child(const int flags)
+{
+ struct sigaction sa;
+
+ sa.sa_flags = flags;
+ sa.sa_handler = &handler;
+ sigemptyset(&sa.sa_mask);
+
+ sigaction(SIGUSR1, &sa, NULL);
+ kill(getpid(), SIGUSR1);
+ exit(handler_called ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static void
+wait_and_check_child(const pid_t pid, const char *fail_message)
+{
+ int status;
+
+ (void)waitpid(pid, &status, 0);
+
+ if (WIFEXITED(status))
+ ATF_CHECK_EQ(EXIT_SUCCESS, WEXITSTATUS(status));
+ else
+ atf_tc_fail("%s; raw exit status was %d", fail_message, status);
+}
+
+static void
+catch(int sig)
+{
+ return;
+}
+
+ATF_TC(sigaction_basic);
+ATF_TC_HEAD(sigaction_basic, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr", "Checks for correct I&D cache"
+ "synchronization after copying out the trampoline code.");
+}
+
+ATF_TC_BODY(sigaction_basic, tc)
+{
+ static struct sigaction sa;
+
+ sa.sa_handler = catch;
+
+ sigaction(SIGUSR1, &sa, 0);
+ kill(getpid(), SIGUSR1);
+ atf_tc_pass();
+}
+
+ATF_TC(sigaction_noflags);
+ATF_TC_HEAD(sigaction_noflags, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks programming a signal with "
+ "sigaction(2) but without any flags");
+}
+
+ATF_TC_BODY(sigaction_noflags, tc)
+{
+ const pid_t pid = fork();
+ if (pid == -1)
+ atf_tc_fail_errno("fork(2) failed");
+ else if (pid == 0)
+ sa_resethand_child(0);
+ else
+ wait_and_check_child(pid, "Child process did not exit cleanly;"
+ " it failed to process the signal");
+}
+
+ATF_TC(sigaction_resethand);
+ATF_TC_HEAD(sigaction_resethand, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that SA_RESETHAND works");
+}
+
+ATF_TC_BODY(sigaction_resethand, tc)
+{
+ const pid_t pid = fork();
+ if (pid == -1)
+ atf_tc_fail_errno("fork(2) failed");
+ else if (pid == 0)
+ sa_resethand_child(SA_RESETHAND);
+ else {
+ wait_and_check_child(pid, "Child process did not exit cleanly;"
+ " it either failed to process the signal or SA_RESETHAND"
+ " is broken");
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, sigaction_basic);
+ ATF_TP_ADD_TC(tp, sigaction_noflags);
+ ATF_TP_ADD_TC(tp, sigaction_resethand);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_sigqueue.c b/contrib/netbsd-tests/lib/libc/sys/t_sigqueue.c
new file mode 100644
index 0000000..f9e0c63
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_sigqueue.c
@@ -0,0 +1,103 @@
+/* $NetBSD: t_sigqueue.c,v 1.4 2011/07/07 16:31:11 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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: t_sigqueue.c,v 1.4 2011/07/07 16:31:11 jruoho Exp $");
+
+
+#include <atf-c.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <unistd.h>
+
+static void handler(int, siginfo_t *, void *);
+
+#define VALUE (int)0xc001dad1
+static int value;
+
+static void
+handler(int signo, siginfo_t *info, void *data)
+{
+ value = info->si_value.sival_int;
+ kill(0, SIGINFO);
+}
+
+ATF_TC(sigqueue_basic);
+ATF_TC_HEAD(sigqueue_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks sigqueue(3) sigval delivery");
+}
+
+ATF_TC_BODY(sigqueue_basic, tc)
+{
+ struct sigaction sa;
+ union sigval sv;
+
+ sa.sa_sigaction = handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+
+ if (sigaction(SIGUSR1, &sa, NULL) != 0)
+ atf_tc_fail("sigaction failed");
+
+ sv.sival_int = VALUE;
+
+ if (sigqueue(0, SIGUSR1, sv) != 0)
+ atf_tc_fail("sigqueue failed");
+
+ sched_yield();
+ ATF_REQUIRE_EQ(sv.sival_int, value);
+}
+
+ATF_TC(sigqueue_err);
+ATF_TC_HEAD(sigqueue_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from sigqueue(3)");
+}
+
+ATF_TC_BODY(sigqueue_err, tc)
+{
+ union sigval sv;
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, sigqueue(getpid(), -1, sv) == -1);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, sigqueue_basic);
+ ATF_TP_ADD_TC(tp, sigqueue_err);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_sigtimedwait.c b/contrib/netbsd-tests/lib/libc/sys/t_sigtimedwait.c
new file mode 100644
index 0000000..64b68d9
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_sigtimedwait.c
@@ -0,0 +1,126 @@
+/* $NetBSD: t_sigtimedwait.c,v 1.2 2013/03/08 23:18:00 martin Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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: t_sigtimedwait.c,v 1.2 2013/03/08 23:18:00 martin Exp $");
+
+#include <sys/time.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <atf-c.h>
+
+
+ATF_TC(sigtimedwait_all0timeout);
+
+ATF_TC_HEAD(sigtimedwait_all0timeout, tc)
+{
+ atf_tc_set_md_var(tc, "timeout", "10");
+ atf_tc_set_md_var(tc, "descr", "Test for PR kern/47625: sigtimedwait"
+ " with a timeout value of all zero should return imediately");
+}
+
+ATF_TC_BODY(sigtimedwait_all0timeout, tc)
+{
+ sigset_t block;
+ struct timespec ts, before, after, len;
+ siginfo_t info;
+ int r;
+
+ sigemptyset(&block);
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ clock_gettime(CLOCK_MONOTONIC, &before);
+ r = sigtimedwait(&block, &info, &ts);
+ clock_gettime(CLOCK_MONOTONIC, &after);
+ ATF_REQUIRE(r == -1);
+ ATF_REQUIRE_ERRNO(EAGAIN, errno);
+ timespecsub(&after, &before, &len);
+ ATF_REQUIRE(len.tv_sec < 1);
+}
+
+ATF_TC(sigtimedwait_NULL_timeout);
+
+ATF_TC_HEAD(sigtimedwait_NULL_timeout, tc)
+{
+ atf_tc_set_md_var(tc, "timeout", "10");
+ atf_tc_set_md_var(tc, "descr", "Test sigtimedwait() without timeout");
+}
+
+ATF_TC_BODY(sigtimedwait_NULL_timeout, tc)
+{
+ sigset_t sig;
+ siginfo_t info;
+ struct itimerval it;
+ int r;
+
+ /* arrange for a SIGALRM signal in a few seconds */
+ memset(&it, 0, sizeof it);
+ it.it_value.tv_sec = 5;
+ ATF_REQUIRE(setitimer(ITIMER_REAL, &it, NULL) == 0);
+
+ /* wait without timeout */
+ sigemptyset(&sig);
+ sigaddset(&sig, SIGALRM);
+ r = sigtimedwait(&sig, &info, NULL);
+ ATF_REQUIRE(r == SIGALRM);
+}
+
+ATF_TC(sigtimedwait_small_timeout);
+
+ATF_TC_HEAD(sigtimedwait_small_timeout, tc)
+{
+ atf_tc_set_md_var(tc, "timeout", "15");
+ atf_tc_set_md_var(tc, "descr", "Test sigtimedwait with a small "
+ "timeout");
+}
+
+ATF_TC_BODY(sigtimedwait_small_timeout, tc)
+{
+ sigset_t block;
+ struct timespec ts;
+ siginfo_t info;
+ int r;
+
+ sigemptyset(&block);
+ ts.tv_sec = 5;
+ ts.tv_nsec = 0;
+ r = sigtimedwait(&block, &info, &ts);
+ ATF_REQUIRE(r == -1);
+ ATF_REQUIRE_ERRNO(EAGAIN, errno);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, sigtimedwait_all0timeout);
+ ATF_TP_ADD_TC(tp, sigtimedwait_NULL_timeout);
+ ATF_TP_ADD_TC(tp, sigtimedwait_small_timeout);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_socketpair.c b/contrib/netbsd-tests/lib/libc/sys/t_socketpair.c
new file mode 100644
index 0000000..532629c3
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_socketpair.c
@@ -0,0 +1,137 @@
+/* $NetBSD: t_socketpair.c,v 1.1 2011/11/05 18:19:02 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 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: t_socketpair.c,v 1.1 2011/11/05 18:19:02 jruoho Exp $");
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+
+static void
+connected(int fd)
+{
+ struct sockaddr_un addr;
+ socklen_t len = (socklen_t)sizeof(addr);
+ ATF_REQUIRE(getpeername(fd, (struct sockaddr*)(void *)&addr,
+ &len) == 0);
+}
+
+static void
+run(int flags)
+{
+ int fd[2], i;
+
+ while ((i = open("/", O_RDONLY)) < 3)
+ ATF_REQUIRE(i != -1);
+
+ ATF_REQUIRE(fcntl(3, F_CLOSEM) != -1);
+
+ ATF_REQUIRE(socketpair(AF_UNIX, SOCK_DGRAM | flags, 0, fd) == 0);
+
+ ATF_REQUIRE(fd[0] == 3);
+ ATF_REQUIRE(fd[1] == 4);
+
+ connected(fd[0]);
+ connected(fd[1]);
+
+ if (flags & SOCK_CLOEXEC) {
+ ATF_REQUIRE((fcntl(fd[0], F_GETFD) & FD_CLOEXEC) != 0);
+ ATF_REQUIRE((fcntl(fd[1], F_GETFD) & FD_CLOEXEC) != 0);
+ } else {
+ ATF_REQUIRE((fcntl(fd[0], F_GETFD) & FD_CLOEXEC) == 0);
+ ATF_REQUIRE((fcntl(fd[1], F_GETFD) & FD_CLOEXEC) == 0);
+ }
+
+ if (flags & SOCK_NONBLOCK) {
+ ATF_REQUIRE((fcntl(fd[0], F_GETFL) & O_NONBLOCK) != 0);
+ ATF_REQUIRE((fcntl(fd[1], F_GETFL) & O_NONBLOCK) != 0);
+ } else {
+ ATF_REQUIRE((fcntl(fd[0], F_GETFL) & O_NONBLOCK) == 0);
+ ATF_REQUIRE((fcntl(fd[1], F_GETFL) & O_NONBLOCK) == 0);
+ }
+
+ ATF_REQUIRE(close(fd[0]) != -1);
+ ATF_REQUIRE(close(fd[1]) != -1);
+}
+
+ATF_TC(socketpair_basic);
+ATF_TC_HEAD(socketpair_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of socketpair(2)");
+}
+
+ATF_TC_BODY(socketpair_basic, tc)
+{
+ run(0);
+}
+
+ATF_TC(socketpair_nonblock);
+ATF_TC_HEAD(socketpair_nonblock, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A non-blocking test of socketpair(2)");
+}
+
+ATF_TC_BODY(socketpair_nonblock, tc)
+{
+ run(SOCK_NONBLOCK);
+}
+
+ATF_TC(socketpair_cloexec);
+ATF_TC_HEAD(socketpair_cloexec, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A close-on-exec of socketpair(2)");
+}
+
+ATF_TC_BODY(socketpair_cloexec, tc)
+{
+ run(SOCK_CLOEXEC);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, socketpair_basic);
+ ATF_TP_ADD_TC(tp, socketpair_nonblock);
+ ATF_TP_ADD_TC(tp, socketpair_cloexec);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_stat.c b/contrib/netbsd-tests/lib/libc/sys/t_stat.c
new file mode 100644
index 0000000..0312e2f
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_stat.c
@@ -0,0 +1,417 @@
+/* $NetBSD: t_stat.c,v 1.4 2012/03/17 08:37:08 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_stat.c,v 1.4 2012/03/17 08:37:08 jruoho Exp $");
+
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <arpa/inet.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <stdio.h>
+
+static const char *path = "stat";
+
+ATF_TC_WITH_CLEANUP(stat_chflags);
+ATF_TC_HEAD(stat_chflags, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test chflags(2) with stat(2)");
+}
+
+ATF_TC_BODY(stat_chflags, tc)
+{
+ struct stat sa, sb;
+ int fd;
+
+ (void)memset(&sa, 0, sizeof(struct stat));
+ (void)memset(&sb, 0, sizeof(struct stat));
+
+ fd = open(path, O_RDONLY | O_CREAT);
+
+ ATF_REQUIRE(fd != -1);
+ ATF_REQUIRE(stat(path, &sa) == 0);
+ ATF_REQUIRE(chflags(path, UF_NODUMP) == 0);
+ ATF_REQUIRE(stat(path, &sb) == 0);
+
+ if (sa.st_flags == sb.st_flags)
+ atf_tc_fail("stat(2) did not detect chflags(2)");
+
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(unlink(path) == 0);
+}
+
+ATF_TC_CLEANUP(stat_chflags, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(stat_dir);
+ATF_TC_HEAD(stat_dir, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test stat(2) with directories");
+}
+
+ATF_TC_BODY(stat_dir, tc)
+{
+ const short depth = 2;
+ struct stat sa, sb;
+ char *argv[2];
+ FTSENT *ftse;
+ FTS *fts;
+ int ops;
+
+ argv[1] = NULL;
+ argv[0] = __UNCONST("/");
+
+ ops = FTS_NOCHDIR;
+ ops |= FTS_PHYSICAL;
+
+ fts = fts_open(argv, ops, NULL);
+ ATF_REQUIRE(fts != NULL);
+
+ while ((ftse = fts_read(fts)) != NULL) {
+
+ if (ftse->fts_level < 1)
+ continue;
+
+ if (ftse->fts_level > depth) {
+ (void)fts_set(fts, ftse, FTS_SKIP);
+ continue;
+ }
+
+ switch(ftse->fts_info) {
+
+ case FTS_DP:
+
+ (void)memset(&sa, 0, sizeof(struct stat));
+ (void)memset(&sb, 0, sizeof(struct stat));
+
+ ATF_REQUIRE(stat(ftse->fts_parent->fts_path,&sa) == 0);
+ ATF_REQUIRE(chdir(ftse->fts_path) == 0);
+ ATF_REQUIRE(stat(".", &sb) == 0);
+
+ /*
+ * The previous two stat(2) calls
+ * should be for the same directory.
+ */
+ if (sa.st_dev != sb.st_dev || sa.st_ino != sb.st_ino)
+ atf_tc_fail("inconsistent stat(2)");
+
+ /*
+ * Check that fts(3)'s stat(2)
+ * call equals the manual one.
+ */
+ if (sb.st_ino != ftse->fts_statp->st_ino)
+ atf_tc_fail("stat(2) and fts(3) differ");
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ (void)fts_close(fts);
+}
+
+ATF_TC(stat_err);
+ATF_TC_HEAD(stat_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from the stat(2) family");
+}
+
+ATF_TC_BODY(stat_err, tc)
+{
+ char buf[NAME_MAX + 1];
+ struct stat st;
+
+ (void)memset(buf, 'x', sizeof(buf));
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, fstat(-1, &st) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENAMETOOLONG, stat(buf, &st) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENAMETOOLONG, lstat(buf, &st) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, stat((void *)-1, &st) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, lstat((void *)-1, &st) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, stat("/etc/passwd", (void *)-1) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, lstat("/etc/passwd", (void *)-1) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, stat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, lstat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1);
+}
+
+ATF_TC_WITH_CLEANUP(stat_mtime);
+ATF_TC_HEAD(stat_mtime, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test modification times with stat(2)");
+}
+
+ATF_TC_BODY(stat_mtime, tc)
+{
+ struct stat sa, sb;
+ int fd[3];
+ size_t i;
+
+ for (i = 0; i < __arraycount(fd); i++) {
+
+ (void)memset(&sa, 0, sizeof(struct stat));
+ (void)memset(&sb, 0, sizeof(struct stat));
+
+ fd[i] = open(path, O_WRONLY | O_CREAT);
+
+ ATF_REQUIRE(fd[i] != -1);
+ ATF_REQUIRE(write(fd[i], "X", 1) == 1);
+ ATF_REQUIRE(stat(path, &sa) == 0);
+
+ (void)sleep(1);
+
+ ATF_REQUIRE(write(fd[i], "X", 1) == 1);
+ ATF_REQUIRE(stat(path, &sb) == 0);
+
+ ATF_REQUIRE(close(fd[i]) == 0);
+ ATF_REQUIRE(unlink(path) == 0);
+
+ if (sa.st_mtime == sb.st_mtime)
+ atf_tc_fail("mtimes did not change");
+ }
+}
+
+ATF_TC_CLEANUP(stat_mtime, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(stat_perm);
+ATF_TC_HEAD(stat_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test permissions with stat(2)");
+ atf_tc_set_md_var(tc, "require.user", "root");
+}
+
+ATF_TC_BODY(stat_perm, tc)
+{
+ struct stat sa, sb;
+ gid_t gid;
+ uid_t uid;
+ int fd;
+
+ (void)memset(&sa, 0, sizeof(struct stat));
+ (void)memset(&sb, 0, sizeof(struct stat));
+
+ uid = getuid();
+ gid = getgid();
+
+ fd = open(path, O_RDONLY | O_CREAT);
+
+ ATF_REQUIRE(fd != -1);
+ ATF_REQUIRE(fstat(fd, &sa) == 0);
+ ATF_REQUIRE(stat(path, &sb) == 0);
+
+ if (gid != sa.st_gid || sa.st_gid != sb.st_gid)
+ atf_tc_fail("invalid GID");
+
+ if (uid != sa.st_uid || sa.st_uid != sb.st_uid)
+ atf_tc_fail("invalid UID");
+
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(unlink(path) == 0);
+}
+
+ATF_TC_CLEANUP(stat_perm, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(stat_size);
+ATF_TC_HEAD(stat_size, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test file sizes with stat(2)");
+}
+
+ATF_TC_BODY(stat_size, tc)
+{
+ struct stat sa, sb, sc;
+ const size_t n = 10;
+ size_t i;
+ int fd;
+
+ fd = open(path, O_WRONLY | O_CREAT);
+ ATF_REQUIRE(fd >= 0);
+
+ for (i = 0; i < n; i++) {
+
+ (void)memset(&sa, 0, sizeof(struct stat));
+ (void)memset(&sb, 0, sizeof(struct stat));
+ (void)memset(&sc, 0, sizeof(struct stat));
+
+ ATF_REQUIRE(fstat(fd, &sa) == 0);
+ ATF_REQUIRE(write(fd, "X", 1) == 1);
+ ATF_REQUIRE(fstat(fd, &sb) == 0);
+ ATF_REQUIRE(stat(path, &sc) == 0);
+
+ if (sa.st_size + 1 != sb.st_size)
+ atf_tc_fail("invalid file size");
+
+ if (sb.st_size != sc.st_size)
+ atf_tc_fail("stat(2) and fstat(2) mismatch");
+ }
+
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(unlink(path) == 0);
+}
+
+ATF_TC_CLEANUP(stat_size, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(stat_socket);
+ATF_TC_HEAD(stat_socket, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test fstat(2) with "
+ "a socket (PR kern/46077)");
+}
+
+ATF_TC_BODY(stat_socket, tc)
+{
+ struct sockaddr_in addr;
+ struct stat st;
+ uint32_t iaddr;
+ int fd, flags;
+
+ (void)memset(&st, 0, sizeof(struct stat));
+ (void)memset(&addr, 0, sizeof(struct sockaddr_in));
+
+ fd = socket(AF_INET, SOCK_STREAM, 0);
+ ATF_REQUIRE(fd >= 0);
+
+ flags = fcntl(fd, F_GETFL);
+
+ ATF_REQUIRE(flags != -1);
+ ATF_REQUIRE(fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1);
+ ATF_REQUIRE(inet_pton(AF_INET, "127.0.0.1", &iaddr) == 1);
+
+ addr.sin_port = htons(42);
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = iaddr;
+
+ errno = 0;
+
+ ATF_REQUIRE_ERRNO(EINPROGRESS,
+ connect(fd, (struct sockaddr *)&addr,
+ sizeof(struct sockaddr_in)) == -1);
+
+ errno = 0;
+
+ if (fstat(fd, &st) != 0 || errno != 0)
+ atf_tc_fail("fstat(2) failed for a EINPROGRESS socket");
+
+ (void)close(fd);
+}
+
+ATF_TC_WITH_CLEANUP(stat_symlink);
+ATF_TC_HEAD(stat_symlink, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test symbolic links with stat(2)");
+}
+
+ATF_TC_BODY(stat_symlink, tc)
+{
+ const char *pathlink = "pathlink";
+ struct stat sa, sb;
+ int fd;
+
+ (void)memset(&sa, 0, sizeof(struct stat));
+ (void)memset(&sb, 0, sizeof(struct stat));
+
+ fd = open(path, O_WRONLY | O_CREAT);
+
+ ATF_REQUIRE(fd >= 0);
+ ATF_REQUIRE(symlink(path, pathlink) == 0);
+ ATF_REQUIRE(stat(pathlink, &sa) == 0);
+ ATF_REQUIRE(lstat(pathlink, &sb) == 0);
+
+ if (S_ISLNK(sa.st_mode) != 0)
+ atf_tc_fail("stat(2) detected symbolic link");
+
+ if (S_ISLNK(sb.st_mode) == 0)
+ atf_tc_fail("lstat(2) did not detect symbolic link");
+
+ if (sa.st_mode == sb.st_mode)
+ atf_tc_fail("inconsistencies between stat(2) and lstat(2)");
+
+ ATF_REQUIRE(unlink(path) == 0);
+ ATF_REQUIRE(unlink(pathlink) == 0);
+}
+
+ATF_TC_CLEANUP(stat_symlink, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, stat_chflags);
+ ATF_TP_ADD_TC(tp, stat_dir);
+ ATF_TP_ADD_TC(tp, stat_err);
+ ATF_TP_ADD_TC(tp, stat_mtime);
+ ATF_TP_ADD_TC(tp, stat_perm);
+ ATF_TP_ADD_TC(tp, stat_size);
+ ATF_TP_ADD_TC(tp, stat_socket);
+ ATF_TP_ADD_TC(tp, stat_symlink);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_swapcontext.c b/contrib/netbsd-tests/lib/libc/sys/t_swapcontext.c
new file mode 100644
index 0000000..de36c88
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_swapcontext.c
@@ -0,0 +1,133 @@
+/* $NetBSD: t_swapcontext.c,v 1.3 2013/05/05 10:28:11 skrll Exp $ */
+
+/*
+ * Copyright (c) 2012 Emmanuel Dreyfus. All rights reserved.
+ *
+ * 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");
+
+#include <ucontext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <lwp.h>
+
+#include <atf-c.h>
+
+#define STACKSIZE 65536
+
+char stack[STACKSIZE];
+ucontext_t nctx;
+ucontext_t octx;
+void *otls;
+void *ntls;
+int val1, val2;
+int alter_tlsbase;
+
+/* ARGSUSED0 */
+static void
+swapfunc(void *arg)
+{
+ ntls = _lwp_getprivate();
+ printf("after swapcontext TLS pointer = %p\n", ntls);
+
+ if (alter_tlsbase) {
+ ATF_REQUIRE_EQ(ntls, &val1);
+ printf("TLS pointer modified by swapcontext()\n");
+ } else {
+ ATF_REQUIRE_EQ(ntls, &val2);
+ printf("TLS pointer left untouched by swapcontext()\n");
+ }
+
+ /* Go back in main */
+ ATF_REQUIRE(swapcontext(&nctx, &octx));
+
+ /* NOTREACHED */
+ return;
+}
+
+static void
+mainfunc(void)
+{
+ printf("Testing if swapcontext() alters TLS pointer if _UC_TLSBASE "
+ "is %s\n", (alter_tlsbase) ? "left set" : "cleared");
+
+ _lwp_setprivate(&val1);
+ printf("before swapcontext TLS pointer = %p\n", &val1);
+
+ ATF_REQUIRE(getcontext(&nctx) == 0);
+
+ nctx.uc_stack.ss_sp = stack;
+ nctx.uc_stack.ss_size = sizeof(stack);
+
+#ifndef _UC_TLSBASE
+ ATF_REQUIRE_MSG(0, "_UC_TLSBASE is not defined");
+#else /* _UC_TLSBASE */
+ ATF_REQUIRE(nctx.uc_flags & _UC_TLSBASE);
+ if (!alter_tlsbase)
+ nctx.uc_flags &= ~_UC_TLSBASE;
+#endif /* _UC_TLSBASE */
+
+ makecontext(&nctx, swapfunc, 0);
+
+ _lwp_setprivate(&val2);
+ otls = _lwp_getprivate();
+ printf("before swapcontext TLS pointer = %p\n", otls);
+ ATF_REQUIRE(swapcontext(&octx, &nctx) == 0);
+
+ printf("Test completed\n");
+}
+
+
+ATF_TC(swapcontext1);
+ATF_TC_HEAD(swapcontext1, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Testing if swapcontext() can let "
+ "TLS pointer untouched");
+}
+ATF_TC_BODY(swapcontext1, tc)
+{
+ alter_tlsbase = 0;
+ mainfunc();
+}
+
+ATF_TC(swapcontext2);
+ATF_TC_HEAD(swapcontext2, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Testing if swapcontext() can "
+ "modify TLS pointer");
+}
+ATF_TC_BODY(swapcontext2, tc)
+{
+ alter_tlsbase = 1;
+ mainfunc();
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, swapcontext1);
+ ATF_TP_ADD_TC(tp, swapcontext2);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_timer_create.c b/contrib/netbsd-tests/lib/libc/sys/t_timer_create.c
new file mode 100644
index 0000000..ce1fb99
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_timer_create.c
@@ -0,0 +1,207 @@
+/* $NetBSD: t_timer_create.c,v 1.4 2012/03/18 07:00:52 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 <atf-c.h>
+#include <errno.h>
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+static timer_t t;
+static bool fail = true;
+
+static void
+timer_signal_handler(int signo, siginfo_t *si, void *osi)
+{
+ timer_t *tp;
+
+ tp = si->si_value.sival_ptr;
+
+ if (*tp == t && signo == SIGALRM)
+ fail = false;
+
+ (void)fprintf(stderr, "%s: %s\n", __func__, strsignal(signo));
+}
+
+static void
+timer_signal_create(clockid_t cid, bool expire)
+{
+ struct itimerspec tim;
+ struct sigaction act;
+ struct sigevent evt;
+ sigset_t set;
+
+ t = 0;
+ fail = true;
+
+ (void)memset(&evt, 0, sizeof(struct sigevent));
+ (void)memset(&act, 0, sizeof(struct sigaction));
+ (void)memset(&tim, 0, sizeof(struct itimerspec));
+
+ /*
+ * Set handler.
+ */
+ act.sa_flags = SA_SIGINFO;
+ act.sa_sigaction = timer_signal_handler;
+
+ ATF_REQUIRE(sigemptyset(&set) == 0);
+ ATF_REQUIRE(sigemptyset(&act.sa_mask) == 0);
+
+ /*
+ * Block SIGALRM while configuring the timer.
+ */
+ ATF_REQUIRE(sigaction(SIGALRM, &act, NULL) == 0);
+ ATF_REQUIRE(sigaddset(&set, SIGALRM) == 0);
+ ATF_REQUIRE(sigprocmask(SIG_SETMASK, &set, NULL) == 0);
+
+ /*
+ * Create the timer (SIGEV_SIGNAL).
+ */
+ evt.sigev_signo = SIGALRM;
+ evt.sigev_value.sival_ptr = &t;
+ evt.sigev_notify = SIGEV_SIGNAL;
+
+ ATF_REQUIRE(timer_create(cid, &evt, &t) == 0);
+
+ /*
+ * Start the timer. After this, unblock the signal.
+ */
+ tim.it_value.tv_sec = expire ? 5 : 1;
+ tim.it_value.tv_nsec = 0;
+
+ ATF_REQUIRE(timer_settime(t, 0, &tim, NULL) == 0);
+
+ (void)sigprocmask(SIG_UNBLOCK, &set, NULL);
+ (void)sleep(2);
+
+ if (expire) {
+ if (!fail)
+ atf_tc_fail("timer fired too soon");
+ } else {
+ if (fail)
+ atf_tc_fail("timer failed to fire");
+ }
+
+ ATF_REQUIRE(timer_delete(t) == 0);
+}
+
+ATF_TC(timer_create_err);
+ATF_TC_HEAD(timer_create_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Check errors from timer_create(2) (PR lib/42434");
+}
+
+ATF_TC_BODY(timer_create_err, tc)
+{
+ struct sigevent ev;
+
+ (void)memset(&ev, 0, sizeof(struct sigevent));
+
+ errno = 0;
+ ev.sigev_signo = -1;
+ ev.sigev_notify = SIGEV_SIGNAL;
+
+ ATF_REQUIRE_ERRNO(EINVAL, timer_create(CLOCK_REALTIME, &ev, &t) == -1);
+
+ errno = 0;
+ ev.sigev_signo = SIGUSR1;
+ ev.sigev_notify = SIGEV_THREAD + 100;
+
+ ATF_REQUIRE_ERRNO(EINVAL, timer_create(CLOCK_REALTIME, &ev, &t) == -1);
+}
+
+ATF_TC(timer_create_real);
+ATF_TC_HEAD(timer_create_real, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr",
+ "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), "
+ "SIGEV_SIGNAL");
+}
+
+ATF_TC_BODY(timer_create_real, tc)
+{
+ timer_signal_create(CLOCK_REALTIME, false);
+}
+
+ATF_TC(timer_create_mono);
+ATF_TC_HEAD(timer_create_mono, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr",
+ "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), "
+ "SIGEV_SIGNAL");
+}
+
+ATF_TC_BODY(timer_create_mono, tc)
+{
+ timer_signal_create(CLOCK_MONOTONIC, false);
+}
+
+ATF_TC(timer_create_real_expire);
+ATF_TC_HEAD(timer_create_real_expire, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr",
+ "Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), "
+ "SIGEV_SIGNAL, with expiration");
+}
+
+ATF_TC_BODY(timer_create_real_expire, tc)
+{
+ timer_signal_create(CLOCK_REALTIME, true);
+}
+
+ATF_TC(timer_create_mono_expire);
+ATF_TC_HEAD(timer_create_mono_expire, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr",
+ "Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), "
+ "SIGEV_SIGNAL, with expiration");
+}
+
+ATF_TC_BODY(timer_create_mono_expire, tc)
+{
+ timer_signal_create(CLOCK_MONOTONIC, true);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, timer_create_err);
+ ATF_TP_ADD_TC(tp, timer_create_real);
+ ATF_TP_ADD_TC(tp, timer_create_mono);
+ ATF_TP_ADD_TC(tp, timer_create_real_expire);
+ ATF_TP_ADD_TC(tp, timer_create_mono_expire);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_truncate.c b/contrib/netbsd-tests/lib/libc/sys/t_truncate.c
new file mode 100644
index 0000000..50a9cba
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_truncate.c
@@ -0,0 +1,175 @@
+/* $NetBSD: t_truncate.c,v 1.2 2011/08/18 19:48:03 dholland Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_truncate.c,v 1.2 2011/08/18 19:48:03 dholland Exp $");
+
+#include <sys/stat.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+static const char path[] = "truncate";
+static const size_t sizes[] = { 8, 16, 512, 1024, 2048, 4094, 3000, 30 };
+
+ATF_TC_WITH_CLEANUP(ftruncate_basic);
+ATF_TC_HEAD(ftruncate_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of ftruncate(2)");
+}
+
+ATF_TC_BODY(ftruncate_basic, tc)
+{
+ struct stat st;
+ size_t i;
+ int fd;
+
+ fd = open(path, O_RDWR | O_CREAT, 0600);
+ ATF_REQUIRE(fd >= 0);
+
+ for (i = 0; i < __arraycount(sizes); i++) {
+
+ (void)memset(&st, 0, sizeof(struct stat));
+
+ ATF_REQUIRE(ftruncate(fd, sizes[i]) == 0);
+ ATF_REQUIRE(fstat(fd, &st) == 0);
+
+ (void)fprintf(stderr, "truncating to %zu bytes\n", sizes[i]);
+
+ if (sizes[i] != (size_t)st.st_size)
+ atf_tc_fail("ftruncate(2) did not truncate");
+ }
+
+ (void)close(fd);
+ (void)unlink(path);
+}
+
+ATF_TC_CLEANUP(ftruncate_basic, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(ftruncate_err);
+ATF_TC_HEAD(ftruncate_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from ftruncate(2)");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(ftruncate_err, tc)
+{
+ int fd;
+
+ fd = open("/etc/passwd", O_RDONLY, 0400);
+ ATF_REQUIRE(fd >= 0);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, ftruncate(-1, 999) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, ftruncate(fd, 999) == -1);
+
+ (void)close(fd);
+}
+
+ATF_TC_WITH_CLEANUP(truncate_basic);
+ATF_TC_HEAD(truncate_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of truncate(2)");
+}
+
+ATF_TC_BODY(truncate_basic, tc)
+{
+ struct stat st;
+ size_t i;
+ int fd;
+
+ fd = open(path, O_RDWR | O_CREAT, 0600);
+ ATF_REQUIRE(fd >= 0);
+
+ for (i = 0; i < __arraycount(sizes); i++) {
+
+ (void)memset(&st, 0, sizeof(struct stat));
+
+ ATF_REQUIRE(truncate(path, sizes[i]) == 0);
+ ATF_REQUIRE(fstat(fd, &st) == 0);
+
+ (void)fprintf(stderr, "truncating to %zu bytes\n", sizes[i]);
+
+ if (sizes[i] != (size_t)st.st_size)
+ atf_tc_fail("truncate(2) did not truncate");
+ }
+
+ (void)close(fd);
+ (void)unlink(path);
+}
+
+ATF_TC_CLEANUP(truncate_basic, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(truncate_err);
+ATF_TC_HEAD(truncate_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test errors from truncate(2)");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(truncate_err, tc)
+{
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, truncate((void *)-1, 999) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EISDIR, truncate("/etc", 999) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, truncate("/a/b/c/d/e/f/g", 999) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EACCES, truncate("/usr/bin/fpr", 999) == -1);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, ftruncate_basic);
+ ATF_TP_ADD_TC(tp, ftruncate_err);
+ ATF_TP_ADD_TC(tp, truncate_basic);
+ ATF_TP_ADD_TC(tp, truncate_err);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_ucontext.c b/contrib/netbsd-tests/lib/libc/sys/t_ucontext.c
new file mode 100644
index 0000000..27d6740
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_ucontext.c
@@ -0,0 +1,76 @@
+/* $NetBSD: t_ucontext.c,v 1.1 2011/10/15 06:54:52 jruoho Exp $ */
+
+/*
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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>
+__COPYRIGHT("@(#) Copyright (c) 2008\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_ucontext.c,v 1.1 2011/10/15 06:54:52 jruoho Exp $");
+
+#include <atf-c.h>
+#include <stdio.h>
+#include <ucontext.h>
+
+ATF_TC(ucontext_basic);
+ATF_TC_HEAD(ucontext_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks {get,set}context(2)");
+}
+
+ATF_TC_BODY(ucontext_basic, tc)
+{
+ ucontext_t u, v, w;
+ volatile int x, y;
+
+ x = 0;
+ y = 0;
+
+ printf("Start\n");
+
+ getcontext(&u);
+ y++;
+
+ printf("x == %d\n", x);
+
+ getcontext(&v);
+
+ if ( x < 20 ) {
+ x++;
+ getcontext(&w);
+ setcontext(&u);
+ }
+
+ printf("End, y = %d\n", y);
+ ATF_REQUIRE_EQ(y, 21);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, ucontext_basic);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_umask.c b/contrib/netbsd-tests/lib/libc/sys/t_umask.c
new file mode 100644
index 0000000..748cbdc
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_umask.c
@@ -0,0 +1,205 @@
+/* $NetBSD: t_umask.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_umask.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
+
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <atf-c.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static const char path[] = "umask";
+static const mode_t mask[] = {
+ S_IRWXU,
+ S_IRUSR,
+ S_IWUSR,
+ S_IXUSR,
+ S_IRWXG,
+ S_IRGRP,
+ S_IWGRP,
+ S_IXGRP,
+ S_IRWXO,
+ S_IROTH,
+ S_IWOTH,
+ S_IXOTH
+};
+
+ATF_TC_WITH_CLEANUP(umask_fork);
+ATF_TC_HEAD(umask_fork, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Check that umask(2) is inherited");
+}
+
+ATF_TC_BODY(umask_fork, tc)
+{
+ mode_t mode;
+ pid_t pid;
+ size_t i;
+ int sta;
+
+ for (i = 0; i < __arraycount(mask) - 1; i++) {
+
+ (void)umask(mask[i] | mask[i + 1]);
+
+ pid = fork();
+
+ if (pid < 0)
+ continue;
+
+ if (pid == 0) {
+
+ mode = umask(mask[i]);
+
+ if (mode != (mask[i] | mask[i + 1]))
+ _exit(EXIT_FAILURE);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ (void)wait(&sta);
+
+ if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
+ goto fail;
+ }
+
+ return;
+
+fail:
+ (void)umask(S_IWGRP | S_IWOTH);
+
+ atf_tc_fail("umask(2) was not inherited");
+}
+
+ATF_TC_CLEANUP(umask_fork, tc)
+{
+ (void)umask(S_IWGRP | S_IWOTH);
+}
+
+ATF_TC_WITH_CLEANUP(umask_open);
+ATF_TC_HEAD(umask_open, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of open(2) and umask(2)");
+}
+
+ATF_TC_BODY(umask_open, tc)
+{
+ const char *str = NULL;
+ struct stat st;
+ size_t i;
+ int fd;
+
+ for (i = 0; i < __arraycount(mask); i++) {
+
+ (void)umask(mask[i]);
+
+ fd = open(path, O_RDWR | O_CREAT, 0777);
+
+ if (fd < 0)
+ continue;
+
+ (void)memset(&st, 0, sizeof(struct stat));
+
+ if (stat(path, &st) != 0) {
+ str = "failed to stat(2)";
+ goto out;
+ }
+
+ if ((st.st_mode & mask[i]) != 0) {
+ str = "invalid umask(2)";
+ goto out;
+ }
+
+ if (unlink(path) != 0) {
+ str = "failed to unlink(2)";
+ goto out;
+ }
+
+ }
+
+out:
+ (void)umask(S_IWGRP | S_IWOTH);
+
+ if (str != NULL)
+ atf_tc_fail("%s", str);
+}
+
+ATF_TC_CLEANUP(umask_open, tc)
+{
+ (void)umask(S_IWGRP | S_IWOTH);
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(umask_previous);
+ATF_TC_HEAD(umask_previous, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test the return value from umask(2)");
+}
+
+ATF_TC_BODY(umask_previous, tc)
+{
+ mode_t mode;
+ size_t i;
+
+ for (i = 0; i < __arraycount(mask); i++) {
+
+ mode = umask(mask[i]);
+ mode = umask(mask[i]);
+
+ if (mode != mask[i])
+ goto fail;
+ }
+
+ return;
+
+fail:
+ (void)umask(S_IWGRP | S_IWOTH);
+
+ atf_tc_fail("umask(2) did not return the previous mask");
+}
+
+ATF_TC_CLEANUP(umask_previous, tc)
+{
+ (void)umask(S_IWGRP | S_IWOTH);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, umask_fork);
+ ATF_TP_ADD_TC(tp, umask_open);
+ ATF_TP_ADD_TC(tp, umask_previous);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_unlink.c b/contrib/netbsd-tests/lib/libc/sys/t_unlink.c
new file mode 100644
index 0000000..38bff4c
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_unlink.c
@@ -0,0 +1,158 @@
+/* $NetBSD: t_unlink.c,v 1.2 2014/04/21 18:05:17 martin Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jukka Ruohonen.
+ *
+ * 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: t_unlink.c,v 1.2 2014/04/21 18:05:17 martin Exp $");
+
+#include <sys/stat.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+
+static char path[] = "unlink";
+
+ATF_TC_WITH_CLEANUP(unlink_basic);
+ATF_TC_HEAD(unlink_basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "A basic test of unlink(2)");
+}
+
+ATF_TC_BODY(unlink_basic, tc)
+{
+ const size_t n = 512;
+ size_t i;
+ int fd;
+
+ for (i = 0; i < n; i++) {
+
+ fd = open(path, O_RDWR | O_CREAT, 0666);
+
+ ATF_REQUIRE(fd != -1);
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(unlink(path) == 0);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, open(path, O_RDONLY) == -1);
+ }
+}
+
+ATF_TC_CLEANUP(unlink_basic, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(unlink_err);
+ATF_TC_HEAD(unlink_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test error conditions of unlink(2)");
+}
+
+ATF_TC_BODY(unlink_err, tc)
+{
+ char buf[PATH_MAX + 1];
+
+ (void)memset(buf, 'x', sizeof(buf));
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBUSY, unlink("/") == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENAMETOOLONG, unlink(buf) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, unlink("/a/b/c/d/e/f/g/h/i/j/k/l/m") == -1);
+}
+
+ATF_TC_CLEANUP(unlink_err, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(unlink_fifo);
+ATF_TC_HEAD(unlink_fifo, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test unlink(2) for a FIFO");
+}
+
+ATF_TC_BODY(unlink_fifo, tc)
+{
+
+ ATF_REQUIRE(mkfifo(path, 0666) == 0);
+ ATF_REQUIRE(unlink(path) == 0);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(ENOENT, open(path, O_RDONLY) == -1);
+}
+
+ATF_TC_CLEANUP(unlink_fifo, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(unlink_perm);
+ATF_TC_HEAD(unlink_perm, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Test permissions with unlink(2)");
+ atf_tc_set_md_var(tc, "require.user", "unprivileged");
+}
+
+ATF_TC_BODY(unlink_perm, tc)
+{
+ int rv;
+
+ errno = 0;
+ rv = unlink("/etc");
+ ATF_REQUIRE_MSG(rv == -1 && (errno == EACCES || errno == EPERM),
+ "unlinking a directory did not fail with EPERM or EACCESS; "
+ "unlink() returned %d, errno %d", rv, errno);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EACCES, unlink("/root/.profile") == -1);
+}
+
+ATF_TC_CLEANUP(unlink_perm, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, unlink_basic);
+ ATF_TP_ADD_TC(tp, unlink_err);
+ ATF_TP_ADD_TC(tp, unlink_fifo);
+ ATF_TP_ADD_TC(tp, unlink_perm);
+
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/sys/t_write.c b/contrib/netbsd-tests/lib/libc/sys/t_write.c
new file mode 100644
index 0000000..2b1324a
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/sys/t_write.c
@@ -0,0 +1,226 @@
+/* $NetBSD: t_write.c,v 1.2 2011/10/19 16:19:30 jruoho Exp $ */
+
+/*-
+ * Copyright (c) 2001, 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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>
+__COPYRIGHT("@(#) Copyright (c) 2008\
+ The NetBSD Foundation, inc. All rights reserved.");
+__RCSID("$NetBSD: t_write.c,v 1.2 2011/10/19 16:19:30 jruoho Exp $");
+
+#include <sys/uio.h>
+#include <sys/syslimits.h>
+
+#include <atf-c.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+static void sighandler(int);
+
+static bool fail = false;
+static const char *path = "write";
+
+static void
+sighandler(int signo)
+{
+ fail = false;
+}
+
+ATF_TC_WITH_CLEANUP(write_err);
+ATF_TC_HEAD(write_err, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks errors from write(2)");
+}
+
+ATF_TC_BODY(write_err, tc)
+{
+ char rbuf[3] = { 'a', 'b', 'c' };
+ char wbuf[3] = { 'x', 'y', 'z' };
+ int fd;
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EBADF, write(-1, wbuf, sizeof(wbuf)) == -1);
+
+ fd = open(path, O_RDWR | O_CREAT);
+
+ if (fd >= 0) {
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(0, write(fd, wbuf, 3) == 3);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EINVAL, write(fd, wbuf, SIZE_MAX) == -1);
+
+ errno = 0;
+ ATF_REQUIRE_ERRNO(EFAULT, write(fd, (void *)-1, 1) == -1);
+
+ /*
+ * Check that the above bogus write(2)
+ * calls did not corrupt the file.
+ */
+ ATF_REQUIRE(lseek(fd, 0, SEEK_SET) == 0);
+ ATF_REQUIRE(read(fd, rbuf, 3) == 3);
+ ATF_REQUIRE(memcmp(rbuf, wbuf, 3) == 0);
+
+ (void)close(fd);
+ (void)unlink(path);
+ }
+}
+
+ATF_TC_CLEANUP(write_err, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(write_pipe);
+ATF_TC_HEAD(write_pipe, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks for EPIPE from write(2)");
+}
+
+ATF_TC_BODY(write_pipe, tc)
+{
+ int fds[2];
+
+ ATF_REQUIRE(pipe(fds) == 0);
+ ATF_REQUIRE(signal(SIGPIPE, sighandler) == 0);
+
+ ATF_REQUIRE(write(fds[1], "x", 1) != -1);
+ ATF_REQUIRE(close(fds[0]) == 0);
+
+ errno = 0;
+ fail = true;
+
+ if (write(fds[1], "x", 1) != -1 || errno != EPIPE)
+ atf_tc_fail_nonfatal("expected EPIPE but write(2) succeeded");
+
+ ATF_REQUIRE(close(fds[1]) == 0);
+
+ if (fail != false)
+ atf_tc_fail_nonfatal("SIGPIPE was not raised");
+}
+
+ATF_TC_WITH_CLEANUP(write_pos);
+ATF_TC_HEAD(write_pos, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks that write(2) "
+ "updates the file position");
+}
+
+ATF_TC_BODY(write_pos, tc)
+{
+ const size_t n = 123;
+ size_t i;
+ int fd;
+
+ fd = open(path, O_RDWR | O_CREAT);
+ ATF_REQUIRE(fd >= 0);
+
+ for (i = 0; i < n; i++) {
+ ATF_REQUIRE(write(fd, "x", 1) == 1);
+ ATF_REQUIRE(lseek(fd, 0, SEEK_CUR) == (off_t)(i + 1));
+ }
+
+ ATF_REQUIRE(close(fd) == 0);
+ ATF_REQUIRE(unlink(path) == 0);
+}
+
+ATF_TC_CLEANUP(write_pos, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC_WITH_CLEANUP(write_ret);
+ATF_TC_HEAD(write_ret, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Checks return values from write(2)");
+}
+
+ATF_TC_BODY(write_ret, tc)
+{
+ const size_t n = 99;
+ char buf[123];
+ size_t i, j;
+ int fd;
+
+ fd = open(path, O_WRONLY | O_CREAT);
+ ATF_REQUIRE(fd >= 0);
+
+ (void)memset(buf, 'x', sizeof(buf));
+
+ for (i = j = 0; i < n; i++)
+ j += write(fd, buf, sizeof(buf));
+
+ if (j != n * 123)
+ atf_tc_fail("inconsistent return values from write(2)");
+
+ (void)close(fd);
+ (void)unlink(path);
+}
+
+ATF_TC_CLEANUP(write_ret, tc)
+{
+ (void)unlink(path);
+}
+
+ATF_TC(writev_iovmax);
+ATF_TC_HEAD(writev_iovmax, tc)
+{
+ atf_tc_set_md_var(tc, "timeout", "10");
+ atf_tc_set_md_var(tc, "descr",
+ "Checks that file descriptor is properly FILE_UNUSE()d "
+ "when iovcnt is greater than IOV_MAX");
+}
+
+ATF_TC_BODY(writev_iovmax, tc)
+{
+ ssize_t retval;
+
+ (void)printf("Calling writev(2, NULL, IOV_MAX + 1)...\n");
+
+ errno = 0;
+ retval = writev(2, NULL, IOV_MAX + 1);
+
+ ATF_REQUIRE_EQ_MSG(retval, -1, "got: %zd", retval);
+ ATF_REQUIRE_EQ_MSG(errno, EINVAL, "got: %s", strerror(errno));
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, write_err);
+ ATF_TP_ADD_TC(tp, write_pipe);
+ ATF_TP_ADD_TC(tp, write_pos);
+ ATF_TP_ADD_TC(tp, write_ret);
+ ATF_TP_ADD_TC(tp, writev_iovmax);
+
+ return atf_no_error();
+}
OpenPOWER on IntegriCloud