diff options
Diffstat (limited to 'tests')
67 files changed, 0 insertions, 16346 deletions
diff --git a/tests/sys/Makefile b/tests/sys/Makefile index dc447d0..9225eab 100644 --- a/tests/sys/Makefile +++ b/tests/sys/Makefile @@ -4,17 +4,9 @@ TESTSDIR= ${TESTSBASE}/sys -TESTS_SUBDIRS+= fifo -TESTS_SUBDIRS+= file TESTS_SUBDIRS+= kern -TESTS_SUBDIRS+= kqueue -TESTS_SUBDIRS+= mqueue -TESTS_SUBDIRS+= mmap TESTS_SUBDIRS+= netinet TESTS_SUBDIRS+= opencrypto -TESTS_SUBDIRS+= posixshm -TESTS_SUBDIRS+= sockets -TESTS_SUBDIRS+= vfs # Items not integrated into kyua runs by default SUBDIR+= pjdfstest diff --git a/tests/sys/Makefile.inc b/tests/sys/Makefile.inc deleted file mode 100644 index f341842..0000000 --- a/tests/sys/Makefile.inc +++ /dev/null @@ -1,3 +0,0 @@ -# $FreeBSD$ - -WARNS?= 6 diff --git a/tests/sys/fifo/Makefile b/tests/sys/fifo/Makefile deleted file mode 100644 index 602bf1e..0000000 --- a/tests/sys/fifo/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# $FreeBSD$ - -TESTSDIR= ${TESTSBASE}/sys/fifo - -PLAIN_TESTS_C+= fifo_create -PLAIN_TESTS_C+= fifo_io -PLAIN_TESTS_C+= fifo_misc -PLAIN_TESTS_C+= fifo_open - -TEST_METADATA.fifo_create+= required_user="root" -TEST_METADATA.fifo_open+= required_user="root" - -.include <bsd.test.mk> diff --git a/tests/sys/fifo/fifo_create.c b/tests/sys/fifo/fifo_create.c deleted file mode 100644 index 2eb01e5..0000000 --- a/tests/sys/fifo/fifo_create.c +++ /dev/null @@ -1,282 +0,0 @@ -/*- - * Copyright (c) 2005-2008 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/stat.h> - -#include <err.h> -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* - * Simple regression test for the creation and destruction of POSIX fifos in - * the file system name space. Using a specially created directory, create - * a fifo in it and check that the following properties are present, as - * specified in IEEE Std 1003.1, 2004 Edition: - * - * - When mkfifo() or mknod(S_IFIFO) is called, on success, a fifo is - * created. - * - * - On an error, no fifo is created. (XXX: Not tested) - * - * - The mode bits on the fifo are a product of combining the umask and - * requested mode. - * - * - The fifo's owner will be the processes effective user ID. (XXX: Not - * tested) - * - * - The fifo's group will be the parent directory's group or the effective - * group ID of the process. For historical reasons, BSD prefers the group - * ID of the process, so we will generate an error if it's not that. (XXX: - * Not tested) - * - * - The st_atime, st_ctime, st_mtime of the fifo will be set appropriately, - * and st_ctime and st_mtime on the directory will be updated. (XXX: We - * test they are updated, not correct) - * - * - EEXIST is returned if the named file already exists. - * - * In addition, we check that we can unlink the fifo, and that if we do, it - * disappears. - * - * This test must run as root in order to usefully frob the process - * credential to test permission parts. - */ - -/* - * All activity occurs within a temporary directory created early in the - * test. - */ -static char temp_dir[PATH_MAX]; - -static void __unused -atexit_temp_dir(void) -{ - - rmdir(temp_dir); -} - -/* - * Basic creation tests: verify that mkfifo(2) (or mknod(2)) creates a fifo, - * that the time stamps on the directory are updated, that if we try twice we - * get EEXIST, and that we can unlink it. - */ -static void -fifo_create_test(int use_mkfifo) -{ - struct stat old_dirsb, dirsb, fifosb; - const char *testname; - char path[] = "testfifo"; - int error; - - if (use_mkfifo) - testname = "mkfifo"; - else - testname = "mknod"; - - /* - * Sleep to make sure that the time stamp on the directory will be - * updated. - */ - if (stat(".", &old_dirsb) < 0) - err(-1, "basic_create_test: %s: stat: %s", testname, - temp_dir); - - sleep(2); - - if (use_mkfifo) { - if (mkfifo(path, 0600) < 0) - err(-1, "basic_create_test: %s: %s", testname, path); - } else { - if (mknod(path, S_IFIFO | 0600, 0) < 0) - err(-1, "basic_create_test: %s: %s", testname, path); - } - - if (stat(path, &fifosb) < 0) { - error = errno; - (void)unlink(path); - errno = error; - err(-1, "basic_create_test: %s: stat: %s", testname, path); - } - - if (!(S_ISFIFO(fifosb.st_mode))) { - (void)unlink(path); - errx(-1, "basic_create_test: %s produced non-fifo", - testname); - } - - if (use_mkfifo) { - if (mkfifo(path, 0600) == 0) - errx(-1, "basic_create_test: dup %s succeeded", - testname); - } else { - if (mknod(path, S_IFIFO | 0600, 0) == 0) - errx(-1, "basic_create_test: dup %s succeeded", - testname); - } - - if (errno != EEXIST) - err(-1, "basic_create_test: dup %s unexpected error", - testname); - - if (stat(".", &dirsb) < 0) { - error = errno; - (void)unlink(path); - errno = error; - err(-1, "basic_create_test: %s: stat: %s", testname, - temp_dir); - } - - if (old_dirsb.st_ctime == dirsb.st_ctime) { - (void)unlink(path); - errx(-1, "basic_create_test: %s: old_dirsb.st_ctime == " - "dirsb.st_ctime", testname); - } - - if (old_dirsb.st_mtime == dirsb.st_mtime) { - (void)unlink(path); - errx(-1, "basic_create_test: %s: old_dirsb.st_mtime == " - "dirsb.st_mtime", testname); - } - - if (unlink(path) < 0) - err(-1, "basic_create_test: %s: unlink: %s", testname, path); - - if (stat(path, &fifosb) == 0) - errx(-1, "basic_create_test: %s: unlink failed to unlink", - testname); - if (errno != ENOENT) - err(-1, "basic_create_test: %s: unlink unexpected error", - testname); -} - -/* - * Having determined that basic create/remove/etc functionality is present - * for fifos, now make sure that the umask, requested permissions, and - * resulting mode are handled properly. - */ -static const struct permission_test { - mode_t pt_umask; - mode_t pt_reqmode; - mode_t pt_mode; -} permission_test[] = { - {0000, 0, S_IFIFO}, - {0000, S_IRWXU, S_IFIFO | S_IRWXU}, - {0000, S_IRWXU | S_IRWXG | S_IRWXO, S_IFIFO | S_IRWXU | S_IRWXG | - S_IRWXO }, - {0077, S_IRWXU, S_IFIFO | S_IRWXU}, - {0077, S_IRWXU | S_IRWXG | S_IRWXO, S_IFIFO | S_IRWXU}, -}; -static const int permission_test_count = sizeof(permission_test) / - sizeof(struct permission_test); - -static void -fifo_permission_test(int use_mkfifo) -{ - const struct permission_test *ptp; - mode_t __unused old_umask; - char path[] = "testfifo"; - const char *testname; - struct stat sb; - int error, i; - - if (use_mkfifo) - testname = "mkfifo"; - else - testname = "mknod"; - - old_umask = umask(0022); - for (i = 0; i < permission_test_count; i++) { - ptp = &permission_test[i]; - - umask(ptp->pt_umask); - if (use_mkfifo) { - if (mkfifo(path, ptp->pt_reqmode) < 0) - err(-1, "fifo_permission_test: %s: %08o " - "%08o %08o\n", testname, ptp->pt_umask, - ptp->pt_reqmode, ptp->pt_mode); - } else { - if (mknod(path, S_IFIFO | ptp->pt_reqmode, 0) < 0) - err(-1, "fifo_permission_test: %s: %08o " - "%08o %08o\n", testname, ptp->pt_umask, - ptp->pt_reqmode, ptp->pt_mode); - } - - if (stat(path, &sb) < 0) { - error = errno; - (void)unlink(path); - errno = error; - err(-1, "fifo_permission_test: %s: %s", testname, - path); - } - - if (sb.st_mode != ptp->pt_mode) { - (void)unlink(path); - errx(-1, "fifo_permission_test: %s: %08o %08o %08o " - "got %08o", testname, ptp->pt_umask, - ptp->pt_reqmode, ptp->pt_mode, sb.st_mode); - } - - if (unlink(path) < 0) - err(-1, "fifo_permission_test: %s: unlink: %s", - testname, path); - } - umask(old_umask); -} - -int -main(void) -{ - int i; - - if (geteuid() != 0) - errx(-1, "must be run as root"); - - strcpy(temp_dir, "fifo_create.XXXXXXXXXXX"); - if (mkdtemp(temp_dir) == NULL) - err(-1, "mkdtemp"); - atexit(atexit_temp_dir); - - if (chdir(temp_dir) < 0) - err(-1, "chdir"); - - /* - * Run each test twice, once with mknod(2) and a second time with - * mkfifo(2). Historically, BSD has not allowed mknod(2) to be used - * to create fifos, but the Single UNIX Specification requires it. - */ - for (i = 0; i < 2; i++) { - fifo_create_test(i); - fifo_permission_test(i); - } - - return (0); -} diff --git a/tests/sys/fifo/fifo_io.c b/tests/sys/fifo/fifo_io.c deleted file mode 100644 index 93d4be7..0000000 --- a/tests/sys/fifo/fifo_io.c +++ /dev/null @@ -1,1399 +0,0 @@ -/*- - * Copyright (c) 2005 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/event.h> -#include <sys/ioctl.h> -#include <sys/select.h> -#include <sys/stat.h> -#include <sys/time.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <poll.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* - * Regression test to exercise POSIX fifo I/O. - * - * We test a number of aspect of behavior, including: - * - * - If there's no data to read, then for blocking fifos, we block, and for - * non-blocking, we return EAGAIN. - * - * - If we write ten bytes, ten bytes can be read, and they're the same - * bytes, in the same order. - * - * - If we write two batches of five bytes, we can read the same ten bytes in - * one read of ten bytes. - * - * - If we write ten bytes, we can read the same ten bytes in two reads of - * five bytes each. - * - * - If we over-fill a buffer (by writing 512k, which we take to be a large - * number above default buffer sizes), we block if there is no reader. - * - * - That once 512k (ish) is read from the other end, the blocked writer - * wakes up. - * - * - When a fifo is empty, poll, select, kqueue, and fionread report it is - * writable but not readable. - * - * - When a fifo has data in it, poll, select, and kqueue report that it is - * writable. - * - * - XXX: blocked reader semantics? - * - * - XXX: event behavior on remote close? - * - * Although behavior of O_RDWR isn't defined for fifos by POSIX, we expect - * "reasonable" behavior, and run some additional tests relating to event - * management on O_RDWR fifo descriptors. - */ - -#define KQUEUE_MAX_EVENT 8 - -/* - * All activity occurs within a temporary directory created early in the - * test. - */ -static char temp_dir[PATH_MAX]; - -static void __unused -atexit_temp_dir(void) -{ - - rmdir(temp_dir); -} - -static void -makefifo(const char *fifoname, const char *testname) -{ - - if (mkfifo(fifoname, 0700) < 0) - err(-1, "%s: makefifo: mkfifo: %s", testname, fifoname); -} - -static void -cleanfifo2(const char *fifoname, int fd1, int fd2) -{ - - if (fd1 != -1) - close(fd1); - if (fd2 != -1) - close(fd2); - (void)unlink(fifoname); -} - -static void -cleanfifo3(const char *fifoname, int fd1, int fd2, int fd3) -{ - - if (fd3 != -1) - close(fd3); - cleanfifo2(fifoname, fd1, fd2); -} - -/* - * Open two different file descriptors for a fifo: one read, one write. Do - * so using non-blocking opens in order to avoid deadlocking the process. - */ -static int -openfifo(const char *fifoname, int *reader_fdp, int *writer_fdp) -{ - int error, fd1, fd2; - - fd1 = open(fifoname, O_RDONLY | O_NONBLOCK); - if (fd1 < 0) - return (-1); - fd2 = open(fifoname, O_WRONLY | O_NONBLOCK); - if (fd2 < 0) { - error = errno; - close(fd1); - errno = error; - return (-1); - } - *reader_fdp = fd1; - *writer_fdp = fd2; - - return (0); -} - -/* - * Open one file descriptor for the fifo, supporting both read and write. - */ -static int -openfifo_rw(const char *fifoname, int *fdp) -{ - int fd; - - fd = open(fifoname, O_RDWR); - if (fd < 0) - return (-1); - *fdp = fd; - - return (0); -} - -static int -set_nonblocking(int fd, const char *testname) -{ - int flags; - - flags = fcntl(fd, F_GETFL); - if (flags < 0) { - warn("%s: fcntl(fd, F_GETFL)", testname); - return(-1); - } - - flags |= O_NONBLOCK; - - if (fcntl(fd, F_SETFL, flags) < 0) { - warn("%s: fcntl(fd, 0x%x)", testname, flags); - return (-1); - } - - return (0); -} - -static int -set_blocking(int fd, const char *testname) -{ - int flags; - - flags = fcntl(fd, F_GETFL); - if (flags < 0) { - warn("%s: fcntl(fd, F_GETFL)", testname); - return(-1); - } - - flags &= ~O_NONBLOCK; - - if (fcntl(fd, F_SETFL, flags) < 0) { - warn("%s: fcntl(fd, 0x%x)", testname, flags); - return (-1); - } - - return (0); -} - -/* - * Drain a file descriptor (fifo) of any readable data. Note: resets the - * blocking state. - */ -static int -drain_fd(int fd, const char *testname) -{ - ssize_t len; - u_char ch; - - if (set_nonblocking(fd, testname) < 0) - return (-1); - - while ((len = read(fd, &ch, sizeof(ch))) > 0); - if (len < 0) { - switch (errno) { - case EAGAIN: - return (0); - default: - warn("%s: drain_fd: read", testname); - return (-1); - } - } - warn("%s: drain_fd: read: returned 0 bytes", testname); - return (-1); -} - -/* - * Simple I/O test: write ten integers, and make sure we get back the same - * integers in the same order. This assumes a minimum fifo buffer > 10 - * bytes in order to not block and deadlock. - */ -static void -test_simpleio(void) -{ - int i, reader_fd, writer_fd; - u_char buffer[10]; - ssize_t len; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) - < 0) { - warn("test_simpleio: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - for (i = 0; i < 10; i++) - buffer[i] = i; - - len = write(writer_fd, (char *)buffer, sizeof(buffer)); - if (len < 0) { - warn("test_simpleio: write"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != sizeof(buffer)) { - warnx("test_simplio: tried %zu but wrote %zd", sizeof(buffer), - len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - len = read(reader_fd, (char *)buffer, sizeof(buffer)); - if (len < 0) { - warn("test_simpleio: read"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != sizeof(buffer)) { - warnx("test_simpleio: tried %zu but read %zd", sizeof(buffer), - len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - for (i = 0; i < 10; i++) { - if (buffer[i] == i) - continue; - warnx("test_simpleio: write byte %d as 0x%02x, but read " - "0x%02x", i, i, buffer[i]); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo2("testfifo", reader_fd, writer_fd); -} - -static volatile int alarm_fired; -/* - * Non-destructive SIGALRM handler. - */ -static void -sigalarm(int signum __unused) -{ - - alarm_fired = 1; -} - -/* - * Wrapper function for write, which uses a timer to interrupt any blocking. - * Because we can't reliably detect EINTR for blocking I/O, we also track - * whether or not our timeout fired. - */ -static int __unused -timed_write(int fd, void *data, size_t len, ssize_t *written_lenp, - int timeout, int *timedoutp, const char *testname) -{ - struct sigaction act, oact; - ssize_t written_len; - int error; - - alarm_fired = 0; - bzero(&act, sizeof(oact)); - act.sa_handler = sigalarm; - if (sigaction(SIGALRM, &act, &oact) < 0) { - warn("%s: timed_write: sigaction", testname); - return (-1); - } - alarm(timeout); - written_len = write(fd, data, len); - error = errno; - alarm(0); - if (sigaction(SIGALRM, &oact, NULL) < 0) { - warn("%s: timed_write: sigaction", testname); - return (-1); - } - if (alarm_fired) - *timedoutp = 1; - else - *timedoutp = 0; - - errno = error; - if (written_len < 0) - return (-1); - *written_lenp = written_len; - return (0); -} - -/* - * Wrapper function for read, which uses a timer to interrupt any blocking. - * Because we can't reliably detect EINTR for blocking I/O, we also track - * whether or not our timeout fired. - */ -static int -timed_read(int fd, void *data, size_t len, ssize_t *read_lenp, - int timeout, int *timedoutp, const char *testname) -{ - struct sigaction act, oact; - ssize_t read_len; - int error; - - alarm_fired = 0; - bzero(&act, sizeof(oact)); - act.sa_handler = sigalarm; - if (sigaction(SIGALRM, &act, &oact) < 0) { - warn("%s: timed_write: sigaction", testname); - return (-1); - } - alarm(timeout); - read_len = read(fd, data, len); - error = errno; - alarm(0); - if (sigaction(SIGALRM, &oact, NULL) < 0) { - warn("%s: timed_write: sigaction", testname); - return (-1); - } - if (alarm_fired) - *timedoutp = 1; - else - *timedoutp = 0; - - errno = error; - if (read_len < 0) - return (-1); - *read_lenp = read_len; - return (0); -} - -/* - * This test operates on blocking and non-blocking fifo file descriptors, in - * order to determine whether they block at good moments or not. By good we - * mean: don't block for non-blocking sockets, and do block for blocking - * ones, assuming there isn't I/O buffer to satisfy the request. - * - * We use a timeout of 5 seconds, concluding that in 5 seconds either all I/O - * that can take place will, and that if we reach the end of the timeout, - * then blocking has occurred. - * - * We assume that the buffer size on a fifo is <512K, and as such, that - * writing that much data without an active reader will result in blocking. - */ -static void -test_blocking_read_empty(void) -{ - int reader_fd, ret, timedout, writer_fd; - ssize_t len; - u_char ch; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) - < 0) { - warn("test_blocking_read_empty: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - /* - * Read one byte from an empty blocking fifo, block as there is no - * data. - */ - if (set_blocking(reader_fd, __func__) < 0) { - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout, - __func__); - if (ret != -1) { - warnx("test_blocking_read_empty: timed_read: returned " - "success"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (errno != EINTR) { - warn("test_blocking_read_empty: timed_read"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - /* - * Read one byte from an empty non-blocking fifo, return EAGAIN as - * there is no data. - */ - if (set_nonblocking(reader_fd, __func__) < 0) { - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout, - __func__); - if (ret != -1) { - warnx("test_blocking_read_empty: timed_read: returned " - "success"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (errno != EAGAIN) { - warn("test_blocking_read_empty: timed_read"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo2("testfifo", reader_fd, writer_fd); -} - -/* - * Write one byte to an empty fifo, then try to read one byte and make sure - * we don't block in either the write or the read. This tests both for - * improper blocking in the send and receive code. - */ -static void -test_blocking_one_byte(void) -{ - int reader_fd, ret, timedout, writer_fd; - ssize_t len; - u_char ch; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("test_blocking: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - if (set_blocking(writer_fd, __func__) < 0) { - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (set_blocking(reader_fd, __func__) < 0) { - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - ch = 0xfe; - ret = timed_write(writer_fd, &ch, sizeof(ch), &len, 5, &timedout, - __func__); - if (ret < 0) { - warn("test_blocking_one_byte: timed_write"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != sizeof(ch)) { - warnx("test_blocking_one_byte: timed_write: tried to write " - "%zu, wrote %zd", sizeof(ch), len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - ch = 0xab; - ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout, - __func__); - if (ret < 0) { - warn("test_blocking_one_byte: timed_read"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != sizeof(ch)) { - warnx("test_blocking_one_byte: timed_read: wanted %zu, " - "read %zd", sizeof(ch), len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (ch != 0xfe) { - warnx("test_blocking_one_byte: timed_read: expected to read " - "0x%02x, read 0x%02x", 0xfe, ch); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo2("testfifo", reader_fd, writer_fd); -} - -/* - * Write one byte to an empty fifo, then try to read one byte and make sure - * we don't get back EAGAIN. - */ -static void -test_nonblocking_one_byte(void) -{ - int reader_fd, ret, timedout, writer_fd; - ssize_t len; - u_char ch; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("test_nonblocking: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - if (set_nonblocking(reader_fd, __func__) < 0) { - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - ch = 0xfe; - ret = timed_write(writer_fd, &ch, sizeof(ch), &len, 5, &timedout, - __func__); - if (ret < 0) { - warn("test_nonblocking_one_byte: timed_write"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != sizeof(ch)) { - warnx("test_nonblocking_one_byte: timed_write: tried to write " - "%zu, wrote %zd", sizeof(ch), len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - ch = 0xab; - ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout, - __func__); - if (ret < 0) { - warn("test_nonblocking_one_byte: timed_read"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != sizeof(ch)) { - warnx("test_nonblocking_one_byte: timed_read: wanted %zu, read " - "%zd", sizeof(ch), len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (ch != 0xfe) { - warnx("test_nonblocking_one_byte: timed_read: expected to read " - "0x%02x, read 0x%02x", 0xfe, ch); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo2("testfifo", reader_fd, writer_fd); -} - -/* - * First of two test cases involving a 512K buffer: write the buffer into a - * blocking file descriptor. We'd like to know it blocks, but the closest we - * can get is to see if SIGALRM fired during the I/O resulting in a partial - * write. - */ -static void -test_blocking_partial_write(void) -{ - int reader_fd, ret, timedout, writer_fd; - u_char *buffer; - ssize_t len; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("test_blocking_partial_write: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - if (set_blocking(writer_fd, __func__) < 0) { - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - buffer = malloc(512*1024); - if (buffer == NULL) { - warn("test_blocking_partial_write: malloc"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - bzero(buffer, 512*1024); - - ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout, - __func__); - if (ret < 0) { - warn("test_blocking_partial_write: timed_write"); - free(buffer); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (!timedout) { - warnx("test_blocking_partial_write: timed_write: blocking " - "socket didn't time out"); - free(buffer); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - free(buffer); - - if (drain_fd(reader_fd, __func__) < 0) { - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo2("testfifo", reader_fd, writer_fd); -} - -/* - * Write a 512K buffer to an empty fifo using a non-blocking file descriptor, - * and make sure it doesn't block. - */ -static void -test_nonblocking_partial_write(void) -{ - int reader_fd, ret, timedout, writer_fd; - u_char *buffer; - ssize_t len; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("test_blocking_partial_write: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - if (set_nonblocking(writer_fd, __func__) < 0) { - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - buffer = malloc(512*1024); - if (buffer == NULL) { - warn("test_blocking_partial_write: malloc"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - bzero(buffer, 512*1024); - - ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout, - __func__); - if (ret < 0) { - warn("test_blocking_partial_write: timed_write"); - free(buffer); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (timedout) { - warnx("test_blocking_partial_write: timed_write: " - "non-blocking socket timed out"); - free(buffer); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (len == 0 || len >= 512*1024) { - warnx("test_blocking_partial_write: timed_write: requested " - "%d, sent %zd", 512*1024, len); - free(buffer); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - free(buffer); - - if (drain_fd(reader_fd, __func__) < 0) { - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo2("testfifo", reader_fd, writer_fd); -} - -/* - * test_coalesce_big_read() verifies that data mingles in the fifo across - * message boundaries by performing two small writes, then a bigger read - * that should return data from both writes. - */ -static void -test_coalesce_big_read(void) -{ - int i, reader_fd, writer_fd; - u_char buffer[10]; - ssize_t len; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("test_coalesce_big_read: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - /* Write five, write five, read ten. */ - for (i = 0; i < 10; i++) - buffer[i] = i; - - len = write(writer_fd, buffer, 5); - if (len < 0) { - warn("test_coalesce_big_read: write 5"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != 5) { - warnx("test_coalesce_big_read: write 5 wrote %zd", len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - len = write(writer_fd, buffer + 5, 5); - if (len < 0) { - warn("test_coalesce_big_read: write 5"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != 5) { - warnx("test_coalesce_big_read: write 5 wrote %zd", len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - len = read(reader_fd, buffer, 10); - if (len < 0) { - warn("test_coalesce_big_read: read 10"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != 10) { - warnx("test_coalesce_big_read: read 10 read %zd", len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - for (i = 0; i < 10; i++) { - if (buffer[i] == i) - continue; - warnx("test_coalesce_big_read: expected to read 0x%02x, " - "read 0x%02x", i, buffer[i]); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo2("testfifo", -1, -1); -} - -/* - * test_coalesce_big_write() verifies that data mingles in the fifo across - * message boundaries by performing one big write, then two smaller reads - * that should return sequential elements of data from the write. - */ -static void -test_coalesce_big_write(void) -{ - int i, reader_fd, writer_fd; - u_char buffer[10]; - ssize_t len; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("test_coalesce_big_write: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - /* Write ten, read five, read five. */ - for (i = 0; i < 10; i++) - buffer[i] = i; - - len = write(writer_fd, buffer, 10); - if (len < 0) { - warn("test_coalesce_big_write: write 10"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != 10) { - warnx("test_coalesce_big_write: write 10 wrote %zd", len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - len = read(reader_fd, buffer, 5); - if (len < 0) { - warn("test_coalesce_big_write: read 5"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != 5) { - warnx("test_coalesce_big_write: read 5 read %zd", len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - len = read(reader_fd, buffer + 5, 5); - if (len < 0) { - warn("test_coalesce_big_write: read 5"); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (len != 5) { - warnx("test_coalesce_big_write: read 5 read %zd", len); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - for (i = 0; i < 10; i++) { - if (buffer[i] == i) - continue; - warnx("test_coalesce_big_write: expected to read 0x%02x, " - "read 0x%02x", i, buffer[i]); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo2("testfifo", -1, -1); -} - -static int -poll_status(int fd, int *readable, int *writable, int *exception, - const char *testname) -{ - struct pollfd fds[1]; - - fds[0].fd = fd; - fds[0].events = POLLIN | POLLOUT | POLLERR; - fds[0].revents = 0; - - if (poll(fds, 1, 0) < 0) { - warn("%s: poll", testname); - return (-1); - } - *readable = (fds[0].revents & POLLIN) ? 1 : 0; - *writable = (fds[0].revents & POLLOUT) ? 1 : 0; - *exception = (fds[0].revents & POLLERR) ? 1 : 0; - return (0); -} - -static int -select_status(int fd, int *readable, int *writable, int *exception, - const char *testname) -{ - struct fd_set readfds, writefds, exceptfds; - struct timeval timeout; - - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_ZERO(&exceptfds); - FD_SET(fd, &readfds); - FD_SET(fd, &writefds); - FD_SET(fd, &exceptfds); - timeout.tv_sec = 0; - timeout.tv_usec = 0; - if (select(fd+1, &readfds, &writefds, &exceptfds, &timeout) < 0) { - warn("%s: select", testname); - return (-1); - } - *readable = FD_ISSET(fd, &readfds) ? 1 : 0; - *writable = FD_ISSET(fd, &writefds) ? 1 : 0; - *exception = FD_ISSET(fd, &exceptfds) ? 1 : 0; - return (0); -} - -/* - * Given an existing kqueue, set up read and write event filters for the - * passed file descriptor. Typically called once for the read endpoint, and - * once for the write endpoint. - */ -static int -kqueue_setup(int kqueue_fd, int fd, const char *testname) -{ - struct kevent kevent_changelist[2]; - struct kevent kevent_eventlist[KQUEUE_MAX_EVENT], *kp; - struct timespec timeout; - int i, ret; - - timeout.tv_sec = 0; - timeout.tv_nsec = 0; - - bzero(&kevent_changelist, sizeof(kevent_changelist)); - EV_SET(&kevent_changelist[0], fd, EVFILT_READ, EV_ADD, 0, 0, 0); - EV_SET(&kevent_changelist[1], fd, EVFILT_WRITE, EV_ADD, 0, 0, 0); - - bzero(&kevent_eventlist, sizeof(kevent_eventlist)); - ret = kevent(kqueue_fd, kevent_changelist, 2, kevent_eventlist, - KQUEUE_MAX_EVENT, &timeout); - if (ret < 0) { - warn("%s:%s: kevent initial register", testname, __func__); - return (-1); - } - - /* - * Verify that the events registered alright. - */ - for (i = 0; i < ret; i++) { - kp = &kevent_eventlist[i]; - if (kp->flags != EV_ERROR) - continue; - errno = kp->data; - warn("%s:%s: kevent register index %d", testname, __func__, - i); - return (-1); - } - - return (0); -} - -static int -kqueue_status(int kqueue_fd, int fd, int *readable, int *writable, - int *exception, const char *testname) -{ - struct kevent kevent_eventlist[KQUEUE_MAX_EVENT], *kp; - struct timespec timeout; - int i, ret; - - timeout.tv_sec = 0; - timeout.tv_nsec = 0; - - ret = kevent(kqueue_fd, NULL, 0, kevent_eventlist, KQUEUE_MAX_EVENT, - &timeout); - if (ret < 0) { - warn("%s: %s: kevent", testname, __func__); - return (-1); - } - - *readable = *writable = *exception = 0; - for (i = 0; i < ret; i++) { - kp = &kevent_eventlist[i]; - if (kp->ident != (u_int)fd) - continue; - if (kp->filter == EVFILT_READ) - *readable = 1; - if (kp->filter == EVFILT_WRITE) - *writable = 1; - } - - return (0); -} - -static int -fionread_status(int fd, int *readable, const char *testname) -{ - int i; - - if (ioctl(fd, FIONREAD, &i) < 0) { - warn("%s: ioctl(FIONREAD)", testname); - return (-1); - } - - if (i > 0) - *readable = 1; - else - *readable = 0; - return (0); -} - -#define READABLE 1 -#define WRITABLE 1 -#define EXCEPTION 1 - -#define NOT_READABLE 0 -#define NOT_WRITABLE 0 -#define NOT_EXCEPTION 0 - -static int -assert_status(int fd, int kqueue_fd, int assert_readable, - int assert_writable, int assert_exception, const char *testname, - const char *conditionname, const char *fdname) -{ - int readable, writable, exception; - - if (poll_status(fd, &readable, &writable, &exception, testname) < 0) - return (-1); - - if (readable != assert_readable || writable != assert_writable || - exception != assert_exception) { - warnx("%s: %s polls r:%d, w:%d, e:%d on %s", testname, - fdname, readable, writable, exception, conditionname); - return (-1); - } - - if (select_status(fd, &readable, &writable, &exception, testname) < 0) - return (-1); - - if (readable != assert_readable || writable != assert_writable || - exception != assert_exception) { - warnx("%s: %s selects r:%d, w:%d, e:%d on %s", testname, - fdname, readable, writable, exception, conditionname); - return (-1); - } - - if (kqueue_status(kqueue_fd, fd, &readable, &writable, &exception, - testname) < 0) - return (-1); - - if (readable != assert_readable || writable != assert_writable || - exception != assert_exception) { - warnx("%s: %s kevent r:%d, w:%d, e:%d on %s", testname, - fdname, readable, writable, exception, conditionname); - return (-1); - } - - if (fionread_status(fd, &readable, __func__) < 0) - return (-1); - - if (readable != assert_readable) { - warnx("%s: %s fionread r:%d on %s", testname, fdname, - readable, conditionname); - return (-1); - } - - return (0); -} - -/* - * test_events() uses poll(), select(), and kevent() to query the status of - * fifo file descriptors and determine whether they match expected state - * based on earlier semantic tests: specifically, whether or not poll/select/ - * kevent will correctly inform on readable/writable state following I/O. - * - * It would be nice to also test status changes as a result of closing of one - * or another fifo endpoint. - */ -static void -test_events_outofbox(void) -{ - int kqueue_fd, reader_fd, writer_fd; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("test_events_outofbox: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - kqueue_fd = kqueue(); - if (kqueue_fd < 0) { - warn("%s: kqueue", __func__); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - /* - * Make sure that fresh, out-of-the-box fifo file descriptors have - * good initial states. The reader_fd should have no active state, - * since it will not be readable (no data in pipe), writable (it's - * a read-only descriptor), and there's no reason for error yet. - */ - if (assert_status(reader_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE, - NOT_EXCEPTION, __func__, "create", "reader_fd") < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - /* - * Make sure that fresh, out-of-the-box fifo file descriptors have - * good initial states. The writer_fd should be ready to write. - */ - if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE, - NOT_EXCEPTION, __func__, "create", "writer_fd") < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); -} - -static void -test_events_write_read_byte(void) -{ - int kqueue_fd, reader_fd, writer_fd; - ssize_t len; - u_char ch; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("test_events_write_read_byte: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - kqueue_fd = kqueue(); - if (kqueue_fd < 0) { - warn("%s: kqueue", __func__); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - /* - * Write a byte to the fifo, and make sure that the read end becomes - * readable, and that the write end remains writable (small write). - */ - ch = 0x00; - len = write(writer_fd, &ch, sizeof(ch)); - if (len < 0) { - warn("%s: write", __func__); - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - if (assert_status(reader_fd, kqueue_fd, READABLE, NOT_WRITABLE, - NOT_EXCEPTION, __func__, "write", "reader_fd") < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - /* - * the writer_fd should remain writable. - */ - if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE, - NOT_EXCEPTION, __func__, "write", "writer_fd") < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - /* - * Read the byte from the reader_fd, and now confirm that that fifo - * becomes unreadable. - */ - len = read(reader_fd, &ch, sizeof(ch)); - if (len < 0) { - warn("%s: read", __func__); - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - if (assert_status(reader_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE, - NOT_EXCEPTION, __func__, "write+read", "reader_fd") < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - /* - * The writer_fd should remain writable. - */ - if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE, - NOT_EXCEPTION, __func__, "write+read", "writer_fd") < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); -} - -/* - * Write a 512k buffer to the fifo in non-blocking mode, and make sure that - * the write end becomes un-writable as a result of a partial write that - * fills the fifo buffer. - */ -static void -test_events_partial_write(void) -{ - int kqueue_fd, reader_fd, writer_fd; - u_char *buffer; - ssize_t len; - - makefifo("testfifo", __func__); - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("test_events_partial_write: openfifo: testfifo"); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - kqueue_fd = kqueue(); - if (kqueue_fd < 0) { - warn("%s: kqueue", __func__); - cleanfifo2("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - if (set_nonblocking(writer_fd, "test_events") < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - buffer = malloc(512*1024); - if (buffer == NULL) { - warn("test_events_partial_write: malloc"); - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - bzero(buffer, 512*1024); - - len = write(writer_fd, buffer, 512*1024); - if (len < 0) { - warn("test_events_partial_write: write"); - free(buffer); - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - free(buffer); - - if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE, - NOT_EXCEPTION, __func__, "big write", "writer_fd") < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - if (drain_fd(reader_fd, "test_events") < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - /* - * Test that the writer_fd has been restored to writable state after - * draining. - */ - if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE, - NOT_EXCEPTION, __func__, "big write + drain", "writer_fd") < 0) { - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); - exit(-1); - } - - cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd); -} - -/* - * We don't comprehensively test O_RDWR file descriptors, but do run a couple - * of event tests to make sure that the fifo implementation doesn't mixed up - * status checks. In particular, at least one past FreeBSD bug exists in - * which the FIONREAD test was performed on the wrong socket implementing the - * fifo, resulting in the fifo never returning readable. - */ -static void -test_events_rdwr(void) -{ - int fd, kqueue_fd; - ssize_t len; - char ch; - - makefifo("testfifo", __func__); - if (openfifo_rw("testfifo", &fd) < 0) { - warn("%s: openfifo_rw: testfifo", __func__); - cleanfifo2("testfifo", -1, -1); - exit(-1); - } - - kqueue_fd = kqueue(); - if (kqueue_fd < 0) { - warn("%s: kqueue", __func__); - cleanfifo2("testifo", fd, -1); - exit(-1); - } - - if (kqueue_setup(kqueue_fd, fd, __func__) < 0) { - cleanfifo2("testfifo", fd, kqueue_fd); - exit(-1); - } - - /* - * On first creation, the O_RDWR descriptor should be writable but - * not readable. - */ - if (assert_status(fd, kqueue_fd, NOT_READABLE, WRITABLE, - NOT_EXCEPTION, __func__, "create", "fd") < 0) { - cleanfifo2("testfifo", fd, kqueue_fd); - exit(-1); - } - - /* - * Write a byte, which should cause the file descriptor to become - * readable and writable. - */ - ch = 0x00; - len = write(fd, &ch, sizeof(ch)); - if (len < 0) { - warn("%s: write", __func__); - cleanfifo2("testfifo", fd, kqueue_fd); - exit(-1); - } - - if (assert_status(fd, kqueue_fd, READABLE, WRITABLE, NOT_EXCEPTION, - __func__, "write", "fd") < 0) { - cleanfifo2("testfifo", fd, kqueue_fd); - exit(-1); - } - - /* - * Read a byte, which should cause the file descriptor to return to - * simply being writable. - */ - len = read(fd, &ch, sizeof(ch)); - if (len < 0) { - warn("%s: read", __func__); - cleanfifo2("testfifo", fd, kqueue_fd); - exit(-1); - } - - if (assert_status(fd, kqueue_fd, NOT_READABLE, WRITABLE, - NOT_EXCEPTION, __func__, "write+read", "fd") < 0) { - cleanfifo2("testfifo", fd, kqueue_fd); - exit(-1); - } - - cleanfifo2("testfifo", fd, kqueue_fd); -} - -int -main(void) -{ - - strcpy(temp_dir, "fifo_io.XXXXXXXXXXX"); - if (mkdtemp(temp_dir) == NULL) - err(-1, "mkdtemp"); - atexit(atexit_temp_dir); - - if (chdir(temp_dir) < 0) - err(-1, "chdir %s", temp_dir); - - test_simpleio(); - test_blocking_read_empty(); - test_blocking_one_byte(); - test_nonblocking_one_byte(); - test_blocking_partial_write(); - test_nonblocking_partial_write(); - test_coalesce_big_read(); - test_coalesce_big_write(); - test_events_outofbox(); - test_events_write_read_byte(); - test_events_partial_write(); - test_events_rdwr(); - - return (0); -} diff --git a/tests/sys/fifo/fifo_misc.c b/tests/sys/fifo/fifo_misc.c deleted file mode 100644 index 888547e..0000000 --- a/tests/sys/fifo/fifo_misc.c +++ /dev/null @@ -1,335 +0,0 @@ -/*- - * Copyright (c) 2005 Robert N. M. Watson - * Copyright (c) 2012 Jilles Tjoelker - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/event.h> -#include <sys/filio.h> -#include <sys/stat.h> -#include <sys/time.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* - * Regression test for piddling details of fifos. - */ - -/* - * All activity occurs within a temporary directory created early in the - * test. - */ -static char temp_dir[PATH_MAX]; - -static void __unused -atexit_temp_dir(void) -{ - - rmdir(temp_dir); -} - -static void -makefifo(const char *fifoname, const char *testname) -{ - - if (mkfifo(fifoname, 0700) < 0) - err(-1, "%s: makefifo: mkfifo: %s", testname, fifoname); -} - -static void -cleanfifo(const char *fifoname, int fd1, int fd2) -{ - - if (fd1 != -1) - close(fd1); - if (fd2 != -1) - close(fd2); - (void)unlink(fifoname); -} - -static int -openfifo(const char *fifoname, int *reader_fdp, int *writer_fdp) -{ - int error, fd1, fd2; - - fd1 = open(fifoname, O_RDONLY | O_NONBLOCK); - if (fd1 < 0) - return (-1); - fd2 = open(fifoname, O_WRONLY | O_NONBLOCK); - if (fd2 < 0) { - error = errno; - close(fd1); - errno = error; - return (-1); - } - *reader_fdp = fd1; - *writer_fdp = fd2; - - return (0); -} - -/* - * POSIX does not allow lseek(2) on fifos, so we expect ESPIPE as a result. - */ -static void -test_lseek(void) -{ - int reader_fd, writer_fd; - - makefifo("testfifo", __func__); - - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("%s: openfifo", __func__); - cleanfifo("testfifo", -1, -1); - exit(-1); - } - - if (lseek(reader_fd, 1, SEEK_CUR) >= 0) { - warnx("%s: lseek succeeded instead of returning ESPIPE", - __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (errno != ESPIPE) { - warn("%s: lseek returned instead of ESPIPE", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo("testfifo", reader_fd, writer_fd); -} - -/* - * truncate(2) on FIFO should silently return success. - */ -static void -test_truncate(void) -{ - - makefifo("testfifo", __func__); - - if (truncate("testfifo", 1024) != 0) { - warn("%s: truncate", __func__); - cleanfifo("testfifo", -1, -1); - exit(-1); - } - - cleanfifo("testfifo", -1, -1); -} - -static int -test_ioctl_setclearflag(int fd, int flag, const char *testname, - const char *fdname, const char *flagname) -{ - int i; - - i = 1; - if (ioctl(fd, flag, &i) < 0) { - warn("%s:%s: ioctl(%s, %s, 1)", testname, __func__, fdname, - flagname); - cleanfifo("testfifo", -1, -1); - exit(-1); - } - - i = 0; - if (ioctl(fd, flag, &i) < 0) { - warn("%s:%s: ioctl(%s, %s, 0)", testname, __func__, fdname, - flagname); - cleanfifo("testfifo", -1, -1); - exit(-1); - } - - return (0); -} - -/* - * Test that various ioctls can be issued against the file descriptor. We - * don't currently test the semantics of these changes here. - */ -static void -test_ioctl(void) -{ - int reader_fd, writer_fd; - - makefifo("testfifo", __func__); - - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("%s: openfifo", __func__); - cleanfifo("testfifo", -1, -1); - exit(-1); - } - - /* - * Set and remove the non-blocking I/O flag. - */ - if (test_ioctl_setclearflag(reader_fd, FIONBIO, __func__, - "reader_fd", "FIONBIO") < 0) { - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (test_ioctl_setclearflag(writer_fd, FIONBIO, __func__, - "writer_fd", "FIONBIO") < 0) { - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - /* - * Set and remove the async I/O flag. - */ - if (test_ioctl_setclearflag(reader_fd, FIOASYNC, __func__, - "reader_fd", "FIOASYNC") < 0) { - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (test_ioctl_setclearflag(writer_fd, FIOASYNC, __func__, - "writer_fd", "FIONASYNC") < 0) { - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo("testfifo", reader_fd, writer_fd); -} - -/* - * fchmod(2)/fchown(2) on FIFO should work. - */ -static void -test_chmodchown(void) -{ - struct stat sb; - int reader_fd, writer_fd; - uid_t u; - gid_t g; - - makefifo("testfifo", __func__); - - if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) { - warn("%s: openfifo", __func__); - cleanfifo("testfifo", -1, -1); - exit(-1); - } - - if (fchmod(reader_fd, 0666) != 0) { - warn("%s: fchmod", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (stat("testfifo", &sb) != 0) { - warn("%s: stat", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if ((sb.st_mode & 0777) != 0666) { - warnx("%s: stat chmod result", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (fstat(writer_fd, &sb) != 0) { - warn("%s: fstat", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if ((sb.st_mode & 0777) != 0666) { - warnx("%s: fstat chmod result", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (fchown(reader_fd, -1, -1) != 0) { - warn("%s: fchown 1", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - u = geteuid(); - if (u == 0) - u = 1; - g = getegid(); - if (fchown(reader_fd, u, g) != 0) { - warn("%s: fchown 2", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - if (stat("testfifo", &sb) != 0) { - warn("%s: stat", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (sb.st_uid != u || sb.st_gid != g) { - warnx("%s: stat chown result", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (fstat(writer_fd, &sb) != 0) { - warn("%s: fstat", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - if (sb.st_uid != u || sb.st_gid != g) { - warnx("%s: fstat chown result", __func__); - cleanfifo("testfifo", reader_fd, writer_fd); - exit(-1); - } - - cleanfifo("testfifo", -1, -1); -} - -int -main(void) -{ - - strcpy(temp_dir, "fifo_misc.XXXXXXXXXXX"); - if (mkdtemp(temp_dir) == NULL) - err(-1, "mkdtemp"); - atexit(atexit_temp_dir); - - if (chdir(temp_dir) < 0) - err(-1, "chdir %s", temp_dir); - - test_lseek(); - test_truncate(); - test_ioctl(); - test_chmodchown(); - - return (0); -} diff --git a/tests/sys/fifo/fifo_open.c b/tests/sys/fifo/fifo_open.c deleted file mode 100644 index 892f481..0000000 --- a/tests/sys/fifo/fifo_open.c +++ /dev/null @@ -1,476 +0,0 @@ -/*- - * Copyright (c) 2005 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* - * Regression test to exercise various POSIX-defined parts of fifo behavior - * described for open(2): - * - * O_NONBLOCK - * When opening a FIFO with O_RDONLY or O_WRONLY set: - * - * - If O_NONBLOCK is set, an open() for reading-only shall return without - * delay. An open() for writing-only shall return an error if no process - * currently has the file open for reading. - * - * - If O_NONBLOCK is clear, an open() for reading-only shall block the - * calling thread until a thread opens the file for writing. An open() - * for writing-only shall block the calling thread until a thread opens - * the file for reading. - * - * When opening a block special or character special file that supports - * non-blocking opens: - * - * - If O_NONBLOCK is set, the open() function shall return without blocking - * for the device to be ready or available. Subsequent behavior of the - * device is device-specific. - * - * - If O_NONBLOCK is clear, the open() function shall block the calling - * thread until the device is ready or available before returning. - * - * Special errors: - * - * [ENXIO] - * O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is set, and no - * process has the file open for reading. - */ - -/* - * In order to test blocking/non-blocking behavior, test processes must - * potentially block themselves until released. As bugs in blocking result - * in processes that won't un-block, we must sacrifice a process to the task, - * watching and potentially killing it after a time-out. The main test - * process is never used to open or act directly on a fifo (other than to - * create or unlink it) in order to avoid the main test process being - * blocked. - */ - -/* - * All activity occurs within a temporary directory created early in the - * test. - */ -static char temp_dir[PATH_MAX]; - -static void __unused -atexit_temp_dir(void) -{ - - rmdir(temp_dir); -} - -/* - * Run a function in a particular test process. - */ -static int -run_in_process(int (*func)(void), pid_t *pidp, const char *errstr) -{ - pid_t pid; - - pid = fork(); - if (pid < 0) { - warn("%s: run_in_process: fork", errstr); - return (-1); - } - - if (pid == 0) - exit(func()); - - if (pidp != NULL) - *pidp = pid; - - return (0); -} - -/* - * Wait for a process on a timeout, and if the timeout expires, kill the - * process. Test each second rather than waiting the full timeout at once to - * minimize the amount of time spent hanging around unnecessarily. - */ -static int -wait_and_timeout(pid_t pid, int timeout, int *status, const char *errstr) -{ - pid_t wpid; - int i; - - /* - * Count up to the timeout, but do a non-hanging waitpid() after each - * second so we can avoid waiting a lot of extra time. - */ - for (i = 0; i < timeout; i++) { - wpid = waitpid(pid, status, WNOHANG); - if (wpid < 0) { - warn("%s: wait_and_timeout: waitpid %d", errstr, pid); - return (-1); - } - - if (wpid == pid) - return (0); - - sleep(1); - } - - wpid = waitpid(pid, status, WNOHANG); - if (wpid < 0) { - warn("%s: wait_and_timeout: waitpid %d", errstr, pid); - return (-1); - } - - if (wpid == pid) - return (0); - - if (kill(pid, SIGTERM) < 0) { - warn("%s: wait_and_timeout: kill %d", errstr, pid); - return (-1); - } - - wpid = waitpid(pid, status, 0); - if (wpid < 0) { - warn("%s: wait_and_timeout: waitpid %d", errstr, pid); - return (-1); - } - - if (wpid != pid) { - warn("%s: waitpid: returned %d not %d", errstr, wpid, pid); - return (-1); - } - - warnx("%s: process blocked", errstr); - return (-1); -} - -static int -non_blocking_open_reader(void) -{ - int fd; - - fd = open("testfifo", O_RDONLY | O_NONBLOCK); - if (fd < 0) - return (errno); - close(fd); - - return (0); -} - -static int -non_blocking_open_writer(void) -{ - int fd; - - fd = open("testfifo", O_WRONLY | O_NONBLOCK); - if (fd < 0) - return (errno); - close(fd); - - return (0); -} - -static int -blocking_open_reader(void) -{ - int fd; - - fd = open("testfifo", O_RDONLY); - if (fd < 0) - return (errno); - close(fd); - - return (0); -} - -static int -blocking_open_writer(void) -{ - int fd; - - fd = open("testfifo", O_WRONLY); - if (fd < 0) - return (errno); - close(fd); - - return (0); -} - -static void -test_blocking_reader(void) -{ - pid_t reader_pid, writer_pid, wpid; - int error, status; - - if (mkfifo("testfifo", 0600) < 0) - err(-1, "test_blocking_reader: mkfifo: testfifo"); - - /* - * Block a process in opening the fifo. - */ - if (run_in_process(blocking_open_reader, &reader_pid, - "test_blocking_reader: blocking_open_reader") < 0) { - (void)unlink("testfifo"); - exit(-1); - } - - /* - * Test that it blocked. - */ - sleep(5); - wpid = waitpid(reader_pid, &status, WNOHANG); - if (wpid < 0) { - error = errno; - (void)unlink("testfifo"); - errno = error; - err(-1, "test_blocking_reader: waitpid %d", reader_pid); - } - - if (wpid != 0 && wpid != reader_pid) { - (void)unlink("testfifo"); - errx(-1, "test_blocking_reader: waitpid %d returned %d", - reader_pid, wpid); - } - - if (wpid == reader_pid) { - (void)unlink("testfifo"); - errx(-1, "test_blocking_reader: blocking child didn't " - "block"); - } - - /* - * Unblock the blocking reader. - */ - if (run_in_process(blocking_open_writer, &writer_pid, - "test_blocking_reader: blocking_open_writer") < 0) { - (void)unlink("testfifo"); - (void)kill(reader_pid, SIGTERM); - (void)waitpid(reader_pid, &status, 0); - exit(-1); - } - - /* - * Make sure both processes exited quickly (<1 second) to make sure - * they didn't block, and GC. - */ - if (wait_and_timeout(reader_pid, 1, &status, - "test_blocking_reader: blocking_open_reader") < 0) { - (void)unlink("testinfo"); - (void)kill(reader_pid, SIGTERM); - (void)kill(writer_pid, SIGTERM); - exit(-1); - } - - if (wait_and_timeout(writer_pid, 1, &status, - "test_blocking_reader: blocking_open_writer") < 0) { - (void)unlink("testinfo"); - (void)kill(writer_pid, SIGTERM); - exit(-1); - } - - if (unlink("testfifo") < 0) - err(-1, "test_blocking_reader: unlink: testfifo"); -} -static void -test_blocking_writer(void) -{ - pid_t reader_pid, writer_pid, wpid; - int error, status; - - if (mkfifo("testfifo", 0600) < 0) - err(-1, "test_blocking_writer: mkfifo: testfifo"); - - /* - * Block a process in opening the fifo. - */ - if (run_in_process(blocking_open_writer, &writer_pid, - "test_blocking_writer: blocking_open_writer") < 0) { - (void)unlink("testfifo"); - exit(-1); - } - - /* - * Test that it blocked. - */ - sleep(5); - wpid = waitpid(writer_pid, &status, WNOHANG); - if (wpid < 0) { - error = errno; - (void)unlink("testfifo"); - errno = error; - err(-1, "test_blocking_writer: waitpid %d", writer_pid); - } - - if (wpid != 0 && wpid != writer_pid) { - (void)unlink("testfifo"); - errx(-1, "test_blocking_writer: waitpid %d returned %d", - writer_pid, wpid); - } - - if (wpid == writer_pid) { - (void)unlink("testfifo"); - errx(-1, "test_blocking_writer: blocking child didn't " - "block"); - } - - /* - * Unblock the blocking writer. - */ - if (run_in_process(blocking_open_reader, &reader_pid, - "test_blocking_writer: blocking_open_reader") < 0) { - (void)unlink("testfifo"); - (void)kill(writer_pid, SIGTERM); - (void)waitpid(writer_pid, &status, 0); - exit(-1); - } - - /* - * Make sure both processes exited quickly (<1 second) to make sure - * they didn't block, and GC. - */ - if (wait_and_timeout(writer_pid, 1, &status, - "test_blocking_writer: blocking_open_writer") < 0) { - (void)unlink("testinfo"); - (void)kill(writer_pid, SIGTERM); - (void)kill(reader_pid, SIGTERM); - (void)waitpid(writer_pid, &status, 0); - (void)waitpid(reader_pid, &status, 0); - exit(-1); - } - - if (wait_and_timeout(reader_pid, 1, &status, - "test_blocking_writer: blocking_open_reader") < 0) { - (void)unlink("testinfo"); - (void)kill(reader_pid, SIGTERM); - (void)waitpid(reader_pid, &status, 0); - exit(-1); - } - - if (unlink("testfifo") < 0) - err(-1, "test_blocking_writer: unlink: testfifo"); -} - -static void -test_non_blocking_reader(void) -{ - int status; - pid_t pid; - - if (mkfifo("testfifo", 0600) < 0) - err(-1, "test_non_blocking_reader: mkfifo: testfifo"); - - if (run_in_process(non_blocking_open_reader, &pid, - "test_non_blocking_reader: non_blocking_open_reader") < 0) { - (void)unlink("testfifo"); - exit(-1); - } - - status = -1; - if (wait_and_timeout(pid, 5, &status, - "test_non_blocking_reader: non_blocking_open_reader") < 0) { - (void)unlink("testfifo"); - exit(-1); - } - - if (WEXITSTATUS(status) != 0) { - (void)unlink("testfifo"); - errno = WEXITSTATUS(status); - err(-1, "test_non_blocking_reader: " - "non_blocking_open_reader: open: testfifo"); - } - - if (unlink("testfifo") < 0) - err(-1, "test_non_blocking_reader: unlink: testfifo"); -} - -static void -test_non_blocking_writer(void) -{ - int status; - pid_t pid; - - if (mkfifo("testfifo", 0600) < 0) - err(-1, "test_non_blocking_writer: mkfifo: testfifo"); - - if (run_in_process(non_blocking_open_writer, &pid, - "test_non_blocking_writer: non_blocking_open_writer") < 0) { - (void)unlink("testfifo"); - exit(-1); - } - - status = -1; - if (wait_and_timeout(pid, 5, &status, - "test_non_blocking_writer: non_blocking_open_writer") < 0) { - (void)unlink("testfifo"); - exit(-1); - } - - if (WEXITSTATUS(status) != ENXIO) { - (void)unlink("testfifo"); - - errno = WEXITSTATUS(status); - if (errno == 0) - errx(-1, "test_non_blocking_writer: " - "non_blocking_open_writer: open succeeded"); - err(-1, "test_non_blocking_writer: " - "non_blocking_open_writer: open: testfifo"); - } - - if (unlink("testfifo") < 0) - err(-1, "test_non_blocking_writer: unlink: testfifo"); -} - -int -main(void) -{ - - if (geteuid() != 0) - errx(-1, "must be run as root"); - - strcpy(temp_dir, "fifo_open.XXXXXXXXXXX"); - if (mkdtemp(temp_dir) == NULL) - err(-1, "mkdtemp"); - if (chdir(temp_dir) < 0) - err(-1, "chdir: %s", temp_dir); - atexit(atexit_temp_dir); - - test_non_blocking_reader(); - test_non_blocking_writer(); - - test_blocking_reader(); - test_blocking_writer(); - - return (0); -} diff --git a/tests/sys/file/Makefile b/tests/sys/file/Makefile deleted file mode 100644 index 6151c9f..0000000 --- a/tests/sys/file/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# $FreeBSD$ - -TESTSDIR= ${TESTSBASE}/sys/file - -BINDIR= ${TESTSDIR} - -TAP_TESTS_C+= closefrom_test -TAP_TESTS_C+= dup_test -TAP_TESTS_C+= fcntlflags_test -TAP_TESTS_SH+= flock_test -PLAIN_TESTS_C+= ftruncate_test -PLAIN_TESTS_C+= newfileops_on_fork_test - -PROGS+= flock_helper - -DPADD.closefrom_test= ${LIBUTIL} -LDADD.closefrom_test= -lutil - -DPADD.flock_helper= ${LIBPTHREAD} -LDADD.flock_helper= -lpthread - -DPADD.newfileops_on_fork_test= ${LIBPTHREAD} -LDADD.newfileops_on_fork_test= -lpthread - -.include <bsd.test.mk> diff --git a/tests/sys/file/closefrom_test.c b/tests/sys/file/closefrom_test.c deleted file mode 100644 index bd4acf6..0000000 --- a/tests/sys/file/closefrom_test.c +++ /dev/null @@ -1,275 +0,0 @@ -/*- - * Copyright (c) 2009 Advanced Computing Technologies LLC - * Written by: John H. Baldwin <jhb@FreeBSD.org> - * 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> -__FBSDID("$FreeBSD$"); - -/* - * Regression tests for the closefrom(2) system call. - */ - -#include <sys/param.h> -#include <sys/mman.h> -#include <sys/user.h> -#include <sys/wait.h> -#include <errno.h> -#include <fcntl.h> -#include <libutil.h> -#include <paths.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -struct shared_info { - int failed; - char tag[64]; - char message[0]; -}; - -static int test = 1; - -static void -ok(const char *descr) -{ - - printf("ok %d - %s\n", test, descr); - test++; -} - -static void -fail(const char *descr, const char *fmt, ...) -{ - va_list ap; - - printf("not ok %d - %s", test, descr); - test++; - if (fmt) { - va_start(ap, fmt); - printf(" # "); - vprintf(fmt, ap); - va_end(ap); - } - printf("\n"); - exit(1); -} - -#define fail_err(descr) fail((descr), "%s", strerror(errno)) - -static void -cok(struct shared_info *info, const char *descr) -{ - - info->failed = 0; - strlcpy(info->tag, descr, sizeof(info->tag)); - exit(0); -} - -static void -cfail(struct shared_info *info, const char *descr, const char *fmt, ...) -{ - va_list ap; - - info->failed = 1; - strlcpy(info->tag, descr, sizeof(info->tag)); - if (fmt) { - va_start(ap, fmt); - vsprintf(info->message, fmt, ap); - va_end(ap); - } - exit(0); -} - -#define cfail_err(info, descr) cfail((info), (descr), "%s", strerror(errno)) - -/* - * Use kinfo_getfile() to fetch the list of file descriptors and figure out - * the highest open file descriptor. - */ -static int -highest_fd(void) -{ - struct kinfo_file *kif; - int cnt, i, highest; - - kif = kinfo_getfile(getpid(), &cnt); - if (kif == NULL) - fail_err("kinfo_getfile"); - highest = INT_MIN; - for (i = 0; i < cnt; i++) - if (kif[i].kf_fd > highest) - highest = kif[i].kf_fd; - free(kif); - return (highest); -} - -static int -devnull(void) -{ - int fd; - - fd = open(_PATH_DEVNULL, O_RDONLY); - if (fd < 0) - fail_err("open(\" "_PATH_DEVNULL" \")"); - return (fd); -} - -int -main(void) -{ - struct shared_info *info; - pid_t pid; - int fd, i, start; - - printf("1..15\n"); - - /* We better start up with fd's 0, 1, and 2 open. */ - start = devnull(); - if (start == -1) - fail("open", "bad descriptor %d", start); - ok("open"); - - /* Make sure highest_fd() works. */ - fd = highest_fd(); - if (start != fd) - fail("highest_fd", "bad descriptor %d != %d", start, fd); - ok("highest_fd"); - - /* Try to use closefrom() for just closing fd 3. */ - closefrom(start + 1); - fd = highest_fd(); - if (fd != start) - fail("closefrom", "highest fd %d", fd); - ok("closefrom"); - - /* Eat up 16 descriptors. */ - for (i = 0; i < 16; i++) - (void)devnull(); - fd = highest_fd(); - if (fd != start + 16) - fail("open 16", "highest fd %d", fd); - ok("open 16"); - - /* Close half of them. */ - closefrom(11); - fd = highest_fd(); - if (fd != 10) - fail("closefrom", "highest fd %d", fd); - ok("closefrom"); - - /* Explicitly close descriptors 6 and 8 to create holes. */ - if (close(6) < 0 || close(8) < 0) - fail_err("close2 "); - ok("close 2"); - - /* Verify that close on 6 and 8 fails with EBADF. */ - if (close(6) == 0) - fail("close(6)", "did not fail"); - if (errno != EBADF) - fail_err("close(6)"); - ok("close(6)"); - if (close(8) == 0) - fail("close(8)", "did not fail"); - if (errno != EBADF) - fail_err("close(8)"); - ok("close(8)"); - - /* Close from 4 on. */ - closefrom(4); - fd = highest_fd(); - if (fd != 3) - fail("closefrom", "highest fd %d", fd); - ok("closefrom"); - - /* Allocate a small SHM region for IPC with our child. */ - info = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_ANON | - MAP_SHARED, -1, 0); - if (info == MAP_FAILED) - fail_err("mmap"); - ok("mmap"); - - /* Fork a child process to test closefrom(0). */ - pid = fork(); - if (pid < 0) - fail_err("fork"); - if (pid == 0) { - /* Child. */ - closefrom(0); - fd = highest_fd(); - if (fd >= 0) - cfail(info, "closefrom(0)", "highest fd %d", fd); - cok(info, "closefrom(0)"); - } - if (wait(NULL) < 0) - fail_err("wait"); - if (info->failed) - fail(info->tag, "%s", info->message); - ok(info->tag); - - /* Fork a child process to test closefrom(-1). */ - pid = fork(); - if (pid < 0) - fail_err("fork"); - if (pid == 0) { - /* Child. */ - closefrom(-1); - fd = highest_fd(); - if (fd >= 0) - cfail(info, "closefrom(-1)", "highest fd %d", fd); - cok(info, "closefrom(-1)"); - } - if (wait(NULL) < 0) - fail_err("wait"); - if (info->failed) - fail(info->tag, "%s", info->message); - ok(info->tag); - - /* Dup stdout to 6. */ - if (dup2(1, 6) < 0) - fail_err("dup2"); - fd = highest_fd(); - if (fd != 6) - fail("dup2", "highest fd %d", fd); - ok("dup2"); - - /* Do a closefrom() starting in a hole. */ - closefrom(4); - fd = highest_fd(); - if (fd != 3) - fail("closefrom", "highest fd %d", fd); - ok("closefrom"); - - /* Do a closefrom() beyond our highest open fd. */ - closefrom(32); - fd = highest_fd(); - if (fd != 3) - fail("closefrom", "highest fd %d", fd); - ok("closefrom"); - - return (0); -} diff --git a/tests/sys/file/dup_test.c b/tests/sys/file/dup_test.c deleted file mode 100644 index 8173818..0000000 --- a/tests/sys/file/dup_test.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * $OpenBSD: dup2test.c,v 1.3 2003/07/31 21:48:08 deraadt Exp $ - * $OpenBSD: dup2_self.c,v 1.3 2003/07/31 21:48:08 deraadt Exp $ - * $OpenBSD: fcntl_dup.c,v 1.2 2003/07/31 21:48:08 deraadt Exp $ - * - * Written by Artur Grabowski <art@openbsd.org> 2002 Public Domain. - * - * $FreeBSD$ - */ - -/* - * Test #1: check if dup(2) works. - * Test #2: check if dup2(2) works. - * Test #3: check if dup2(2) returned a fd we asked for. - * Test #4: check if dup2(2) cleared close-on-exec flag for duped fd. - * Test #5: check if dup2(2) allows to dup fd to itself. - * Test #6: check if dup2(2) returned a fd we asked for. - * Test #7: check if dup2(2) did not clear close-on-exec flag for duped fd. - * Test #8: check if fcntl(F_DUPFD) works. - * Test #9: check if fcntl(F_DUPFD) cleared close-on-exec flag for duped fd. - * Test #10: check if dup2() to a fd > current maximum number of open files - * limit work. - * Test #11: check if fcntl(F_DUP2FD) works. - * Test #12: check if fcntl(F_DUP2FD) returned a fd we asked for. - * Test #13: check if fcntl(F_DUP2FD) cleared close-on-exec flag for duped fd. - * Test #14: check if fcntl(F_DUP2FD) allows to dup fd to itself. - * Test #15: check if fcntl(F_DUP2FD) returned a fd we asked for. - * Test #16: check if fcntl(F_DUP2FD) did not clear close-on-exec flag for - * duped fd. - * Test #17: check if fcntl(F_DUP2FD) to a fd > current maximum number of open - * files limit work. - * Test #18: check if fcntl(F_DUPFD_CLOEXEC) works. - * Test #19: check if fcntl(F_DUPFD_CLOEXEC) set close-on-exec flag for duped - * fd. - * Test #20: check if fcntl(F_DUP2FD_CLOEXEC) works. - * Test #21: check if fcntl(F_DUP2FD_CLOEXEC) returned a fd we asked for. - * Test #22: check if fcntl(F_DUP2FD_CLOEXEC) set close-on-exec flag for duped - * fd. - * Test #23: check if fcntl(F_DUP2FD_CLOEXEC) to a fd > current maximum number - * of open files limit work. - * Test #24: check if dup3(O_CLOEXEC) works. - * Test #25: check if dup3(O_CLOEXEC) returned a fd we asked for. - * Test #26: check if dup3(O_CLOEXEC) set close-on-exec flag for duped fd. - * Test #27: check if dup3(0) works. - * Test #28: check if dup3(0) returned a fd we asked for. - * Test #29: check if dup3(0) cleared close-on-exec flag for duped fd. - * Test #30: check if dup3(O_CLOEXEC) fails if oldfd == newfd. - * Test #31: check if dup3(0) fails if oldfd == newfd. - * Test #32: check if dup3(O_CLOEXEC) to a fd > current maximum number of - * open files limit work. - */ - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/resource.h> - -#include <err.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -static int getafile(void); - -static int -getafile(void) -{ - int fd; - - char temp[] = "/tmp/dup2XXXXXXXXX"; - if ((fd = mkstemp(temp)) < 0) - err(1, "mkstemp"); - remove(temp); - if (ftruncate(fd, 1024) != 0) - err(1, "ftruncate"); - return (fd); -} - -int -main(int __unused argc, char __unused *argv[]) -{ - struct rlimit rlp; - int orgfd, fd1, fd2, test = 0; - - orgfd = getafile(); - - printf("1..32\n"); - - /* If dup(2) ever work? */ - if ((fd1 = dup(orgfd)) < 0) - err(1, "dup"); - printf("ok %d - dup(2) works\n", ++test); - - /* Set close-on-exec */ - if (fcntl(fd1, F_SETFD, 1) != 0) - err(1, "fcntl(F_SETFD)"); - - /* If dup2(2) ever work? */ - if ((fd2 = dup2(fd1, fd1 + 1)) < 0) - err(1, "dup2"); - printf("ok %d - dup2(2) works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1 + 1) - printf("no ok %d - dup2(2) didn't give us the right fd\n", - test); - else - printf("ok %d - dup2(2) returned a correct fd\n", test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) != 0) - printf("not ok %d - dup2(2) didn't clear close-on-exec\n", - test); - else - printf("ok %d - dup2(2) cleared close-on-exec\n", test); - - /* - * Dup to itself. - * - * We're testing a small tweak in dup2 semantics. - * Normally dup and dup2 will clear the close-on-exec - * flag on the new fd (which appears to be an implementation - * mistake from start and not some planned behavior). - * In today's implementations of dup and dup2 we have to make - * an effort to really clear that flag. But all tested - * implementations of dup2 have another tweak. If we - * dup2(old, new) when old == new, the syscall short-circuits - * and returns early (because there is no need to do all the - * work (and there is a risk for serious mistakes)). - * So although the docs say that dup2 should "take 'old', - * close 'new' perform a dup(2) of 'old' into 'new'" - * the docs are not really followed because close-on-exec - * is not cleared on 'new'. - * - * Since everyone has this bug, we pretend that this is - * the way it is supposed to be and test here that it really - * works that way. - * - * This is a fine example on where two separate implementation - * fuckups take out each other and make the end-result the way - * it was meant to be. - */ - if ((fd2 = dup2(fd1, fd1)) < 0) - err(1, "dup2"); - printf("ok %d - dup2(2) to itself works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1) - printf("not ok %d - dup2(2) didn't give us the right fd\n", - test); - else - printf("ok %d - dup2(2) to itself returned a correct fd\n", - test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) == 0) - printf("not ok %d - dup2(2) cleared close-on-exec\n", test); - else - printf("ok %d - dup2(2) didn't clear close-on-exec\n", test); - - /* Does fcntl(F_DUPFD) work? */ - if ((fd2 = fcntl(fd1, F_DUPFD, 10)) < 0) - err(1, "fcntl(F_DUPFD)"); - if (fd2 < 10) - printf("not ok %d - fcntl(F_DUPFD) returned wrong fd %d\n", - ++test, fd2); - else - printf("ok %d - fcntl(F_DUPFD) works\n", ++test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) != 0) - printf( - "not ok %d - fcntl(F_DUPFD) didn't clear close-on-exec\n", - test); - else - printf("ok %d - fcntl(F_DUPFD) cleared close-on-exec\n", test); - - ++test; - if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) - err(1, "getrlimit"); - if ((fd2 = dup2(fd1, rlp.rlim_cur + 1)) >= 0) - printf("not ok %d - dup2(2) bypassed NOFILE limit\n", test); - else - printf("ok %d - dup2(2) didn't bypass NOFILE limit\n", test); - - /* If fcntl(F_DUP2FD) ever work? */ - if ((fd2 = fcntl(fd1, F_DUP2FD, fd1 + 1)) < 0) - err(1, "fcntl(F_DUP2FD)"); - printf("ok %d - fcntl(F_DUP2FD) works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1 + 1) - printf( - "no ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD) returned a correct fd\n", - test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) != 0) - printf( - "not ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n", - test); - - /* Dup to itself */ - if ((fd2 = fcntl(fd1, F_DUP2FD, fd1)) < 0) - err(1, "fcntl(F_DUP2FD)"); - printf("ok %d - fcntl(F_DUP2FD) to itself works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1) - printf( - "not ok %d - fcntl(F_DUP2FD) didn't give us the right fd\n", - test); - else - printf( - "ok %d - fcntl(F_DUP2FD) to itself returned a correct fd\n", - test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) == 0) - printf("not ok %d - fcntl(F_DUP2FD) cleared close-on-exec\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD) didn't clear close-on-exec\n", - test); - - ++test; - if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) - err(1, "getrlimit"); - if ((fd2 = fcntl(fd1, F_DUP2FD, rlp.rlim_cur + 1)) >= 0) - printf("not ok %d - fcntl(F_DUP2FD) bypassed NOFILE limit\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD) didn't bypass NOFILE limit\n", - test); - - /* Does fcntl(F_DUPFD_CLOEXEC) work? */ - if ((fd2 = fcntl(fd1, F_DUPFD_CLOEXEC, 10)) < 0) - err(1, "fcntl(F_DUPFD_CLOEXEC)"); - if (fd2 < 10) - printf("not ok %d - fcntl(F_DUPFD_CLOEXEC) returned wrong fd %d\n", - ++test, fd2); - else - printf("ok %d - fcntl(F_DUPFD_CLOEXEC) works\n", ++test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) != 1) - printf( - "not ok %d - fcntl(F_DUPFD_CLOEXEC) didn't set close-on-exec\n", - test); - else - printf("ok %d - fcntl(F_DUPFD_CLOEXEC) set close-on-exec\n", - test); - - /* If fcntl(F_DUP2FD_CLOEXEC) ever work? */ - if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, fd1 + 1)) < 0) - err(1, "fcntl(F_DUP2FD_CLOEXEC)"); - printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1 + 1) - printf( - "no ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't give us the right fd\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) returned a correct fd\n", - test); - - /* Was close-on-exec set? */ - ++test; - if (fcntl(fd2, F_GETFD) != FD_CLOEXEC) - printf( - "not ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't set close-on-exec\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) set close-on-exec\n", - test); - - /* - * It is unclear what F_DUP2FD_CLOEXEC should do when duplicating a - * file descriptor onto itself. - */ - - ++test; - if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) - err(1, "getrlimit"); - if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, rlp.rlim_cur + 1)) >= 0) - printf("not ok %d - fcntl(F_DUP2FD_CLOEXEC) bypassed NOFILE limit\n", - test); - else - printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't bypass NOFILE limit\n", - test); - - /* Does dup3(O_CLOEXEC) ever work? */ - if ((fd2 = dup3(fd1, fd1 + 1, O_CLOEXEC)) < 0) - err(1, "dup3(O_CLOEXEC)"); - printf("ok %d - dup3(O_CLOEXEC) works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1 + 1) - printf( - "no ok %d - dup3(O_CLOEXEC) didn't give us the right fd\n", - test); - else - printf("ok %d - dup3(O_CLOEXEC) returned a correct fd\n", - test); - - /* Was close-on-exec set? */ - ++test; - if (fcntl(fd2, F_GETFD) != FD_CLOEXEC) - printf( - "not ok %d - dup3(O_CLOEXEC) didn't set close-on-exec\n", - test); - else - printf("ok %d - dup3(O_CLOEXEC) set close-on-exec\n", - test); - - /* Does dup3(0) ever work? */ - if ((fd2 = dup3(fd1, fd1 + 1, 0)) < 0) - err(1, "dup3(0)"); - printf("ok %d - dup3(0) works\n", ++test); - - /* Do we get the right fd? */ - ++test; - if (fd2 != fd1 + 1) - printf( - "no ok %d - dup3(0) didn't give us the right fd\n", - test); - else - printf("ok %d - dup3(0) returned a correct fd\n", - test); - - /* Was close-on-exec cleared? */ - ++test; - if (fcntl(fd2, F_GETFD) != 0) - printf( - "not ok %d - dup3(0) didn't clear close-on-exec\n", - test); - else - printf("ok %d - dup3(0) cleared close-on-exec\n", - test); - - /* dup3() does not allow duplicating to the same fd */ - ++test; - if (dup3(fd1, fd1, O_CLOEXEC) != -1) - printf( - "not ok %d - dup3(fd1, fd1, O_CLOEXEC) succeeded\n", test); - else - printf("ok %d - dup3(fd1, fd1, O_CLOEXEC) failed\n", test); - - ++test; - if (dup3(fd1, fd1, 0) != -1) - printf( - "not ok %d - dup3(fd1, fd1, 0) succeeded\n", test); - else - printf("ok %d - dup3(fd1, fd1, 0) failed\n", test); - - ++test; - if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) - err(1, "getrlimit"); - if ((fd2 = dup3(fd1, rlp.rlim_cur + 1, O_CLOEXEC)) >= 0) - printf("not ok %d - dup3(O_CLOEXEC) bypassed NOFILE limit\n", - test); - else - printf("ok %d - dup3(O_CLOEXEC) didn't bypass NOFILE limit\n", - test); - - return (0); -} diff --git a/tests/sys/file/fcntlflags_test.c b/tests/sys/file/fcntlflags_test.c deleted file mode 100644 index bcb3b54..0000000 --- a/tests/sys/file/fcntlflags_test.c +++ /dev/null @@ -1,110 +0,0 @@ -/*- - * Copyright (c) 2013 Jilles Tjoelker - * 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. - * - * $FreeBSD$ - */ - -#include <sys/cdefs.h> - -#include <fcntl.h> -#include <stdio.h> -#include <unistd.h> - -/* - * O_ACCMODE is currently defined incorrectly. This is what it should be. - * Various code depends on the incorrect value. - */ -#define CORRECT_O_ACCMODE (O_ACCMODE | O_EXEC) - -static int testnum; - -static void -subtests(const char *path, int omode, const char *omodetext) -{ - int fd, flags1, flags2, flags3; - - fd = open(path, omode); - if (fd == -1) - printf("not ok %d - open(\"%s\", %s) failed\n", - testnum++, path, omodetext); - else - printf("ok %d - open(\"%s\", %s) succeeded\n", - testnum++, path, omodetext); - flags1 = fcntl(fd, F_GETFL); - if (flags1 == -1) - printf("not ok %d - fcntl(F_GETFL) failed\n", testnum++); - else if ((flags1 & CORRECT_O_ACCMODE) == omode) - printf("ok %d - fcntl(F_GETFL) gave correct result\n", - testnum++); - else - printf("not ok %d - fcntl(F_GETFL) gave incorrect result " - "(%#x & %#x != %#x)\n", - testnum++, flags1, CORRECT_O_ACCMODE, omode); - if (fcntl(fd, F_SETFL, flags1) == -1) - printf("not ok %d - fcntl(F_SETFL) same flags failed\n", - testnum++); - else - printf("ok %d - fcntl(F_SETFL) same flags succeeded\n", - testnum++); - flags2 = fcntl(fd, F_GETFL); - if (flags2 == -1) - printf("not ok %d - fcntl(F_GETFL) failed\n", testnum++); - else if (flags2 == flags1) - printf("ok %d - fcntl(F_GETFL) gave same result\n", - testnum++); - else - printf("not ok %d - fcntl(F_SETFL) caused fcntl(F_GETFL) to " - "change from %#x to %#x\n", - testnum++, flags1, flags2); - if (fcntl(fd, F_SETFL, flags2 | O_NONBLOCK) == -1) - printf("not ok %d - fcntl(F_SETFL) O_NONBLOCK failed\n", - testnum++); - else - printf("ok %d - fcntl(F_SETFL) O_NONBLOCK succeeded\n", - testnum++); - flags3 = fcntl(fd, F_GETFL); - if (flags3 == -1) - printf("not ok %d - fcntl(F_GETFL) failed\n", testnum++); - else if (flags3 == (flags2 | O_NONBLOCK)) - printf("ok %d - fcntl(F_GETFL) gave expected result\n", - testnum++); - else - printf("not ok %d - fcntl(F_SETFL) gave unexpected result " - "(%#x != %#x)\n", - testnum++, flags3, flags2 | O_NONBLOCK); - (void)close(fd); -} - -int -main(int argc __unused, char **argv __unused) -{ - printf("1..24\n"); - testnum = 1; - subtests("/dev/null", O_RDONLY, "O_RDONLY"); - subtests("/dev/null", O_WRONLY, "O_WRONLY"); - subtests("/dev/null", O_RDWR, "O_RDWR"); - subtests("/bin/sh", O_EXEC, "O_EXEC"); - return (0); -} diff --git a/tests/sys/file/flock_helper.c b/tests/sys/file/flock_helper.c deleted file mode 100644 index 49e47b8..0000000 --- a/tests/sys/file/flock_helper.c +++ /dev/null @@ -1,1598 +0,0 @@ -/*- - * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ - * Authors: Doug Rabson <dfr@rabson.org> - * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE 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. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/file.h> -#include <sys/time.h> -#ifdef __FreeBSD__ -#include <sys/mount.h> -#endif -#include <sys/stat.h> -#include <sys/wait.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#ifdef __FreeBSD__ -#if __FreeBSD_version >= 800028 -#define HAVE_SYSID -#endif -#include <sys/cdefs.h> -#else -#ifndef nitems -#define nitems(x) (sizeof((x)) / sizeof((x)[0])) -#endif - -#ifndef __unused -#ifdef __GNUC__ -#define __unused __attribute__((__unused__)) -#else -#define __unused -#endif -#endif -#endif - -static int verbose = 0; - -static int -make_file(const char *pathname, off_t sz) -{ - struct stat st; - const char *template = "/flocktempXXXXXX"; - size_t len; - char *filename; - int fd; - - if (stat(pathname, &st) == 0) { - if (S_ISREG(st.st_mode)) { - fd = open(pathname, O_RDWR); - if (fd < 0) - err(1, "open(%s)", pathname); - if (ftruncate(fd, sz) < 0) - err(1, "ftruncate"); - return (fd); - } - } - - len = strlen(pathname) + strlen(template) + 1; - filename = malloc(len); - strcpy(filename, pathname); - strcat(filename, template); - fd = mkstemp(filename); - if (fd < 0) - err(1, "mkstemp"); - if (ftruncate(fd, sz) < 0) - err(1, "ftruncate"); - if (unlink(filename) < 0) - err(1, "unlink"); - free(filename); - - return (fd); -} - -static void -ignore_alarm(int __unused sig) -{ -} - -static int -safe_waitpid(pid_t pid) -{ - int save_errno; - int status; - - save_errno = errno; - errno = 0; - while (waitpid(pid, &status, 0) != pid) { - if (errno == EINTR) - continue; - err(1, "waitpid"); - } - errno = save_errno; - - return (status); -} - -#define FAIL(test) \ - do { \ - if (test) { \ - printf("FAIL (%s)\n", #test); \ - return -1; \ - } \ - } while (0) - -#define SUCCEED \ - do { printf("SUCCEED\n"); return 0; } while (0) - -/* - * Test 1 - F_GETLK on unlocked region - * - * If no lock is found that would prevent this lock from being - * created, the structure is left unchanged by this function call - * except for the lock type which is set to F_UNLCK. - */ -static int -test1(int fd, __unused int argc, const __unused char **argv) -{ - struct flock fl1, fl2; - - memset(&fl1, 1, sizeof(fl1)); - fl1.l_type = F_WRLCK; - fl1.l_whence = SEEK_SET; - fl2 = fl1; - - if (fcntl(fd, F_GETLK, &fl1) < 0) - err(1, "F_GETLK"); - - printf("1 - F_GETLK on unlocked region: "); - FAIL(fl1.l_start != fl2.l_start); - FAIL(fl1.l_len != fl2.l_len); - FAIL(fl1.l_pid != fl2.l_pid); - FAIL(fl1.l_type != F_UNLCK); - FAIL(fl1.l_whence != fl2.l_whence); -#ifdef HAVE_SYSID - FAIL(fl1.l_sysid != fl2.l_sysid); -#endif - - SUCCEED; -} - -/* - * Test 2 - F_SETLK on locked region - * - * If a shared or exclusive lock cannot be set, fcntl returns - * immediately with EACCES or EAGAIN. - */ -static int -test2(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should return -1 with errno set to either EACCES or - * EAGAIN. - */ - printf("2 - F_SETLK on locked region: "); - res = fcntl(fd, F_SETLK, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - FAIL(res == 0); - FAIL(errno != EACCES && errno != EAGAIN); - - SUCCEED; -} - -/* - * Test 3 - F_SETLKW on locked region - * - * If a shared or exclusive lock is blocked by other locks, the - * process waits until the request can be satisfied. - * - * XXX this test hangs on FreeBSD NFS filesystems due to limitations - * in FreeBSD's client (and server) lockd implementation. - */ -static int -test3(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("3 - F_SETLKW on locked region: "); - - alarm(1); - - res = fcntl(fd, F_SETLKW, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - FAIL(res == 0); - FAIL(errno != EINTR); - - SUCCEED; -} - -/* - * Test 4 - F_GETLK on locked region - * - * Get the first lock that blocks the lock. - */ -static int -test4(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 99; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should return a lock structure reflecting the lock we - * made in the child process. - */ - if (fcntl(fd, F_GETLK, &fl) < 0) - err(1, "F_GETLK"); - - printf("4 - F_GETLK on locked region: "); - FAIL(fl.l_start != 0); - FAIL(fl.l_len != 99); - FAIL(fl.l_type != F_WRLCK); - FAIL(fl.l_pid != pid); -#ifdef HAVE_SYSID - FAIL(fl.l_sysid != 0); -#endif - - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - SUCCEED; -} - -/* - * Test 5 - F_SETLKW simple deadlock - * - * If a blocking shared lock request would cause a deadlock (i.e. the - * lock request is blocked by a process which is itself blocked on a - * lock currently owned by the process making the new request), - * EDEADLK is returned. - */ -static int -test5(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. Because our test relies on the child process being - * blocked on the parent's lock, we can't easily use a pipe to - * synchronize so we just sleep in the parent to given the - * child a chance to setup. - * - * To create the deadlock condition, we arrange for the parent - * to lock the first byte of the file and the child to lock - * the second byte. After locking the second byte, the child - * will attempt to lock the first byte of the file, and - * block. The parent will then attempt to lock the second byte - * (owned by the child) which should cause deadlock. - */ - int pid; - struct flock fl; - int res; - - /* - * Lock the first byte in the parent. - */ - fl.l_start = 0; - fl.l_len = 1; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK 1 (parent)"); - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * Lock the second byte in the child and then block on - * the parent's lock. - */ - fl.l_start = 1; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - fl.l_start = 0; - if (fcntl(fd, F_SETLKW, &fl) < 0) - err(1, "F_SETLKW (child)"); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - sleep(1); - - /* - * fcntl should immediately return -1 with errno set to - * EDEADLK. If the alarm fires, we failed to detect the - * deadlock. - */ - alarm(1); - printf("5 - F_SETLKW simple deadlock: "); - - fl.l_start = 1; - res = fcntl(fd, F_SETLKW, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - - FAIL(res == 0); - FAIL(errno != EDEADLK); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_UNLCK"); - - /* - * Cancel the alarm to avoid confusing later tests. - */ - alarm(0); - - SUCCEED; -} - -/* - * Test 6 - F_SETLKW complex deadlock. - * - * This test involves three process, P, C1 and C2. We set things up so - * that P locks byte zero, C1 locks byte 1 and C2 locks byte 2. We - * also block C2 by attempting to lock byte zero. Lastly, P attempts - * to lock a range including byte 1 and 2. This represents a deadlock - * (due to C2's blocking attempt to lock byte zero). - */ -static int -test6(int fd, __unused int argc, const __unused char **argv) -{ - /* - * Because our test relies on the child process being blocked - * on the parent's lock, we can't easily use a pipe to - * synchronize so we just sleep in the parent to given the - * children a chance to setup. - */ - int pid1, pid2; - struct flock fl; - int res; - - /* - * Lock the first byte in the parent. - */ - fl.l_start = 0; - fl.l_len = 1; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK 1 (parent)"); - - pid1 = fork(); - if (pid1 < 0) - err(1, "fork"); - - if (pid1 == 0) { - /* - * C1 - * Lock the second byte in the child and then sleep - */ - fl.l_start = 1; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child1)"); - pause(); - exit(0); - } - - pid2 = fork(); - if (pid2 < 0) - err(1, "fork"); - - if (pid2 == 0) { - /* - * C2 - * Lock the third byte in the child and then block on - * the parent's lock. - */ - fl.l_start = 2; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child2)"); - fl.l_start = 0; - if (fcntl(fd, F_SETLKW, &fl) < 0) - err(1, "F_SETLKW (child2)"); - exit(0); - } - - /* - * Wait until the children have set their locks and then - * perform the test. - */ - sleep(1); - - /* - * fcntl should immediately return -1 with errno set to - * EDEADLK. If the alarm fires, we failed to detect the - * deadlock. - */ - alarm(1); - printf("6 - F_SETLKW complex deadlock: "); - - fl.l_start = 1; - fl.l_len = 2; - res = fcntl(fd, F_SETLKW, &fl); - kill(pid1, SIGTERM); - safe_waitpid(pid1); - kill(pid2, SIGTERM); - safe_waitpid(pid2); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_UNLCK"); - - FAIL(res == 0); - FAIL(errno != EDEADLK); - - /* - * Cancel the alarm to avoid confusing later tests. - */ - alarm(0); - - SUCCEED; -} - -/* - * Test 7 - F_SETLK shared lock on exclusive locked region - * - * If a shared or exclusive lock cannot be set, fcntl returns - * immediately with EACCES or EAGAIN. - */ -static int -test7(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("7 - F_SETLK shared lock on exclusive locked region: "); - - fl.l_type = F_RDLCK; - res = fcntl(fd, F_SETLK, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - FAIL(res == 0); - FAIL(errno != EACCES && errno != EAGAIN); - - SUCCEED; -} - -/* - * Test 8 - F_SETLK shared lock on share locked region - * - * When a shared lock is set on a segment of a file, other processes - * shall be able to set shared locks on that segment or a portion of - * it. - */ -static int -test8(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_RDLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("8 - F_SETLK shared lock on share locked region: "); - - fl.l_type = F_RDLCK; - res = fcntl(fd, F_SETLK, &fl); - - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_UNLCK"); - - FAIL(res != 0); - - SUCCEED; -} - -/* - * Test 9 - F_SETLK exclusive lock on share locked region - * - * If a shared or exclusive lock cannot be set, fcntl returns - * immediately with EACCES or EAGAIN. - */ -static int -test9(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_RDLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("9 - F_SETLK exclusive lock on share locked region: "); - - fl.l_type = F_WRLCK; - res = fcntl(fd, F_SETLK, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - FAIL(res == 0); - FAIL(errno != EACCES && errno != EAGAIN); - - SUCCEED; -} - -/* - * Test 10 - trying to set bogus pid or sysid values - * - * The l_pid and l_sysid fields are only used with F_GETLK to return - * the process ID of the process holding a blocking lock and the - * system ID of the system that owns that process - */ -static int -test10(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_pid = 9999; -#ifdef HAVE_SYSID - fl.l_sysid = 9999; -#endif - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - printf("10 - trying to set bogus pid or sysid values: "); - - if (fcntl(fd, F_GETLK, &fl) < 0) - err(1, "F_GETLK"); - - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - FAIL(fl.l_pid != pid); -#ifdef HAVE_SYSID - FAIL(fl.l_sysid != 0); -#endif - - SUCCEED; -} - -/* - * Test 11 - remote locks - * - * XXX temporary interface which will be removed when the kernel lockd - * is added. - */ -static int -test11(int fd, __unused int argc, const __unused char **argv) -{ -#ifdef F_SETLK_REMOTE - struct flock fl; - int res; - - if (geteuid() != 0) - return 0; - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_pid = 9999; - fl.l_sysid = 1001; - - printf("11 - remote locks: "); - - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - fl.l_sysid = 1002; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res == 0); - FAIL(errno != EACCES && errno != EAGAIN); - - res = fcntl(fd, F_GETLK, &fl); - FAIL(res != 0); - FAIL(fl.l_pid != 9999); - FAIL(fl.l_sysid != 1001); - - fl.l_type = F_UNLCK; - fl.l_sysid = 1001; - fl.l_start = 0; - fl.l_len = 0; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - fl.l_pid = 1234; - fl.l_sysid = 1001; - fl.l_start = 0; - fl.l_len = 1; - fl.l_whence = SEEK_SET; - fl.l_type = F_RDLCK; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - fl.l_sysid = 1002; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - fl.l_type = F_UNLCKSYS; - fl.l_sysid = 1001; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - fl.l_type = F_WRLCK; - res = fcntl(fd, F_GETLK, &fl); - FAIL(res != 0); - FAIL(fl.l_pid != 1234); - FAIL(fl.l_sysid != 1002); - - fl.l_type = F_UNLCKSYS; - fl.l_sysid = 1002; - res = fcntl(fd, F_SETLK_REMOTE, &fl); - FAIL(res != 0); - - SUCCEED; -#else - return 0; -#endif -} - -/* - * Test 12 - F_SETLKW on locked region which is then unlocked - * - * If a shared or exclusive lock is blocked by other locks, the - * process waits until the request can be satisfied. - */ -static int -test12(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - - sleep(1); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("12 - F_SETLKW on locked region which is then unlocked: "); - - //alarm(1); - - res = fcntl(fd, F_SETLKW, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - FAIL(res != 0); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_UNLCK"); - - SUCCEED; -} - -/* - * Test 13 - F_SETLKW on locked region, race with owner - * - * If a shared or exclusive lock is blocked by other locks, the - * process waits until the request can be satisfied. - */ -static int -test13(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int i; - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - struct itimerval itv; - - printf("13 - F_SETLKW on locked region, race with owner: "); - fflush(stdout); - - for (i = 0; i < 100; i++) { - if (pipe(pfd) < 0) - err(1, "pipe"); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - - usleep(1); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - while (read(pfd[0], &ch, 1) != 1) { - if (errno == EINTR) - continue; - err(1, "reading from pipe (child)"); - } - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 0; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 2; - setitimer(ITIMER_REAL, &itv, NULL); - - res = fcntl(fd, F_SETLKW, &fl); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - FAIL(!(res == 0 || (res == -1 && errno == EINTR))); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_UNLCK; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "F_UNLCK"); - } - SUCCEED; -} - -/* - * Test 14 - soak test - */ -static int -test14(int fd, int argc, const char **argv) -{ -#define CHILD_COUNT 20 - /* - * We create a set of child processes and let each one run - * through a random sequence of locks and unlocks. - */ - int i, j, id, id_base; - int pids[CHILD_COUNT], pid; - char buf[128]; - char tbuf[128]; - int map[128]; - char outbuf[512]; - struct flock fl; - struct itimerval itv; - int status; - - id_base = 0; - if (argc >= 2) - id_base = strtol(argv[1], NULL, 0); - - printf("14 - soak test: "); - fflush(stdout); - - for (i = 0; i < 128; i++) - map[i] = F_UNLCK; - - for (i = 0; i < CHILD_COUNT; i++) { - - pid = fork(); - if (pid < 0) - err(1, "fork"); - if (pid) { - /* - * Parent - record the pid and continue. - */ - pids[i] = pid; - continue; - } - - /* - * Child - do some work and exit. - */ - id = id_base + i; - srandom(getpid()); - - for (j = 0; j < 50; j++) { - int start, end, len; - int set, wrlock; - - do { - start = random() & 127; - end = random() & 127; - } while (end <= start); - - set = random() & 1; - wrlock = random() & 1; - - len = end - start; - fl.l_start = start; - fl.l_len = len; - fl.l_whence = SEEK_SET; - if (set) - fl.l_type = wrlock ? F_WRLCK : F_RDLCK; - else - fl.l_type = F_UNLCK; - - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 0; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 3000; - setitimer(ITIMER_REAL, &itv, NULL); - - if (fcntl(fd, F_SETLKW, &fl) < 0) { - if (errno == EDEADLK || errno == EINTR) { - if (verbose) { - snprintf(outbuf, sizeof(outbuf), - "%d[%d]: %s [%d .. %d] %s\n", - id, j, - set ? (wrlock ? "write lock" - : "read lock") - : "unlock", start, end, - errno == EDEADLK - ? "deadlock" - : "interrupted"); - write(1, outbuf, - strlen(outbuf)); - } - continue; - } else { - perror("fcntl"); - } - } - - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 0; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &itv, NULL); - - if (verbose) { - snprintf(outbuf, sizeof(outbuf), - "%d[%d]: %s [%d .. %d] succeeded\n", - id, j, - set ? (wrlock ? "write lock" : "read lock") - : "unlock", start, end); - write(1, outbuf, strlen(outbuf)); - } - - if (set) { - if (wrlock) { - /* - * We got a write lock - write - * our ID to each byte that we - * managed to claim. - */ - for (i = start; i < end; i++) - map[i] = F_WRLCK; - memset(&buf[start], id, len); - if (pwrite(fd, &buf[start], len, - start) != len) { - printf("%d: short write\n", id); - exit(1); - } - } else { - /* - * We got a read lock - read - * the bytes which we claimed - * so that we can check that - * they don't change - * unexpectedly. - */ - for (i = start; i < end; i++) - map[i] = F_RDLCK; - if (pread(fd, &buf[start], len, - start) != len) { - printf("%d: short read\n", id); - exit(1); - } - } - } else { - for (i = start; i < end; i++) - map[i] = F_UNLCK; - } - - usleep(1000); - - /* - * Read back the whole region so that we can - * check that all the bytes we have some kind - * of claim to have the correct value. - */ - if (pread(fd, tbuf, sizeof(tbuf), 0) != sizeof(tbuf)) { - printf("%d: short read\n", id); - exit(1); - } - - for (i = 0; i < 128; i++) { - if (map[i] != F_UNLCK && buf[i] != tbuf[i]) { - snprintf(outbuf, sizeof(outbuf), - "%d: byte %d expected %d, " - "got %d\n", id, i, buf[i], tbuf[i]); - write(1, outbuf, strlen(outbuf)); - exit(1); - } - } - } - if (verbose) - printf("%d[%d]: done\n", id, j); - - exit(0); - } - - status = 0; - for (i = 0; i < CHILD_COUNT; i++) { - status += safe_waitpid(pids[i]); - } - if (status) - FAIL(status != 0); - - SUCCEED; -} - -/* - * Test 15 - flock(2) semantcs - * - * When a lock holder has a shared lock and attempts to upgrade that - * shared lock to exclusive, it must drop the shared lock before - * blocking on the exclusive lock. - * - * To test this, we first arrange for two shared locks on the file, - * and then attempt to upgrade one of them to exclusive. This should - * drop one of the shared locks and block. We interrupt the blocking - * lock request and examine the lock state of the file after dropping - * the other shared lock - there should be no active locks at this - * point. - */ -static int -test15(int fd, __unused int argc, const __unused char **argv) -{ -#ifdef LOCK_EX - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - * - * Since we only have one file descriptors and lock ownership - * for flock(2) goes with the file descriptor, we use fcntl to - * set the child's shared lock. - */ - int pid; - int pfd[2]; - struct flock fl; - char ch; - int res; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a shared lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_RDLCK; - fl.l_whence = SEEK_SET; - if (fcntl(fd, F_SETLK, &fl) < 0) - err(1, "fcntl(F_SETLK) (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - (void)dup(fd); - if (flock(fd, LOCK_SH) < 0) - err(1, "flock shared"); - - /* - * flock should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("15 - flock(2) semantics: "); - - alarm(1); - flock(fd, LOCK_EX); - - /* - * Kill the child to force it to drop its locks. - */ - kill(pid, SIGTERM); - safe_waitpid(pid); - - fl.l_start = 0; - fl.l_len = 0; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - res = fcntl(fd, F_GETLK, &fl); - - close(pfd[0]); - close(pfd[1]); - FAIL(res != 0); - FAIL(fl.l_type != F_UNLCK); - - SUCCEED; -#else - return 0; -#endif -} - -struct test_ctx { - struct flock tc_fl; - int tc_fd; -}; - -static void * -test16_func(void *tc_in) -{ - uintptr_t error; - struct test_ctx *tc = tc_in; - - error = fcntl(tc->tc_fd, F_SETLKW, &tc->tc_fl); - - pthread_exit((void *)error); -} - -#define THREADS 10 - -/* - * Test 16 - F_SETLKW from two threads - * - * If two threads within a process are blocked on a lock and the lock - * is granted, make sure things are sane. - */ -static int -test16(int fd, __unused int argc, const __unused char **argv) -{ - /* - * We create a child process to hold the lock which we will - * test. We use a pipe to communicate with the child. - */ - int pid; - int pfd[2]; - struct test_ctx tc = { .tc_fd = fd }; - char ch; - int i; - int error; - pthread_t thr[THREADS]; - - if (pipe(pfd) < 0) - err(1, "pipe"); - - tc.tc_fl.l_start = 0; - tc.tc_fl.l_len = 0; - tc.tc_fl.l_type = F_WRLCK; - tc.tc_fl.l_whence = SEEK_SET; - - pid = fork(); - if (pid < 0) - err(1, "fork"); - - if (pid == 0) { - /* - * We are the child. We set a write lock and then - * write one byte back to the parent to tell it. The - * parent will kill us when its done. - */ - if (fcntl(fd, F_SETLK, &tc.tc_fl) < 0) - err(1, "F_SETLK (child)"); - if (write(pfd[1], "a", 1) < 0) - err(1, "writing to pipe (child)"); - pause(); - exit(0); - } - - /* - * Wait until the child has set its lock and then perform the - * test. - */ - if (read(pfd[0], &ch, 1) != 1) - err(1, "reading from pipe (child)"); - - /* - * fcntl should wait until the alarm and then return -1 with - * errno set to EINTR. - */ - printf("16 - F_SETLKW on locked region by two threads: "); - - for (i = 0; i < THREADS; i++) { - error = pthread_create(&thr[i], NULL, test16_func, &tc); - if (error) - err(1, "pthread_create"); - } - - /* - * Sleep, then kill the child. This makes me a little sad, but it's - * tricky to tell whether the threads are all really blocked by this - * point. - */ - sleep(1); - kill(pid, SIGTERM); - safe_waitpid(pid); - close(pfd[0]); - close(pfd[1]); - - for (i = 0; i < THREADS; i++) { - void *res; - error = pthread_join(thr[i], &res); - if (error) - err(1, "pthread_join"); - FAIL((uintptr_t)res != 0); - } - - SUCCEED; -} - -struct test { - int (*testfn)(int, int, const char **); /* function to perform the test */ - int num; /* test number */ - int intr; /* non-zero if the test interrupts a lock */ -}; - -static struct test tests[] = { - { test1, 1, 0 }, - { test2, 2, 0 }, - { test3, 3, 1 }, - { test4, 4, 0 }, - { test5, 5, 1 }, - { test6, 6, 1 }, - { test7, 7, 0 }, - { test8, 8, 0 }, - { test9, 9, 0 }, - { test10, 10, 0 }, - { test11, 11, 1 }, - { test12, 12, 0 }, - { test13, 13, 1 }, - { test14, 14, 0 }, - { test15, 15, 1 }, - { test16, 16, 1 }, -}; - -int -main(int argc, const char *argv[]) -{ - int testnum; - int fd; - int nointr; - unsigned i; - struct sigaction sa; - int test_argc; - const char **test_argv; - - if (argc < 2) { - errx(1, "usage: flock <directory> [test number] ..."); - } - - fd = make_file(argv[1], 1024); - if (argc >= 3) { - testnum = strtol(argv[2], NULL, 0); - test_argc = argc - 2; - test_argv = argv + 2; - } else { - testnum = 0; - test_argc = 0; - test_argv = 0; - } - - sa.sa_handler = ignore_alarm; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigaction(SIGALRM, &sa, 0); - - nointr = 0; -#if defined(__FreeBSD__) && __FreeBSD_version < 800040 - { - /* - * FreeBSD with userland NLM can't interrupt a blocked - * lock request on an NFS mounted filesystem. - */ - struct statfs st; - fstatfs(fd, &st); - nointr = !strcmp(st.f_fstypename, "nfs"); - } -#endif - - for (i = 0; i < nitems(tests); i++) { - if (tests[i].intr && nointr) - continue; - if (!testnum || tests[i].num == testnum) - tests[i].testfn(fd, test_argc, test_argv); - } - - return 0; -} diff --git a/tests/sys/file/flock_test.sh b/tests/sys/file/flock_test.sh deleted file mode 100755 index ac3e799..0000000 --- a/tests/sys/file/flock_test.sh +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/sh -# -# Copyright 2014 EMC Corp. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * 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. -# * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT -# OWNER 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. -# -# $FreeBSD$ - -# Testcase # 11 is racy; uses an undocumented kernel interface for testing -# locking -# Testcase # 16 is racy/doesn't handle EINTR properly -last_testcase=16 - -echo "1..$last_testcase" - -for n in `seq 1 $last_testcase`; do - todomsg="" - - if [ $n -eq 11 ]; then - todomsg=" # TODO: racy testcase" - # Test 16 fails: - # F_SETLKW on locked region by two threads: FAIL ((uintptr_t)res != 0) - elif [ $n -eq 16 ]; then - todomsg=" # TODO: racy testcase (doesn't handle EINTR properly)" - fi - - $(dirname $0)/flock_helper . $n | grep -q SUCCEED - if [ $? -eq 0 ]; then - echo "ok $n$todomsg" - else - echo "not ok $n$todomsg" - fi -done diff --git a/tests/sys/file/ftruncate_test.c b/tests/sys/file/ftruncate_test.c deleted file mode 100644 index 7eaba14..0000000 --- a/tests/sys/file/ftruncate_test.c +++ /dev/null @@ -1,177 +0,0 @@ -/*- - * Copyright (c) 2006 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -/* - * Very simple regression test. - * - * Future tests that might be of interest: - * - * - Make sure we get EISDIR on a directory. - */ - -#include <sys/types.h> -#include <sys/event.h> -#include <sys/socket.h> -#include <sys/stat.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <limits.h> -#include <stdio.h> -#include <unistd.h> - -/* - * Select various potentially interesting lengths at and around power of 2 - * edges. - */ -static off_t lengths[] = {0, 1, 2, 3, 4, 127, 128, 129, 511, 512, 513, 1023, - 1024, 1025, 2047, 2048, 2049, 4095, 4096, 4097, 8191, 8192, 8193, 16383, - 16384, 16385}; -static int lengths_count = sizeof(lengths) / sizeof(off_t); - -int -main(int argc, char *argv[]) -{ - int error, fd, fds[2], i, read_only_fd; - char path[PATH_MAX]; - struct stat sb; - ssize_t size; - off_t len; - char ch; - - /* - * Tests using a writable temporary file: grow and then shrink a file - * using ftruncate and various lengths. Make sure that a negative - * file length is rejected. Make sure that when we grow the file, - * bytes now in the range of the file size return 0. - * - * Save a read-only reference to the file to use later for read-only - * descriptor tests. - */ - snprintf(path, PATH_MAX, "/tmp/ftruncate.XXXXXXXXXXXXX"); - fd = mkstemp(path); - if (fd < 0) - err(-1, "mkstemp"); - read_only_fd = open(path, O_RDONLY); - if (read_only_fd < 0) { - error = errno; - (void)unlink(path); - errno = error; - err(-1, "open(%s, O_RDONLY)", path); - } - (void)unlink(path); - - if (ftruncate(fd, -1) == 0) - errx(-1, "ftruncate(fd, -1) succeeded"); - if (errno != EINVAL) - err(-1, "ftruncate(fd, -1) returned wrong error"); - - for (i = 0; i < lengths_count; i++) { - len = lengths[i]; - if (ftruncate(fd, len) < 0) - err(-1, "ftruncate(%jd) up", (intmax_t)len); - if (fstat(fd, &sb) < 0) - err(-1, "stat"); - if (sb.st_size != len) - errx(-1, "fstat with len=%jd returned len %jd up", - (intmax_t)len, (intmax_t)sb.st_size); - if (len != 0) { - size = pread(fd, &ch, sizeof(ch), len - 1); - if (size < 0) - err(-1, "pread on len %jd up", (intmax_t)len); - if (size != sizeof(ch)) - errx(-1, "pread len %jd size %jd up", - (intmax_t)len, (intmax_t)size); - if (ch != 0) - errx(-1, - "pread length %jd size %jd ch %d up", - (intmax_t)len, (intmax_t)size, ch); - } - } - - for (i = lengths_count - 1; i >= 0; i--) { - len = lengths[i]; - if (ftruncate(fd, len) < 0) - err(-1, "ftruncate(%jd) down", (intmax_t)len); - if (fstat(fd, &sb) < 0) - err(-1, "stat"); - if (sb.st_size != len) - errx(-1, "fstat(%jd) returned %jd down", (intmax_t)len, - sb.st_size); - } - close(fd); - - /* - * Make sure that a read-only descriptor can't be truncated. - */ - if (ftruncate(read_only_fd, 0) == 0) - errx(-1, "ftruncate(read_only_fd) succeeded"); - if (errno != EINVAL) - err(-1, "ftruncate(read_only_fd) returned wrong error"); - close(read_only_fd); - - /* - * Make sure that ftruncate on sockets doesn't work. - */ - fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (fd < 0) - err(-1, "socket(PF_UNIX, SOCK_STREAM, 0)"); - if (ftruncate(fd, 0) == 0) - errx(-1, "ftruncate(socket) succeeded"); - if (errno != EINVAL) - err(-1, "ftruncate(socket) returned wrong error"); - close(fd); - - /* - * Make sure that ftruncate on pipes doesn't work. - */ - if (pipe(fds) < 0) - err(-1, "pipe"); - if (ftruncate(fds[0], 0) == 0) - errx(-1, "ftruncate(pipe) succeeded"); - if (errno != EINVAL) - err(-1, "ftruncate(pipe) returned wrong error"); - close(fds[0]); - close(fds[1]); - - /* - * Make sure that ftruncate on kqueues doesn't work. - */ - fd = kqueue(); - if (fd < 0) - err(-1, "kqueue"); - if (ftruncate(fds[0], 0) == 0) - errx(-1, "ftruncate(kqueue) succeeded"); - if (errno != EINVAL) - err(-1, "ftruncate(kqueue) returned wrong error"); - close(fd); - - return (0); -} diff --git a/tests/sys/file/newfileops_on_fork_test.c b/tests/sys/file/newfileops_on_fork_test.c deleted file mode 100644 index 8713a82..0000000 --- a/tests/sys/file/newfileops_on_fork_test.c +++ /dev/null @@ -1,121 +0,0 @@ -/*- - * Copyright (c) 2009 Robert N. M. Watson - * All rights reserved. - * - * This software was developed at the University of Cambridge Computer - * Laboratory with support from a grant from Google, Inc. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * When a multi-threaded application calls fork(2) from one thread while - * another thread is blocked in accept(2), we prefer that the file descriptor - * to be returned by accept(2) not appear in the child process. Test this by - * creating a thread blocked in accept(2), then forking a child and seeing if - * the fd it would have returned is defined in the child or not. - */ - -#include <sys/socket.h> -#include <sys/wait.h> - -#include <netinet/in.h> - -#include <err.h> -#include <errno.h> -#include <pthread.h> -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#define PORT 9000 - -static int listen_fd; - -static void * -do_accept(__unused void *arg) -{ - int accept_fd; - - accept_fd = accept(listen_fd, NULL, NULL); - if (accept_fd < 0) - err(-1, "accept"); - - return (NULL); -} - -static void -do_fork(void) -{ - int pid; - - pid = fork(); - if (pid < 0) - err(-1, "fork"); - if (pid > 0) { - waitpid(pid, NULL, 0); - exit(0); - } - - /* - * We will call ftruncate(2) on the next available file descriptor, - * listen_fd+1, and get back EBADF if it's not a valid descriptor, - * and EINVAL if it is. This (currently) works fine in practice. - */ - if (ftruncate(listen_fd + 1, 0 < 0)) { - if (errno == EBADF) - exit(0); - else if (errno == EINVAL) - errx(-1, "file descriptor still open in child"); - else - err(-1, "unexpected error"); - } else - errx(-1, "ftruncate succeeded"); -} - -int -main(__unused int argc, __unused char *argv[]) -{ - struct sockaddr_in sin; - pthread_t accept_thread; - - listen_fd = socket(PF_INET, SOCK_STREAM, 0); - if (listen_fd < 0) - err(-1, "socket"); - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_len = sizeof(sin); - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(PORT); - if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) - err(-1, "bind"); - if (listen(listen_fd, -1) <0) - err(-1, "listen"); - if (pthread_create(&accept_thread, NULL, do_accept, NULL) != 0) - err(-1, "pthread_create"); - sleep(1); /* Easier than using a CV. */; - do_fork(); - exit(0); -} diff --git a/tests/sys/kqueue/Makefile b/tests/sys/kqueue/Makefile deleted file mode 100644 index 43277ca..0000000 --- a/tests/sys/kqueue/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# $FreeBSD$ -# -# svn://mark.heily.com/libkqueue/trunk/test -# Last update: r114 -# -# libkqueue and test suite by Mark Heily <mark@heily.com> -# - -TAP_TESTS_SH= kqueue_test - -TESTSDIR= ${TESTSBASE}/sys/kqueue -BINDIR= ${TESTSDIR} - -PROGS= kqtest - -SRCS.kqtest= \ - main.c \ - read.c \ - timer.c \ - vnode.c \ - proc.c \ - signal.c \ - user.c -WARNS?= 2 - -.include <bsd.test.mk> diff --git a/tests/sys/kqueue/common.h b/tests/sys/kqueue/common.h deleted file mode 100644 index aada778..0000000 --- a/tests/sys/kqueue/common.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily <mark@heily.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#ifndef _COMMON_H -#define _COMMON_H - - -#if HAVE_ERR_H -# include <err.h> -#else -# define err(rc,msg,...) do { perror(msg); exit(rc); } while (0) -# define errx(rc,msg,...) do { puts(msg); exit(rc); } while (0) -#endif -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <stdint.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> - -#include <sys/event.h> - -#include "config.h" - -extern char *cur_test_id; -int vnode_fd; - -extern const char * kevent_to_str(struct kevent *); -struct kevent * kevent_get(int); - - -void kevent_cmp(struct kevent *, struct kevent *); - -void -kevent_add(int kqfd, struct kevent *kev, - uintptr_t ident, - short filter, - u_short flags, - u_int fflags, - intptr_t data, - void *udata); - -/* DEPRECATED: */ -#define KEV_CMP(kev,_ident,_filter,_flags) do { \ - if (kev.ident != (_ident) || \ - kev.filter != (_filter) || \ - kev.flags != (_flags)) \ - err(1, "kevent mismatch: got [%d,%d,%d] but expecting [%d,%d,%d]", \ - (int)_ident, (int)_filter, (int)_flags,\ - (int)kev.ident, kev.filter, kev.flags);\ -} while (0); - -/* Checks if any events are pending, which is an error. */ -extern void test_no_kevents(void); - -extern void test_begin(const char *); -extern void success(void); - -#endif /* _COMMON_H */ diff --git a/tests/sys/kqueue/config.h b/tests/sys/kqueue/config.h deleted file mode 100644 index a204092..0000000 --- a/tests/sys/kqueue/config.h +++ /dev/null @@ -1,13 +0,0 @@ -/* $FreeBSD$ */ - -#define HAVE_ERR_H 1 -#define HAVE_SYS_EVENT_H 1 -#define HAVE_EV_DISPATCH 1 -#define HAVE_EV_RECEIPT 1 -#undef HAVE_NOTE_TRUNCATE -#define HAVE_EVFILT_TIMER 1 -#define HAVE_EVFILT_USER 1 -#define PROGRAM "libkqueue-test" -#define VERSION "0.1" -#define TARGET "freebsd" -#define CFLAGS "-g -O0 -Wall -Werror" diff --git a/tests/sys/kqueue/kqueue_test.sh b/tests/sys/kqueue/kqueue_test.sh deleted file mode 100755 index 62a7e23..0000000 --- a/tests/sys/kqueue/kqueue_test.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -cd $(dirname $0) -i=1 -./kqtest | while read line; do - echo $line | grep -q passed - if [ $? -eq 0 ]; then - echo "ok - $i $line" - : $(( i += 1 )) - fi - - echo $line | grep -q 'tests completed' - if [ $? -eq 0 ]; then - echo -n "1.." - echo $line | cut -d' ' -f3 - fi -done diff --git a/tests/sys/kqueue/main.c b/tests/sys/kqueue/main.c deleted file mode 100644 index f76c4e2..0000000 --- a/tests/sys/kqueue/main.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily <mark@heily.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#include <sys/types.h> - -#include "config.h" -#include "common.h" - -int testnum = 1; -char *cur_test_id = NULL; -int kqfd; - -extern void test_evfilt_read(); -extern void test_evfilt_signal(); -extern void test_evfilt_vnode(); -extern void test_evfilt_timer(); -extern void test_evfilt_proc(); -#if HAVE_EVFILT_USER -extern void test_evfilt_user(); -#endif - -/* Checks if any events are pending, which is an error. */ -void -test_no_kevents(void) -{ - int nfds; - struct timespec timeo; - struct kevent kev; - - puts("confirming that there are no events pending"); - memset(&timeo, 0, sizeof(timeo)); - nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo); - if (nfds != 0) { - puts("\nUnexpected event:"); - puts(kevent_to_str(&kev)); - errx(1, "%d event(s) pending, but none expected:", nfds); - } -} - -/* Retrieve a single kevent */ -struct kevent * -kevent_get(int kqfd) -{ - int nfds; - struct kevent *kev; - - if ((kev = calloc(1, sizeof(*kev))) == NULL) - err(1, "out of memory"); - - nfds = kevent(kqfd, NULL, 0, kev, 1, NULL); - if (nfds < 1) - err(1, "kevent(2)"); - - return (kev); -} - -char * -kevent_fflags_dump(struct kevent *kev) -{ - char *buf; - -#define KEVFFL_DUMP(attrib) \ - if (kev->fflags & attrib) \ - strncat(buf, #attrib" ", 64); - - if ((buf = calloc(1, 1024)) == NULL) - abort(); - - /* Not every filter has meaningful fflags */ - if (kev->filter != EVFILT_VNODE) { - snprintf(buf, 1024, "fflags = %d", kev->fflags); - return (buf); - } - - snprintf(buf, 1024, "fflags = %d (", kev->fflags); - KEVFFL_DUMP(NOTE_DELETE); - KEVFFL_DUMP(NOTE_WRITE); - KEVFFL_DUMP(NOTE_EXTEND); -#if HAVE_NOTE_TRUNCATE - KEVFFL_DUMP(NOTE_TRUNCATE); -#endif - KEVFFL_DUMP(NOTE_ATTRIB); - KEVFFL_DUMP(NOTE_LINK); - KEVFFL_DUMP(NOTE_RENAME); -#if HAVE_NOTE_REVOKE - KEVFFL_DUMP(NOTE_REVOKE); -#endif - buf[strlen(buf) - 1] = ')'; - - return (buf); -} - -char * -kevent_flags_dump(struct kevent *kev) -{ - char *buf; - -#define KEVFL_DUMP(attrib) \ - if (kev->flags & attrib) \ - strncat(buf, #attrib" ", 64); - - if ((buf = calloc(1, 1024)) == NULL) - abort(); - - snprintf(buf, 1024, "flags = %d (", kev->flags); - KEVFL_DUMP(EV_ADD); - KEVFL_DUMP(EV_ENABLE); - KEVFL_DUMP(EV_DISABLE); - KEVFL_DUMP(EV_DELETE); - KEVFL_DUMP(EV_ONESHOT); - KEVFL_DUMP(EV_CLEAR); - KEVFL_DUMP(EV_EOF); - KEVFL_DUMP(EV_ERROR); -#if HAVE_EV_DISPATCH - KEVFL_DUMP(EV_DISPATCH); -#endif -#if HAVE_EV_RECEIPT - KEVFL_DUMP(EV_RECEIPT); -#endif - buf[strlen(buf) - 1] = ')'; - - return (buf); -} - -/* Copied from ../kevent.c kevent_dump() and improved */ -const char * -kevent_to_str(struct kevent *kev) -{ - char buf[512]; - - snprintf(&buf[0], sizeof(buf), - "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]", - (u_int) kev->ident, - kev->filter, - kevent_flags_dump(kev), - kevent_fflags_dump(kev), - (int) kev->data, - kev->udata); - - return (strdup(buf)); -} - -void -kevent_add(int kqfd, struct kevent *kev, - uintptr_t ident, - short filter, - u_short flags, - u_int fflags, - intptr_t data, - void *udata) -{ - EV_SET(kev, ident, filter, flags, fflags, data, NULL); - if (kevent(kqfd, kev, 1, NULL, 0, NULL) < 0) { - printf("Unable to add the following kevent:\n%s\n", - kevent_to_str(kev)); - err(1, "kevent(): %s", strerror(errno)); - } -} - -void -kevent_cmp(struct kevent *k1, struct kevent *k2) -{ -/* XXX- - Workaround for inconsistent implementation of kevent(2) - */ -#ifdef __FreeBSD__ - if (k1->flags & EV_ADD) - k2->flags |= EV_ADD; -#endif - if (memcmp(k1, k2, sizeof(*k1)) != 0) { - printf("kevent_cmp: mismatch:\n %s !=\n %s\n", - kevent_to_str(k1), kevent_to_str(k2)); - abort(); - } -} - -void -test_begin(const char *func) -{ - if (cur_test_id) - free(cur_test_id); - cur_test_id = strdup(func); - if (!cur_test_id) - err(1, "strdup failed"); - - printf("\n\nTest %d: %s\n", testnum++, func); -} - -void -success(void) -{ - printf("%-70s %s\n", cur_test_id, "passed"); - free(cur_test_id); - cur_test_id = NULL; -} - -void -test_kqueue(void) -{ - test_begin("kqueue()"); - if ((kqfd = kqueue()) < 0) - err(1, "kqueue()"); - test_no_kevents(); - success(); -} - -void -test_kqueue_close(void) -{ - test_begin("close(kq)"); - if (close(kqfd) < 0) - err(1, "close()"); - success(); -} - -int -main(int argc, char **argv) -{ - int test_proc = 1; - int test_socket = 1; - int test_signal = 1; - int test_vnode = 1; - int test_timer = 1; -#ifdef __FreeBSD__ - int test_user = 1; -#else - /* XXX-FIXME temporary */ - int test_user = 0; -#endif - - while (argc) { - if (strcmp(argv[0], "--no-proc") == 0) - test_proc = 0; - if (strcmp(argv[0], "--no-socket") == 0) - test_socket = 0; - if (strcmp(argv[0], "--no-timer") == 0) - test_timer = 0; - if (strcmp(argv[0], "--no-signal") == 0) - test_signal = 0; - if (strcmp(argv[0], "--no-vnode") == 0) - test_vnode = 0; - if (strcmp(argv[0], "--no-user") == 0) - test_user = 0; - argv++; - argc--; - } - - test_kqueue(); - test_kqueue_close(); - - if (test_socket) - test_evfilt_read(); - if (test_signal) - test_evfilt_signal(); - if (test_vnode) - test_evfilt_vnode(); -#if HAVE_EVFILT_USER - if (test_user) - test_evfilt_user(); -#endif - if (test_timer) - test_evfilt_timer(); - if (test_proc) - test_evfilt_proc(); - - printf("\n---\n" - "+OK All %d tests completed.\n", testnum - 1); - return (0); -} diff --git a/tests/sys/kqueue/proc.c b/tests/sys/kqueue/proc.c deleted file mode 100644 index 6288ee6..0000000 --- a/tests/sys/kqueue/proc.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily <mark@heily.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#include <sys/stat.h> - -#include <err.h> - -#include "config.h" -#include "common.h" - -static int sigusr1_caught = 0; - -int kqfd; - -static void -sig_handler(int signum) -{ - sigusr1_caught = 1; -} - -static void -add_and_delete(void) -{ - struct kevent kev; - pid_t pid; - - /* Create a child that waits to be killed and then exits */ - pid = fork(); - if (pid == 0) { - struct stat s; - if (fstat(kqfd, &s) != -1) - errx(1, "kqueue inherited across fork! (%s() at %s:%d)", - __func__, __FILE__, __LINE__); - - pause(); - exit(2); - } - printf(" -- child created (pid %d)\n", (int) pid); - - test_begin("kevent(EVFILT_PROC, EV_ADD)"); - - test_no_kevents(); - kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL); - test_no_kevents(); - - success(); - - test_begin("kevent(EVFILT_PROC, EV_DELETE)"); - - sleep(1); - test_no_kevents(); - kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_DELETE, 0, 0, NULL); - if (kill(pid, SIGKILL) < 0) - err(1, "kill"); - sleep(1); - test_no_kevents(); - - success(); - -} - -#ifdef TODO -static void -event_trigger(void) -{ - struct kevent kev; - pid_t pid; - - test_begin("kevent(EVFILT_PROC, wait)"); - - /* Create a child that waits to be killed and then exits */ - pid = fork(); - if (pid == 0) { - pause(); - printf(" -- child caught signal, exiting\n"); - exit(2); - } - printf(" -- child created (pid %d)\n", (int) pid); - - test_no_kevents(); - kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL); - - /* Cause the child to exit, then retrieve the event */ - printf(" -- killing process %d\n", (int) pid); - if (kill(pid, SIGUSR1) < 0) - err(1, "kill"); - kevent_cmp(&kev, kevent_get(kqfd)); - test_no_kevents(); - - success(); -} - -void -test_kevent_signal_disable(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGKILL) < 0) - err(1, "kill"); - - test_no_kevents(); - - success(); -} - -void -test_kevent_signal_enable(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - kev.flags = EV_ADD | EV_CLEAR; -#if LIBKQUEUE - kev.data = 1; /* WORKAROUND */ -#else - kev.data = 2; // one extra time from test_kevent_signal_disable() -#endif - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Delete the watch */ - kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_kevent_signal_del(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - /* Delete the kevent */ - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - test_no_kevents(); - success(); -} - -void -test_kevent_signal_oneshot(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - kev.flags |= EV_CLEAR; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Send another one and make sure we get no events */ - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - test_no_kevents(); - - success(); -} -#endif - -void -test_evfilt_proc() -{ - kqfd = kqueue(); - - signal(SIGUSR1, sig_handler); - - add_and_delete(); - -#if TODO - event_trigger(); -#endif - - signal(SIGUSR1, SIG_DFL); - -#if TODO - test_kevent_signal_add(); - test_kevent_signal_del(); - test_kevent_signal_get(); - test_kevent_signal_disable(); - test_kevent_signal_enable(); - test_kevent_signal_oneshot(); -#endif - close(kqfd); -} diff --git a/tests/sys/kqueue/read.c b/tests/sys/kqueue/read.c deleted file mode 100644 index cc65427..0000000 --- a/tests/sys/kqueue/read.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily <mark@heily.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#include "common.h" - -int kqfd; -int sockfd[2]; - -static void -kevent_socket_drain(void) -{ - char buf[1]; - - /* Drain the read buffer, then make sure there are no more events. */ - puts("draining the read buffer"); - if (read(sockfd[0], &buf[0], 1) < 1) - err(1, "read(2)"); -} - -static void -kevent_socket_fill(void) -{ - puts("filling the read buffer"); - if (write(sockfd[1], ".", 1) < 1) - err(1, "write(2)"); -} - - -void -test_kevent_socket_add(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_ADD)"; - struct kevent kev; - - test_begin(test_id); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_kevent_socket_get(void) -{ - const char *test_id = "kevent(EVFILT_READ) wait"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - kevent_socket_drain(); - test_no_kevents(); - - kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_kevent_socket_clear(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_CLEAR)"; - struct kevent kev; - - test_begin(test_id); - - test_no_kevents(); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - kevent_socket_fill(); - - kev.data = 2; - kevent_cmp(&kev, kevent_get(kqfd)); - - /* We filled twice, but drain once. Edge-triggered would not generate - additional events. - */ - kevent_socket_drain(); - test_no_kevents(); - - kevent_socket_drain(); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_kevent_socket_disable_and_enable(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_DISABLE)"; - struct kevent kev; - - test_begin(test_id); - - /* Add an event, then disable it. */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DISABLE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - test_no_kevents(); - - /* Re-enable the knote, then see if an event is generated */ - kev.flags = EV_ENABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - kev.flags = EV_ADD; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - kevent_socket_drain(); - - kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_kevent_socket_del(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_fill(); - test_no_kevents(); - kevent_socket_drain(); - - success(); -} - -void -test_kevent_socket_oneshot(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_ONESHOT)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - puts("-- re-adding knote"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - puts("-- getting one event"); - kevent_socket_fill(); - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - puts("-- checking knote disabled"); - test_no_kevents(); - - /* Try to delete the knote, it should already be deleted */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == 0) - err(1, "%s", test_id); - - kevent_socket_drain(); - - success(); -} - - -#if HAVE_EV_DISPATCH -void -test_kevent_socket_dispatch(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_DISPATCH)"; - - test_begin(test_id); - - struct kevent kev; - - /* Re-add the watch and make sure no events are pending */ - puts("-- re-adding knote"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_DISPATCH, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - /* The event will occur only once, even though EV_CLEAR is not - specified. */ - kevent_socket_fill(); - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - test_no_kevents(); - - /* Since the knote is disabled, the EV_DELETE operation succeeds. */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kevent_socket_drain(); - - success(); -} -#endif /* HAVE_EV_DISPATCH */ - -#if BROKEN -void -test_kevent_socket_lowat(void) -{ - const char *test_id = "kevent(EVFILT_READ, NOTE_LOWAT)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - puts("-- re-adding knote, setting low watermark to 2 bytes"); - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD | EV_ONESHOT, NOTE_LOWAT, 2, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - puts("-- checking that one byte does not trigger an event.."); - kevent_socket_fill(); - test_no_kevents(); - - puts("-- checking that two bytes triggers an event.."); - kevent_socket_fill(); - if (kevent(kqfd, NULL, 0, &kev, 1, NULL) != 1) - err(1, "%s", test_id); - KEV_CMP(kev, sockfd[0], EVFILT_READ, 0); - test_no_kevents(); - - kevent_socket_drain(); - kevent_socket_drain(); - - success(); -} -#endif - -void -test_kevent_socket_eof(void) -{ - const char *test_id = "kevent(EVFILT_READ, EV_EOF)"; - struct kevent kev; - - test_begin(test_id); - - /* Re-add the watch and make sure no events are pending */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_ADD, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - if (close(sockfd[1]) < 0) - err(1, "close(2)"); - - kev.flags |= EV_EOF; - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Delete the watch */ - EV_SET(&kev, sockfd[0], EVFILT_READ, EV_DELETE, 0, 0, &sockfd[0]); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_evfilt_read() -{ - /* Create a connected pair of full-duplex sockets for testing socket events */ - if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd) < 0) - abort(); - - kqfd = kqueue(); - test_kevent_socket_add(); - test_kevent_socket_del(); - test_kevent_socket_get(); - test_kevent_socket_disable_and_enable(); - test_kevent_socket_oneshot(); - test_kevent_socket_clear(); -#if HAVE_EV_DISPATCH - test_kevent_socket_dispatch(); -#endif - test_kevent_socket_eof(); - close(kqfd); -} diff --git a/tests/sys/kqueue/signal.c b/tests/sys/kqueue/signal.c deleted file mode 100644 index 14e751d..0000000 --- a/tests/sys/kqueue/signal.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily <mark@heily.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#include "common.h" - -int kqfd; - -void -test_kevent_signal_add(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_kevent_signal_get(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, wait)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - kev.flags |= EV_CLEAR; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - success(); -} - -void -test_kevent_signal_disable(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - test_no_kevents(); - - success(); -} - -void -test_kevent_signal_enable(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - kev.flags = EV_ADD | EV_CLEAR; -#if LIBKQUEUE - kev.data = 1; /* WORKAROUND */ -#else - kev.data = 2; // one extra time from test_kevent_signal_disable() -#endif - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Delete the watch */ - kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_kevent_signal_del(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - /* Delete the kevent */ - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - test_no_kevents(); - success(); -} - -void -test_kevent_signal_oneshot(void) -{ - const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Block SIGUSR1, then send it to ourselves */ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) - err(1, "sigprocmask"); - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - - kev.flags |= EV_CLEAR; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Send another one and make sure we get no events */ - if (kill(getpid(), SIGUSR1) < 0) - err(1, "kill"); - test_no_kevents(); - - success(); -} - -void -test_evfilt_signal() -{ - kqfd = kqueue(); - test_kevent_signal_add(); - test_kevent_signal_del(); - test_kevent_signal_get(); - test_kevent_signal_disable(); - test_kevent_signal_enable(); - test_kevent_signal_oneshot(); - close(kqfd); -} diff --git a/tests/sys/kqueue/timer.c b/tests/sys/kqueue/timer.c deleted file mode 100644 index 766125d..0000000 --- a/tests/sys/kqueue/timer.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily <mark@heily.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#include "common.h" - -int kqfd; - -void -test_kevent_timer_add(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, EV_ADD)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_kevent_timer_del(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - test_no_kevents(); - - success(); -} - -void -test_kevent_timer_get(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, wait)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kev.flags |= EV_CLEAR; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -static void -test_oneshot(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT)"; - struct kevent kev; - - test_begin(test_id); - - test_no_kevents(); - - EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Retrieve the event */ - kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Check if the event occurs again */ - sleep(3); - test_no_kevents(); - - - success(); -} - -static void -test_periodic(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, periodic)"; - struct kevent kev; - - test_begin(test_id); - - test_no_kevents(); - - EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 1000,NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Retrieve the event */ - kev.flags = EV_ADD | EV_CLEAR; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Check if the event occurs again */ - sleep(1); - kevent_cmp(&kev, kevent_get(kqfd)); - - /* Delete the event */ - kev.flags = EV_DELETE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -static void -disable_and_enable(void) -{ - const char *test_id = "kevent(EVFILT_TIMER, EV_DISABLE and EV_ENABLE)"; - struct kevent kev; - - test_begin(test_id); - - test_no_kevents(); - - /* Add the watch and immediately disable it */ - EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - kev.flags = EV_DISABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - test_no_kevents(); - - /* Re-enable and check again */ - kev.flags = EV_ENABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT; - kev.data = 1; - kevent_cmp(&kev, kevent_get(kqfd)); - - success(); -} - -void -test_evfilt_timer() -{ - kqfd = kqueue(); - test_kevent_timer_add(); - test_kevent_timer_del(); - test_kevent_timer_get(); - test_oneshot(); - test_periodic(); - disable_and_enable(); - close(kqfd); -} diff --git a/tests/sys/kqueue/user.c b/tests/sys/kqueue/user.c deleted file mode 100644 index 9ba25f9..0000000 --- a/tests/sys/kqueue/user.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily <mark@heily.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#include "common.h" - -int kqfd; - -static void -add_and_delete(void) -{ - const char *test_id = "kevent(EVFILT_USER, EV_ADD and EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); - test_no_kevents(); - - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_DELETE, 0, 0, NULL); - test_no_kevents(); - - success(); -} - -static void -event_wait(void) -{ - const char *test_id = "kevent(EVFILT_USER, wait)"; - struct kevent kev; - - test_begin(test_id); - - test_no_kevents(); - - /* Add the event, and then trigger it */ - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD | EV_CLEAR, 0, 0, NULL); - kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); - - kev.fflags &= ~NOTE_FFCTRLMASK; - kev.fflags &= ~NOTE_TRIGGER; - kev.flags = EV_CLEAR; - kevent_cmp(&kev, kevent_get(kqfd)); - - test_no_kevents(); - - success(); -} - -static void -disable_and_enable(void) -{ - const char *test_id = "kevent(EVFILT_USER, EV_DISABLE and EV_ENABLE)"; - struct kevent kev; - - test_begin(test_id); - - test_no_kevents(); - - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ADD, 0, 0, NULL); - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_DISABLE, 0, 0, NULL); - - /* Trigger the event, but since it is disabled, nothing will happen. */ - kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); - test_no_kevents(); - - kevent_add(kqfd, &kev, 1, EVFILT_USER, EV_ENABLE, 0, 0, NULL); - kevent_add(kqfd, &kev, 1, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); - - kev.flags = EV_CLEAR; - kev.fflags &= ~NOTE_FFCTRLMASK; - kev.fflags &= ~NOTE_TRIGGER; - kevent_cmp(&kev, kevent_get(kqfd)); - - success(); -} - -static void -oneshot(void) -{ - const char *test_id = "kevent(EVFILT_USER, EV_ONESHOT)"; - struct kevent kev; - - test_begin(test_id); - - test_no_kevents(); - - kevent_add(kqfd, &kev, 2, EVFILT_USER, EV_ADD | EV_ONESHOT, 0, 0, NULL); - - puts(" -- event 1"); - kevent_add(kqfd, &kev, 2, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); - - kev.flags = EV_ONESHOT; - kev.fflags &= ~NOTE_FFCTRLMASK; - kev.fflags &= ~NOTE_TRIGGER; - kevent_cmp(&kev, kevent_get(kqfd)); - - test_no_kevents(); - - success(); -} - -void -test_evfilt_user() -{ - kqfd = kqueue(); - - add_and_delete(); - event_wait(); - disable_and_enable(); - oneshot(); - /* TODO: try different fflags operations */ - - close(kqfd); -} diff --git a/tests/sys/kqueue/vnode.c b/tests/sys/kqueue/vnode.c deleted file mode 100644 index dfa0b5e..0000000 --- a/tests/sys/kqueue/vnode.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2009 Mark Heily <mark@heily.com> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * $FreeBSD$ - */ - -#include "common.h" - -int kqfd; -int vnode_fd; - -void -test_kevent_vnode_add(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_ADD)"; - const char *testfile = "/tmp/kqueue-test.tmp"; - struct kevent kev; - - test_begin(test_id); - - system("touch /tmp/kqueue-test.tmp"); - vnode_fd = open(testfile, O_RDONLY); - if (vnode_fd < 0) - err(1, "open of %s", testfile); - else - printf("vnode_fd = %d\n", vnode_fd); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD, - NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_kevent_vnode_note_delete(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (unlink("/tmp/kqueue-test.tmp") < 0) - err(1, "unlink"); - - kevent_cmp(&kev, kevent_get(kqfd)); - - success(); -} - -void -test_kevent_vnode_note_write(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_WRITE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("echo hello >> /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - /* BSD kqueue adds NOTE_EXTEND even though it was not requested */ - /* BSD kqueue removes EV_ENABLE */ - kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue - kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue - kevent_cmp(&kev, kevent_get(kqfd)); - - success(); -} - -void -test_kevent_vnode_note_attrib(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_ATTRIB)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(); -} - -void -test_kevent_vnode_note_rename(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, NOTE_RENAME)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("mv /tmp/kqueue-test.tmp /tmp/kqueue-test2.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_RENAME) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - if (system("mv /tmp/kqueue-test2.tmp /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - success(); -} - -void -test_kevent_vnode_del(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_DELETE)"; - struct kevent kev; - - test_begin(test_id); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - success(); -} - -void -test_kevent_vnode_disable_and_enable(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_DISABLE and EV_ENABLE)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - test_no_kevents(); - - /* Add the watch and immediately disable it */ - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - kev.flags = EV_DISABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - /* Confirm that the watch is disabled */ - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - test_no_kevents(); - - /* Re-enable and check again */ - kev.flags = EV_ENABLE; - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - success(); -} - -#if HAVE_EV_DISPATCH -void -test_kevent_vnode_dispatch(void) -{ - const char *test_id = "kevent(EVFILT_VNODE, EV_DISPATCH)"; - struct kevent kev; - int nfds; - - test_begin(test_id); - - test_no_kevents(); - - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "%s", test_id); - - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - - nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL); - if (nfds < 1) - err(1, "%s", test_id); - if (kev.ident != vnode_fd || - kev.filter != EVFILT_VNODE || - kev.fflags != NOTE_ATTRIB) - err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", - test_id, (unsigned int)kev.ident, kev.filter, kev.flags); - - /* Confirm that the watch is disabled automatically */ - puts("-- checking that watch is disabled"); - if (system("touch /tmp/kqueue-test.tmp") < 0) - err(1, "system"); - test_no_kevents(); - - /* Delete the watch */ - EV_SET(&kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL); - if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) - err(1, "remove watch failed: %s", test_id); - - success(); -} -#endif /* HAVE_EV_DISPATCH */ - -void -test_evfilt_vnode() -{ - kqfd = kqueue(); - test_kevent_vnode_add(); - test_kevent_vnode_del(); - test_kevent_vnode_disable_and_enable(); -#if HAVE_EV_DISPATCH - test_kevent_vnode_dispatch(); -#endif - test_kevent_vnode_note_write(); - test_kevent_vnode_note_attrib(); - test_kevent_vnode_note_rename(); - test_kevent_vnode_note_delete(); - close(kqfd); -} diff --git a/tests/sys/mmap/Makefile b/tests/sys/mmap/Makefile deleted file mode 100644 index 98809b4..0000000 --- a/tests/sys/mmap/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD$ - -TESTSDIR= ${TESTSBASE}/sys/mmap - -TAP_TESTS_C+= mmap - -.include <bsd.test.mk> diff --git a/tests/sys/mmap/mmap.c b/tests/sys/mmap/mmap.c deleted file mode 100644 index 7591a09..0000000 --- a/tests/sys/mmap/mmap.c +++ /dev/null @@ -1,105 +0,0 @@ -/*- - * Copyright (c) 2009 Simon L. Nielsen <simon@FreeBSD.org>, - * Bjoern A. Zeeb <bz@FreeBSD.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE 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. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/mman.h> -#include <sys/sysctl.h> -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <string.h> - -static const struct { - void *addr; - int ok[2]; /* Depending on security.bsd.map_at_zero {0, !=0}. */ -} tests[] = { - { (void *)0, { 0, 1 } }, /* Test sysctl. */ - { (void *)1, { 0, 0 } }, - { (void *)(PAGE_SIZE - 1), { 0, 0 } }, - { (void *)PAGE_SIZE, { 1, 1 } }, - { (void *)-1, { 0, 0 } }, - { (void *)(-PAGE_SIZE), { 0, 0 } }, - { (void *)(-1 - PAGE_SIZE), { 0, 0 } }, - { (void *)(-1 - PAGE_SIZE - 1), { 0, 0 } }, - { (void *)(0x1000 * PAGE_SIZE), { 1, 1 } }, -}; - -#define MAP_AT_ZERO "security.bsd.map_at_zero" - -int -main(void) -{ - void *p; - size_t len; - int i, error, mib[3], map_at_zero; - - error = 0; - - /* Get the current sysctl value of security.bsd.map_at_zero. */ - len = sizeof(mib) / sizeof(*mib); - if (sysctlnametomib(MAP_AT_ZERO, mib, &len) == -1) { - printf("1..0 # SKIP: sysctlnametomib(\"%s\") failed: %s\n", - MAP_AT_ZERO, strerror(errno)); - return (0); - } - - len = sizeof(map_at_zero); - if (sysctl(mib, 3, &map_at_zero, &len, NULL, 0) == -1) { - printf("1..0 # SKIP: sysctl for %s failed: %s\n", MAP_AT_ZERO, - strerror(errno)); - return (0); - } - - /* Normalize to 0 or 1 for array access. */ - map_at_zero = !!map_at_zero; - - printf("1..%zu\n", nitems(tests)); - for (i = 0; i < (int)nitems(tests); i++) { - p = mmap((void *)tests[i].addr, PAGE_SIZE, - PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_FIXED, - -1, 0); - if (p == MAP_FAILED) { - if (tests[i].ok[map_at_zero] != 0) - error++; - printf("%sok %d # mmap(%p, ...) failed\n", - tests[i].ok[map_at_zero] == 0 ? "" : "not ", - i + 1, - tests[i].addr); - } else { - if (tests[i].ok[map_at_zero] != 1) - error++; - printf("%sok %d # mmap(%p, ...) succeeded: p=%p\n", - tests[i].ok[map_at_zero] == 1 ? "" : "not ", - i + 1, - tests[i].addr, p); - } - } - - return (error != 0); -} diff --git a/tests/sys/mqueue/Makefile b/tests/sys/mqueue/Makefile deleted file mode 100644 index 230fcb7..0000000 --- a/tests/sys/mqueue/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# $FreeBSD$ - -TESTSDIR= ${TESTSBASE}/sys/mqueue - -ATF_TESTS_SH= mqueue_test - -BINDIR= ${TESTSDIR} - -PROGS+= mqtest1 -PROGS+= mqtest2 -PROGS+= mqtest3 -PROGS+= mqtest4 -PROGS+= mqtest5 - -LDADD+= -lrt -DPADD+= ${LIBRT} - -WARNS?= 6 - -.include <bsd.test.mk> diff --git a/tests/sys/mqueue/mqtest1.c b/tests/sys/mqueue/mqtest1.c deleted file mode 100644 index 5590b87..0000000 --- a/tests/sys/mqueue/mqtest1.c +++ /dev/null @@ -1,53 +0,0 @@ -/* $FreeBSD$ */ - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <mqueue.h> -#include <signal.h> -#include <stdio.h> - -#define MQNAME "/mytstqueue1" - -int -main(void) -{ - struct mq_attr attr, attr2; - struct sigevent sigev; - mqd_t mq; - int status; - - attr.mq_maxmsg = 2; - attr.mq_msgsize = 100; - mq = mq_open(MQNAME, O_CREAT | O_RDWR | O_EXCL, 0666, &attr); - if (mq == (mqd_t)-1) - err(1, "mq_open"); - status = mq_unlink(MQNAME); - if (status) - err(1, "mq_unlink"); - status = mq_getattr(mq, &attr2); - if (status) - err(1, "mq_getattr"); - if (attr.mq_maxmsg != attr2.mq_maxmsg) - err(1, "mq_maxmsg changed"); - if (attr.mq_msgsize != attr2.mq_msgsize) - err(1, "mq_msgsize changed"); - - sigev.sigev_notify = SIGEV_SIGNAL; - sigev.sigev_signo = SIGRTMIN; - status = mq_notify(mq, &sigev); - if (status) - err(1, "mq_notify"); - status = mq_notify(mq, &sigev); - if (status == 0) - err(1, "mq_notify 2"); - else if (errno != EBUSY) - err(1, "mq_notify 3"); - status = mq_notify(mq, NULL); - if (status) - err(1, "mq_notify 4"); - status = mq_close(mq); - if (status) - err(1, "mq_close"); - return (0); -} diff --git a/tests/sys/mqueue/mqtest2.c b/tests/sys/mqueue/mqtest2.c deleted file mode 100644 index aaef43b..0000000 --- a/tests/sys/mqueue/mqtest2.c +++ /dev/null @@ -1,97 +0,0 @@ -/* $FreeBSD$ */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <err.h> -#include <fcntl.h> -#include <mqueue.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#define MQNAME "/mytstqueue2" -#define LOOPS 1000 -#define PRIO 10 - -static void -alarmhandler(int sig __unused) -{ - write(1, "timeout\n", 8); - _exit(1); -} - -int -main(void) -{ - struct mq_attr attr; - mqd_t mq; - int status; - pid_t pid; - - mq_unlink(MQNAME); - - attr.mq_maxmsg = 5; - attr.mq_msgsize = 128; - mq = mq_open(MQNAME, O_CREAT | O_RDWR | O_EXCL, 0666, &attr); - if (mq == (mqd_t)-1) - err(1, "mq_open"); - status = mq_getattr(mq, &attr); - if (status) - err(1, "mq_getattr"); - pid = fork(); - if (pid == 0) { /* child */ - char *buf; - int j, i; - unsigned int prio; - - mq_close(mq); - - signal(SIGALRM, alarmhandler); - - mq = mq_open(MQNAME, O_RDWR); - if (mq == (mqd_t)-1) - err(1, "child: mq_open"); - buf = malloc(attr.mq_msgsize); - for (j = 0; j < LOOPS; ++j) { - alarm(3); - status = mq_receive(mq, buf, attr.mq_msgsize, &prio); - if (status == -1) - err(2, "child: mq_receive"); - for (i = 0; i < attr.mq_msgsize; ++i) - if (buf[i] != i) - err(3, "child: message data corrupted"); - if (prio != PRIO) - err(4, "child: priority is incorrect: %d", - prio); - } - alarm(0); - free(buf); - mq_close(mq); - return (0); - } else if (pid == -1) { - err(1, "fork()"); - } else { - char *buf; - int i, j; - - signal(SIGALRM, alarmhandler); - buf = malloc(attr.mq_msgsize); - for (j = 0; j < LOOPS; ++j) { - for (i = 0; i < attr.mq_msgsize; ++i) - buf[i] = i; - alarm(3); - status = mq_send(mq, buf, attr.mq_msgsize, PRIO); - if (status) - err(1, "mq_send"); - } - alarm(3); - wait(&status); - alarm(0); - } - status = mq_close(mq); - if (status) - err(1, "mq_close"); - mq_unlink(MQNAME); - return (0); -} diff --git a/tests/sys/mqueue/mqtest3.c b/tests/sys/mqueue/mqtest3.c deleted file mode 100644 index 4ee812c..0000000 --- a/tests/sys/mqueue/mqtest3.c +++ /dev/null @@ -1,112 +0,0 @@ -/* $FreeBSD$ */ - -#include <sys/types.h> -#include <sys/select.h> -#include <sys/wait.h> -#include <err.h> -#include <fcntl.h> -#include <mqueue.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#define MQNAME "/mytstqueue3" -#define LOOPS 1000 -#define PRIO 10 - -static void -sighandler(int sig __unused) -{ - write(1, "timeout\n", 8); - _exit(1); -} - -int -main(void) -{ - fd_set set; - struct mq_attr attr; - int status; - mqd_t mq; - pid_t pid; - - mq_unlink(MQNAME); - - attr.mq_maxmsg = 5; - attr.mq_msgsize = 128; - mq = mq_open(MQNAME, O_CREAT | O_RDWR | O_EXCL, 0666, &attr); - if (mq == (mqd_t)-1) - err(1, "mq_open()"); - status = mq_getattr(mq, &attr); - if (status) - err(1, "mq_getattr()"); - - pid = fork(); - if (pid == 0) { /* child */ - char *buf; - int j, i; - unsigned int prio; - - mq_close(mq); - - signal(SIGALRM, sighandler); - - mq = mq_open(MQNAME, O_RDWR); - if (mq == (mqd_t)-1) - err(1, "child process: mq_open"); - buf = malloc(attr.mq_msgsize); - for (j = 0; j < LOOPS; ++j) { - FD_ZERO(&set); - FD_SET(__mq_oshandle(mq), &set); - alarm(3); - status = select(__mq_oshandle(mq)+1, &set, NULL, NULL, NULL); - if (status != 1) - err(1, "child process: select()"); - status = mq_receive(mq, buf, attr.mq_msgsize, &prio); - if (status == -1) - err(2, "child process: mq_receive"); - for (i = 0; i < attr.mq_msgsize; ++i) - if (buf[i] != i) - err(3, "message data corrupted"); - if (prio != PRIO) - err(4, "priority is incorrect: %d", prio); - } - alarm(0); - free(buf); - mq_close(mq); - return (0); - } else if (pid == -1) { - err(1, "fork()"); - } else { - char *buf; - int i, j; - - signal(SIGALRM, sighandler); - buf = malloc(attr.mq_msgsize); - for (j = 0; j < LOOPS; ++j) { - for (i = 0; i < attr.mq_msgsize; ++i) { - buf[i] = i; - } - alarm(3); - FD_ZERO(&set); - FD_SET(__mq_oshandle(mq), &set); - status = select(__mq_oshandle(mq)+1, NULL, &set, NULL, NULL); - if (status != 1) - err(1, "select()"); - status = mq_send(mq, buf, attr.mq_msgsize, PRIO); - if (status) { - kill(pid, SIGKILL); - err(2, "mq_send()"); - } - } - alarm(3); - wait(&status); - alarm(0); - } - status = mq_close(mq); - if (status) - err(1, "mq_close"); - mq_unlink(MQNAME); - return (0); -} diff --git a/tests/sys/mqueue/mqtest4.c b/tests/sys/mqueue/mqtest4.c deleted file mode 100644 index d249cf6..0000000 --- a/tests/sys/mqueue/mqtest4.c +++ /dev/null @@ -1,116 +0,0 @@ -/* $FreeBSD$ */ - -#include <sys/types.h> -#include <sys/event.h> -#include <sys/select.h> -#include <sys/wait.h> -#include <err.h> -#include <fcntl.h> -#include <mqueue.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#define MQNAME "/mytstqueue4" -#define LOOPS 1000 -#define PRIO 10 - -static void -sighandler(int sig __unused) -{ - write(1, "timeout\n", 8); - _exit(1); -} - -int -main(void) -{ - struct kevent kev; - struct mq_attr attr; - mqd_t mq; - int kq, status; - pid_t pid; - - mq_unlink(MQNAME); - - attr.mq_maxmsg = 5; - attr.mq_msgsize = 128; - mq = mq_open(MQNAME, O_CREAT | O_RDWR | O_EXCL, 0666, &attr); - if (mq == (mqd_t) -1) - err(1, "mq_open()"); - status = mq_getattr(mq, &attr); - if (status) - err(1, "mq_getattr()"); - pid = fork(); - if (pid == 0) { /* child */ - char *buf; - int j, i; - unsigned int prio; - - mq_close(mq); - kq = kqueue(); - mq = mq_open(MQNAME, O_RDWR); - if (mq == (mqd_t)-1) - err(1, "child: mq_open"); - EV_SET(&kev, __mq_oshandle(mq), EVFILT_READ, EV_ADD, 0, 0, 0); - status = kevent(kq, &kev, 1, NULL, 0, NULL); - if (status == -1) - err(1, "child: kevent"); - buf = malloc(attr.mq_msgsize); - for (j = 0; j < LOOPS; ++j) { - alarm(3); - status = kevent(kq, NULL, 0, &kev, 1, NULL); - if (status != 1) - err(1, "child: kevent 2"); - status = mq_receive(mq, buf, attr.mq_msgsize, &prio); - if (status == -1) - err(2, "child: mq_receive"); - for (i = 0; i < attr.mq_msgsize; ++i) - if (buf[i] != i) - err(3, "child: message data corrupted"); - if (prio != PRIO) - err(4, "child: priority is incorrect: %d", - prio); - } - alarm(0); - free(buf); - mq_close(mq); - return (0); - } else if (pid == -1) { - err(1, "fork()"); - } else { - char *buf; - int i, j; - - signal(SIGALRM, sighandler); - kq = kqueue(); - EV_SET(&kev, __mq_oshandle(mq), EVFILT_WRITE, EV_ADD, 0, 0, 0); - status = kevent(kq, &kev, 1, NULL, 0, NULL); - if (status == -1) - err(1, "kevent"); - buf = malloc(attr.mq_msgsize); - for (j = 0; j < LOOPS; ++j) { - for (i = 0; i < attr.mq_msgsize; ++i) { - buf[i] = i; - } - alarm(3); - status = kevent(kq, NULL, 0, &kev, 1, NULL); - if (status != 1) - err(1, "child: kevent 2"); - status = mq_send(mq, buf, attr.mq_msgsize, PRIO); - if (status) { - err(2, "mq_send()"); - } - } - free(buf); - alarm(3); - wait(&status); - alarm(0); - } - status = mq_close(mq); - if (status) - err(1, "mq_close"); - mq_unlink(MQNAME); - return (0); -} diff --git a/tests/sys/mqueue/mqtest5.c b/tests/sys/mqueue/mqtest5.c deleted file mode 100644 index 7f4d554..0000000 --- a/tests/sys/mqueue/mqtest5.c +++ /dev/null @@ -1,124 +0,0 @@ -/* $FreeBSD$ */ - -#include <sys/types.h> -#include <sys/event.h> -#include <sys/select.h> -#include <sys/wait.h> -#include <err.h> -#include <fcntl.h> -#include <mqueue.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#define MQNAME "/mytstqueue5" -#define LOOPS 1000 -#define PRIO 10 - -static void -sighandler(int sig __unused) -{ - write(1, "timeout\n", 8); - _exit(1); -} - -int -main(void) -{ - int status; - struct mq_attr attr; - struct sigaction sa; - sigset_t set; - siginfo_t info; - mqd_t mq; - pid_t pid; - - mq_unlink(MQNAME); - - sigemptyset(&set); - sigaddset(&set, SIGRTMIN); - sigprocmask(SIG_BLOCK, &set, NULL); - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = (void *) SIG_DFL; - sigaction(SIGRTMIN, &sa, NULL); - - attr.mq_maxmsg = 5; - attr.mq_msgsize = 128; - mq = mq_open(MQNAME, O_CREAT | O_RDWR | O_EXCL, 0666, &attr); - if (mq == (mqd_t)-1) - err(1, "mq_open()"); - status = mq_getattr(mq, &attr); - if (status) - err(1, "mq_getattr()"); - pid = fork(); - if (pid == 0) { /* child */ - int prio, j, i; - char *buf; - struct sigevent sigev; - - signal(SIGALRM, sighandler); - - sigev.sigev_notify = SIGEV_SIGNAL; - sigev.sigev_signo = SIGRTMIN; - sigev.sigev_value.sival_int = 2; - - mq_close(mq); - mq = mq_open(MQNAME, O_RDWR | O_NONBLOCK); - if (mq == (mqd_t)-1) - err(1, "child: mq_open"); - buf = malloc(attr.mq_msgsize); - for (j = 0; j < LOOPS; ++j) { - alarm(3); - status = mq_notify(mq, &sigev); - if (status) - err(1, "child: mq_notify"); - status = sigwaitinfo(&set, &info); - if (status == -1) - err(1, "child: sigwaitinfo"); - if (info.si_value.sival_int != 2) - err(1, "child: sival_int"); - status = mq_receive(mq, buf, attr.mq_msgsize, &prio); - if (status == -1) - err(2, "child: mq_receive"); - for (i = 0; i < attr.mq_msgsize; ++i) - if (buf[i] != i) - err(3, "child: message data corrupted"); - if (prio != PRIO) - err(4, "child: priority is incorrect: %d", - prio); - } - alarm(0); - free(buf); - mq_close(mq); - return (0); - } else if (pid == -1) { - err(1, "fork()"); - } else { - char *buf; - int i, j; - - signal(SIGALRM, sighandler); - buf = malloc(attr.mq_msgsize); - for (j = 0; j < LOOPS; ++j) { - for (i = 0; i < attr.mq_msgsize; ++i) { - buf[i] = i; - } - alarm(3); - status = mq_send(mq, buf, attr.mq_msgsize, PRIO); - if (status) { - kill(pid, SIGKILL); - err(2, "mq_send()"); - } - } - alarm(3); - wait(&status); - alarm(0); - } - status = mq_close(mq); - if (status) - err(1, "mq_close"); - mq_unlink(MQNAME); - return (0); -} diff --git a/tests/sys/posixshm/Makefile b/tests/sys/posixshm/Makefile deleted file mode 100644 index cb27345..0000000 --- a/tests/sys/posixshm/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD$ - -TESTSDIR= ${TESTSBASE}/sys/posixshm - -TAP_TESTS_C= posixshm_test -SRCS.posixshm_test= posixshm.c test.c - -WARNS?= 6 - -.include <bsd.test.mk> diff --git a/tests/sys/posixshm/posixshm.c b/tests/sys/posixshm/posixshm.c deleted file mode 100644 index e21f45a..0000000 --- a/tests/sys/posixshm/posixshm.c +++ /dev/null @@ -1,627 +0,0 @@ -/*- - * Copyright (c) 2006 Robert N. M. Watson - * 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> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/mman.h> -#include <sys/resource.h> -#include <sys/stat.h> -#include <sys/syscall.h> -#include <sys/wait.h> - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "test.h" - -#define TEST_PATH "/tmp/posixshm_regression_test" - -/* - * Attempt a shm_open() that should fail with an expected error of 'error'. - */ -static void -shm_open_should_fail(const char *path, int flags, mode_t mode, int error) -{ - int fd; - - fd = shm_open(path, flags, mode); - if (fd >= 0) { - fail_err("shm_open() didn't fail"); - close(fd); - return; - } - if (errno != error) { - fail_errno("shm_open"); - return; - } - pass(); -} - -/* - * Attempt a shm_unlink() that should fail with an expected error of 'error'. - */ -static void -shm_unlink_should_fail(const char *path, int error) -{ - - if (shm_unlink(path) >= 0) { - fail_err("shm_unlink() didn't fail"); - return; - } - if (errno != error) { - fail_errno("shm_unlink"); - return; - } - pass(); -} - -/* - * Open the test object and write '1' to the first byte. Returns valid fd - * on success and -1 on failure. - */ -static int -scribble_object(void) -{ - char *page; - int fd; - - fd = shm_open(TEST_PATH, O_CREAT | O_EXCL | O_RDWR, 0777); - if (fd < 0 && errno == EEXIST) { - if (shm_unlink(TEST_PATH) < 0) { - fail_errno("shm_unlink"); - return (-1); - } - fd = shm_open(TEST_PATH, O_CREAT | O_EXCL | O_RDWR, 0777); - } - if (fd < 0) { - fail_errno("shm_open"); - return (-1); - } - if (ftruncate(fd, getpagesize()) < 0) { - fail_errno("ftruncate"); - close(fd); - shm_unlink(TEST_PATH); - return (-1); - } - - page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, - 0); - if (page == MAP_FAILED) { - fail_errno("mmap"); - close(fd); - shm_unlink(TEST_PATH); - return (-1); - } - - page[0] = '1'; - - if (munmap(page, getpagesize()) < 0) { - fail_errno("munmap"); - close(fd); - shm_unlink(TEST_PATH); - return (-1); - } - - return (fd); -} - -static void -remap_object(void) -{ - char *page; - int fd; - - fd = scribble_object(); - if (fd < 0) - return; - - page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, - 0); - if (page == MAP_FAILED) { - fail_errno("mmap(2)"); - close(fd); - shm_unlink(TEST_PATH); - return; - } - - if (page[0] != '1') { - fail_err("missing data"); - close(fd); - shm_unlink(TEST_PATH); - return; - } - - close(fd); - if (munmap(page, getpagesize()) < 0) { - fail_errno("munmap"); - shm_unlink(TEST_PATH); - return; - } - - if (shm_unlink(TEST_PATH) < 0) { - fail_errno("shm_unlink"); - return; - } - - pass(); -} -TEST(remap_object, "remap object"); - -static void -reopen_object(void) -{ - char *page; - int fd; - - fd = scribble_object(); - if (fd < 0) - return; - close(fd); - - fd = shm_open(TEST_PATH, O_RDONLY, 0777); - if (fd < 0) { - fail_errno("shm_open(2)"); - shm_unlink(TEST_PATH); - return; - } - page = mmap(0, getpagesize(), PROT_READ, MAP_SHARED, fd, 0); - if (page == MAP_FAILED) { - fail_errno("mmap(2)"); - close(fd); - shm_unlink(TEST_PATH); - return; - } - - if (page[0] != '1') { - fail_err("missing data"); - munmap(page, getpagesize()); - close(fd); - shm_unlink(TEST_PATH); - return; - } - - munmap(page, getpagesize()); - close(fd); - shm_unlink(TEST_PATH); - pass(); -} -TEST(reopen_object, "reopen object"); - -static void -readonly_mmap_write(void) -{ - char *page; - int fd; - - fd = shm_open(TEST_PATH, O_RDONLY | O_CREAT, 0777); - if (fd < 0) { - fail_errno("shm_open"); - return; - } - - /* PROT_WRITE should fail with EACCES. */ - page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, - 0); - if (page != MAP_FAILED) { - fail_err("mmap(PROT_WRITE) succeeded"); - munmap(page, getpagesize()); - close(fd); - shm_unlink(TEST_PATH); - return; - } - if (errno != EACCES) { - fail_errno("mmap"); - close(fd); - shm_unlink(TEST_PATH); - return; - } - - close(fd); - shm_unlink(TEST_PATH); - pass(); -} -TEST(readonly_mmap_write, "RDONLY object"); - -static void -open_after_unlink(void) -{ - int fd; - - fd = shm_open(TEST_PATH, O_RDONLY | O_CREAT, 0777); - if (fd < 0) { - fail_errno("shm_open(1)"); - return; - } - close(fd); - - if (shm_unlink(TEST_PATH) < 0) { - fail_errno("shm_unlink"); - return; - } - - shm_open_should_fail(TEST_PATH, O_RDONLY, 0777, ENOENT); -} -TEST(open_after_unlink, "open after unlink"); - -static void -open_invalid_path(void) -{ - - shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL); -} -TEST(open_invalid_path, "open invalid path"); - -static void -open_write_only(void) -{ - - shm_open_should_fail(TEST_PATH, O_WRONLY, 0777, EINVAL); -} -TEST(open_write_only, "open with O_WRONLY"); - -static void -open_extra_flags(void) -{ - - shm_open_should_fail(TEST_PATH, O_RDONLY | O_DIRECT, 0777, EINVAL); -} -TEST(open_extra_flags, "open with extra flags"); - -static void -open_anon(void) -{ - int fd; - - fd = shm_open(SHM_ANON, O_RDWR, 0777); - if (fd < 0) { - fail_errno("shm_open"); - return; - } - close(fd); - pass(); -} -TEST(open_anon, "open anonymous object"); - -static void -open_anon_readonly(void) -{ - - shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL); -} -TEST(open_anon_readonly, "open SHM_ANON with O_RDONLY"); - -static void -open_bad_path_pointer(void) -{ - - shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT); -} -TEST(open_bad_path_pointer, "open bad path pointer"); - -static void -open_path_too_long(void) -{ - char *page; - - page = malloc(MAXPATHLEN + 1); - memset(page, 'a', MAXPATHLEN); - page[MAXPATHLEN] = '\0'; - shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG); - free(page); -} -TEST(open_path_too_long, "open pathname too long"); - -static void -open_nonexisting_object(void) -{ - - shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT); -} -TEST(open_nonexisting_object, "open nonexistent object"); - -static void -exclusive_create_existing_object(void) -{ - int fd; - - fd = shm_open("/tmp/notreallythere", O_RDONLY | O_CREAT, 0777); - if (fd < 0) { - fail_errno("shm_open(O_CREAT)"); - return; - } - close(fd); - - shm_open_should_fail("/tmp/notreallythere", O_RDONLY | O_CREAT | O_EXCL, - 0777, EEXIST); - - shm_unlink("/tmp/notreallythere"); -} -TEST(exclusive_create_existing_object, "O_EXCL of existing object"); - -static void -trunc_resets_object(void) -{ - struct stat sb; - int fd; - - /* Create object and set size to 1024. */ - fd = shm_open(TEST_PATH, O_RDWR | O_CREAT, 0777); - if (fd < 0) { - fail_errno("shm_open(1)"); - return; - } - if (ftruncate(fd, 1024) < 0) { - fail_errno("ftruncate"); - close(fd); - return; - } - if (fstat(fd, &sb) < 0) { - fail_errno("fstat(1)"); - close(fd); - return; - } - if (sb.st_size != 1024) { - fail_err("size %d != 1024", (int)sb.st_size); - close(fd); - return; - } - close(fd); - - /* Open with O_TRUNC which should reset size to 0. */ - fd = shm_open(TEST_PATH, O_RDWR | O_TRUNC, 0777); - if (fd < 0) { - fail_errno("shm_open(2)"); - return; - } - if (fstat(fd, &sb) < 0) { - fail_errno("fstat(2)"); - close(fd); - return; - } - if (sb.st_size != 0) { - fail_err("size after O_TRUNC %d != 0", (int)sb.st_size); - close(fd); - return; - } - close(fd); - if (shm_unlink(TEST_PATH) < 0) { - fail_errno("shm_unlink"); - return; - } - pass(); -} -TEST(trunc_resets_object, "O_TRUNC resets size"); - -static void -unlink_bad_path_pointer(void) -{ - - shm_unlink_should_fail((char *)1024, EFAULT); -} -TEST(unlink_bad_path_pointer, "unlink bad path pointer"); - -static void -unlink_path_too_long(void) -{ - char *page; - - page = malloc(MAXPATHLEN + 1); - memset(page, 'a', MAXPATHLEN); - page[MAXPATHLEN] = '\0'; - shm_unlink_should_fail(page, ENAMETOOLONG); - free(page); -} -TEST(unlink_path_too_long, "unlink pathname too long"); - -static void -test_object_resize(void) -{ - pid_t pid; - struct stat sb; - char *page; - int fd, status; - - /* Start off with a size of a single page. */ - fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0777); - if (fd < 0) { - fail_errno("shm_open"); - return; - } - if (ftruncate(fd, getpagesize()) < 0) { - fail_errno("ftruncate(1)"); - close(fd); - return; - } - if (fstat(fd, &sb) < 0) { - fail_errno("fstat(1)"); - close(fd); - return; - } - if (sb.st_size != getpagesize()) { - fail_err("first resize failed"); - close(fd); - return; - } - - /* Write a '1' to the first byte. */ - page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, - 0); - if (page == MAP_FAILED) { - fail_errno("mmap(1)"); - close(fd); - return; - } - - page[0] = '1'; - - if (munmap(page, getpagesize()) < 0) { - fail_errno("munmap(1)"); - close(fd); - return; - } - - /* Grow the object to 2 pages. */ - if (ftruncate(fd, getpagesize() * 2) < 0) { - fail_errno("ftruncate(2)"); - close(fd); - return; - } - if (fstat(fd, &sb) < 0) { - fail_errno("fstat(2)"); - close(fd); - return; - } - if (sb.st_size != getpagesize() * 2) { - fail_err("second resize failed"); - close(fd); - return; - } - - /* Check for '1' at the first byte. */ - page = mmap(0, getpagesize() * 2, PROT_READ | PROT_WRITE, MAP_SHARED, - fd, 0); - if (page == MAP_FAILED) { - fail_errno("mmap(2)"); - close(fd); - return; - } - - if (page[0] != '1') { - fail_err("missing data at 0"); - close(fd); - return; - } - - /* Write a '2' at the start of the second page. */ - page[getpagesize()] = '2'; - - /* Shrink the object back to 1 page. */ - if (ftruncate(fd, getpagesize()) < 0) { - fail_errno("ftruncate(3)"); - close(fd); - return; - } - if (fstat(fd, &sb) < 0) { - fail_errno("fstat(3)"); - close(fd); - return; - } - if (sb.st_size != getpagesize()) { - fail_err("third resize failed"); - close(fd); - return; - } - - /* - * Fork a child process to make sure the second page is no - * longer valid. - */ - pid = fork(); - if (pid < 0) { - fail_errno("fork"); - close(fd); - return; - } - - if (pid == 0) { - struct rlimit lim; - char c; - - /* Don't generate a core dump. */ - getrlimit(RLIMIT_CORE, &lim); - lim.rlim_cur = 0; - setrlimit(RLIMIT_CORE, &lim); - - /* - * The previous ftruncate(2) shrunk the backing object - * so that this address is no longer valid, so reading - * from it should trigger a SIGSEGV. - */ - c = page[getpagesize()]; - fprintf(stderr, "child: page 1: '%c'\n", c); - exit(0); - } - if (wait(&status) < 0) { - fail_errno("wait"); - close(fd); - return; - } - if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGSEGV) { - fail_err("child terminated with status %x", status); - close(fd); - return; - } - - /* Grow the object back to 2 pages. */ - if (ftruncate(fd, getpagesize() * 2) < 0) { - fail_errno("ftruncate(4)"); - close(fd); - return; - } - if (fstat(fd, &sb) < 0) { - fail_errno("fstat(4)"); - close(fd); - return; - } - if (sb.st_size != getpagesize() * 2) { - fail_err("second resize failed"); - close(fd); - return; - } - - /* - * Note that the mapping at 'page' for the second page is - * still valid, and now that the shm object has been grown - * back up to 2 pages, there is now memory backing this page - * so the read will work. However, the data should be zero - * rather than '2' as the old data was thrown away when the - * object was shrunk and the new pages when an object are - * grown are zero-filled. - */ - if (page[getpagesize()] != 0) { - fail_err("invalid data at %d", getpagesize()); - close(fd); - return; - } - - close(fd); - pass(); -} -TEST(test_object_resize, "object resize"); - -int -main(void) -{ - - run_tests(); - return (0); -} diff --git a/tests/sys/posixshm/test.c b/tests/sys/posixshm/test.c deleted file mode 100644 index 8583a0d..0000000 --- a/tests/sys/posixshm/test.c +++ /dev/null @@ -1,128 +0,0 @@ -/*- - * Copyright (c) 2008 Yahoo!, Inc. - * All rights reserved. - * Written by: John Baldwin <jhb@FreeBSD.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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> -__FBSDID("$FreeBSD$"); - -#include <stdarg.h> -#include <stdio.h> - -#include "test.h" - -static int test_index; -static struct regression_test *test; -static int test_acknowleged; - -SET_DECLARE(regression_tests_set, struct regression_test); - -/* - * Outputs a test summary of the following: - * - * <status> <test #> [name] [# <fmt> [fmt args]] - */ -static void -vprint_status(const char *status, const char *fmt, va_list ap) -{ - - printf("%s %d", status, test_index); - if (test->rt_name) - printf(" - %s", test->rt_name); - if (fmt) { - printf(" # "); - vprintf(fmt, ap); - } - printf("\n"); - test_acknowleged = 1; -} - -static void -print_status(const char *status, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vprint_status(status, fmt, ap); - va_end(ap); -} - -void -pass(void) -{ - - print_status("ok", NULL); -} - -void -fail(void) -{ - - print_status("not ok", NULL); -} - -void -fail_err(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vprint_status("not ok", fmt, ap); - va_end(ap); -} - -void -skip(const char *reason) -{ - - print_status("ok", "skip %s", reason); -} - -void -todo(const char *reason) -{ - - print_status("not ok", "TODO %s", reason); -} - -void -run_tests(void) -{ - struct regression_test **testp; - - printf("1..%td\n", SET_COUNT(regression_tests_set)); - test_index = 1; - SET_FOREACH(testp, regression_tests_set) { - test_acknowleged = 0; - test = *testp; - test->rt_function(); - if (!test_acknowleged) - print_status("not ok", "unknown status"); - test_index++; - } -} diff --git a/tests/sys/posixshm/test.h b/tests/sys/posixshm/test.h deleted file mode 100644 index 505679b..0000000 --- a/tests/sys/posixshm/test.h +++ /dev/null @@ -1,59 +0,0 @@ -/*- - * Copyright (c) 2008 Yahoo!, Inc. - * All rights reserved. - * Written by: John Baldwin <jhb@FreeBSD.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * 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. - * - * $FreeBSD$ - */ - -#ifndef __TEST_H__ -#define __TEST_H__ - -#include <sys/linker_set.h> - -struct regression_test { - void (*rt_function)(void); - const char *rt_name; -}; - -#define TEST(function, name) \ - static struct regression_test _regtest_##function = { \ - (function), \ - (name) \ - }; \ - DATA_SET(regression_tests_set, _regtest_##function) - -void fail(void); -void fail_err(const char *fmt, ...); -void pass(void); -void run_tests(void); -void skip(const char *reason); -void todo(const char *reason); - -#define fail_errno(tag) fail_err("%s: %s", (tag), strerror(errno)) - -#endif /* !__TEST_H__ */ diff --git a/tests/sys/sockets/Makefile b/tests/sys/sockets/Makefile deleted file mode 100644 index ac18a8e..0000000 --- a/tests/sys/sockets/Makefile +++ /dev/null @@ -1,54 +0,0 @@ -# $FreeBSD$ -# -# Some of these tests fail on 11.0-CURRENT @ r280355 with DEBUG bits on - -TESTSDIR= ${TESTSBASE}/sys/socket - -BINDIR= ${TESTSDIR} - -PROGS+= unix_cmsg - -TAP_TESTS_C+= accept_fd_leak_test -# accf_data_attach: not ok 9 - setsockopt() after listen() failed with 2 (No such file or directory) -TAP_TESTS_C+= accf_data_attach_test -PLAIN_TESTS_C+= fstat_test -PLAIN_TESTS_C+= kqueue_test -PLAIN_TESTS_C+= listen_backlog_test -PLAIN_TESTS_C+= listenclose_test -PLAIN_TESTS_C+= pr_atomic_test -PLAIN_TESTS_C+= reconnect_test -# rtsocket: socket(PF_ROUTE, SOCK_STREAM, 0): Protocol wrong type for socket -PLAIN_TESTS_C+= rtsocket_test -PLAIN_TESTS_C+= sblock_test -TAP_TESTS_C+= sendfile_test -PLAIN_TESTS_C+= shutdown_test -PLAIN_TESTS_C+= sigpipe_test -TAP_TESTS_C+= so_setfib_test -PLAIN_TESTS_C+= socketpair_test -PLAIN_TESTS_C+= unix_bindconnect_test -PLAIN_TESTS_C+= unix_close_race_test -# Lots of failures -TAP_TESTS_SH+= unix_cmsg_test -# unix_gc: twosome_drop1: sendfd: before 0 after 0 -PLAIN_TESTS_C+= unix_gc_test -# unix_passfd: test8-rights+creds+payload: recvmsg: 24 bytes received -PLAIN_TESTS_C+= unix_passfd_test -PLAIN_TESTS_C+= unix_sendtorace_test -# unix_socket: socket(PF_LOCAL, SOCK_RAW, 0): Protocol wrong type for socket -PLAIN_TESTS_C+= unix_socket_test -PLAIN_TESTS_C+= unix_sorflush_test -# zerosend: tcp_0write: bind(127.0.0.1, 10001): Address already in use -PLAIN_TESTS_C+= zerosend_test - -DPADD.sendfile_test+= ${LIBMD} -LDADD.sendfile_test+= -lmd - -# XXX: this doesn't work..? -#WARNS.unix_cmsg= 3 -#WARNS.unix_gc= 3 -#WARNS.unix_passfd= 3 -#WARNS.zerosend= 2 - -WARNS= 2 - -.include <bsd.test.mk> diff --git a/tests/sys/sockets/README.unix_cmsg b/tests/sys/sockets/README.unix_cmsg deleted file mode 100644 index df51723..0000000 --- a/tests/sys/sockets/README.unix_cmsg +++ /dev/null @@ -1,160 +0,0 @@ -$FreeBSD$ - -About unix_cmsg -=============== - -This program is a collection of regression tests for ancillary data -(control information) for PF_LOCAL sockets (local domain or Unix domain -sockets). There are tests for stream and datagram sockets. - -Usually each test does following steps: creates Server, forks Client, -Client sends something to Server, Server verifies whether everything is -correct in received message(s). - -It is better to change the owner of unix_cmsg to some safe user -(eg. nobody:nogroup) and set SUID and SGID bits, else some tests that -check credentials can give correct results for wrong implementation. - -It is better to run this program by a user that belongs to more -than 16 groups. - -Available options -================= - -usage: unix_cmsg [-dh] [-n num] [-s size] [-t type] [-z value] [testno] - - Options are: - -d Output debugging information - -h Output the help message and exit - -n num Number of messages to send - -s size Specify size of data for IPC - -t type Specify socket type (stream, dgram) for tests - -z value Do not send data in a message (bit 0x1), do not send - data array associated with a cmsghdr structure (bit 0x2) - testno Run one test by its number (require the -t option) - -Description -=========== - -If Client sends something to Server, then it sends 5 messages by default. -Number of messages can be changed in the -n command line option. Number -of messages will be given as N in the following descriptions. - -If Client sends something to Server, then it sends some data (few bytes) -in each message by default. The size of this data can be changed by the -s -command line option. The "-s 0" command line option means, that Client will -send zero bytes represented by { NULL, 0 } value of struct iovec{}, referenced -by the msg_iov field from struct msghdr{}. The "-z 1" or "-z 3" command line -option means, that Client will send zero bytes represented by the NULL value -in the msg_iov field from struct msghdr{}. - -If Client sends some ancillary data object, then this ancillary data object -always has associated data array by default. The "-z 2" or "-z 3" option -means, that Client will not send associated data array if possible. - -For SOCK_STREAM sockets: ------------------------ - - 1: Sending, receiving cmsgcred - - Client connects to Server and sends N messages with SCM_CREDS ancillary - data object. Server should receive N messages, each message should - have SCM_CREDS ancillary data object followed by struct cmsgcred{}. - - 2: Receiving sockcred (listening socket) - - Server creates a listening stream socket and sets the LOCAL_CREDS - socket option for it. Client connects to Server two times, each time - it sends N messages. Server accepts two connections and receives N - messages from each connection. The first message from each connection - should have SCM_CREDS ancillary data object followed by struct sockcred{}, - next messages from the same connection should not have ancillary data. - - 3: Receiving sockcred (accepted socket) - - Client connects to Server. Server accepts connection and sets the - LOCAL_CREDS socket option for just accepted socket. Client sends N - messages to Server. Server should receive N messages, the first - message should have SCM_CREDS ancillary data object followed by - struct sockcred{}, next messages should not have ancillary data. - - 4: Sending cmsgcred, receiving sockcred - - Server creates a listening stream socket and sets the LOCAL_CREDS - socket option for it. Client connects to Server and sends N messages - with SCM_CREDS ancillary data object. Server should receive N messages, - the first message should have SCM_CREDS ancillary data object followed - by struct sockcred{}, each of next messages should have SCM_CREDS - ancillary data object followed by struct cmsgcred{}. - - 5: Sending, receiving timeval - - Client connects to Server and sends message with SCM_TIMESTAMP ancillary - data object. Server should receive one message with SCM_TIMESTAMP - ancillary data object followed by struct timeval{}. - - 6: Sending, receiving bintime - - Client connects to Server and sends message with SCM_BINTIME ancillary - data object. Server should receive one message with SCM_BINTIME - ancillary data object followed by struct bintime{}. - - 7: Checking cmsghdr.cmsg_len - - Client connects to Server and tries to send several messages with - SCM_CREDS ancillary data object that has wrong cmsg_len field in its - struct cmsghdr{}. All these attempts should fail, since cmsg_len - in all requests is less than CMSG_LEN(0). - - 8: Check LOCAL_PEERCRED socket option - - This test does not use ancillary data, but can be implemented here. - Client connects to Server. Both Client and Server verify that - credentials of the peer are correct using LOCAL_PEERCRED socket option. - -For SOCK_DGRAM sockets: ----------------------- - - 1: Sending, receiving cmsgcred - - Client connects to Server and sends N messages with SCM_CREDS ancillary - data object. Server should receive N messages, each message should - have SCM_CREDS ancillary data object followed by struct cmsgcred{}. - - 2: Receiving sockcred - - Server creates datagram socket and sets the LOCAL_CREDS socket option - for it. Client sends N messages to Server. Server should receive N - messages, each message should have SCM_CREDS ancillary data object - followed by struct sockcred{}. - - 3: Sending cmsgcred, receiving sockcred - - Server creates datagram socket and sets the LOCAL_CREDS socket option - for it. Client sends N messages with SCM_CREDS ancillary data object - to Server. Server should receive N messages, the first message should - have SCM_CREDS ancillary data object followed by struct sockcred{}, - each of next messages should have SCM_CREDS ancillary data object - followed by struct cmsgcred{}. - - 4: Sending, receiving timeval - - Client sends one message with SCM_TIMESTAMP ancillary data object - to Server. Server should receive one message with SCM_TIMESTAMP - ancillary data object followed by struct timeval{}. - - 5: Sending, receiving bintime - - Client sends one message with SCM_BINTIME ancillary data object - to Server. Server should receive one message with SCM_BINTIME - ancillary data object followed by struct bintime{}. - - 6: Checking cmsghdr.cmsg_len - - Client tries to send Server several messages with SCM_CREDS ancillary - data object that has wrong cmsg_len field in its struct cmsghdr{}. - All these attempts should fail, since cmsg_len in all requests is less - than CMSG_LEN(0). - -- Andrey Simonenko -andreysimonenko@users.sourceforge.net diff --git a/tests/sys/sockets/accept_fd_leak_test.c b/tests/sys/sockets/accept_fd_leak_test.c deleted file mode 100644 index 659c22d..0000000 --- a/tests/sys/sockets/accept_fd_leak_test.c +++ /dev/null @@ -1,215 +0,0 @@ -/*- - * Copyright (c) 2004 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/wait.h> - -#include <netinet/in.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#define BIND_ATTEMPTS 10 -#define LOOPS 500 -#define NUM_ATTEMPTS 1000 - -static volatile int quit; - -static void -child_died(int sig __unused) -{ - - quit = 1; -} - -/* - * This test is intended to detect a leak of a file descriptor in the process - * following a failed non-blocking accept. It measures an available fd - * baseline, then performs 1000 failing accepts, then checks to see what the - * next fd is. It relies on sequential fd allocation, and will test for it - * briefly before beginning (not 100% reliable, but a good start). - */ -int -main(void) -{ - struct sockaddr_in sin; - socklen_t size; - pid_t child; - int fd1, fd2, fd3, i, listen_port, s, status; - - printf("1..2\n"); - - /* - * Check for sequential fd allocation, and give up early if not. - */ - fd1 = dup(STDIN_FILENO); - fd2 = dup(STDIN_FILENO); - if (fd2 != fd1 + 1) - errx(-1, "Non-sequential fd allocation\n"); - - s = socket(PF_INET, SOCK_STREAM, 0); - if (s == -1) - errx(-1, "socket: %s", strerror(errno)); - - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - srandomdev(); - - for (i = 0; i < BIND_ATTEMPTS; i++) { - /* Pick a random unprivileged port 1025-65535 */ - listen_port = MAX((int)random() % 65535, 1025); - sin.sin_port = htons(listen_port); - if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == 0) - break; - warn("bind with %d failed", listen_port); - usleep(1000); - } - if (i >= BIND_ATTEMPTS) { - printf("Bail out!\n"); - exit(1); - } - - if (listen(s, -1) != 0) - errx(-1, "listen: %s", strerror(errno)); - - i = fcntl(s, F_GETFL); - if (i == -1) - errx(-1, "ioctl(F_GETFL): %s", strerror(errno)); - i |= O_NONBLOCK; - if (fcntl(s, F_SETFL, i) != 0) - errx(-1, "ioctl(F_SETFL): %s", strerror(errno)); - i = fcntl(s, F_GETFL); - if (i == -1) - errx(-1, "ioctl(F_GETFL): %s", strerror(errno)); - if ((i & O_NONBLOCK) != O_NONBLOCK) - errx(-1, "Failed to set O_NONBLOCK (i=0x%x)\n", i); - - for (i = 0; i < LOOPS; i++) { - size = sizeof(sin); - if (accept(s, (struct sockaddr *)&sin, &size) != -1) - errx(-1, "accept succeeded\n"); - if (errno != EAGAIN) - errx(-1, "accept: %s", strerror(errno)); - } - - /* - * Allocate a file descriptor and make sure it's fd2+2. 2 because - * we allocate an fd for the socket. - */ - fd3 = dup(STDIN_FILENO); - if (fd3 != fd2 + 2) - printf("not ok 1 - (%d, %d, %d)\n", fd1, fd2, fd3); - else - printf("ok 1\n"); - - /* - * Try failing accept's w/o non-blocking where the destination - * address pointer is invalid. - */ - close(fd3); - signal(SIGCHLD, child_died); - child = fork(); - if (child < 0) - errx(-1, "fork: %s", strerror(errno)); - - /* - * Child process does `NUM_ATTEMPTS` connects. - */ - if (child == 0) { - close(fd1); - close(fd2); - close(s); - - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(listen_port); - - for (i = 0; i < NUM_ATTEMPTS; i++) { - s = socket(PF_INET, SOCK_STREAM, 0); - if (s == -1) - errx(-1, "socket: %s", strerror(errno)); - if (connect(s, (struct sockaddr *)&sin, - sizeof(sin)) < 0) - errx(-1, "connect: %s", strerror(errno)); - close(s); - } - _exit(0); - } - - /* Reset back to a blocking socket. */ - i = fcntl(s, F_GETFL); - if (i == -1) - errx(-1, "ioctl(F_GETFL): %s", strerror(errno)); - i &= ~O_NONBLOCK; - if (fcntl(s, F_SETFL, i) != 0) - errx(-1, "ioctl(F_SETFL): %s", strerror(errno)); - i = fcntl(s, F_GETFL); - if (i == -1) - errx(-1, "ioctl(F_GETFL): %s", strerror(errno)); - if (i & O_NONBLOCK) - errx(-1, "Failed to clear O_NONBLOCK (i=0x%x)\n", i); - - /* Do `NUM_ATTEMPTS` accepts with an invalid pointer. */ - for (i = 0; !quit && i < NUM_ATTEMPTS; i++) { - size = sizeof(sin); - if (accept(s, (struct sockaddr *)(uintptr_t)(0x100), - &size) != -1) - errx(-1, "accept succeeded\n"); - if (errno != EFAULT) - errx(-1, "accept: %s", strerror(errno)); - } - - if (waitpid(child, &status, 0) < 0) - errx(-1, "waitpid: %s", strerror(errno)); - if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) - warnx("child process died"); - - /* - * Allocate a file descriptor and make sure it's fd2+2. 2 because - * we allocate an fd for the socket. - */ - fd3 = dup(STDIN_FILENO); - if (fd3 != fd2 + 2) - printf("not ok 2 - (%d, %d, %d)\n", fd1, fd2, fd3); - else - printf("ok 2\n"); - - return (0); -} diff --git a/tests/sys/sockets/accf_data_attach_test.c b/tests/sys/sockets/accf_data_attach_test.c deleted file mode 100644 index 59ea68c..0000000 --- a/tests/sys/sockets/accf_data_attach_test.c +++ /dev/null @@ -1,216 +0,0 @@ -/*- - * Copyright (c) 2004 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/socket.h> - -#include <netinet/in.h> - -#include <err.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#define ACCF_NAME "dataready" - -/* - * A number of small tests to confirm that attaching ACCF_DATA accept filters - * to inet4 ports works as expected. We test: - * - * - That no accept filter is attached on a newly created socket. - * - That bind() has no affect on the accept filter state. - * - That we can't attach an accept filter to a socket that isn't in the - * listen state. - * - That after we fail to attach the filter, querying the kernel shows no - * filter attached. - * - That we can attach an accept filter to a socket that is in the listen - * state. - * - That once an accept filter is attached, we can query to make sure it is - * attached. - * - That once an accept filter is attached, we can remove it and query to - * make sure it is removed. - */ -int -main(void) -{ - struct accept_filter_arg afa; - struct sockaddr_in sin; - socklen_t len; - int lso, ret; - - printf("1..11\n"); - - /* - * Step 0. Open socket(). - */ - lso = socket(PF_INET, SOCK_STREAM, 0); - if (lso == -1) - errx(-1, "not ok 1 - socket: %s", strerror(errno)); - printf("ok 1 - socket\n"); - - /* - * Step 1. After socket(). Should return EINVAL, since no accept - * filter should be attached. - */ - bzero(&afa, sizeof(afa)); - len = sizeof(afa); - ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); - if (ret != -1) - errx(-1, "not ok 2 - getsockopt() after socket() succeeded"); - if (errno != EINVAL) - errx(-1, "not ok 2 - getsockopt() after socket() failed with " - "%d (%s)", errno, strerror(errno)); - printf("ok 2 - getsockopt\n"); - - /* - * Step 2. Bind(). Ideally this will succeed. - */ - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_port = htons(8080); - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - if (bind(lso, (struct sockaddr *)&sin, sizeof(sin)) < 0) - errx(-1, "not ok 3 - bind %s", strerror(errno)); - printf("ok 3 - bind\n"); - - /* - * Step 3: After bind(). getsockopt() should return EINVAL, since no - * accept filter should be attached. - */ - len = sizeof(afa); - ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); - if (ret != -1) - errx(-1, "not ok 4 - getsockopt() after bind() succeeded"); - if (errno != EINVAL) - errx(-1, "not ok 4 - getsockopt() after bind() failed with %d (%s)", - errno, strerror(errno)); - printf("ok 4 - getsockopt\n"); - - /* - * Step 4: Setsockopt() before listen(). Should fail, since it's not - * yet a listen() socket. - */ - bzero(&afa, sizeof(afa)); - strcpy(afa.af_name, ACCF_NAME); - ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)); - if (ret == 0) - errx(-1, "not ok 5 - setsockopt() before listen() succeeded"); - printf("ok 5 - setsockopt\n"); - - /* - * Step 5: Getsockopt() after pre-listen() setsockopt(). Should - * fail with EINVAL, since setsockopt() should have failed. - */ - len = sizeof(afa); - ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); - if (ret == 0) - errx(-1, "not ok 6 - getsockopt() after pre-listen() setsockopt() " - "succeeded"); - if (errno != EINVAL) - errx(-1, "not ok 6 - pre-listen() getsockopt() failed with %d (%s)", - errno, strerror(errno)); - printf("ok 6 - getsockopt\n"); - - /* - * Step 6: listen(). - */ - if (listen(lso, -1) < 0) - errx(-1, "not ok 7 - listen: %s", strerror(errno)); - printf("ok 7 - listen\n"); - - /* - * Step 7: Getsockopt() after listen(). Should fail with EINVAL, - * since we have not installed accept filter yet. - */ - len = sizeof(afa); - ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); - if (ret == 0) - errx(-1, "not ok 8 - getsockopt() after listen() but before " - "setsockopt() succeeded"); - if (errno != EINVAL) - errx(-1, "not ok 8 - getsockopt() after listen() but before " - "setsockopt() failed with %d (%s)", errno, strerror(errno)); - printf("ok 8 - getsockopt\n"); - - /* - * Step 8: After listen(). This call to setsockopt() should succeed. - */ - bzero(&afa, sizeof(afa)); - strcpy(afa.af_name, ACCF_NAME); - ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)); - if (ret != 0) - errx(-1, "not ok 9 - setsockopt() after listen() failed with %d " - "(%s)", errno, strerror(errno)); - printf("ok 9 - setsockopt\n"); - - /* - * Step 9: After setsockopt(). Should succeed and identify - * ACCF_NAME. - */ - bzero(&afa, sizeof(afa)); - len = sizeof(afa); - ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); - if (ret != 0) - errx(-1, "not ok 10 - getsockopt() after listen() setsockopt() " - "failed with %d (%s)", errno, strerror(errno)); - if (len != sizeof(afa)) - errx(-1, "not ok 10 - getsockopt() after setsockopet() after " - "listen() returned wrong size (got %d expected %zd)", len, - sizeof(afa)); - if (strcmp(afa.af_name, ACCF_NAME) != 0) - errx(-1, "not ok 10 - getsockopt() after setsockopt() after " - "listen() mismatch (got %s expected %s)", afa.af_name, - ACCF_NAME); - printf("ok 10 - getsockopt\n"); - - /* - * Step 10: Remove accept filter. After removing the accept filter - * getsockopt() should fail with EINVAL. - */ - ret = setsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0); - if (ret != 0) - errx(-1, "not ok 11 - setsockopt() after listen() " - "failed with %d (%s)", errno, strerror(errno)); - bzero(&afa, sizeof(afa)); - len = sizeof(afa); - ret = getsockopt(lso, SOL_SOCKET, SO_ACCEPTFILTER, &afa, &len); - if (ret == 0) - errx(-1, "not ok 11 - getsockopt() after removing " - "the accept filter returns valid accept filter %s", - afa.af_name); - if (errno != EINVAL) - errx(-1, "not ok 11 - getsockopt() after removing the accept" - "filter failed with %d (%s)", errno, strerror(errno)); - printf("ok 11 - setsockopt\n"); - - close(lso); - return (0); -} diff --git a/tests/sys/sockets/fstat_test.c b/tests/sys/sockets/fstat_test.c deleted file mode 100644 index 6ea931d..0000000 --- a/tests/sys/sockets/fstat_test.c +++ /dev/null @@ -1,71 +0,0 @@ -/*- - * Copyright (c) 2008 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> - -#include <err.h> -#include <unistd.h> - -/* - * Basic test to make sure that fstat(2) returns success on various socket - * types. In the future we should also validate the fields, confirming - * expected results such as the effect of shutdown(2) on permissions, etc. - */ - -static void -dotest(int domain, int type, int protocol) -{ - struct stat sb; - int sock; - - sock = socket(domain, type, protocol); - if (sock < 0) - err(-1, "socket(%d, %d, %d)", domain, type, protocol); - - if (fstat(sock, &sb) < 0) - err(-1, "fstat on socket(%d, %d, %d)", domain, type, - protocol); - - close(sock); -} - -int -main(void) -{ - - dotest(PF_INET, SOCK_DGRAM, 0); - dotest(PF_INET, SOCK_STREAM, 0); - dotest(PF_INET6, SOCK_DGRAM, 0); - dotest(PF_INET6, SOCK_STREAM, 0); - dotest(PF_LOCAL, SOCK_DGRAM, 0); - dotest(PF_LOCAL, SOCK_STREAM, 0); - - return (0); -} diff --git a/tests/sys/sockets/kqueue_test.c b/tests/sys/sockets/kqueue_test.c deleted file mode 100644 index f73704a..0000000 --- a/tests/sys/sockets/kqueue_test.c +++ /dev/null @@ -1,368 +0,0 @@ -/*- - * Copyright (c) 2004 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/event.h> -#include <sys/socket.h> -#include <sys/time.h> - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -static int curtest = 1; - -/*- - * This test uses UNIX domain socket pairs to perform some basic exercising - * of kqueue functionality on sockets. In particular, testing that for read - * and write filters, we see the correct detection of whether reads and - * writes should actually be able to occur. - * - * TODO: - * - Test read/write filters for listen/accept sockets. - * - Handle the XXXRW below regarding datagram sockets. - * - Test that watermark/buffer size "data" fields returned by kqueue are - * correct. - * - Check that kqueue does something sensible when the remote endpoing is - * closed. - */ - -#define OK(testname) printf("ok %d - %s\n", curtest, testname); \ - curtest++; - -static void -fail(int error, const char *func, const char *socktype, const char *rest) -{ - - printf("not ok %d\n", curtest); - - if (socktype == NULL) - printf("# %s(): %s\n", func, strerror(error)); - else if (rest == NULL) - printf("# %s(%s): %s\n", func, socktype, - strerror(error)); - else - printf("# %s(%s, %s): %s\n", func, socktype, rest, - strerror(error)); - exit(-1); -} - -static void -fail_assertion(const char *func, const char *socktype, const char *rest, - const char *assertion) -{ - - printf("not ok %d - %s\n", curtest, assertion); - - if (socktype == NULL) - printf("# %s(): assertion %s failed\n", func, - assertion); - else if (rest == NULL) - printf("# %s(%s): assertion %s failed\n", func, - socktype, assertion); - else - printf("# %s(%s, %s): assertion %s failed\n", func, - socktype, rest, assertion); - exit(-1); -} - -/* - * Test read kevent on a socket pair: check to make sure endpoint 0 isn't - * readable when we start, then write to endpoint 1 and confirm that endpoint - * 0 is now readable. Drain the write, then check that it's not readable - * again. Use non-blocking kqueue operations and socket operations. - */ -static void -test_evfilt_read(int kq, int fd[2], const char *socktype) -{ - struct timespec ts; - struct kevent ke; - ssize_t len; - char ch; - int i; - - EV_SET(&ke, fd[0], EVFILT_READ, EV_ADD, 0, 0, NULL); - if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) - fail(errno, "kevent", socktype, "EVFILT_READ, EV_ADD"); - OK("EVFILT_READ, EV_ADD"); - - /* - * Confirm not readable to begin with, no I/O yet. - */ - ts.tv_sec = 0; - ts.tv_nsec = 0; - i = kevent(kq, NULL, 0, &ke, 1, &ts); - if (i == -1) - fail(errno, "kevent", socktype, "EVFILT_READ"); - OK("EVFILT_READ"); - if (i != 0) - fail_assertion("kevent", socktype, "EVFILT_READ", - "empty socket unreadable"); - OK("empty socket unreadable"); - - /* - * Write a byte to one end. - */ - ch = 'a'; - len = write(fd[1], &ch, sizeof(ch)); - if (len == -1) - fail(errno, "write", socktype, NULL); - OK("write one byte"); - if (len != sizeof(ch)) - fail_assertion("write", socktype, NULL, "write length"); - OK("write one byte length"); - - /* - * Other end should now be readable. - */ - ts.tv_sec = 0; - ts.tv_nsec = 0; - i = kevent(kq, NULL, 0, &ke, 1, &ts); - if (i == -1) - fail(errno, "kevent", socktype, "EVFILT_READ"); - OK("EVFILT_READ"); - if (i != 1) - fail_assertion("kevent", socktype, "EVFILT_READ", - "non-empty socket unreadable"); - OK("non-empty socket unreadable"); - - /* - * Read a byte to clear the readable state. - */ - len = read(fd[0], &ch, sizeof(ch)); - if (len == -1) - fail(errno, "read", socktype, NULL); - OK("read one byte"); - if (len != sizeof(ch)) - fail_assertion("read", socktype, NULL, "read length"); - OK("read one byte length"); - - /* - * Now re-check for readability. - */ - ts.tv_sec = 0; - ts.tv_nsec = 0; - i = kevent(kq, NULL, 0, &ke, 1, &ts); - if (i == -1) - fail(errno, "kevent", socktype, "EVFILT_READ"); - OK("EVFILT_READ"); - if (i != 0) - fail_assertion("kevent", socktype, "EVFILT_READ", - "empty socket unreadable"); - OK("empty socket unreadable"); - - EV_SET(&ke, fd[0], EVFILT_READ, EV_DELETE, 0, 0, NULL); - if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) - fail(errno, "kevent", socktype, "EVFILT_READ, EV_DELETE"); - OK("EVFILT_READ, EV_DELETE"); -} - -static void -test_evfilt_write(int kq, int fd[2], const char *socktype) -{ - struct timespec ts; - struct kevent ke; - ssize_t len; - char ch; - int i; - - EV_SET(&ke, fd[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL); - if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) - fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_ADD"); - OK("EVFILE_WRITE, EV_ADD"); - - /* - * Confirm writable to begin with, no I/O yet. - */ - ts.tv_sec = 0; - ts.tv_nsec = 0; - i = kevent(kq, NULL, 0, &ke, 1, &ts); - if (i == -1) - fail(errno, "kevent", socktype, "EVFILT_WRITE"); - OK("EVFILE_WRITE"); - if (i != 1) - fail_assertion("kevent", socktype, "EVFILT_WRITE", - "empty socket unwritable"); - OK("empty socket unwritable"); - - /* - * Write bytes into the socket until we can't write anymore. - */ - ch = 'a'; - while ((len = write(fd[0], &ch, sizeof(ch))) == sizeof(ch)) {}; - if (len == -1 && errno != EAGAIN && errno != ENOBUFS) - fail(errno, "write", socktype, NULL); - OK("write"); - if (len != -1 && len != sizeof(ch)) - fail_assertion("write", socktype, NULL, "write length"); - OK("write length"); - - /* - * Check to make sure the socket is no longer writable. - */ - ts.tv_sec = 0; - ts.tv_nsec = 0; - i = kevent(kq, NULL, 0, &ke, 1, &ts); - if (i == -1) - fail(errno, "kevent", socktype, "EVFILT_WRITE"); - OK("EVFILT_WRITE"); - if (i != 0) - fail_assertion("kevent", socktype, "EVFILT_WRITE", - "full socket writable"); - OK("full socket writable"); - - EV_SET(&ke, fd[0], EVFILT_WRITE, EV_DELETE, 0, 0, NULL); - if (kevent(kq, &ke, 1, NULL, 0, NULL) == -1) - fail(errno, "kevent", socktype, "EVFILT_WRITE, EV_DELETE"); - OK("EVFILT_WRITE, EV_DELETE"); -} - -/* - * Basic registration exercise for kqueue(2). Create several types/brands of - * sockets, and confirm that we can register for various events on them. - */ -int -main(void) -{ - int kq, sv[2]; - - printf("1..49\n"); - - kq = kqueue(); - if (kq == -1) - fail(errno, "kqueue", NULL, NULL); - OK("kqueue()"); - - /* - * Create a UNIX domain datagram socket, and attach/test/detach a - * read filter on it. - */ - if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1) - fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL); - OK("socketpair() 1"); - - if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0) - fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); - OK("fcntl() 1"); - if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0) - fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); - OK("fnctl() 2"); - - test_evfilt_read(kq, sv, "PF_UNIX, SOCK_DGRAM"); - - if (close(sv[0]) == -1) - fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]"); - OK("close() 1"); - if (close(sv[1]) == -1) - fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]"); - OK("close() 2"); - -#if 0 - /* - * XXXRW: We disable the write test in the case of datagram sockets, - * as kqueue can't tell when the remote socket receive buffer is - * full, whereas the UNIX domain socket implementation can tell and - * returns ENOBUFS. - */ - /* - * Create a UNIX domain datagram socket, and attach/test/detach a - * write filter on it. - */ - if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1) - fail(errno, "socketpair", "PF_UNIX, SOCK_DGRAM", NULL); - - if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0) - fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); - if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0) - fail(errno, "fcntl", "PF_UNIX, SOCK_DGRAM", "O_NONBLOCK"); - - test_evfilt_write(kq, sv, "PF_UNIX, SOCK_DGRAM"); - - if (close(sv[0]) == -1) - fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[0]"); - if (close(sv[1]) == -1) - fail(errno, "close", "PF_UNIX/SOCK_DGRAM", "sv[1]"); -#endif - - /* - * Create a UNIX domain stream socket, and attach/test/detach a - * read filter on it. - */ - if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) - fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL); - OK("socketpair() 2"); - - if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0) - fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); - OK("fcntl() 3"); - if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0) - fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); - OK("fcntl() 4"); - - test_evfilt_read(kq, sv, "PF_UNIX, SOCK_STREAM"); - - if (close(sv[0]) == -1) - fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]"); - OK("close() 3"); - if (close(sv[1]) == -1) - fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]"); - OK("close() 4"); - - /* - * Create a UNIX domain stream socket, and attach/test/detach a - * write filter on it. - */ - if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) - fail(errno, "socketpair", "PF_UNIX, SOCK_STREAM", NULL); - OK("socketpair() 3"); - - if (fcntl(sv[0], F_SETFL, O_NONBLOCK) != 0) - fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); - OK("fcntl() 5"); - if (fcntl(sv[1], F_SETFL, O_NONBLOCK) != 0) - fail(errno, "fcntl", "PF_UNIX, SOCK_STREAM", "O_NONBLOCK"); - OK("fcntl() 6"); - - test_evfilt_write(kq, sv, "PF_UNIX, SOCK_STREAM"); - - if (close(sv[0]) == -1) - fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[0]"); - OK("close() 5"); - if (close(sv[1]) == -1) - fail(errno, "close", "PF_UNIX/SOCK_STREAM", "sv[1]"); - OK("close() 6"); - - if (close(kq) == -1) - fail(errno, "close", "kq", NULL); - OK("close() 7"); - - return (0); -} diff --git a/tests/sys/sockets/listen_backlog_test.c b/tests/sys/sockets/listen_backlog_test.c deleted file mode 100644 index 2276393..0000000 --- a/tests/sys/sockets/listen_backlog_test.c +++ /dev/null @@ -1,383 +0,0 @@ -/*- - * Copyright (c) 2005 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/sysctl.h> - -#include <err.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -/* - * This regression test is intended to validate that the backlog parameter - * set by listen() is properly set, can be retrieved using SO_LISTENQLIMIT, - * and that it can be updated by later calls to listen(). We also check that - * SO_LISTENQLIMIT cannot be set. - * - * Future things to test: - * - * - That if we change the value of kern.ipc.somaxconn, the limits really - * do change. - * - * - That limits are, approximately, enforced and implemented. - * - * - All this on multiple socket types -- i.e., PF_LOCAL. - * - * - That we also test SO_LISTENQLEN and SO_LISTENINCQLEN. - */ - -/* - * We retrieve kern.ipc.somaxconn before running the tests in order to use a - * run-time set value of SOMAXCONN, rather than compile-time set. We assume - * that no other process will be simultaneously frobbing it, and these tests - * may fail if that assumption is not held. - */ -static int somaxconn; - -/* - * Retrieve the current socket listen queue limit using SO_LISTENQLIMIT. - */ -static int -socket_get_backlog(int sock, int *backlogp, const char *testclass, - const char *test, const char *testfunc) -{ - socklen_t len; - int i; - - len = sizeof(i); - if (getsockopt(sock, SOL_SOCKET, SO_LISTENQLIMIT, &i, &len) < 0) { - warn("%s: %s: %s: socket_get_backlog: getsockopt(" - "SOL_SOCKET, SO_LISTENQLIMIT)", testclass, test, - testfunc); - return (-1); - } - - if (len != sizeof(i)) { - warnx("%s: %s: %s: socket_get_backlog: getsockopt(" - "SOL_SOCKET, SO_LISTENQLIMIT): returned size %d", - testclass, test, testfunc, len); - return (-1); - } - - *backlogp = i; - - return (0); -} - -/* - * Create a socket, check the queue limit on creation, perform a listen(), - * and make sure that the limit was set as expected by listen(). - */ -static int -socket_listen(int domain, int type, int protocol, int backlog, - int create_backlog_assertion, int listen_backlog_assertion, int *sockp, - const char *domainstring, const char *typestring, const char *testclass, - const char *test) -{ - int backlog_retrieved, sock; - - sock = socket(domain, type, protocol); - if (sock < 0) { - warn("%s: %s: socket_listen: socket(%s, %s)", testclass, - test, domainstring, typestring); - close(sock); - return (-1); - } - - if (socket_get_backlog(sock, &backlog_retrieved, testclass, test, - "socket_listen") < 0) { - close(sock); - return (-1); - } - - if (backlog_retrieved != create_backlog_assertion) { - warnx("%s: %s: socket_listen: create backlog is %d not %d", - testclass, test, backlog_retrieved, - create_backlog_assertion); - close(sock); - return (-1); - } - - if (listen(sock, backlog) < 0) { - warn("%s: %s: socket_listen: listen(, %d)", testclass, test, - backlog); - close(sock); - return (-1); - } - - if (socket_get_backlog(sock, &backlog_retrieved, testclass, test, - "socket_listen") < 0) { - close(sock); - return (-1); - } - - if (backlog_retrieved != listen_backlog_assertion) { - warnx("%s: %s: socket_listen: listen backlog is %d not %d", - testclass, test, backlog_retrieved, - listen_backlog_assertion); - close(sock); - return (-1); - } - - *sockp = sock; - return (0); -} - -/* - * This test creates sockets and tests default states before and after - * listen(). Specifically, we expect a queue limit of 0 before listen, and - * then various settings for after listen(). If the passed backlog was - * either < 0 or > somaxconn, it should be set to somaxconn; otherwise, the - * passed queue depth. - */ -static void -test_defaults(void) -{ - int sock; - - /* - * First pass. Confirm the default is 0. Listen with a backlog of - * 0 and confirm it gets set that way. - */ - if (socket_listen(PF_INET, SOCK_STREAM, 0, 0, 0, 0, &sock, "PF_INET", - "SOCK_STREAM", "test_defaults", "default_0_listen_0") < 0) - exit(-1); - close(sock); - - /* - * Second pass. Listen with a backlog of -1 and make sure it is set - * to somaxconn. - */ - if (socket_listen(PF_INET, SOCK_STREAM, 0, -1, 0, somaxconn, &sock, - "PF_INET", "SOCK_STREAM", "test_defaults", "default_0_listen_-1") - < 0) - exit(-1); - close(sock); - - /* - * Third pass. Listen with a backlog of 1 and make sure it is set to - * 1. - */ - if (socket_listen(PF_INET, SOCK_STREAM, 0, 1, 0, 1, &sock, "PF_INET", - "SOCK_STREAM", "test_defaults", "default_0_listen_1") < 0) - exit(-1); - close(sock); - - /* - * Fourth pass. Listen with a backlog of somaxconn and make sure it - * is set to somaxconn. - */ - if (socket_listen(PF_INET, SOCK_STREAM, 0, somaxconn, 0, somaxconn, - &sock, "PF_INET", "SOCK_STREAM", "test_defaults", - "default_0_listen_somaxconn") < 0) - exit(-1); - close(sock); - - /* - * Fifth pass. Listen with a backlog of somaxconn+1 and make sure it - * is set to somaxconn. - */ - if (socket_listen(PF_INET, SOCK_STREAM, 0, somaxconn+1, 0, somaxconn, - &sock, "PF_INET", "SOCK_STREAM", "test_defaults", - "default_0_listen_somaxconn+1") < 0) - exit(-1); - close(sock); -} - -/* - * Create a socket, set the initial listen() state, then update the queue - * depth using listen(). Check that the backlog is as expected after both - * the first and second listen(). - */ -static int -socket_listen_update(int domain __unused, int type __unused, - int protocol __unused, int backlog, - int update_backlog, int listen_backlog_assertion, - int update_backlog_assertion, int *sockp, const char *domainstring, - const char *typestring, const char *testclass, const char *test) -{ - int backlog_retrieved, sock; - - sock = socket(PF_INET, SOCK_STREAM, 0); - if (sock < 0) { - warn("%s: %s: socket_listen_update: socket(%s, %s)", - testclass, test, domainstring, typestring); - return (-1); - } - - if (listen(sock, backlog) < 0) { - warn("%s: %s: socket_listen_update: initial listen(, %d)", - testclass, test, backlog); - close(sock); - return (-1); - } - - if (socket_get_backlog(sock, &backlog_retrieved, testclass, test, - "socket_listen_update") < 0) { - close(sock); - return (-1); - } - - if (backlog_retrieved != listen_backlog_assertion) { - warnx("%s: %s: socket_listen_update: initial backlog is %d " - "not %d", testclass, test, backlog_retrieved, - listen_backlog_assertion); - close(sock); - return (-1); - } - - if (listen(sock, update_backlog) < 0) { - warn("%s: %s: socket_listen_update: update listen(, %d)", - testclass, test, update_backlog); - close(sock); - return (-1); - } - - if (socket_get_backlog(sock, &backlog_retrieved, testclass, test, - "socket_listen_update") < 0) { - close(sock); - return (-1); - } - - if (backlog_retrieved != update_backlog_assertion) { - warnx("%s: %s: socket_listen_update: updated backlog is %d " - "not %d", testclass, test, backlog_retrieved, - update_backlog_assertion); - close(sock); - return (-1); - } - - *sockp = sock; - return (0); -} - -/* - * This test tests using listen() to update the queue depth after a socket - * has already been marked as listening. We test several cases: setting the - * socket < 0, 0, 1, somaxconn, and somaxconn + 1. - */ -static void -test_listen_update(void) -{ - int sock; - - /* - * Set to 5, update to -1, which should give somaxconn. - */ - if (socket_listen_update(PF_INET, SOCK_STREAM, 0, 5, -1, 5, somaxconn, - &sock, "PF_INET", "SOCK_STREAM", "test_listen_update", - "update_5,-1") < 0) - exit(-1); - close(sock); - - /* - * Set to 5, update to 0, which should give 0. - */ - if (socket_listen_update(PF_INET, SOCK_STREAM, 0, 5, 0, 5, 0, &sock, - "PF_INET", "SOCK_STREAM", "test_listen_update", "update_5,0") - < 0) - exit(-1); - close(sock); - - /* - * Set to 5, update to 1, which should give 1. - */ - if (socket_listen_update(PF_INET, SOCK_STREAM, 0, 5, 1, 5, 1, &sock, - "PF_INET", "SOCK_STREAM", "test_listen_update", "update_5,1") - < 0) - exit(-1); - close(sock); - - /* - * Set to 5, update to somaxconn, which should give somaxconn. - */ - if (socket_listen_update(PF_INET, SOCK_STREAM, 0, 5, somaxconn, 5, - somaxconn, &sock, "PF_INET", "SOCK_STREAM", "test_listen_update", - "update_5,somaxconn") < 0) - exit(-1); - close(sock); - - /* - * Set to 5, update to somaxconn+1, which should give somaxconn. - */ - if (socket_listen_update(PF_INET, SOCK_STREAM, 0, 5, somaxconn+1, 5, - somaxconn, &sock, "PF_INET", "SOCK_STREAM", "test_listen_update", - "update_5,somaxconn+1") < 0) - exit(-1); - close(sock); -} - -/* - * SO_LISTENQLIMIT is a read-only socket option, so make sure we get an error - * if we try to write it. - */ -static void -test_set_qlimit(void) -{ - int i, ret, sock; - - sock = socket(PF_INET, SOCK_STREAM, 0); - if (sock < 0) - err(-1, "test_set_qlimit: socket(PF_INET, SOCK_STREAM)"); - - i = 0; - ret = setsockopt(sock, SOL_SOCKET, SO_LISTENQLIMIT, &i, sizeof(i)); - if (ret < 0 && errno != ENOPROTOOPT) { - warn("test_set_qlimit: setsockopt(SOL_SOCKET, " - "SO_LISTENQLIMIT, 0): unexpected error"); - close(sock); - } - - if (ret == 0) { - warnx("test_set_qlimit: setsockopt(SOL_SOCKET, " - "SO_LISTENQLIMIT, 0) succeeded"); - close(sock); - exit(-1); - } - close(sock); -} - -int -main(void) -{ - size_t len; - - len = sizeof(somaxconn); - if (sysctlbyname("kern.ipc.somaxconn", &somaxconn, &len, NULL, 0) - < 0) - err(-1, "sysctlbyname(kern.ipc.somaxconn)"); - - test_defaults(); - test_listen_update(); - test_set_qlimit(); - - return (0); -} diff --git a/tests/sys/sockets/listenclose_test.c b/tests/sys/sockets/listenclose_test.c deleted file mode 100644 index f920846..0000000 --- a/tests/sys/sockets/listenclose_test.c +++ /dev/null @@ -1,111 +0,0 @@ -/*- - * Copyright (c) 2004-2005 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/socket.h> - -#include <netinet/in.h> - -#include <arpa/inet.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -/* - * The listenclose regression test is designed to catch kernel bugs that may - * trigger as a result of performing a close on a listen() socket with as-yet - * unaccepted connections in its queues. This results in the connections - * being aborted, which is a not-often-followed code path. To do this, we - * create a local TCP socket, build a non-blocking connection to it, and then - * close the accept socket. The connection must be non-blocking or the - * program will block and as such connect() will not return as accept() is - * never called. - */ - -int -main(void) -{ - int listen_sock, connect_sock; - struct sockaddr_in sin; - socklen_t len; - u_short port; - int arg; - - listen_sock = socket(PF_INET, SOCK_STREAM, 0); - if (listen_sock == -1) - errx(-1, - "socket(PF_INET, SOCK_STREAM, 0) for listen socket: %s", - strerror(errno)); - - - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = 0; - - if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) - errx(-1, "bind(%s, %d) for listen socket: %s", - inet_ntoa(sin.sin_addr), 0, strerror(errno)); - - len = sizeof(sin); - if (getsockname(listen_sock, (struct sockaddr *)&sin, &len) < 0) - errx(-1, "getsockname() for listen socket: %s", - strerror(errno)); - port = sin.sin_port; - - if (listen(listen_sock, -1) < 0) - errx(-1, "listen() for listen socket: %s", strerror(errno)); - - connect_sock = socket(PF_INET, SOCK_STREAM, 0); - if (connect_sock == -1) - errx(-1, "socket(PF_INET, SOCK_STREAM, 0) for connect " - "socket: %s", strerror(errno)); - - arg = O_NONBLOCK; - if (fcntl(connect_sock, F_SETFL, &arg) < 0) - errx(-1, "socket(PF_INET, SOCK_STREAM, 0) for connect socket" - ": %s", strerror(errno)); - - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = port; - - if (connect(connect_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) - errx(-1, "connect() for connect socket: %s", strerror(errno)); - close(connect_sock); - close(listen_sock); - - return (0); -} diff --git a/tests/sys/sockets/pr_atomic_test.c b/tests/sys/sockets/pr_atomic_test.c deleted file mode 100644 index e902cf7..0000000 --- a/tests/sys/sockets/pr_atomic_test.c +++ /dev/null @@ -1,109 +0,0 @@ -/*- - * Copyright (c) 2006 Bruce M. Simpson - * 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. - * - * $FreeBSD$ - */ - -/* - * Regression test for uiomove in kernel; specifically for PR kern/38495. - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include <stdlib.h> -#include <signal.h> -#include <setjmp.h> -#include <string.h> -#include <err.h> -#include <errno.h> -#include <unistd.h> - -static char socket_path[] = "tmp.XXXXXX"; - -static jmp_buf myjmpbuf; - -static void handle_sigalrm(int signo __unused) -{ - longjmp(myjmpbuf, 1); -} - -int -main(void) -{ - struct sockaddr_un un; - pid_t pid; - int s; - - if (mkstemp(socket_path) == -1) - err(1, "mkstemp"); - s = socket(PF_LOCAL, SOCK_DGRAM, 0); - if (s == -1) - errx(-1, "socket"); - memset(&un, 0, sizeof(un)); - un.sun_family = AF_LOCAL; - unlink(socket_path); - strcpy(un.sun_path, socket_path); - if (bind(s, (struct sockaddr *)&un, sizeof(un)) == -1) - errx(-1, "bind"); - pid = fork(); - if (pid == -1) - errx(-1, "fork"); - if (pid == 0) { - int conn; - char buf[] = "AAAAAAAAA"; - - close(s); - conn = socket(AF_LOCAL, SOCK_DGRAM, 0); - if (conn == -1) - errx(-1,"socket"); - if (sendto(conn, buf, sizeof(buf), 0, (struct sockaddr *)&un, - sizeof(un)) != sizeof(buf)) - errx(-1,"sendto"); - close(conn); - _exit(0); - } - - sleep(5); - - /* Make sure the data is there when we try to receive it. */ - if (recvfrom(s, (void *)-1, 1, 0, NULL, NULL) != -1) - errx(-1,"recvfrom succeeded when failure expected"); - - (void)signal(SIGALRM, handle_sigalrm); - if (setjmp(myjmpbuf) == 0) { - /* - * This recvfrom will panic an unpatched system, and block - * a patched one. - */ - alarm(5); - (void)recvfrom(s, (void *)-1, 1, 0, NULL, NULL); - } - - /* We should reach here via longjmp() and all should be well. */ - - return (0); -} diff --git a/tests/sys/sockets/reconnect_test.c b/tests/sys/sockets/reconnect_test.c deleted file mode 100644 index 27f32cc..0000000 --- a/tests/sys/sockets/reconnect_test.c +++ /dev/null @@ -1,132 +0,0 @@ -/*- - * Copyright (c) 2005 Maxim Sobolev - * 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. - * - * $FreeBSD$ - */ - -/* - * The reconnect regression test is designed to catch kernel bug that may - * prevent changing association of already associated datagram unix domain - * socket when server side of connection has been closed. - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/uio.h> -#include <sys/un.h> -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <string.h> -#include <unistd.h> - -static char uds_name1[] = "reconnect.XXXXXXXX"; -static char uds_name2[] = "reconnect.XXXXXXXX"; - -#define sstosa(ss) ((struct sockaddr *)(ss)) - -static void -prepare_ifsun(struct sockaddr_un *ifsun, const char *path) -{ - - memset(ifsun, '\0', sizeof(*ifsun)); -#if !defined(__linux__) && !defined(__solaris__) - ifsun->sun_len = strlen(path); -#endif - ifsun->sun_family = AF_LOCAL; - strcpy(ifsun->sun_path, path); -} - -static int -create_uds_server(const char *path) -{ - struct sockaddr_un ifsun; - int sock; - - prepare_ifsun(&ifsun, path); - - unlink(ifsun.sun_path); - - sock = socket(PF_LOCAL, SOCK_DGRAM, 0); - if (sock == -1) - err(1, "can't create socket"); - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sock, sizeof(sock)); - if (bind(sock, sstosa(&ifsun), sizeof(ifsun)) < 0) - err(1, "can't bind to a socket"); - - return sock; -} - -static void -connect_uds_server(int sock, const char *path) -{ - struct sockaddr_un ifsun; - int e; - - prepare_ifsun(&ifsun, path); - - e = connect(sock, sstosa(&ifsun), sizeof(ifsun)); - if (e < 0) - err(1, "can't connect to a socket"); -} - -static void -cleanup(void) -{ - - unlink(uds_name1); - unlink(uds_name2); -} - -int -main() -{ - int s_sock1, s_sock2, c_sock; - - atexit(cleanup); - - if (mkstemp(uds_name1) == -1) - err(1, "mkstemp"); - unlink(uds_name1); - s_sock1 = create_uds_server(uds_name1); - - if (mkstemp(uds_name2) == -1) - err(1, "mkstemp"); - unlink(uds_name2); - s_sock2 = create_uds_server(uds_name2); - - c_sock = socket(PF_LOCAL, SOCK_DGRAM, 0); - if (c_sock < 0) - err(1, "can't create socket"); - - connect_uds_server(c_sock, uds_name1); - close(s_sock1); - connect_uds_server(c_sock, uds_name2); - - exit (0); -} diff --git a/tests/sys/sockets/rtsocket_test.c b/tests/sys/sockets/rtsocket_test.c deleted file mode 100644 index b5824b3..0000000 --- a/tests/sys/sockets/rtsocket_test.c +++ /dev/null @@ -1,101 +0,0 @@ -/*- - * Copyright (c) 2006 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -/* - * Simple routing socket regression test: create and destroy a raw routing - * socket, and make sure that dgram and stream don't work, socketpair, etc. - */ - -#include <sys/types.h> -#include <sys/socket.h> - -#include <net/route.h> - -#include <err.h> -#include <errno.h> -#include <unistd.h> - -int -main(void) -{ - int sock, socks[2]; - - sock = socket(PF_ROUTE, SOCK_STREAM, 0); - if (sock >= 0) { - close(sock); - errx(-1, "socket(PF_ROUTE, SOCK_STREAM, 0) returned %d", - sock); - } - - if (errno != EPROTONOSUPPORT) - err(-1, "socket(PF_ROUTE, SOCK_STREAM, 0)"); - - sock = socket(PF_ROUTE, SOCK_DGRAM, 0); - if (sock >= 0) { - close(sock); - errx(-1, "socket(PF_ROUTE, SOCK_DGRAM, 0) returned %d", - sock); - } - - if (errno != EPROTONOSUPPORT) - err(-1, "socket(PF_ROUTE, SOCK_DGRAM, 0)"); - - sock = socket(PF_ROUTE, SOCK_RAW, 0); - if (sock < 0) - err(-1, "socket(PF_ROUTE, SOCK_RAW, 0)"); - close(sock); - - if (socketpair(PF_ROUTE, SOCK_STREAM, 0, socks) == 0) { - close(socks[0]); - close(socks[1]); - errx(-1, - "socketpair(PF_ROUTE, SOCK_STREAM, 0, socks) success"); - } - - if (errno != EPROTONOSUPPORT) - err(-1, "socketpair(PF_ROUTE, SOCK_STREAM, 0, socks)"); - - if (socketpair(PF_ROUTE, SOCK_DGRAM, 0, socks) == 0) { - close(socks[0]); - close(socks[1]); - errx(-1, - "socketpair(PF_ROUTE, SOCK_DGRAM, 0, socks) success"); - } - - if (errno != EPROTONOSUPPORT) - err(-1, "socketpair(PF_ROUTE, SOCK_DGRAM, 0, socks)"); - - if (socketpair(PF_ROUTE, SOCK_RAW, 0, socks) == 0) { - close(socks[0]); - close(socks[1]); - errx(-1, - "socketpair(PF_ROUTE, SOCK_STREAM, 0, socks) success"); - } - - return (0); -} diff --git a/tests/sys/sockets/sblock_test.c b/tests/sys/sockets/sblock_test.c deleted file mode 100644 index 415c4d4..0000000 --- a/tests/sys/sockets/sblock_test.c +++ /dev/null @@ -1,207 +0,0 @@ -/*- - * Copyright (c) 2007 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -/* - * Sockets serialize I/O in each direction in order to avoid interlacing of - * I/O by multiple processes or threcvs recving or sending the socket. This - * is done using some form of kernel lock (varies by kernel version), called - * "sblock" in FreeBSD. However, to avoid unkillable processes waiting on - * I/O that may be entirely controlled by a remote network endpoint, that - * lock acquisition must be interruptible. - * - * To test this, set up a local domain stream socket pair and a set of three - * processes. Two processes block in recv(), the first on sbwait (wait for - * I/O), and the second on the sblock waiting for the first to finish. A - * third process is responsible for signalling the second process, then - * writing to the socket. Depending on the error returned in the second - * process, we can tell whether the sblock wait was interrupted, or if - * instead the process only woke up when the write was performed. - */ - -#include <sys/socket.h> - -#include <err.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -static int interrupted; -static void -signal_handler(int signum __unused) -{ - - interrupted++; -} - -/* - * Process that will perform a blocking recv on a UNIX domain socket. This - * should return one byte of data. - */ -static void -blocking_recver(int fd) -{ - ssize_t len; - char ch; - - len = recv(fd, &ch, sizeof(ch), 0); - if (len < 0) - err(-1, "FAIL: blocking_recver: recv"); - if (len == 0) - errx(-1, "FAIL: blocking_recver: recv: eof"); - if (len != 1) - errx(-1, "FAIL: blocking_recver: recv: %zd bytes", len); - if (interrupted) - errx(-1, "FAIL: blocking_recver: interrupted wrong pid"); -} - -/* - * Process that will perform a locking recv on a UNIX domain socket. - * - * This is where we figure out if the test worked or not. If it has failed, - * then recv() will return EOF, as the close() arrives before the signal, - * meaning that the wait for the sblock was not interrupted; if it has - * succeeded, we get EINTR as the signal interrupts the lock request. - */ -static void -locking_recver(int fd) -{ - ssize_t len; - char ch; - - if (sleep(1) != 0) - err(-1, "FAIL: locking_recver: sleep"); - len = recv(fd, &ch, sizeof(ch), 0); - if (len < 0 && errno != EINTR) - err(-1, "FAIL: locking_recver: recv"); - if (len < 0 && errno == EINTR) { - fprintf(stderr, "PASS\n"); - exit(0); - } - if (len == 0) - errx(-1, "FAIL: locking_recver: recv: eof"); - if (!interrupted) - errx(-1, "FAIL: locking_recver: not interrupted"); -} - -static void -signaller(pid_t locking_recver_pid, int fd) -{ - ssize_t len; - char ch; - - if (sleep(2) != 0) { - warn("signaller sleep(2)"); - return; - } - if (kill(locking_recver_pid, SIGHUP) < 0) { - warn("signaller kill(%d)", locking_recver_pid); - return; - } - if (sleep(1) != 0) { - warn("signaller sleep(1)"); - return; - } - len = send(fd, &ch, sizeof(ch), 0); - if (len < 0) { - warn("signaller send"); - return; - } - if (len != sizeof(ch)) { - warnx("signaller send ret %zd", len); - return; - } - if (close(fd) < 0) { - warn("signaller close"); - return; - } - if (sleep(1) != 0) { - warn("signaller sleep(1)"); - return; - } -} - -int -main(void) -{ - int error, fds[2], recver_fd, sender_fd; - pid_t blocking_recver_pid; - pid_t locking_recver_pid; - struct sigaction sa; - - if (sigaction(SIGHUP, NULL, &sa) < 0) - err(-1, "FAIL: sigaction(SIGHUP, NULL, &sa)"); - - sa.sa_handler = signal_handler; - if (sa.sa_flags & SA_RESTART) - printf("SIGHUP restartable by default (cleared)\n"); - sa.sa_flags &= ~SA_RESTART; - - if (sigaction(SIGHUP, &sa, NULL) < 0) - err(-1, "FAIL: sigaction(SIGHUP, &sa, NULL)"); - -#if 0 - if (signal(SIGHUP, signal_handler) == SIG_ERR) - err(-1, "FAIL: signal(SIGHUP)"); -#endif - - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0) - err(-1, "FAIL: socketpair(PF_LOCAL, SOGK_STREAM, 0)"); - - sender_fd = fds[0]; - recver_fd = fds[1]; - - blocking_recver_pid = fork(); - if (blocking_recver_pid < 0) - err(-1, "FAIL: fork"); - if (blocking_recver_pid == 0) { - close(sender_fd); - blocking_recver(recver_fd); - exit(0); - } - - locking_recver_pid = fork(); - if (locking_recver_pid < 0) { - error = errno; - kill(blocking_recver_pid, SIGKILL); - errno = error; - err(-1, "FAIL: fork"); - } - if (locking_recver_pid == 0) { - close(sender_fd); - locking_recver(recver_fd); - exit(0); - } - - signaller(locking_recver_pid, sender_fd); - - kill(blocking_recver_pid, SIGKILL); - kill(locking_recver_pid, SIGKILL); - exit(0); -} diff --git a/tests/sys/sockets/sendfile_test.c b/tests/sys/sockets/sendfile_test.c deleted file mode 100644 index 18ae9ad..0000000 --- a/tests/sys/sockets/sendfile_test.c +++ /dev/null @@ -1,486 +0,0 @@ -/*- - * Copyright (c) 2006 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/wait.h> - -#include <netinet/in.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <md5.h> -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* - * Simple regression test for sendfile. Creates a file sized at four pages - * and then proceeds to send it over a series of sockets, exercising a number - * of cases and performing limited validation. - */ - -#define FAIL(msg) {printf("# %s\n", msg); \ - return (-1);} - -#define FAIL_ERR(msg) {printf("# %s: %s\n", msg, strerror(errno)); \ - return (-1);} - -#define TEST_PORT 5678 -#define TEST_MAGIC 0x4440f7bb -#define TEST_PAGES 4 -#define TEST_SECONDS 30 - -struct test_header { - uint32_t th_magic; - uint32_t th_header_length; - uint32_t th_offset; - uint32_t th_length; - char th_md5[33]; -}; - -struct sendfile_test { - uint32_t hdr_length; - uint32_t offset; - uint32_t length; - uint32_t file_size; -}; - -static int file_fd; -static char path[PATH_MAX]; -static int listen_socket; -static int accept_socket; - -static int test_th(struct test_header *th, uint32_t *header_length, - uint32_t *offset, uint32_t *length); -static void signal_alarm(int signum); -static void setup_alarm(int seconds); -static void cancel_alarm(void); -static int receive_test(void); -static void run_child(void); -static int new_test_socket(int *connect_socket); -static void init_th(struct test_header *th, uint32_t header_length, - uint32_t offset, uint32_t length); -static int send_test(int connect_socket, struct sendfile_test); -static int write_test_file(size_t file_size); -static void run_parent(void); -static void cleanup(void); - - -static int -test_th(struct test_header *th, uint32_t *header_length, uint32_t *offset, - uint32_t *length) -{ - - if (th->th_magic != htonl(TEST_MAGIC)) - FAIL("magic number not found in header") - *header_length = ntohl(th->th_header_length); - *offset = ntohl(th->th_offset); - *length = ntohl(th->th_length); - return (0); -} - -static void -signal_alarm(int signum) -{ - (void)signum; - - printf("# test timeout\n"); - - if (accept_socket > 0) - close(accept_socket); - if (listen_socket > 0) - close(listen_socket); - - _exit(-1); -} - -static void -setup_alarm(int seconds) -{ - struct itimerval itv; - bzero(&itv, sizeof(itv)); - (void)seconds; - itv.it_value.tv_sec = seconds; - - signal(SIGALRM, signal_alarm); - setitimer(ITIMER_REAL, &itv, NULL); -} - -static void -cancel_alarm(void) -{ - struct itimerval itv; - bzero(&itv, sizeof(itv)); - setitimer(ITIMER_REAL, &itv, NULL); -} - -static int -receive_test(void) -{ - uint32_t header_length, offset, length, counter; - struct test_header th; - ssize_t len; - char buf[10240]; - MD5_CTX md5ctx; - char *rxmd5; - - len = read(accept_socket, &th, sizeof(th)); - if (len < 0 || (size_t)len < sizeof(th)) - FAIL_ERR("read") - - if (test_th(&th, &header_length, &offset, &length) != 0) - return (-1); - - MD5Init(&md5ctx); - - counter = 0; - while (1) { - len = read(accept_socket, buf, sizeof(buf)); - if (len < 0 || len == 0) - break; - counter += len; - MD5Update(&md5ctx, buf, len); - } - - rxmd5 = MD5End(&md5ctx, NULL); - - if ((counter != header_length+length) || - memcmp(th.th_md5, rxmd5, 33) != 0) - FAIL("receive length mismatch") - - free(rxmd5); - return (0); -} - -static void -run_child(void) -{ - struct sockaddr_in sin; - int rc = 0; - - listen_socket = socket(PF_INET, SOCK_STREAM, 0); - if (listen_socket < 0) { - printf("# socket: %s\n", strerror(errno)); - rc = -1; - } - - if (!rc) { - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(TEST_PORT); - - if (bind(listen_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0) { - printf("# bind: %s\n", strerror(errno)); - rc = -1; - } - } - - if (!rc && listen(listen_socket, -1) < 0) { - printf("# listen: %s\n", strerror(errno)); - rc = -1; - } - - if (!rc) { - accept_socket = accept(listen_socket, NULL, NULL); - setup_alarm(TEST_SECONDS); - if (receive_test() != 0) - rc = -1; - } - - cancel_alarm(); - if (accept_socket > 0) - close(accept_socket); - if (listen_socket > 0) - close(listen_socket); - - _exit(rc); -} - -static int -new_test_socket(int *connect_socket) -{ - struct sockaddr_in sin; - int rc = 0; - - *connect_socket = socket(PF_INET, SOCK_STREAM, 0); - if (*connect_socket < 0) - FAIL_ERR("socket") - - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(TEST_PORT); - - if (connect(*connect_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0) - FAIL_ERR("connect") - - return (rc); -} - -static void -init_th(struct test_header *th, uint32_t header_length, uint32_t offset, - uint32_t length) -{ - bzero(th, sizeof(*th)); - th->th_magic = htonl(TEST_MAGIC); - th->th_header_length = htonl(header_length); - th->th_offset = htonl(offset); - th->th_length = htonl(length); - - MD5FileChunk(path, th->th_md5, offset, length); -} - -static int -send_test(int connect_socket, struct sendfile_test test) -{ - struct test_header th; - struct sf_hdtr hdtr, *hdtrp; - struct iovec headers; - char *header; - ssize_t len; - int length; - off_t off; - - len = lseek(file_fd, 0, SEEK_SET); - if (len != 0) - FAIL_ERR("lseek") - - struct stat st; - if (fstat(file_fd, &st) < 0) - FAIL_ERR("fstat") - length = st.st_size - test.offset; - if (test.length > 0 && test.length < (uint32_t)length) - length = test.length; - - init_th(&th, test.hdr_length, test.offset, length); - - len = write(connect_socket, &th, sizeof(th)); - if (len != sizeof(th)) - return (-1); - - if (test.hdr_length != 0) { - header = malloc(test.hdr_length); - if (header == NULL) - FAIL_ERR("malloc") - - hdtrp = &hdtr; - bzero(&headers, sizeof(headers)); - headers.iov_base = header; - headers.iov_len = test.hdr_length; - bzero(&hdtr, sizeof(hdtr)); - hdtr.headers = &headers; - hdtr.hdr_cnt = 1; - hdtr.trailers = NULL; - hdtr.trl_cnt = 0; - } else { - hdtrp = NULL; - header = NULL; - } - - if (sendfile(file_fd, connect_socket, test.offset, test.length, - hdtrp, &off, 0) < 0) { - if (header != NULL) - free(header); - FAIL_ERR("sendfile") - } - - if (length == 0) { - struct stat sb; - - if (fstat(file_fd, &sb) == 0) - length = sb.st_size - test.offset; - } - - if (header != NULL) - free(header); - - if (off != length) - FAIL("offset != length") - - return (0); -} - -static int -write_test_file(size_t file_size) -{ - char *page_buffer; - ssize_t len; - static size_t current_file_size = 0; - - if (file_size == current_file_size) - return (0); - else if (file_size < current_file_size) { - if (ftruncate(file_fd, file_size) != 0) - FAIL_ERR("ftruncate"); - current_file_size = file_size; - return (0); - } - - page_buffer = malloc(file_size); - if (page_buffer == NULL) - FAIL_ERR("malloc") - bzero(page_buffer, file_size); - - len = write(file_fd, page_buffer, file_size); - if (len < 0) - FAIL_ERR("write") - - len = lseek(file_fd, 0, SEEK_SET); - if (len < 0) - FAIL_ERR("lseek") - if (len != 0) - FAIL("len != 0") - - free(page_buffer); - current_file_size = file_size; - return (0); -} - -static void -run_parent(void) -{ - int connect_socket; - int status; - int test_num; - int test_count; - int pid; - size_t desired_file_size = 0; - - const int pagesize = getpagesize(); - - struct sendfile_test tests[] = { - { .hdr_length = 0, .offset = 0, .length = 1 }, - { .hdr_length = 0, .offset = 0, .length = pagesize }, - { .hdr_length = 0, .offset = 1, .length = 1 }, - { .hdr_length = 0, .offset = 1, .length = pagesize }, - { .hdr_length = 0, .offset = pagesize, .length = pagesize }, - { .hdr_length = 0, .offset = 0, .length = 2*pagesize }, - { .hdr_length = 0, .offset = 0, .length = 0 }, - { .hdr_length = 0, .offset = pagesize, .length = 0 }, - { .hdr_length = 0, .offset = 2*pagesize, .length = 0 }, - { .hdr_length = 0, .offset = TEST_PAGES*pagesize, .length = 0 }, - { .hdr_length = 0, .offset = 0, .length = pagesize, - .file_size = 1 } - }; - - test_count = sizeof(tests) / sizeof(tests[0]); - printf("1..%d\n", test_count); - - for (test_num = 1; test_num <= test_count; test_num++) { - - desired_file_size = tests[test_num - 1].file_size; - if (desired_file_size == 0) - desired_file_size = TEST_PAGES * pagesize; - if (write_test_file(desired_file_size) != 0) { - printf("not ok %d\n", test_num); - continue; - } - - pid = fork(); - if (pid == -1) { - printf("not ok %d\n", test_num); - continue; - } - - if (pid == 0) - run_child(); - - usleep(250000); - - if (new_test_socket(&connect_socket) != 0) { - printf("not ok %d\n", test_num); - kill(pid, SIGALRM); - close(connect_socket); - continue; - } - - if (send_test(connect_socket, tests[test_num-1]) != 0) { - printf("not ok %d\n", test_num); - kill(pid, SIGALRM); - close(connect_socket); - continue; - } - - close(connect_socket); - if (waitpid(pid, &status, 0) == pid) { - if (WIFEXITED(status) && WEXITSTATUS(status) == 0) - printf("%s %d\n", "ok", test_num); - else - printf("%s %d\n", "not ok", test_num); - } - else { - printf("not ok %d\n", test_num); - } - } -} - -static void -cleanup(void) -{ - - unlink(path); -} - -int -main(int argc, char *argv[]) -{ - int pagesize; - - path[0] = '\0'; - - pagesize = getpagesize(); - - if (argc == 1) { - snprintf(path, sizeof(path), "sendfile.XXXXXXXXXXXX"); - file_fd = mkstemp(path); - if (file_fd == -1) - FAIL_ERR("mkstemp"); - } else if (argc == 2) { - (void)strlcpy(path, argv[1], sizeof(path)); - file_fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0600); - if (file_fd == -1) - FAIL_ERR("open"); - } else { - FAIL("usage: sendfile [path]"); - } - - atexit(cleanup); - - run_parent(); - return (0); -} diff --git a/tests/sys/sockets/shutdown_test.c b/tests/sys/sockets/shutdown_test.c deleted file mode 100644 index 3d23c94..0000000 --- a/tests/sys/sockets/shutdown_test.c +++ /dev/null @@ -1,110 +0,0 @@ -/*- - * Copyright (C) 2005 The FreeBSD Project. 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/socket.h> - -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <err.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -int -main(void) -{ - struct sockaddr_in sock; - socklen_t len; - int listen_sock, connect_sock; - u_short port; - - listen_sock = -1; - - /* Shutdown(2) on an invalid file descriptor has to return EBADF. */ - if ((shutdown(listen_sock, SHUT_RDWR) != -1) && (errno != EBADF)) - errx(-1, "shutdown() for invalid file descriptor does not " - "return EBADF"); - - listen_sock = socket(PF_INET, SOCK_STREAM, 0); - if (listen_sock == -1) - errx(-1, - "socket(PF_INET, SOCK_STREAM, 0) for listen socket: %s", - strerror(errno)); - - bzero(&sock, sizeof(sock)); - sock.sin_len = sizeof(sock); - sock.sin_family = AF_INET; - sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sock.sin_port = 0; - - if (bind(listen_sock, (struct sockaddr *)&sock, sizeof(sock)) < 0) - errx(-1, "bind(%s, %d) for listen socket: %s", - inet_ntoa(sock.sin_addr), sock.sin_port, strerror(errno)); - - len = sizeof(sock); - if (getsockname(listen_sock, (struct sockaddr *)&sock, &len) < 0) - errx(-1, "getsockname() for listen socket: %s", - strerror(errno)); - port = sock.sin_port; - - if (listen(listen_sock, -1) < 0) - errx(-1, "listen() for listen socket: %s", strerror(errno)); - - connect_sock = socket(PF_INET, SOCK_STREAM, 0); - if (connect_sock == -1) - errx(-1, "socket(PF_INET, SOCK_STREAM, 0) for connect " - "socket: %s", strerror(errno)); - - bzero(&sock, sizeof(sock)); - sock.sin_len = sizeof(sock); - sock.sin_family = AF_INET; - sock.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sock.sin_port = port; - - if (connect(connect_sock, (struct sockaddr *)&sock, sizeof(sock)) < 0) - errx(-1, "connect() for connect socket: %s", strerror(errno)); - /* Try to pass an invalid flags. */ - if ((shutdown(connect_sock, SHUT_RD - 1) != -1) && (errno != EINVAL)) - errx(-1, "shutdown(SHUT_RD - 1) does not return EINVAL"); - if ((shutdown(connect_sock, SHUT_RDWR + 1) != -1) && (errno != EINVAL)) - errx(-1, "shutdown(SHUT_RDWR + 1) does not return EINVAL"); - - if (shutdown(connect_sock, SHUT_RD) < 0) - errx(-1, "shutdown(SHUT_RD) for connect socket: %s", - strerror(errno)); - if (shutdown(connect_sock, SHUT_WR) < 0) - errx(-1, "shutdown(SHUT_WR) for connect socket: %s", - strerror(errno)); - - close(connect_sock); - close(listen_sock); - - return (0); -} diff --git a/tests/sys/sockets/sigpipe_test.c b/tests/sys/sockets/sigpipe_test.c deleted file mode 100644 index 894d9de..0000000 --- a/tests/sys/sockets/sigpipe_test.c +++ /dev/null @@ -1,322 +0,0 @@ -/*- - * Copyright (c) 2005 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/socket.h> - -#include <netinet/in.h> - -#include <err.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* - * This regression test is intended to verify whether or not SIGPIPE is - * properly generated in several simple test cases, as well as testing - * whether SO_NOSIGPIPE disables SIGPIPE, if available on the system. - * SIGPIPE is generated if a write or send is attempted on a socket that has - * been shutdown for write. This test runs several test cases with UNIX - * domain sockets and TCP sockets to confirm that either EPIPE or SIGPIPE is - * properly returned. - * - * For the purposes of testing TCP, an unused port number must be specified. - */ -static void -usage(void) -{ - - errx(-1, "usage: sigpipe tcpport"); -} - -/* - * Signal catcher. Set a global flag that can be tested by the caller. - */ -static int signaled; -static int -got_signal(void) -{ - - return (signaled); -} - -static void -signal_handler(int signum __unused) -{ - - signaled = 1; -} - -static void -signal_setup(const char *testname) -{ - - signaled = 0; - if (signal(SIGPIPE, signal_handler) == SIG_ERR) - err(-1, "%s: signal(SIGPIPE)", testname); -} - -static void -test_send(const char *testname, int sock) -{ - ssize_t len; - char ch; - - ch = 0; - len = send(sock, &ch, sizeof(ch), 0); - if (len < 0) { - if (errno == EPIPE) - return; - err(-1, "%s: send", testname); - } - errx(-1, "%s: send: returned %zd", testname, len); -} - -static void -test_write(const char *testname, int sock) -{ - ssize_t len; - char ch; - - ch = 0; - len = write(sock, &ch, sizeof(ch)); - if (len < 0) { - if (errno == EPIPE) - return; - err(-1, "%s: write", testname); - } - errx(-1, "%s: write: returned %zd", testname, len); -} - -static void -test_send_wantsignal(const char *testname, int sock1, int sock2) -{ - - if (shutdown(sock2, SHUT_WR) < 0) - err(-1, "%s: shutdown", testname); - signal_setup(testname); - test_send(testname, sock2); - if (!got_signal()) - errx(-1, "%s: send: didn't receive SIGPIPE", testname); - close(sock1); - close(sock2); -} - -#ifdef SO_NOSIGPIPE -static void -test_send_dontsignal(const char *testname, int sock1, int sock2) -{ - int i; - - i = 1; - if (setsockopt(sock2, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof(i)) < 0) - err(-1, "%s: setsockopt(SOL_SOCKET, SO_NOSIGPIPE)", testname); - if (shutdown(sock2, SHUT_WR) < 0) - err(-1, "%s: shutdown", testname); - signal_setup(testname); - test_send(testname, sock2); - if (got_signal()) - errx(-1, "%s: send: got SIGPIPE", testname); - close(sock1); - close(sock2); -} -#endif - -static void -test_write_wantsignal(const char *testname, int sock1, int sock2) -{ - - if (shutdown(sock2, SHUT_WR) < 0) - err(-1, "%s: shutdown", testname); - signal_setup(testname); - test_write(testname, sock2); - if (!got_signal()) - errx(-1, "%s: write: didn't receive SIGPIPE", testname); - close(sock1); - close(sock2); -} - -#ifdef SO_NOSIGPIPE -static void -test_write_dontsignal(const char *testname, int sock1, int sock2) -{ - int i; - - i = 1; - if (setsockopt(sock2, SOL_SOCKET, SO_NOSIGPIPE, &i, sizeof(i)) < 0) - err(-1, "%s: setsockopt(SOL_SOCKET, SO_NOSIGPIPE)", testname); - if (shutdown(sock2, SHUT_WR) < 0) - err(-1, "%s: shutdown", testname); - signal_setup(testname); - test_write(testname, sock2); - if (got_signal()) - errx(-1, "%s: write: got SIGPIPE", testname); - close(sock1); - close(sock2); -} -#endif - -static int listen_sock; -static void -tcp_setup(u_short port) -{ - struct sockaddr_in sin; - - listen_sock = socket(PF_INET, SOCK_STREAM, 0); - if (listen_sock < 0) - err(-1, "tcp_setup: listen"); - - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(port); - - if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) - err(-1, "tcp_setup: bind"); - - if (listen(listen_sock, -1) < 0) - err(-1, "tcp_setup: listen"); -} - -static void -tcp_teardown(void) -{ - - close(listen_sock); -} - -static void -tcp_pair(u_short port, int sock[2]) -{ - int accept_sock, connect_sock; - struct sockaddr_in sin; - socklen_t len; - - connect_sock = socket(PF_INET, SOCK_STREAM, 0); - if (connect_sock < 0) - err(-1, "tcp_pair: socket"); - - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(port); - - if (connect(connect_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) - err(-1, "tcp_pair: connect"); - - sleep(1); /* Time for TCP to settle. */ - - len = sizeof(sin); - accept_sock = accept(listen_sock, (struct sockaddr *)&sin, &len); - if (accept_sock < 0) - err(-1, "tcp_pair: accept"); - - sleep(1); /* Time for TCP to settle. */ - - sock[0] = accept_sock; - sock[1] = connect_sock; -} - -int -main(int argc, char *argv[]) -{ - char *dummy; - int sock[2]; - long port; - - if (argc != 2) - usage(); - - port = strtol(argv[1], &dummy, 10); - if (port < 0 || port > 65535 || *dummy != '\0') - usage(); - -#ifndef SO_NOSIGPIPE - warnx("sigpipe: SO_NOSIGPIPE not defined, skipping some tests"); -#endif - - /* - * UNIX domain socketpair(). - */ - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) - err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); - test_send_wantsignal("test_send_wantsignal(PF_LOCAL)", sock[0], - sock[1]); - -#ifdef SO_NOSIGPIPE - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) - err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); - test_send_dontsignal("test_send_dontsignal(PF_LOCAL)", sock[0], - sock[1]); -#endif - - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) - err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); - test_write_wantsignal("test_write_wantsignal(PF_LOCAL)", sock[0], - sock[1]); - -#ifdef SO_NOSIGPIPE - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sock) < 0) - err(-1, "socketpair(PF_LOCAL, SOCK_STREAM)"); - test_write_dontsignal("test_write_dontsignal(PF_LOCAL)", sock[0], - sock[1]); -#endif - - /* - * TCP. - */ - tcp_setup(port); - tcp_pair(port, sock); - test_send_wantsignal("test_send_wantsignal(PF_INET)", sock[0], - sock[1]); - -#ifdef SO_NOSIGPIPE - tcp_pair(port, sock); - test_send_dontsignal("test_send_dontsignal(PF_INET)", sock[0], - sock[1]); -#endif - - tcp_pair(port, sock); - test_write_wantsignal("test_write_wantsignal(PF_INET)", sock[0], - sock[1]); - -#ifdef SO_NOSIGPIPE - tcp_pair(port, sock); - test_write_dontsignal("test_write_dontsignal(PF_INET)", sock[0], - sock[1]); -#endif - tcp_teardown(); - - fprintf(stderr, "PASS\n"); - return (0); -} diff --git a/tests/sys/sockets/so_setfib_test.c b/tests/sys/sockets/so_setfib_test.c deleted file mode 100644 index 50cb020..0000000 --- a/tests/sys/sockets/so_setfib_test.c +++ /dev/null @@ -1,200 +0,0 @@ -/*- - * Copyright (c) 2012 Cisco Systems, Inc. - * All rights reserved. - * - * This software was developed by Bjoern Zeeb under contract to - * Cisco Systems, Inc.. - * - * 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. - * - * $FreeBSD$ - */ - -/* - * Regression test on SO_SETFIB setsockopt(2). - * - * Check that the expected domain(9) families all handle the socket option - * correctly and do proper bounds checks. - * - * Test plan: - * 1. Get system wide number of FIBs from sysctl and convert to index (-= 1). - * 2. For each protocol family (INET, INET6, ROUTE and LOCAL) open socketes of - * type (STREAM, DGRAM and RAW) as supported. - * 3. Do a sequence of -2, -1, 0, .. n, n+1, n+2 SO_SETFIB sockopt calls, - * expecting the first two and last two to fail (valid 0 ... n). - * 4. Try 3 random numbers. Calculate result based on valid range. - * 5. Repeat for next domain family and type from (2) on. - */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/sysctl.h> - -#include <err.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -static struct t_dom { - int domain; - const char *name; -} t_dom[] = { -#ifdef INET6 - { .domain = PF_INET6, .name = "PF_INET6" }, -#endif -#ifdef INET - { .domain = PF_INET, .name = "PF_INET" }, -#endif - { .domain = PF_ROUTE, .name = "PF_ROUTE" }, - { .domain = PF_LOCAL, .name = "PF_LOCAL" }, -}; - -static struct t_type { - int type; - const char *name; -} t_type[] = { - { .type = SOCK_STREAM, .name = "SOCK_STREAM" }, - { .type = SOCK_DGRAM, .name = "SOCK_DGRAM" }, - { .type = SOCK_RAW, .name = "SOCK_RAW" }, -}; - -/* - * Number of FIBs as read from net.fibs sysctl - 1. Initialize to clear out of - * bounds value to not accidentally run on a limited range. - */ -static int rt_numfibs = -42; - -/* Number of test case. */ -static int testno = 1; - - -/* - * Try the setsockopt with given FIB number i on socket s. - * Handle result given on error and valid range and errno. - */ -static void -so_setfib(int s, int i, u_int dom, u_int type) -{ - int error; - - error = setsockopt(s, SOL_SOCKET, SO_SETFIB, &i, sizeof(i)); - /* For out of bounds we expect an error. */ - if (error == -1 && (i < 0 || i > rt_numfibs)) - printf("ok %d %s_%s_%d\n", testno, t_dom[dom].name, - t_type[type].name, i); - else if (error != -1 && (i < 0 || i > rt_numfibs)) - printf("not ok %d %s_%s_%d # setsockopt(%d, SOL_SOCKET, " - "SO_SETFIB, %d, ..) unexpectedly succeeded\n", testno, - t_dom[dom].name, t_type[type].name, i, s, i); - else if (error == 0) - printf("ok %d %s_%s_%d\n", testno, t_dom[dom].name, - t_type[type].name, i); - else if (errno != EINVAL) - printf("not ok %d %s_%s_%d # setsockopt(%d, SOL_SOCKET, " - "SO_SETFIB, %d, ..) unexpected error: %s\n", testno, - t_dom[dom].name, t_type[type].name, i, s, i, - strerror(errno)); - else - printf("not ok %d %s_%s_%d\n", testno, t_dom[dom].name, - t_type[type].name, i); - - /* Test run done, next please. */ - testno++; -} - -/* - * Main test. Open socket given domain family and type. For each FIB, out of - * bounds FIB numbers and 3 random FIB numbers set the socket option. - */ -static void -t(u_int dom, u_int type) -{ - int i, s; - - /* PF_ROUTE only supports RAW socket types, while PF_LOCAL does not. */ - if (t_dom[dom].domain == PF_ROUTE && t_type[type].type != SOCK_RAW) - return; - if (t_dom[dom].domain == PF_LOCAL && t_type[type].type == SOCK_RAW) - return; - - /* Open socket for given combination. */ - s = socket(t_dom[dom].domain, t_type[type].type, 0); - if (s == -1) { - printf("not ok %d %s_%s # socket(): %s\n", testno, - t_dom[dom].name, t_type[type].name, strerror(errno)); - testno++; - return; - } - - /* Test FIBs -2, -1, 0, .. n, n + 1, n + 2. */ - for (i = -2; i <= (rt_numfibs + 2); i++) - so_setfib(s, i, dom, type); - - /* Test 3 random FIB numbers. */ - for (i = 0; i < 3; i++) - so_setfib(s, (int)random(), dom, type); - - /* Close socket. */ - close(s); -} - -/* - * Returns 0 if no program error, 1 on sysctlbyname error. - * Test results are communicated by printf("[not ]ok <n> .."). - */ -int -main(int argc __unused, char *argv[] __unused) -{ - u_int i, j; - size_t s; - - if (geteuid() != 0) { - printf("1..0 # SKIP: must be root"); - return (0); - } - - /* Initalize randomness. */ - srandomdev(); - - /* Get number of FIBs supported by kernel. */ - s = sizeof(rt_numfibs); - if (sysctlbyname("net.fibs", &rt_numfibs, &s, NULL, 0) == -1) - err(1, "sysctlbyname(net.fibs, ..)"); - - printf("1..%lu\n", - (nitems(t_dom) - 1) * nitems(t_type) * (2 + rt_numfibs + 2 + 3)); - - /* Adjust from number to index. */ - rt_numfibs -= 1; - - /* Run tests. */ - for (i = 0; i < sizeof(t_dom) / sizeof(struct t_dom); i++) - for (j = 0; j < sizeof(t_type) / sizeof(struct t_type); j++) - t(i, j); - - return (0); -} - -/* end */ diff --git a/tests/sys/sockets/socketpair_test.c b/tests/sys/sockets/socketpair_test.c deleted file mode 100644 index 779878a..0000000 --- a/tests/sys/sockets/socketpair_test.c +++ /dev/null @@ -1,161 +0,0 @@ -/*- - * Copyright (c) 2004 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/socket.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* - * Open, then close a set of UNIX domain socket pairs for datagram and - * stream. - * - * Confirm that we can't open INET datagram or stream socket pairs. - * - * More tests should be added, including confirming that sending on either - * endpoint results in data at the other, that the right kind of socket was - * created (stream vs. datagram), and that message boundaries fall in the - * right places. - */ -int -main(void) -{ - int fd1, fd2, fd3; - int sv[2]; - - /* - * UNIX domain socket pair, datagram. - */ - if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) != 0) { - fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM): %s\n", - strerror(errno)); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - if (close(sv[0]) != 0) { - fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM) close 0: %s\n", - strerror(errno)); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - if (close(sv[1]) != 0) { - fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM) close 1: %s\n", - strerror(errno)); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - - /* - * UNIX domain socket pair, stream. - */ - if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) != 0) { - fprintf(stderr, "socketpair(PF_UNIX, SOCK_STREAM): %s\n", - strerror(errno)); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - if (close(sv[0]) != 0) { - fprintf(stderr, "socketpair(PF_UNIX, SOCK_STREAM) close 0: %s\n", - strerror(errno)); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - if (close(sv[1]) != 0) { - fprintf(stderr, "socketpair(PF_UNIX, SOCK_STREAM) close 1: " - "%s\n", strerror(errno)); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - - /* - * Confirm that PF_INET datagram socket pair creation fails. - */ - if (socketpair(PF_INET, SOCK_DGRAM, 0, sv) == 0) { - fprintf(stderr, "socketpair(PF_INET, SOCK_DGRAM): opened\n"); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - if (errno != EOPNOTSUPP) { - fprintf(stderr, "socketpair(PF_INET, SOCK_DGRAM): %s\n", - strerror(errno)); - fprintf(stderr, "FAIL\n"); - } - - /* - * Confirm that PF_INET stream socket pair creation fails. - */ - if (socketpair(PF_INET, SOCK_STREAM, 0, sv) == 0) { - fprintf(stderr, "socketpair(PF_INET, SOCK_STREAM): opened\n"); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - if (errno != EOPNOTSUPP) { - fprintf(stderr, "socketpair(PF_INET, SOCK_STREAM): %s\n", - strerror(errno)); - fprintf(stderr, "FAIL\n"); - } - - /* - * Check for sequential fd allocation, and give up early if not. - */ - fd1 = dup(STDIN_FILENO); - fd2 = dup(STDIN_FILENO); - if (fd2 != fd1 + 1) { - fprintf(stderr, "Non-sequential fd allocation\n"); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - - /* Allocate a socketpair using a bad destination address. */ - if (socketpair(PF_UNIX, SOCK_DGRAM, 0, NULL) == 0) { - fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM, NULL): opened\n"); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - if (errno != EFAULT) { - fprintf(stderr, "socketpair(PF_UNIX, SOCK_DGRAM, NULL): %s\n", - strerror(errno)); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - - /* Allocate a file descriptor and make sure it's fd2+1. */ - fd3 = dup(STDIN_FILENO); - if (fd3 != fd2 + 1) { - fprintf(stderr, "socketpair(..., NULL) allocated descriptors\n"); - fprintf(stderr, "FAIL\n"); - exit(-1); - } - - fprintf(stderr, "PASS\n"); - exit(0); -} diff --git a/tests/sys/sockets/unix_bindconnect_test.c b/tests/sys/sockets/unix_bindconnect_test.c deleted file mode 100644 index 079dc4d..0000000 --- a/tests/sys/sockets/unix_bindconnect_test.c +++ /dev/null @@ -1,318 +0,0 @@ -/*- - * Copyright (c) 2005 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include <err.h> -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -/* - * Simple regression test to exercise some error cases relating to the use of - * bind() and connect() on UNIX domain sockets. In particular, make sure - * that when two sockets rendezvous using the file system name space, they - * get the expected success/failure cases. - * - * TODO: - * - Check that the resulting file mode/owner are right. - * - Do the same tests with UNIX domain sockets. - * - Check the results of getsockaddr() and getpeeraddr(). - */ - -#define SOCK_NAME_ONE "socket.1" -#define SOCK_NAME_TWO "socket.2" - -#define UNWIND_MAX 1024 - -static int unwind_len; -static struct unwind { - char u_path[PATH_MAX]; -} unwind_list[UNWIND_MAX]; - -static void -push_path(const char *path) -{ - - if (unwind_len >= UNWIND_MAX) - err(-1, "push_path: one path too many (%s)", path); - - strlcpy(unwind_list[unwind_len].u_path, path, PATH_MAX); - unwind_len++; -} - -static void -unwind(void) -{ - int i; - - for (i = unwind_len - 1; i >= 0; i--) { - unlink(unwind_list[i].u_path); - rmdir(unwind_list[i].u_path); - } -} - -static int -bind_test(const char *directory_path) -{ - char socket_path[PATH_MAX]; - struct sockaddr_un sun; - int sock1, sock2; - - sock1 = socket(PF_UNIX, SOCK_STREAM, 0); - if (sock1 < 0) { - warn("bind_test: socket(PF_UNIX, SOCK_STREAM, 0)"); - return (-1); - } - - if (snprintf(socket_path, sizeof(socket_path), "%s/%s", - directory_path, SOCK_NAME_ONE) >= PATH_MAX) { - warn("bind_test: snprintf(socket_path)"); - close(sock1); - return (-1); - } - - bzero(&sun, sizeof(sun)); - sun.sun_len = sizeof(sun); - sun.sun_family = AF_UNIX; - if (snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", socket_path) - >= (int)sizeof(sun.sun_path)) { - warn("bind_test: snprintf(sun.sun_path)"); - close(sock1); - return (-1); - } - - if (bind(sock1, (struct sockaddr *)&sun, sizeof(sun)) < 0) { - warn("bind_test: bind(sun) #1"); - close(sock1); - return (-1); - } - - push_path(socket_path); - - /* - * Once a STREAM UNIX domain socket has been bound, it can't be - * rebound. Expected error is EINVAL. - */ - if (bind(sock1, (struct sockaddr *)&sun, sizeof(sun)) == 0) { - warnx("bind_test: bind(sun) #2 succeeded"); - close(sock1); - return (-1); - } - if (errno != EINVAL) { - warn("bind_test: bind(sun) #2"); - close(sock1); - return (-1); - } - - sock2 = socket(PF_UNIX, SOCK_STREAM, 0); - if (sock2 < 0) { - warn("bind_test: socket(PF_UNIX, SOCK_STREAM, 0)"); - close(sock1); - return (-1); - } - - /* - * Since a socket is already bound to the pathname, it can't be bound - * to a second socket. Expected error is EADDRINUSE. - */ - if (bind(sock2, (struct sockaddr *)&sun, sizeof(sun)) == 0) { - warnx("bind_test: bind(sun) #3 succeeded"); - close(sock1); - close(sock2); - return (-1); - } - if (errno != EADDRINUSE) { - warn("bind_test: bind(sun) #2"); - close(sock1); - close(sock2); - return (-1); - } - - close(sock1); - - /* - * The socket bound to the pathname has been closed, but the pathname - * can't be reused without first being unlinked. Expected error is - * EADDRINUSE. - */ - if (bind(sock2, (struct sockaddr *)&sun, sizeof(sun)) == 0) { - warnx("bind_test: bind(sun) #4 succeeded"); - close(sock2); - return (-1); - } - if (errno != EADDRINUSE) { - warn("bind_test: bind(sun) #4"); - close(sock2); - return (-1); - } - - unlink(socket_path); - - /* - * The pathname is now free, so the socket should be able to bind to - * it. - */ - if (bind(sock2, (struct sockaddr *)&sun, sizeof(sun)) < 0) { - warn("bind_test: bind(sun) #5"); - close(sock2); - return (-1); - } - - close(sock2); - return (0); -} - -static int -connect_test(const char *directory_path) -{ - char socket_path[PATH_MAX]; - struct sockaddr_un sun; - int sock1, sock2; - - sock1 = socket(PF_UNIX, SOCK_STREAM, 0); - if (sock1 < 0) { - warn("connect_test: socket(PF_UNIX, SOCK_STREAM, 0)"); - return (-1); - } - - if (snprintf(socket_path, sizeof(socket_path), "%s/%s", - directory_path, SOCK_NAME_TWO) >= PATH_MAX) { - warn("connect_test: snprintf(socket_path)"); - close(sock1); - return (-1); - } - - bzero(&sun, sizeof(sun)); - sun.sun_len = sizeof(sun); - sun.sun_family = AF_UNIX; - if (snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", socket_path) - >= (int)sizeof(sun.sun_path)) { - warn("connect_test: snprintf(sun.sun_path)"); - close(sock1); - return (-1); - } - - /* - * Try connecting to a path that doesn't yet exist. Should fail with - * ENOENT. - */ - if (connect(sock1, (struct sockaddr *)&sun, sizeof(sun)) == 0) { - warnx("connect_test: connect(sun) #1 succeeded"); - close(sock1); - return (-1); - } - if (errno != ENOENT) { - warn("connect_test: connect(sun) #1"); - close(sock1); - return (-1); - } - - if (bind(sock1, (struct sockaddr *)&sun, sizeof(sun)) < 0) { - warn("connect_test: bind(sun) #1"); - close(sock1); - return (-1); - } - - if (listen(sock1, 3) < 0) { - warn("connect_test: listen(sock1)"); - close(sock1); - return (-1); - } - - push_path(socket_path); - - sock2 = socket(PF_UNIX, SOCK_STREAM, 0); - if (sock2 < 0) { - warn("socket(PF_UNIX, SOCK_STREAM, 0)"); - close(sock1); - return (-1); - } - - /* - * Do a simple connect and make sure that works. - */ - if (connect(sock2, (struct sockaddr *)&sun, sizeof(sun)) < 0) { - warn("connect(sun) #2"); - close(sock1); - return (-1); - } - - close(sock2); - - close(sock1); - - sock2 = socket(PF_UNIX, SOCK_STREAM, 0); - if (sock2 < 0) { - warn("socket(PF_UNIX, SOCK_STREAM, 0)"); - return (-1); - } - - /* - * Confirm that once the listen socket is closed, we get a - * connection refused (ECONNREFUSED) when attempting to connect to - * the pathname. - */ - if (connect(sock2, (struct sockaddr *)&sun, sizeof(sun)) == 0) { - warnx("connect(sun) #3 succeeded"); - close(sock2); - return (-1); - } - if (errno != ECONNREFUSED) { - warn("connect(sun) #3"); - close(sock2); - return (-1); - } - - close(sock2); - unlink(socket_path); - return (0); -} -int -main(void) -{ - char directory_path[PATH_MAX]; - int error; - - strlcpy(directory_path, "/tmp/unix_bind.XXXXXXX", PATH_MAX); - if (mkdtemp(directory_path) == NULL) - err(-1, "mkdtemp"); - push_path(directory_path); - - error = bind_test(directory_path); - - if (error == 0) - error = connect_test(directory_path); - - unwind(); - return (error); -} diff --git a/tests/sys/sockets/unix_close_race_test.c b/tests/sys/sockets/unix_close_race_test.c deleted file mode 100644 index 89c1b20..0000000 --- a/tests/sys/sockets/unix_close_race_test.c +++ /dev/null @@ -1,143 +0,0 @@ -/*- - * Copyright (c) 2010 Mikolaj Golub - * 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. - * - * $FreeBSD$ - */ - -/* - * This regression test attempts to trigger a race that occurs when both - * endpoints of a connected UNIX domain socket are closed at once. The two - * close paths may run concurrently leading to a call to sodisconnect() on an - * already-closed socket in kernel. Before it was fixed, this might lead to - * ENOTCONN being returned improperly from close(). - * - * This race is fairly timing-dependent, so it effectively requires SMP, and - * may not even trigger then. - */ - -#include <sys/types.h> -#include <sys/select.h> -#include <sys/socket.h> -#include <sys/sysctl.h> -#include <sys/un.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdlib.h> -#include <stdio.h> -#include <strings.h> -#include <string.h> -#include <unistd.h> -#include <err.h> - -static char socket_path[] = "tmp.XXXXXXXX"; - -#define USLEEP 100 -#define LOOPS 100000 - -int -main(void) -{ - struct sockaddr_un servaddr; - int listenfd, connfd, pid; - u_int counter, ncpus; - size_t len; - - len = sizeof(ncpus); - if (sysctlbyname("kern.smp.cpus", &ncpus, &len, NULL, 0) < 0) - err(1, "kern.smp.cpus"); - if (len != sizeof(ncpus)) - errx(1, "kern.smp.cpus: invalid length"); - if (ncpus < 2) - warnx("SMP not present, test may be unable to trigger race"); - - if (mkstemp(socket_path) == -1) - err(1, "mkstemp failed"); - unlink(socket_path); - - /* - * Create a UNIX domain socket that the child will repeatedly - * accept() from, and that the parent will repeatedly connect() to. - */ - if ((listenfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) - err(1, "parent: socket error"); - (void)unlink(socket_path); - bzero(&servaddr, sizeof(servaddr)); - servaddr.sun_family = AF_LOCAL; - strcpy(servaddr.sun_path, socket_path); - if (bind(listenfd, (struct sockaddr *) &servaddr, - sizeof(servaddr)) < 0) - err(1, "parent: bind error"); - if (listen(listenfd, 1024) < 0) - err(1, "parent: listen error"); - - pid = fork(); - if (pid == -1) - err(1, "fork()"); - if (pid != 0) { - /* - * In the parent, repeatedly connect and disconnect from the - * socket, attempting to induce the race. - */ - close(listenfd); - sleep(1); - bzero(&servaddr, sizeof(servaddr)); - servaddr.sun_family = AF_LOCAL; - strcpy(servaddr.sun_path, socket_path); - for (counter = 0; counter < LOOPS; counter++) { - if ((connfd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0) { - (void)kill(pid, SIGTERM); - err(1, "parent: socket error"); - } - if (connect(connfd, (struct sockaddr *)&servaddr, - sizeof(servaddr)) < 0) { - (void)kill(pid, SIGTERM); - err(1, "parent: connect error"); - } - if (close(connfd) < 0) { - (void)kill(pid, SIGTERM); - err(1, "parent: close error"); - } - usleep(USLEEP); - } - (void)kill(pid, SIGTERM); - } else { - /* - * In the child, loop accepting and closing. We may pick up - * the race here so report errors from close(). - */ - for ( ; ; ) { - if ((connfd = accept(listenfd, - (struct sockaddr *)NULL, NULL)) < 0) - err(1, "child: accept error"); - if (close(connfd) < 0) - err(1, "child: close error"); - } - } - printf("OK\n"); - exit(0); -} diff --git a/tests/sys/sockets/unix_cmsg.c b/tests/sys/sockets/unix_cmsg.c deleted file mode 100644 index d91cef4..0000000 --- a/tests/sys/sockets/unix_cmsg.c +++ /dev/null @@ -1,1969 +0,0 @@ -/*- - * Copyright (c) 2005 Andrey Simonenko - * 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> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/resource.h> -#include <sys/time.h> -#include <sys/select.h> -#include <sys/socket.h> -#include <sys/ucred.h> -#include <sys/un.h> -#include <sys/wait.h> - -#include <ctype.h> -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <inttypes.h> -#include <limits.h> -#include <paths.h> -#include <signal.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* - * There are tables with tests descriptions and pointers to test - * functions. Each t_*() function returns 0 if its test passed, - * -1 if its test failed, -2 if some system error occurred. - * If a test function returns -2, then a program exits. - * - * If a test function forks a client process, then it waits for its - * termination. If a return code of a client process is not equal - * to zero, or if a client process was terminated by a signal, then - * a test function returns -1 or -2 depending on exit status of - * a client process. - * - * Each function which can block, is run under TIMEOUT. If timeout - * occurs, then a test function returns -2 or a client process exits - * with a non-zero return code. - */ - -#ifndef LISTENQ -# define LISTENQ 1 -#endif - -#ifndef TIMEOUT -# define TIMEOUT 2 -#endif - -static int t_cmsgcred(void); -static int t_sockcred_1(void); -static int t_sockcred_2(void); -static int t_cmsgcred_sockcred(void); -static int t_timeval(void); -static int t_bintime(void); -static int t_cmsg_len(void); -static int t_peercred(void); - -struct test_func { - int (*func)(void); - const char *desc; -}; - -static const struct test_func test_stream_tbl[] = { - { - .func = NULL, - .desc = "All tests" - }, - { - .func = t_cmsgcred, - .desc = "Sending, receiving cmsgcred" - }, - { - .func = t_sockcred_1, - .desc = "Receiving sockcred (listening socket)" - }, - { - .func = t_sockcred_2, - .desc = "Receiving sockcred (accepted socket)" - }, - { - .func = t_cmsgcred_sockcred, - .desc = "Sending cmsgcred, receiving sockcred" - }, - { - .func = t_timeval, - .desc = "Sending, receiving timeval" - }, - { - .func = t_bintime, - .desc = "Sending, receiving bintime" - }, - { - .func = t_cmsg_len, - .desc = "Check cmsghdr.cmsg_len" - }, - { - .func = t_peercred, - .desc = "Check LOCAL_PEERCRED socket option" - } -}; - -#define TEST_STREAM_TBL_SIZE \ - (sizeof(test_stream_tbl) / sizeof(test_stream_tbl[0])) - -static const struct test_func test_dgram_tbl[] = { - { - .func = NULL, - .desc = "All tests" - }, - { - .func = t_cmsgcred, - .desc = "Sending, receiving cmsgcred" - }, - { - .func = t_sockcred_2, - .desc = "Receiving sockcred" - }, - { - .func = t_cmsgcred_sockcred, - .desc = "Sending cmsgcred, receiving sockcred" - }, - { - .func = t_timeval, - .desc = "Sending, receiving timeval" - }, - { - .func = t_bintime, - .desc = "Sending, receiving bintime" - }, - { - .func = t_cmsg_len, - .desc = "Check cmsghdr.cmsg_len" - } -}; - -#define TEST_DGRAM_TBL_SIZE \ - (sizeof(test_dgram_tbl) / sizeof(test_dgram_tbl[0])) - -static bool debug = false; -static bool server_flag = true; -static bool send_data_flag = true; -static bool send_array_flag = true; -static bool failed_flag = false; - -static int sock_type; -static const char *sock_type_str; - -static const char *proc_name; - -static char work_dir[] = _PATH_TMP "unix_cmsg.XXXXXXX"; -static int serv_sock_fd; -static struct sockaddr_un serv_addr_sun; - -static struct { - char *buf_send; - char *buf_recv; - size_t buf_size; - u_int msg_num; -} ipc_msg; - -#define IPC_MSG_NUM_DEF 5 -#define IPC_MSG_NUM_MAX 10 -#define IPC_MSG_SIZE_DEF 7 -#define IPC_MSG_SIZE_MAX 128 - -static struct { - uid_t uid; - uid_t euid; - gid_t gid; - gid_t egid; - gid_t *gid_arr; - int gid_num; -} proc_cred; - -static pid_t client_pid; - -#define SYNC_SERVER 0 -#define SYNC_CLIENT 1 -#define SYNC_RECV 0 -#define SYNC_SEND 1 - -static int sync_fd[2][2]; - -#define LOGMSG_SIZE 128 - -static void logmsg(const char *, ...) __printflike(1, 2); -static void logmsgx(const char *, ...) __printflike(1, 2); -static void dbgmsg(const char *, ...) __printflike(1, 2); -static void output(const char *, ...) __printflike(1, 2); - -static void -usage(bool verbose) -{ - u_int i; - - printf("usage: %s [-dh] [-n num] [-s size] [-t type] " - "[-z value] [testno]\n", getprogname()); - if (!verbose) - return; - printf("\n Options are:\n\ - -d Output debugging information\n\ - -h Output the help message and exit\n\ - -n num Number of messages to send\n\ - -s size Specify size of data for IPC\n\ - -t type Specify socket type (stream, dgram) for tests\n\ - -z value Do not send data in a message (bit 0x1), do not send\n\ - data array associated with a cmsghdr structure (bit 0x2)\n\ - testno Run one test by its number (require the -t option)\n\n"); - printf(" Available tests for stream sockets:\n"); - for (i = 0; i < TEST_STREAM_TBL_SIZE; ++i) - printf(" %u: %s\n", i, test_stream_tbl[i].desc); - printf("\n Available tests for datagram sockets:\n"); - for (i = 0; i < TEST_DGRAM_TBL_SIZE; ++i) - printf(" %u: %s\n", i, test_dgram_tbl[i].desc); -} - -static void -output(const char *format, ...) -{ - char buf[LOGMSG_SIZE]; - va_list ap; - - va_start(ap, format); - if (vsnprintf(buf, sizeof(buf), format, ap) < 0) - err(EXIT_FAILURE, "output: vsnprintf failed"); - write(STDOUT_FILENO, buf, strlen(buf)); - va_end(ap); -} - -static void -logmsg(const char *format, ...) -{ - char buf[LOGMSG_SIZE]; - va_list ap; - int errno_save; - - errno_save = errno; - va_start(ap, format); - if (vsnprintf(buf, sizeof(buf), format, ap) < 0) - err(EXIT_FAILURE, "logmsg: vsnprintf failed"); - if (errno_save == 0) - output("%s: %s\n", proc_name, buf); - else - output("%s: %s: %s\n", proc_name, buf, strerror(errno_save)); - va_end(ap); - errno = errno_save; -} - -static void -vlogmsgx(const char *format, va_list ap) -{ - char buf[LOGMSG_SIZE]; - - if (vsnprintf(buf, sizeof(buf), format, ap) < 0) - err(EXIT_FAILURE, "logmsgx: vsnprintf failed"); - output("%s: %s\n", proc_name, buf); - -} - -static void -logmsgx(const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - vlogmsgx(format, ap); - va_end(ap); -} - -static void -dbgmsg(const char *format, ...) -{ - va_list ap; - - if (debug) { - va_start(ap, format); - vlogmsgx(format, ap); - va_end(ap); - } -} - -static int -run_tests(int type, u_int testno1) -{ - const struct test_func *tf; - u_int i, testno2, failed_num; - - sock_type = type; - if (type == SOCK_STREAM) { - sock_type_str = "SOCK_STREAM"; - tf = test_stream_tbl; - i = TEST_STREAM_TBL_SIZE - 1; - } else { - sock_type_str = "SOCK_DGRAM"; - tf = test_dgram_tbl; - i = TEST_DGRAM_TBL_SIZE - 1; - } - if (testno1 == 0) { - testno1 = 1; - testno2 = i; - } else - testno2 = testno1; - - output("Running tests for %s sockets:\n", sock_type_str); - failed_num = 0; - for (i = testno1, tf += testno1; i <= testno2; ++tf, ++i) { - output(" %u: %s\n", i, tf->desc); - switch (tf->func()) { - case -1: - ++failed_num; - break; - case -2: - logmsgx("some system error or timeout occurred"); - return (-1); - } - } - - if (failed_num != 0) - failed_flag = true; - - if (testno1 != testno2) { - if (failed_num == 0) - output("-- all tests passed!\n"); - else - output("-- %u test%s failed!\n", - failed_num, failed_num == 1 ? "" : "s"); - } else { - if (failed_num == 0) - output("-- test passed!\n"); - else - output("-- test failed!\n"); - } - - return (0); -} - -static int -init(void) -{ - struct sigaction sigact; - size_t idx; - int rv; - - proc_name = "SERVER"; - - sigact.sa_handler = SIG_IGN; - sigact.sa_flags = 0; - sigemptyset(&sigact.sa_mask); - if (sigaction(SIGPIPE, &sigact, (struct sigaction *)NULL) < 0) { - logmsg("init: sigaction"); - return (-1); - } - - if (ipc_msg.buf_size == 0) - ipc_msg.buf_send = ipc_msg.buf_recv = NULL; - else { - ipc_msg.buf_send = malloc(ipc_msg.buf_size); - ipc_msg.buf_recv = malloc(ipc_msg.buf_size); - if (ipc_msg.buf_send == NULL || ipc_msg.buf_recv == NULL) { - logmsg("init: malloc"); - return (-1); - } - for (idx = 0; idx < ipc_msg.buf_size; ++idx) - ipc_msg.buf_send[idx] = (char)idx; - } - - proc_cred.uid = getuid(); - proc_cred.euid = geteuid(); - proc_cred.gid = getgid(); - proc_cred.egid = getegid(); - proc_cred.gid_num = getgroups(0, (gid_t *)NULL); - if (proc_cred.gid_num < 0) { - logmsg("init: getgroups"); - return (-1); - } - proc_cred.gid_arr = malloc(proc_cred.gid_num * - sizeof(*proc_cred.gid_arr)); - if (proc_cred.gid_arr == NULL) { - logmsg("init: malloc"); - return (-1); - } - if (getgroups(proc_cred.gid_num, proc_cred.gid_arr) < 0) { - logmsg("init: getgroups"); - return (-1); - } - - memset(&serv_addr_sun, 0, sizeof(serv_addr_sun)); - rv = snprintf(serv_addr_sun.sun_path, sizeof(serv_addr_sun.sun_path), - "%s/%s", work_dir, proc_name); - if (rv < 0) { - logmsg("init: snprintf"); - return (-1); - } - if ((size_t)rv >= sizeof(serv_addr_sun.sun_path)) { - logmsgx("init: not enough space for socket pathname"); - return (-1); - } - serv_addr_sun.sun_family = PF_LOCAL; - serv_addr_sun.sun_len = SUN_LEN(&serv_addr_sun); - - return (0); -} - -static int -client_fork(void) -{ - int fd1, fd2; - - if (pipe(sync_fd[SYNC_SERVER]) < 0 || - pipe(sync_fd[SYNC_CLIENT]) < 0) { - logmsg("client_fork: pipe"); - return (-1); - } - client_pid = fork(); - if (client_pid == (pid_t)-1) { - logmsg("client_fork: fork"); - return (-1); - } - if (client_pid == 0) { - proc_name = "CLIENT"; - server_flag = false; - fd1 = sync_fd[SYNC_SERVER][SYNC_RECV]; - fd2 = sync_fd[SYNC_CLIENT][SYNC_SEND]; - } else { - fd1 = sync_fd[SYNC_SERVER][SYNC_SEND]; - fd2 = sync_fd[SYNC_CLIENT][SYNC_RECV]; - } - if (close(fd1) < 0 || close(fd2) < 0) { - logmsg("client_fork: close"); - return (-1); - } - return (client_pid != 0); -} - -static void -client_exit(int rv) -{ - if (close(sync_fd[SYNC_SERVER][SYNC_SEND]) < 0 || - close(sync_fd[SYNC_CLIENT][SYNC_RECV]) < 0) { - logmsg("client_exit: close"); - rv = -1; - } - rv = rv == 0 ? EXIT_SUCCESS : -rv; - dbgmsg("exit: code %d", rv); - _exit(rv); -} - -static int -client_wait(void) -{ - int status; - pid_t pid; - - dbgmsg("waiting for client"); - - if (close(sync_fd[SYNC_SERVER][SYNC_RECV]) < 0 || - close(sync_fd[SYNC_CLIENT][SYNC_SEND]) < 0) { - logmsg("client_wait: close"); - return (-1); - } - - pid = waitpid(client_pid, &status, 0); - if (pid == (pid_t)-1) { - logmsg("client_wait: waitpid"); - return (-1); - } - - if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != EXIT_SUCCESS) { - logmsgx("client exit status is %d", - WEXITSTATUS(status)); - return (-WEXITSTATUS(status)); - } - } else { - if (WIFSIGNALED(status)) - logmsgx("abnormal termination of client, signal %d%s", - WTERMSIG(status), WCOREDUMP(status) ? - " (core file generated)" : ""); - else - logmsgx("termination of client, unknown status"); - return (-1); - } - - return (0); -} - -int -main(int argc, char *argv[]) -{ - const char *errstr; - u_int testno, zvalue; - int opt, rv; - bool dgram_flag, stream_flag; - - ipc_msg.buf_size = IPC_MSG_SIZE_DEF; - ipc_msg.msg_num = IPC_MSG_NUM_DEF; - dgram_flag = stream_flag = false; - while ((opt = getopt(argc, argv, "dhn:s:t:z:")) != -1) - switch (opt) { - case 'd': - debug = true; - break; - case 'h': - usage(true); - return (EXIT_SUCCESS); - case 'n': - ipc_msg.msg_num = strtonum(optarg, 1, - IPC_MSG_NUM_MAX, &errstr); - if (errstr != NULL) - errx(EXIT_FAILURE, "option -n: number is %s", - errstr); - break; - case 's': - ipc_msg.buf_size = strtonum(optarg, 0, - IPC_MSG_SIZE_MAX, &errstr); - if (errstr != NULL) - errx(EXIT_FAILURE, "option -s: number is %s", - errstr); - break; - case 't': - if (strcmp(optarg, "stream") == 0) - stream_flag = true; - else if (strcmp(optarg, "dgram") == 0) - dgram_flag = true; - else - errx(EXIT_FAILURE, "option -t: " - "wrong socket type"); - break; - case 'z': - zvalue = strtonum(optarg, 0, 3, &errstr); - if (errstr != NULL) - errx(EXIT_FAILURE, "option -z: number is %s", - errstr); - if (zvalue & 0x1) - send_data_flag = false; - if (zvalue & 0x2) - send_array_flag = false; - break; - default: - usage(false); - return (EXIT_FAILURE); - } - - if (optind < argc) { - if (optind + 1 != argc) - errx(EXIT_FAILURE, "too many arguments"); - testno = strtonum(argv[optind], 0, UINT_MAX, &errstr); - if (errstr != NULL) - errx(EXIT_FAILURE, "test number is %s", errstr); - if (stream_flag && testno >= TEST_STREAM_TBL_SIZE) - errx(EXIT_FAILURE, "given test %u for stream " - "sockets does not exist", testno); - if (dgram_flag && testno >= TEST_DGRAM_TBL_SIZE) - errx(EXIT_FAILURE, "given test %u for datagram " - "sockets does not exist", testno); - } else - testno = 0; - - if (!dgram_flag && !stream_flag) { - if (testno != 0) - errx(EXIT_FAILURE, "particular test number " - "can be used with the -t option only"); - dgram_flag = stream_flag = true; - } - - if (mkdtemp(work_dir) == NULL) - err(EXIT_FAILURE, "mkdtemp(%s)", work_dir); - - rv = EXIT_FAILURE; - if (init() < 0) - goto done; - - if (stream_flag) - if (run_tests(SOCK_STREAM, testno) < 0) - goto done; - if (dgram_flag) - if (run_tests(SOCK_DGRAM, testno) < 0) - goto done; - - rv = EXIT_SUCCESS; -done: - if (rmdir(work_dir) < 0) { - logmsg("rmdir(%s)", work_dir); - rv = EXIT_FAILURE; - } - return (failed_flag ? EXIT_FAILURE : rv); -} - -static int -socket_close(int fd) -{ - int rv; - - rv = 0; - if (close(fd) < 0) { - logmsg("socket_close: close"); - rv = -1; - } - if (server_flag && fd == serv_sock_fd) - if (unlink(serv_addr_sun.sun_path) < 0) { - logmsg("socket_close: unlink(%s)", - serv_addr_sun.sun_path); - rv = -1; - } - return (rv); -} - -static int -socket_create(void) -{ - struct timeval tv; - int fd; - - fd = socket(PF_LOCAL, sock_type, 0); - if (fd < 0) { - logmsg("socket_create: socket(PF_LOCAL, %s, 0)", sock_type_str); - return (-1); - } - if (server_flag) - serv_sock_fd = fd; - - tv.tv_sec = TIMEOUT; - tv.tv_usec = 0; - if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 || - setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) { - logmsg("socket_create: setsockopt(SO_RCVTIMEO/SO_SNDTIMEO)"); - goto failed; - } - - if (server_flag) { - if (bind(fd, (struct sockaddr *)&serv_addr_sun, - serv_addr_sun.sun_len) < 0) { - logmsg("socket_create: bind(%s)", - serv_addr_sun.sun_path); - goto failed; - } - if (sock_type == SOCK_STREAM) { - int val; - - if (listen(fd, LISTENQ) < 0) { - logmsg("socket_create: listen"); - goto failed; - } - val = fcntl(fd, F_GETFL, 0); - if (val < 0) { - logmsg("socket_create: fcntl(F_GETFL)"); - goto failed; - } - if (fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) { - logmsg("socket_create: fcntl(F_SETFL)"); - goto failed; - } - } - } - - return (fd); - -failed: - if (close(fd) < 0) - logmsg("socket_create: close"); - if (server_flag) - if (unlink(serv_addr_sun.sun_path) < 0) - logmsg("socket_close: unlink(%s)", - serv_addr_sun.sun_path); - return (-1); -} - -static int -socket_connect(int fd) -{ - dbgmsg("connect"); - - if (connect(fd, (struct sockaddr *)&serv_addr_sun, - serv_addr_sun.sun_len) < 0) { - logmsg("socket_connect: connect(%s)", serv_addr_sun.sun_path); - return (-1); - } - return (0); -} - -static int -sync_recv(void) -{ - ssize_t ssize; - int fd; - char buf; - - dbgmsg("sync: wait"); - - fd = sync_fd[server_flag ? SYNC_SERVER : SYNC_CLIENT][SYNC_RECV]; - - ssize = read(fd, &buf, 1); - if (ssize < 0) { - logmsg("sync_recv: read"); - return (-1); - } - if (ssize < 1) { - logmsgx("sync_recv: read %zd of 1 byte", ssize); - return (-1); - } - - dbgmsg("sync: received"); - - return (0); -} - -static int -sync_send(void) -{ - ssize_t ssize; - int fd; - - dbgmsg("sync: send"); - - fd = sync_fd[server_flag ? SYNC_CLIENT : SYNC_SERVER][SYNC_SEND]; - - ssize = write(fd, "", 1); - if (ssize < 0) { - logmsg("sync_send: write"); - return (-1); - } - if (ssize < 1) { - logmsgx("sync_send: sent %zd of 1 byte", ssize); - return (-1); - } - - return (0); -} - -static int -message_send(int fd, const struct msghdr *msghdr) -{ - const struct cmsghdr *cmsghdr; - size_t size; - ssize_t ssize; - - size = msghdr->msg_iov != 0 ? msghdr->msg_iov->iov_len : 0; - dbgmsg("send: data size %zu", size); - dbgmsg("send: msghdr.msg_controllen %u", - (u_int)msghdr->msg_controllen); - cmsghdr = CMSG_FIRSTHDR(msghdr); - if (cmsghdr != NULL) - dbgmsg("send: cmsghdr.cmsg_len %u", - (u_int)cmsghdr->cmsg_len); - - ssize = sendmsg(fd, msghdr, 0); - if (ssize < 0) { - logmsg("message_send: sendmsg"); - return (-1); - } - if ((size_t)ssize != size) { - logmsgx("message_send: sendmsg: sent %zd of %zu bytes", - ssize, size); - return (-1); - } - - if (!send_data_flag) - if (sync_send() < 0) - return (-1); - - return (0); -} - -static int -message_sendn(int fd, struct msghdr *msghdr) -{ - u_int i; - - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - if (message_send(fd, msghdr) < 0) - return (-1); - } - return (0); -} - -static int -message_recv(int fd, struct msghdr *msghdr) -{ - const struct cmsghdr *cmsghdr; - size_t size; - ssize_t ssize; - - if (!send_data_flag) - if (sync_recv() < 0) - return (-1); - - size = msghdr->msg_iov != NULL ? msghdr->msg_iov->iov_len : 0; - ssize = recvmsg(fd, msghdr, MSG_WAITALL); - if (ssize < 0) { - logmsg("message_recv: recvmsg"); - return (-1); - } - if ((size_t)ssize != size) { - logmsgx("message_recv: recvmsg: received %zd of %zu bytes", - ssize, size); - return (-1); - } - - dbgmsg("recv: data size %zd", ssize); - dbgmsg("recv: msghdr.msg_controllen %u", - (u_int)msghdr->msg_controllen); - cmsghdr = CMSG_FIRSTHDR(msghdr); - if (cmsghdr != NULL) - dbgmsg("recv: cmsghdr.cmsg_len %u", - (u_int)cmsghdr->cmsg_len); - - if (memcmp(ipc_msg.buf_recv, ipc_msg.buf_send, size) != 0) { - logmsgx("message_recv: received message has wrong content"); - return (-1); - } - - return (0); -} - -static int -socket_accept(int listenfd) -{ - fd_set rset; - struct timeval tv; - int fd, rv, val; - - dbgmsg("accept"); - - FD_ZERO(&rset); - FD_SET(listenfd, &rset); - tv.tv_sec = TIMEOUT; - tv.tv_usec = 0; - rv = select(listenfd + 1, &rset, (fd_set *)NULL, (fd_set *)NULL, &tv); - if (rv < 0) { - logmsg("socket_accept: select"); - return (-1); - } - if (rv == 0) { - logmsgx("socket_accept: select timeout"); - return (-1); - } - - fd = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL); - if (fd < 0) { - logmsg("socket_accept: accept"); - return (-1); - } - - val = fcntl(fd, F_GETFL, 0); - if (val < 0) { - logmsg("socket_accept: fcntl(F_GETFL)"); - goto failed; - } - if (fcntl(fd, F_SETFL, val & ~O_NONBLOCK) < 0) { - logmsg("socket_accept: fcntl(F_SETFL)"); - goto failed; - } - - return (fd); - -failed: - if (close(fd) < 0) - logmsg("socket_accept: close"); - return (-1); -} - -static int -check_msghdr(const struct msghdr *msghdr, size_t size) -{ - if (msghdr->msg_flags & MSG_TRUNC) { - logmsgx("msghdr.msg_flags has MSG_TRUNC"); - return (-1); - } - if (msghdr->msg_flags & MSG_CTRUNC) { - logmsgx("msghdr.msg_flags has MSG_CTRUNC"); - return (-1); - } - if (msghdr->msg_controllen < size) { - logmsgx("msghdr.msg_controllen %u < %zu", - (u_int)msghdr->msg_controllen, size); - return (-1); - } - if (msghdr->msg_controllen > 0 && size == 0) { - logmsgx("msghdr.msg_controllen %u > 0", - (u_int)msghdr->msg_controllen); - return (-1); - } - return (0); -} - -static int -check_cmsghdr(const struct cmsghdr *cmsghdr, int type, size_t size) -{ - if (cmsghdr == NULL) { - logmsgx("cmsghdr is NULL"); - return (-1); - } - if (cmsghdr->cmsg_level != SOL_SOCKET) { - logmsgx("cmsghdr.cmsg_level %d != SOL_SOCKET", - cmsghdr->cmsg_level); - return (-1); - } - if (cmsghdr->cmsg_type != type) { - logmsgx("cmsghdr.cmsg_type %d != %d", - cmsghdr->cmsg_type, type); - return (-1); - } - if (cmsghdr->cmsg_len != CMSG_LEN(size)) { - logmsgx("cmsghdr.cmsg_len %u != %zu", - (u_int)cmsghdr->cmsg_len, CMSG_LEN(size)); - return (-1); - } - return (0); -} - -static int -check_groups(const char *gid_arr_str, const gid_t *gid_arr, - const char *gid_num_str, int gid_num, bool all_gids) -{ - int i; - - for (i = 0; i < gid_num; ++i) - dbgmsg("%s[%d] %lu", gid_arr_str, i, (u_long)gid_arr[i]); - - if (all_gids) { - if (gid_num != proc_cred.gid_num) { - logmsgx("%s %d != %d", gid_num_str, gid_num, - proc_cred.gid_num); - return (-1); - } - } else { - if (gid_num > proc_cred.gid_num) { - logmsgx("%s %d > %d", gid_num_str, gid_num, - proc_cred.gid_num); - return (-1); - } - } - if (memcmp(gid_arr, proc_cred.gid_arr, - gid_num * sizeof(*gid_arr)) != 0) { - logmsgx("%s content is wrong", gid_arr_str); - for (i = 0; i < gid_num; ++i) - if (gid_arr[i] != proc_cred.gid_arr[i]) { - logmsgx("%s[%d] %lu != %lu", - gid_arr_str, i, (u_long)gid_arr[i], - (u_long)proc_cred.gid_arr[i]); - break; - } - return (-1); - } - return (0); -} - -static int -check_xucred(const struct xucred *xucred, socklen_t len) -{ - if (len != sizeof(*xucred)) { - logmsgx("option value size %zu != %zu", - (size_t)len, sizeof(*xucred)); - return (-1); - } - - dbgmsg("xucred.cr_version %u", xucred->cr_version); - dbgmsg("xucred.cr_uid %lu", (u_long)xucred->cr_uid); - dbgmsg("xucred.cr_ngroups %d", xucred->cr_ngroups); - - if (xucred->cr_version != XUCRED_VERSION) { - logmsgx("xucred.cr_version %u != %d", - xucred->cr_version, XUCRED_VERSION); - return (-1); - } - if (xucred->cr_uid != proc_cred.euid) { - logmsgx("xucred.cr_uid %lu != %lu (EUID)", - (u_long)xucred->cr_uid, (u_long)proc_cred.euid); - return (-1); - } - if (xucred->cr_ngroups == 0) { - logmsgx("xucred.cr_ngroups == 0"); - return (-1); - } - if (xucred->cr_ngroups < 0) { - logmsgx("xucred.cr_ngroups < 0"); - return (-1); - } - if (xucred->cr_ngroups > XU_NGROUPS) { - logmsgx("xucred.cr_ngroups %hu > %u (max)", - xucred->cr_ngroups, XU_NGROUPS); - return (-1); - } - if (xucred->cr_groups[0] != proc_cred.egid) { - logmsgx("xucred.cr_groups[0] %lu != %lu (EGID)", - (u_long)xucred->cr_groups[0], (u_long)proc_cred.egid); - return (-1); - } - if (check_groups("xucred.cr_groups", xucred->cr_groups, - "xucred.cr_ngroups", xucred->cr_ngroups, false) < 0) - return (-1); - return (0); -} - -static int -check_scm_creds_cmsgcred(struct cmsghdr *cmsghdr) -{ - const struct cmsgcred *cmsgcred; - - if (check_cmsghdr(cmsghdr, SCM_CREDS, sizeof(*cmsgcred)) < 0) - return (-1); - - cmsgcred = (struct cmsgcred *)CMSG_DATA(cmsghdr); - - dbgmsg("cmsgcred.cmcred_pid %ld", (long)cmsgcred->cmcred_pid); - dbgmsg("cmsgcred.cmcred_uid %lu", (u_long)cmsgcred->cmcred_uid); - dbgmsg("cmsgcred.cmcred_euid %lu", (u_long)cmsgcred->cmcred_euid); - dbgmsg("cmsgcred.cmcred_gid %lu", (u_long)cmsgcred->cmcred_gid); - dbgmsg("cmsgcred.cmcred_ngroups %d", cmsgcred->cmcred_ngroups); - - if (cmsgcred->cmcred_pid != client_pid) { - logmsgx("cmsgcred.cmcred_pid %ld != %ld", - (long)cmsgcred->cmcred_pid, (long)client_pid); - return (-1); - } - if (cmsgcred->cmcred_uid != proc_cred.uid) { - logmsgx("cmsgcred.cmcred_uid %lu != %lu", - (u_long)cmsgcred->cmcred_uid, (u_long)proc_cred.uid); - return (-1); - } - if (cmsgcred->cmcred_euid != proc_cred.euid) { - logmsgx("cmsgcred.cmcred_euid %lu != %lu", - (u_long)cmsgcred->cmcred_euid, (u_long)proc_cred.euid); - return (-1); - } - if (cmsgcred->cmcred_gid != proc_cred.gid) { - logmsgx("cmsgcred.cmcred_gid %lu != %lu", - (u_long)cmsgcred->cmcred_gid, (u_long)proc_cred.gid); - return (-1); - } - if (cmsgcred->cmcred_ngroups == 0) { - logmsgx("cmsgcred.cmcred_ngroups == 0"); - return (-1); - } - if (cmsgcred->cmcred_ngroups < 0) { - logmsgx("cmsgcred.cmcred_ngroups %d < 0", - cmsgcred->cmcred_ngroups); - return (-1); - } - if (cmsgcred->cmcred_ngroups > CMGROUP_MAX) { - logmsgx("cmsgcred.cmcred_ngroups %d > %d", - cmsgcred->cmcred_ngroups, CMGROUP_MAX); - return (-1); - } - if (cmsgcred->cmcred_groups[0] != proc_cred.egid) { - logmsgx("cmsgcred.cmcred_groups[0] %lu != %lu (EGID)", - (u_long)cmsgcred->cmcred_groups[0], (u_long)proc_cred.egid); - return (-1); - } - if (check_groups("cmsgcred.cmcred_groups", cmsgcred->cmcred_groups, - "cmsgcred.cmcred_ngroups", cmsgcred->cmcred_ngroups, false) < 0) - return (-1); - return (0); -} - -static int -check_scm_creds_sockcred(struct cmsghdr *cmsghdr) -{ - const struct sockcred *sockcred; - - if (check_cmsghdr(cmsghdr, SCM_CREDS, - SOCKCREDSIZE(proc_cred.gid_num)) < 0) - return (-1); - - sockcred = (struct sockcred *)CMSG_DATA(cmsghdr); - - dbgmsg("sockcred.sc_uid %lu", (u_long)sockcred->sc_uid); - dbgmsg("sockcred.sc_euid %lu", (u_long)sockcred->sc_euid); - dbgmsg("sockcred.sc_gid %lu", (u_long)sockcred->sc_gid); - dbgmsg("sockcred.sc_egid %lu", (u_long)sockcred->sc_egid); - dbgmsg("sockcred.sc_ngroups %d", sockcred->sc_ngroups); - - if (sockcred->sc_uid != proc_cred.uid) { - logmsgx("sockcred.sc_uid %lu != %lu", - (u_long)sockcred->sc_uid, (u_long)proc_cred.uid); - return (-1); - } - if (sockcred->sc_euid != proc_cred.euid) { - logmsgx("sockcred.sc_euid %lu != %lu", - (u_long)sockcred->sc_euid, (u_long)proc_cred.euid); - return (-1); - } - if (sockcred->sc_gid != proc_cred.gid) { - logmsgx("sockcred.sc_gid %lu != %lu", - (u_long)sockcred->sc_gid, (u_long)proc_cred.gid); - return (-1); - } - if (sockcred->sc_egid != proc_cred.egid) { - logmsgx("sockcred.sc_egid %lu != %lu", - (u_long)sockcred->sc_egid, (u_long)proc_cred.egid); - return (-1); - } - if (sockcred->sc_ngroups == 0) { - logmsgx("sockcred.sc_ngroups == 0"); - return (-1); - } - if (sockcred->sc_ngroups < 0) { - logmsgx("sockcred.sc_ngroups %d < 0", - sockcred->sc_ngroups); - return (-1); - } - if (sockcred->sc_ngroups != proc_cred.gid_num) { - logmsgx("sockcred.sc_ngroups %d != %u", - sockcred->sc_ngroups, proc_cred.gid_num); - return (-1); - } - if (check_groups("sockcred.sc_groups", sockcred->sc_groups, - "sockcred.sc_ngroups", sockcred->sc_ngroups, true) < 0) - return (-1); - return (0); -} - -static int -check_scm_timestamp(struct cmsghdr *cmsghdr) -{ - const struct timeval *timeval; - - if (check_cmsghdr(cmsghdr, SCM_TIMESTAMP, sizeof(struct timeval)) < 0) - return (-1); - - timeval = (struct timeval *)CMSG_DATA(cmsghdr); - - dbgmsg("timeval.tv_sec %"PRIdMAX", timeval.tv_usec %"PRIdMAX, - (intmax_t)timeval->tv_sec, (intmax_t)timeval->tv_usec); - - return (0); -} - -static int -check_scm_bintime(struct cmsghdr *cmsghdr) -{ - const struct bintime *bintime; - - if (check_cmsghdr(cmsghdr, SCM_BINTIME, sizeof(struct bintime)) < 0) - return (-1); - - bintime = (struct bintime *)CMSG_DATA(cmsghdr); - - dbgmsg("bintime.sec %"PRIdMAX", bintime.frac %"PRIu64, - (intmax_t)bintime->sec, bintime->frac); - - return (0); -} - -static void -msghdr_init_generic(struct msghdr *msghdr, struct iovec *iov, void *cmsg_data) -{ - msghdr->msg_name = NULL; - msghdr->msg_namelen = 0; - if (send_data_flag) { - iov->iov_base = server_flag ? - ipc_msg.buf_recv : ipc_msg.buf_send; - iov->iov_len = ipc_msg.buf_size; - msghdr->msg_iov = iov; - msghdr->msg_iovlen = 1; - } else { - msghdr->msg_iov = NULL; - msghdr->msg_iovlen = 0; - } - msghdr->msg_control = cmsg_data; - msghdr->msg_flags = 0; -} - -static void -msghdr_init_server(struct msghdr *msghdr, struct iovec *iov, - void *cmsg_data, size_t cmsg_size) -{ - msghdr_init_generic(msghdr, iov, cmsg_data); - msghdr->msg_controllen = cmsg_size; - dbgmsg("init: data size %zu", msghdr->msg_iov != NULL ? - msghdr->msg_iov->iov_len : (size_t)0); - dbgmsg("init: msghdr.msg_controllen %u", - (u_int)msghdr->msg_controllen); -} - -static void -msghdr_init_client(struct msghdr *msghdr, struct iovec *iov, - void *cmsg_data, size_t cmsg_size, int type, size_t arr_size) -{ - struct cmsghdr *cmsghdr; - - msghdr_init_generic(msghdr, iov, cmsg_data); - if (cmsg_data != NULL) { - msghdr->msg_controllen = send_array_flag ? - cmsg_size : CMSG_SPACE(0); - cmsghdr = CMSG_FIRSTHDR(msghdr); - cmsghdr->cmsg_level = SOL_SOCKET; - cmsghdr->cmsg_type = type; - cmsghdr->cmsg_len = CMSG_LEN(send_array_flag ? arr_size : 0); - } else - msghdr->msg_controllen = 0; -} - -static int -t_generic(int (*client_func)(int), int (*server_func)(int)) -{ - int fd, rv, rv_client; - - switch (client_fork()) { - case 0: - fd = socket_create(); - if (fd < 0) - rv = -2; - else { - rv = client_func(fd); - if (socket_close(fd) < 0) - rv = -2; - } - client_exit(rv); - break; - case 1: - fd = socket_create(); - if (fd < 0) - rv = -2; - else { - rv = server_func(fd); - rv_client = client_wait(); - if (rv == 0 || (rv == -2 && rv_client != 0)) - rv = rv_client; - if (socket_close(fd) < 0) - rv = -2; - } - break; - default: - rv = -2; - } - return (rv); -} - -static int -t_cmsgcred_client(int fd) -{ - struct msghdr msghdr; - struct iovec iov[1]; - void *cmsg_data; - size_t cmsg_size; - int rv; - - if (sync_recv() < 0) - return (-2); - - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, - SCM_CREDS, sizeof(struct cmsgcred)); - - if (socket_connect(fd) < 0) - goto done; - - if (message_sendn(fd, &msghdr) < 0) - goto done; - - rv = 0; -done: - free(cmsg_data); - return (rv); -} - -static int -t_cmsgcred_server(int fd1) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data; - size_t cmsg_size; - u_int i; - int fd2, rv; - - if (sync_send() < 0) - return (-2); - - fd2 = -1; - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - rv = -1; - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - - msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); - if (message_recv(fd2, &msghdr) < 0) { - rv = -2; - break; - } - - if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) - break; - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (check_scm_creds_cmsgcred(cmsghdr) < 0) - break; - } - if (i > ipc_msg.msg_num) - rv = 0; -done: - free(cmsg_data); - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_cmsgcred(void) -{ - return (t_generic(t_cmsgcred_client, t_cmsgcred_server)); -} - -static int -t_sockcred_client(int type, int fd) -{ - struct msghdr msghdr; - struct iovec iov[1]; - int rv; - - if (sync_recv() < 0) - return (-2); - - rv = -2; - - msghdr_init_client(&msghdr, iov, NULL, 0, 0, 0); - - if (socket_connect(fd) < 0) - goto done; - - if (type == 2) - if (sync_recv() < 0) - goto done; - - if (message_sendn(fd, &msghdr) < 0) - goto done; - - rv = 0; -done: - return (rv); -} - -static int -t_sockcred_server(int type, int fd1) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data; - size_t cmsg_size; - u_int i; - int fd2, rv, val; - - fd2 = -1; - rv = -2; - - cmsg_size = CMSG_SPACE(SOCKCREDSIZE(proc_cred.gid_num)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - - if (type == 1) { - dbgmsg("setting LOCAL_CREDS"); - val = 1; - if (setsockopt(fd1, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { - logmsg("setsockopt(LOCAL_CREDS)"); - goto done; - } - } - - if (sync_send() < 0) - goto done; - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - if (type == 2) { - dbgmsg("setting LOCAL_CREDS"); - val = 1; - if (setsockopt(fd2, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { - logmsg("setsockopt(LOCAL_CREDS)"); - goto done; - } - if (sync_send() < 0) - goto done; - } - - rv = -1; - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - - msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); - if (message_recv(fd2, &msghdr) < 0) { - rv = -2; - break; - } - - if (i > 1 && sock_type == SOCK_STREAM) { - if (check_msghdr(&msghdr, 0) < 0) - break; - } else { - if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) - break; - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (check_scm_creds_sockcred(cmsghdr) < 0) - break; - } - } - if (i > ipc_msg.msg_num) - rv = 0; -done: - free(cmsg_data); - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_sockcred_1(void) -{ - u_int i; - int fd, rv, rv_client; - - switch (client_fork()) { - case 0: - for (i = 1; i <= 2; ++i) { - dbgmsg("client #%u", i); - fd = socket_create(); - if (fd < 0) - rv = -2; - else { - rv = t_sockcred_client(1, fd); - if (socket_close(fd) < 0) - rv = -2; - } - if (rv != 0) - break; - } - client_exit(rv); - break; - case 1: - fd = socket_create(); - if (fd < 0) - rv = -2; - else { - rv = t_sockcred_server(1, fd); - if (rv == 0) - rv = t_sockcred_server(3, fd); - rv_client = client_wait(); - if (rv == 0 || (rv == -2 && rv_client != 0)) - rv = rv_client; - if (socket_close(fd) < 0) - rv = -2; - } - break; - default: - rv = -2; - } - - return (rv); -} - -static int -t_sockcred_2_client(int fd) -{ - return (t_sockcred_client(2, fd)); -} - -static int -t_sockcred_2_server(int fd) -{ - return (t_sockcred_server(2, fd)); -} - -static int -t_sockcred_2(void) -{ - return (t_generic(t_sockcred_2_client, t_sockcred_2_server)); -} - -static int -t_cmsgcred_sockcred_server(int fd1) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data, *cmsg1_data, *cmsg2_data; - size_t cmsg_size, cmsg1_size, cmsg2_size; - u_int i; - int fd2, rv, val; - - fd2 = -1; - rv = -2; - - cmsg1_size = CMSG_SPACE(SOCKCREDSIZE(proc_cred.gid_num)); - cmsg2_size = CMSG_SPACE(sizeof(struct cmsgcred)); - cmsg1_data = malloc(cmsg1_size); - cmsg2_data = malloc(cmsg2_size); - if (cmsg1_data == NULL || cmsg2_data == NULL) { - logmsg("malloc"); - goto done; - } - - dbgmsg("setting LOCAL_CREDS"); - val = 1; - if (setsockopt(fd1, 0, LOCAL_CREDS, &val, sizeof(val)) < 0) { - logmsg("setsockopt(LOCAL_CREDS)"); - goto done; - } - - if (sync_send() < 0) - goto done; - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - cmsg_data = cmsg1_data; - cmsg_size = cmsg1_size; - rv = -1; - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - - msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); - if (message_recv(fd2, &msghdr) < 0) { - rv = -2; - break; - } - - if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) - break; - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (i == 1 || sock_type == SOCK_DGRAM) { - if (check_scm_creds_sockcred(cmsghdr) < 0) - break; - } else { - if (check_scm_creds_cmsgcred(cmsghdr) < 0) - break; - } - - cmsg_data = cmsg2_data; - cmsg_size = cmsg2_size; - } - if (i > ipc_msg.msg_num) - rv = 0; -done: - free(cmsg1_data); - free(cmsg2_data); - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_cmsgcred_sockcred(void) -{ - return (t_generic(t_cmsgcred_client, t_cmsgcred_sockcred_server)); -} - -static int -t_timeval_client(int fd) -{ - struct msghdr msghdr; - struct iovec iov[1]; - void *cmsg_data; - size_t cmsg_size; - int rv; - - if (sync_recv() < 0) - return (-2); - - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct timeval)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, - SCM_TIMESTAMP, sizeof(struct timeval)); - - if (socket_connect(fd) < 0) - goto done; - - if (message_sendn(fd, &msghdr) < 0) - goto done; - - rv = 0; -done: - free(cmsg_data); - return (rv); -} - -static int -t_timeval_server(int fd1) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data; - size_t cmsg_size; - u_int i; - int fd2, rv; - - if (sync_send() < 0) - return (-2); - - fd2 = -1; - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct timeval)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - rv = -1; - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - - msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); - if (message_recv(fd2, &msghdr) < 0) { - rv = -2; - break; - } - - if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) - break; - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (check_scm_timestamp(cmsghdr) < 0) - break; - } - if (i > ipc_msg.msg_num) - rv = 0; -done: - free(cmsg_data); - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_timeval(void) -{ - return (t_generic(t_timeval_client, t_timeval_server)); -} - -static int -t_bintime_client(int fd) -{ - struct msghdr msghdr; - struct iovec iov[1]; - void *cmsg_data; - size_t cmsg_size; - int rv; - - if (sync_recv() < 0) - return (-2); - - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct bintime)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, - SCM_BINTIME, sizeof(struct bintime)); - - if (socket_connect(fd) < 0) - goto done; - - if (message_sendn(fd, &msghdr) < 0) - goto done; - - rv = 0; -done: - free(cmsg_data); - return (rv); -} - -static int -t_bintime_server(int fd1) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data; - size_t cmsg_size; - u_int i; - int fd2, rv; - - if (sync_send() < 0) - return (-2); - - fd2 = -1; - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct bintime)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - rv = -1; - for (i = 1; i <= ipc_msg.msg_num; ++i) { - dbgmsg("message #%u", i); - - msghdr_init_server(&msghdr, iov, cmsg_data, cmsg_size); - if (message_recv(fd2, &msghdr) < 0) { - rv = -2; - break; - } - - if (check_msghdr(&msghdr, sizeof(*cmsghdr)) < 0) - break; - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (check_scm_bintime(cmsghdr) < 0) - break; - } - if (i > ipc_msg.msg_num) - rv = 0; -done: - free(cmsg_data); - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_bintime(void) -{ - return (t_generic(t_bintime_client, t_bintime_server)); -} - -static int -t_cmsg_len_client(int fd) -{ - struct msghdr msghdr; - struct iovec iov[1]; - struct cmsghdr *cmsghdr; - void *cmsg_data; - size_t size, cmsg_size; - socklen_t socklen; - int rv; - - if (sync_recv() < 0) - return (-2); - - rv = -2; - - cmsg_size = CMSG_SPACE(sizeof(struct cmsgcred)); - cmsg_data = malloc(cmsg_size); - if (cmsg_data == NULL) { - logmsg("malloc"); - goto done; - } - msghdr_init_client(&msghdr, iov, cmsg_data, cmsg_size, - SCM_CREDS, sizeof(struct cmsgcred)); - cmsghdr = CMSG_FIRSTHDR(&msghdr); - - if (socket_connect(fd) < 0) - goto done; - - size = msghdr.msg_iov != NULL ? msghdr.msg_iov->iov_len : 0; - rv = -1; - for (socklen = 0; socklen < CMSG_LEN(0); ++socklen) { - cmsghdr->cmsg_len = socklen; - dbgmsg("send: data size %zu", size); - dbgmsg("send: msghdr.msg_controllen %u", - (u_int)msghdr.msg_controllen); - dbgmsg("send: cmsghdr.cmsg_len %u", - (u_int)cmsghdr->cmsg_len); - if (sendmsg(fd, &msghdr, 0) < 0) - continue; - logmsgx("sent message with cmsghdr.cmsg_len %u < %u", - (u_int)cmsghdr->cmsg_len, (u_int)CMSG_LEN(0)); - break; - } - if (socklen == CMSG_LEN(0)) - rv = 0; - - if (sync_send() < 0) { - rv = -2; - goto done; - } -done: - free(cmsg_data); - return (rv); -} - -static int -t_cmsg_len_server(int fd1) -{ - int fd2, rv; - - if (sync_send() < 0) - return (-2); - - rv = -2; - - if (sock_type == SOCK_STREAM) { - fd2 = socket_accept(fd1); - if (fd2 < 0) - goto done; - } else - fd2 = fd1; - - if (sync_recv() < 0) - goto done; - - rv = 0; -done: - if (sock_type == SOCK_STREAM && fd2 >= 0) - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_cmsg_len(void) -{ - return (t_generic(t_cmsg_len_client, t_cmsg_len_server)); -} - -static int -t_peercred_client(int fd) -{ - struct xucred xucred; - socklen_t len; - - if (sync_recv() < 0) - return (-1); - - if (socket_connect(fd) < 0) - return (-1); - - len = sizeof(xucred); - if (getsockopt(fd, 0, LOCAL_PEERCRED, &xucred, &len) < 0) { - logmsg("getsockopt(LOCAL_PEERCRED)"); - return (-1); - } - - if (check_xucred(&xucred, len) < 0) - return (-1); - - return (0); -} - -static int -t_peercred_server(int fd1) -{ - struct xucred xucred; - socklen_t len; - int fd2, rv; - - if (sync_send() < 0) - return (-2); - - fd2 = socket_accept(fd1); - if (fd2 < 0) - return (-2); - - len = sizeof(xucred); - if (getsockopt(fd2, 0, LOCAL_PEERCRED, &xucred, &len) < 0) { - logmsg("getsockopt(LOCAL_PEERCRED)"); - rv = -2; - goto done; - } - - if (check_xucred(&xucred, len) < 0) { - rv = -1; - goto done; - } - - rv = 0; -done: - if (socket_close(fd2) < 0) - rv = -2; - return (rv); -} - -static int -t_peercred(void) -{ - return (t_generic(t_peercred_client, t_peercred_server)); -} diff --git a/tests/sys/sockets/unix_cmsg_test.sh b/tests/sys/sockets/unix_cmsg_test.sh deleted file mode 100644 index c4a0b34..0000000 --- a/tests/sys/sockets/unix_cmsg_test.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cmd=`echo $0 | sed -e 's,_test$,,'` - -IFS= -n=0 - -run() -{ - result=`${cmd} -t $2 $3 ${5%% *} 2>&1` - if [ $? -ne 0 ]; then - echo -n "not " - fi - echo "ok $1 - $4 ${5#* }" - echo ${result} | grep -E "SERVER|CLIENT" | while read line; do - echo "# ${line}" - done -} - -echo "1..47" - -for t1 in \ - "1 Sending, receiving cmsgcred" \ - "4 Sending cmsgcred, receiving sockcred" \ - "5 Sending, receiving timeval" \ - "6 Sending, receiving bintime" \ - "7 Check cmsghdr.cmsg_len" -do - for t2 in \ - "0 " \ - "1 (no data)" \ - "2 (no array)" \ - "3 (no data, array)" - do - n=$((n + 1)) - run ${n} stream "-z ${t2%% *}" STREAM "${t1} ${t2#* }" - done -done - -for t1 in \ - "2 Receiving sockcred (listening socket)" \ - "3 Receiving sockcred (accepted socket)" -do - for t2 in \ - "0 " \ - "1 (no data)" - do - n=$((n + 1)) - run ${n} stream "-z ${t2%% *}" STREAM "${t1} ${t2#* }" - done -done - -n=$((n + 1)) -run ${n} stream "-z 0" STREAM "8 Check LOCAL_PEERCRED socket option" - -for t1 in \ - "1 Sending, receiving cmsgcred" \ - "3 Sending cmsgcred, receiving sockcred" \ - "4 Sending, receiving timeval" \ - "5 Sending, receiving bintime" \ - "6 Check cmsghdr.cmsg_len" -do - for t2 in \ - "0 " \ - "1 (no data)" \ - "2 (no array)" \ - "3 (no data, array)" - do - n=$((n + 1)) - run ${n} dgram "-z ${t2%% *}" DGRAM "${t1} ${t2#* }" - done -done - -for t1 in \ - "2 Receiving sockcred" -do - for t2 in \ - "0 " \ - "1 (no data)" - do - n=$((n + 1)) - run ${n} dgram "-z ${t2%% *}" DGRAM "${t1} ${t2#* }" - done -done diff --git a/tests/sys/sockets/unix_gc_test.c b/tests/sys/sockets/unix_gc_test.c deleted file mode 100644 index 8cae2d9..0000000 --- a/tests/sys/sockets/unix_gc_test.c +++ /dev/null @@ -1,808 +0,0 @@ -/*- - * Copyright (c) 2007 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -/* - * A few regression tests for UNIX domain sockets. Run from single-user mode - * as it checks the openfiles sysctl to look for leaks, and we don't want that - * changing due to other processes doing stuff. - */ - -#include <sys/types.h> -#include <sys/signal.h> -#include <sys/socket.h> -#include <sys/sysctl.h> -#include <sys/un.h> -#include <sys/wait.h> - -#include <netinet/in.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -static int forcegc = 1; -static char dpath[PATH_MAX]; -static const char *test; - -static int -getsysctl(const char *name) -{ - size_t len; - int i; - - len = sizeof(i); - if (sysctlbyname(name, &i, &len, NULL, 0) < 0) - err(-1, "%s", name); - return (i); -} - -static int -getopenfiles(void) -{ - - return (getsysctl("kern.openfiles")); -} - -static int -getinflight(void) -{ - - return (getsysctl("net.local.inflight")); -} - -static int -getdeferred(void) -{ - - return (getsysctl("net.local.deferred")); -} - -static void -sendfd(int fd, int fdtosend) -{ - struct msghdr mh; - struct message { struct cmsghdr msg_hdr; int fd; } m; - ssize_t len; - int after_inflight, before_inflight; - - before_inflight = getinflight(); - - bzero(&mh, sizeof(mh)); - bzero(&m, sizeof(m)); - mh.msg_control = &m; - mh.msg_controllen = sizeof(m); - m.msg_hdr.cmsg_len = sizeof(m); - m.msg_hdr.cmsg_level = SOL_SOCKET; - m.msg_hdr.cmsg_type = SCM_RIGHTS; - m.fd = fdtosend; - len = sendmsg(fd, &mh, 0); - if (len < 0) - err(-1, "%s: sendmsg", test); - after_inflight = getinflight(); - if (after_inflight != before_inflight + 1) - errx(-1, "%s: sendfd: before %d after %d\n", test, - before_inflight, after_inflight); -} - -static void -close2(int fd1, int fd2) -{ - - close(fd1); - close(fd2); -} - -static void -close3(int fd1, int fd2, int fd3) -{ - - close2(fd1, fd2); - close(fd3); -} - -static void -close4(int fd1, int fd2, int fd3, int fd4) -{ - - close2(fd1, fd2); - close2(fd3, fd4); -} - -static void -close5(int fd1, int fd2, int fd3, int fd4, int fd5) -{ - - close3(fd1, fd2, fd3); - close2(fd4, fd5); -} - -static int -my_socket(int domain, int type, int proto) -{ - int sock; - - sock = socket(domain, type, proto); - if (sock < 0) - err(-1, "%s: socket", test); - return (sock); -} - -static void -my_bind(int sock, struct sockaddr *sa, socklen_t len) -{ - - if (bind(sock, sa, len) < 0) - err(-1, "%s: bind", test); -} - -static void -my_connect(int sock, struct sockaddr *sa, socklen_t len) -{ - - if (connect(sock, sa, len) < 0 && errno != EINPROGRESS) - err(-1, "%s: connect", test); -} - -static void -my_listen(int sock, int backlog) -{ - - if (listen(sock, backlog) < 0) - err(-1, "%s: listen", test); -} - -static void -my_socketpair(int *sv) -{ - - if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) - err(-1, "%s: socketpair", test); -} - -static void -my_getsockname(int s, struct sockaddr *sa, socklen_t *salen) -{ - - if (getsockname(s, sa, salen) < 0) - err(-1, "%s: getsockname", test); -} - -static void -setnonblock(int s) -{ - - if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) - err(-1, "%s: fcntl(F_SETFL, O_NONBLOCK)", test); -} - -static void -alloc3fds(int *s, int *sv) -{ - - if ((*s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) - err(-1, "%s: socket", test); - if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) < 0) - err(-1, "%s: socketpair", test); -} - -static void -alloc5fds(int *s, int *sva, int *svb) -{ - - if ((*s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) - err(-1, "%s: socket", test); - if (socketpair(PF_UNIX, SOCK_STREAM, 0, sva) < 0) - err(-1, "%s: socketpair", test); - if (socketpair(PF_UNIX, SOCK_STREAM, 0, svb) < 0) - err(-1, "%s: socketpair", test); -} - -static void -save_sysctls(int *before_inflight, int *before_openfiles) -{ - - *before_inflight = getinflight(); - *before_openfiles = getopenfiles(); -} - -/* - * Try hard to make sure that the GC does in fact run before we test the - * condition of things. - */ -static void -trigger_gc(void) -{ - int s; - - if (forcegc) { - if ((s = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) - err(-1, "trigger_gc: socket"); - close(s); - } - sleep(1); -} - -static void -test_sysctls(int before_inflight, int before_openfiles) -{ - int after_inflight, after_openfiles; - - trigger_gc(); - after_inflight = getinflight(); - if (after_inflight != before_inflight) - warnx("%s: before inflight: %d, after inflight: %d", - test, before_inflight, after_inflight); - - after_openfiles = getopenfiles(); - if (after_openfiles != before_openfiles) - warnx("%s: before: %d, after: %d", test, before_openfiles, - after_openfiles); -} - -static void -twosome_nothing(void) -{ - int inflight, openfiles; - int sv[2]; - - /* - * Create a pair, close in one order. - */ - test = "twosome_nothing1"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - my_socketpair(sv); - close2(sv[0], sv[1]); - test_sysctls(inflight, openfiles); - - /* - * Create a pair, close in the other order. - */ - test = "twosome_nothing2"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - my_socketpair(sv); - close2(sv[0], sv[1]); - test_sysctls(inflight, openfiles); -} - -/* - * Using a socket pair, send various endpoints over the pair and close in - * various orders. - */ -static void -twosome_drop_work(const char *testname, int sendvia, int tosend, int closefirst) -{ - int inflight, openfiles; - int sv[2]; - - printf("%s\n", testname); - test = testname; - save_sysctls(&inflight, &openfiles); - my_socketpair(sv); - sendfd(sv[sendvia], sv[tosend]); - if (closefirst == 0) - close2(sv[0], sv[1]); - else - close2(sv[1], sv[0]); - test_sysctls(inflight, openfiles); -} - -static void -twosome_drop(void) -{ - - /* - * In various combations, some wastefully symmetric, create socket - * pairs and send one or another endpoint over one or another - * endpoint, closing the endpoints in various orders. - */ - twosome_drop_work("twosome_drop1", 0, 0, 0); - twosome_drop_work("twosome_drop2", 0, 0, 1); - twosome_drop_work("twosome_drop3", 0, 1, 0); - twosome_drop_work("twosome_drop4", 0, 1, 1); - twosome_drop_work("twosome_drop5", 1, 0, 0); - twosome_drop_work("twosome_drop6", 1, 0, 1); - twosome_drop_work("twosome_drop7", 1, 1, 0); - twosome_drop_work("twosome_drop8", 1, 1, 1); -} - -static void -threesome_nothing(void) -{ - int inflight, openfiles; - int s, sv[2]; - - test = "threesome_nothing"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - alloc3fds(&s, sv); - close3(s, sv[0], sv[1]); - test_sysctls(inflight, openfiles); -} - -/* - * threesome_drop: create a pair and a spare, send the spare over the pair, and - * close in various orders and make sure all the fds went away. - */ -static void -threesome_drop(void) -{ - int inflight, openfiles; - int s, sv[2]; - - /* - * threesome_drop1: close sent send receive - */ - test = "threesome_drop1"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - alloc3fds(&s, sv); - sendfd(sv[0], s); - close3(s, sv[0], sv[1]); - test_sysctls(inflight, openfiles); - - /* - * threesome_drop2: close sent receive send - */ - test = "threesome_drop2"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - alloc3fds(&s, sv); - sendfd(sv[0], s); - close3(s, sv[1], sv[0]); - test_sysctls(inflight, openfiles); - - /* - * threesome_drop3: close receive sent send - */ - test = "threesome_drop3"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - alloc3fds(&s, sv); - sendfd(sv[0], s); - close3(sv[1], s, sv[0]); - test_sysctls(inflight, openfiles); - - /* - * threesome_drop4: close receive send sent - */ - test = "threesome_drop4"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - alloc3fds(&s, sv); - sendfd(sv[0], s); - close3(sv[1], sv[0], s); - test_sysctls(inflight, openfiles); - - /* - * threesome_drop5: close send receive sent - */ - test = "threesome_drop5"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - alloc3fds(&s, sv); - sendfd(sv[0], s); - close3(sv[0], sv[1], s); - test_sysctls(inflight, openfiles); - - /* - * threesome_drop6: close send sent receive - */ - test = "threesome_drop6"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - alloc3fds(&s, sv); - close3(sv[0], s, sv[1]); - test_sysctls(inflight, openfiles); -} - -/* - * Fivesome tests: create two socket pairs and a spare, send the spare over - * the first socket pair, then send the first socket pair over the second - * socket pair, and GC. Do various closes at various points to exercise - * various cases. - */ -static void -fivesome_nothing(void) -{ - int inflight, openfiles; - int spare, sva[2], svb[2]; - - test = "fivesome_nothing"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - alloc5fds(&spare, sva, svb); - close5(spare, sva[0], sva[1], svb[0], svb[1]); - test_sysctls(inflight, openfiles); -} - -static void -fivesome_drop_work(const char *testname, int close_spare_after_send, - int close_sva_after_send) -{ - int inflight, openfiles; - int spare, sva[2], svb[2]; - - printf("%s\n", testname); - test = testname; - save_sysctls(&inflight, &openfiles); - alloc5fds(&spare, sva, svb); - - /* - * Send spare over sva. - */ - sendfd(sva[0], spare); - if (close_spare_after_send) - close(spare); - - /* - * Send sva over svb. - */ - sendfd(svb[0], sva[0]); - sendfd(svb[0], sva[1]); - if (close_sva_after_send) - close2(sva[0], sva[1]); - - close2(svb[0], svb[1]); - - if (!close_sva_after_send) - close2(sva[0], sva[1]); - if (!close_spare_after_send) - close(spare); - - test_sysctls(inflight, openfiles); -} - -static void -fivesome_drop(void) -{ - - fivesome_drop_work("fivesome_drop1", 0, 0); - fivesome_drop_work("fivesome_drop2", 0, 1); - fivesome_drop_work("fivesome_drop3", 1, 0); - fivesome_drop_work("fivesome_drop4", 1, 1); -} - -/* - * Create a somewhat nasty dual-socket socket intended to upset the garbage - * collector if mark-and-sweep is wrong. - */ -static void -complex_cycles(void) -{ - int inflight, openfiles; - int spare, sva[2], svb[2]; - - test = "complex_cycles"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - alloc5fds(&spare, sva, svb); - sendfd(sva[0], svb[0]); - sendfd(sva[0], svb[1]); - sendfd(svb[0], sva[0]); - sendfd(svb[0], sva[1]); - sendfd(svb[0], spare); - sendfd(sva[0], spare); - close5(spare, sva[0], sva[1], svb[0], svb[1]); - test_sysctls(inflight, openfiles); -} - -/* - * Listen sockets can also be passed over UNIX domain sockets, so test - * various cases, including ones where listen sockets have waiting sockets - * hanging off them... - */ -static void -listen_nothing(void) -{ - struct sockaddr_un sun; - struct sockaddr_in sin; - int inflight, openfiles; - int s; - - test = "listen_nothing_unp"; - printf("%s\n", test); - bzero(&sun, sizeof(sun)); - sun.sun_family = AF_LOCAL; - sun.sun_len = sizeof(sun); - snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test); - save_sysctls(&inflight, &openfiles); - s = my_socket(PF_LOCAL, SOCK_STREAM, 0); - my_bind(s, (struct sockaddr *)&sun, sizeof(sun)); - my_listen(s, -1); - close(s); - (void)unlink(sun.sun_path); - test_sysctls(inflight, openfiles); - - test = "listen_nothing_inet"; - printf("%s\n", test); - bzero(&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_len = sizeof(sin); - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(0); - save_sysctls(&inflight, &openfiles); - s = my_socket(PF_INET, SOCK_STREAM, 0); - my_bind(s, (struct sockaddr *)&sin, sizeof(sin)); - my_listen(s, -1); - close(s); - test_sysctls(inflight, openfiles); -} - -/* - * Send a listen UDP socket over a UNIX domain socket. - * - * Send a listen TCP socket over a UNIX domain socket. - * - * Do each twice, with closing of the listen socket vs. socketpair in - * different orders. - */ -static void -listen_drop(void) -{ - struct sockaddr_un sun; - struct sockaddr_in sin; - int inflight, openfiles; - int s, sv[2]; - - bzero(&sun, sizeof(sun)); - sun.sun_family = AF_LOCAL; - sun.sun_len = sizeof(sun); - - /* - * Close listen socket first. - */ - test = "listen_drop_unp1"; - printf("%s\n", test); - snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test); - save_sysctls(&inflight, &openfiles); - s = my_socket(PF_LOCAL, SOCK_STREAM, 0); - my_bind(s, (struct sockaddr *)&sun, sizeof(sun)); - my_listen(s, -1); - my_socketpair(sv); - sendfd(sv[0], s); - close3(s, sv[0], sv[1]); - test_sysctls(inflight, openfiles); - - /* - * Close socketpair first. - */ - test = "listen_drop_unp2"; - printf("%s\n", test); - snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s", dpath, test); - save_sysctls(&inflight, &openfiles); - s = my_socket(PF_LOCAL, SOCK_STREAM, 0); - my_bind(s, (struct sockaddr *)&sun, sizeof(sun)); - my_listen(s, -1); - my_socketpair(sv); - sendfd(sv[0], s); - close3(sv[0], sv[1], s); - test_sysctls(inflight, openfiles); - - sin.sin_family = AF_INET; - sin.sin_len = sizeof(sin); - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - sin.sin_port = htons(0); - - /* - * Close listen socket first. - */ - test = "listen_drop_inet1"; - printf("%s\n", test); - bzero(&sun, sizeof(sun)); - save_sysctls(&inflight, &openfiles); - s = my_socket(PF_INET, SOCK_STREAM, 0); - my_bind(s, (struct sockaddr *)&sin, sizeof(sin)); - my_listen(s, -1); - my_socketpair(sv); - sendfd(sv[0], s); - close3(s, sv[0], sv[1]); - test_sysctls(inflight, openfiles); - - /* - * Close socketpair first. - */ - test = "listen_drop_inet2"; - printf("%s\n", test); - bzero(&sun, sizeof(sun)); - save_sysctls(&inflight, &openfiles); - s = my_socket(PF_INET, SOCK_STREAM, 0); - my_bind(s, (struct sockaddr *)&sin, sizeof(sin)); - my_listen(s, -1); - my_socketpair(sv); - sendfd(sv[0], s); - close3(sv[0], sv[1], s); - test_sysctls(inflight, openfiles); -} - -/* - * Up things a notch with listen sockets: add connections that can be - * accepted to the listen queues. - */ -static void -listen_connect_nothing(void) -{ - struct sockaddr_in sin; - int slisten, sconnect, sv[2]; - int inflight, openfiles; - socklen_t len; - - test = "listen_connect_nothing"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - - slisten = my_socket(PF_INET, SOCK_STREAM, 0); - my_bind(slisten, (struct sockaddr *)&sin, sizeof(sin)); - my_listen(slisten, -1); - - my_socketpair(sv); - - len = sizeof(sin); - my_getsockname(slisten, (struct sockaddr *)&sin, &len); - - sconnect = my_socket(PF_INET, SOCK_STREAM, 0); - setnonblock(sconnect); - my_connect(sconnect, (struct sockaddr *)&sin, len); - - sleep(1); - - close4(slisten, sconnect, sv[0], sv[1]); - - test_sysctls(inflight, openfiles); -} - -static void -listen_connect_drop(void) -{ - struct sockaddr_in sin; - int slisten, sconnect, sv[2]; - int inflight, openfiles; - socklen_t len; - - test = "listen_connect_drop"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - - slisten = my_socket(PF_INET, SOCK_STREAM, 0); - my_bind(slisten, (struct sockaddr *)&sin, sizeof(sin)); - my_listen(slisten, -1); - - my_socketpair(sv); - - len = sizeof(sin); - my_getsockname(slisten, (struct sockaddr *)&sin, &len); - - sconnect = my_socket(PF_INET, SOCK_STREAM, 0); - setnonblock(sconnect); - my_connect(sconnect, (struct sockaddr *)&sin, len); - - sleep(1); - sendfd(sv[0], slisten); - close3(slisten, sv[0], sv[1]); - sleep(1); - close(sconnect); - - test_sysctls(inflight, openfiles); -} - -static void -recursion(void) -{ - int fd[2], ff[2]; - int inflight, openfiles, deferred, deferred1; - - test = "recursion"; - printf("%s\n", test); - save_sysctls(&inflight, &openfiles); - deferred = getdeferred(); - - my_socketpair(fd); - - for (;;) { - if (socketpair(PF_UNIX, SOCK_STREAM, 0, ff) == -1) { - if (errno == EMFILE || errno == ENFILE) - break; - err(-1, "socketpair"); - } - sendfd(ff[0], fd[0]); - sendfd(ff[0], fd[1]); - close2(fd[1], fd[0]); - fd[0] = ff[0]; - fd[1] = ff[1]; - } - close2(fd[0], fd[1]); - sleep(1); - test_sysctls(inflight, openfiles); - deferred1 = getdeferred(); - if (deferred != deferred1) - errx(-1, "recursion: deferred before %d after %d", deferred, - deferred1); -} - -#define RMDIR "rm -Rf " -int -main(int argc, char *argv[]) -{ - char cmd[sizeof(RMDIR) + PATH_MAX]; - int serrno; - pid_t pid; - - strlcpy(dpath, "/tmp/unpgc.XXXXXXXX", sizeof(dpath)); - if (mkdtemp(dpath) == NULL) - err(-1, "mkdtemp"); - - /* - * Set up a parent process to GC temporary storage when we're done. - */ - pid = fork(); - if (pid < 0) { - serrno = errno; - (void)rmdir(dpath); - errno = serrno; - err(-1, "fork"); - } - if (pid > 0) { - signal(SIGINT, SIG_IGN); - while (waitpid(pid, NULL, 0) != pid); - snprintf(cmd, sizeof(cmd), "%s %s", RMDIR, dpath); - (void)system(cmd); - exit(0); - } - - printf("Start: inflight %d open %d\n", getinflight(), - getopenfiles()); - - twosome_nothing(); - twosome_drop(); - - threesome_nothing(); - threesome_drop(); - - fivesome_nothing(); - fivesome_drop(); - - complex_cycles(); - - listen_nothing(); - listen_drop(); - - listen_connect_nothing(); - listen_connect_drop(); - - recursion(); - - printf("Finish: inflight %d open %d\n", getinflight(), - getopenfiles()); - return (0); -} diff --git a/tests/sys/sockets/unix_passfd_test.c b/tests/sys/sockets/unix_passfd_test.c deleted file mode 100644 index 07ef589..0000000 --- a/tests/sys/sockets/unix_passfd_test.c +++ /dev/null @@ -1,389 +0,0 @@ -/*- - * Copyright (c) 2005 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/sysctl.h> -#include <sys/un.h> - -#include <err.h> -#include <fcntl.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* - * UNIX domain sockets allow file descriptors to be passed via "ancillary - * data", or control messages. This regression test is intended to exercise - * this facility, both performing some basic tests that it operates, and also - * causing some kernel edge cases to execute, such as garbage collection when - * there are cyclic file descriptor references. Right now we test only with - * stream sockets, but ideally we'd also test with datagram sockets. - */ - -static void -domainsocketpair(const char *test, int *fdp) -{ - - if (socketpair(PF_UNIX, SOCK_STREAM, 0, fdp) < 0) - err(-1, "%s: socketpair(PF_UNIX, SOCK_STREAM)", test); -} - -static void -closesocketpair(int *fdp) -{ - - close(fdp[0]); - close(fdp[1]); -} - -static void -devnull(const char *test, int *fdp) -{ - int fd; - - fd = open("/dev/null", O_RDONLY); - if (fd < 0) - err(-1, "%s: open(/dev/null)", test); - *fdp = fd; -} - -static void -tempfile(const char *test, int *fdp) -{ - char path[PATH_MAX]; - int fd; - - snprintf(path, PATH_MAX, "/tmp/unix_passfd.XXXXXXXXXXXXXXX"); - fd = mkstemp(path); - if (fd < 0) - err(-1, "%s: mkstemp(%s)", test, path); - (void)unlink(path); - *fdp = fd; -} - -static void -dofstat(const char *test, int fd, struct stat *sb) -{ - - if (fstat(fd, sb) < 0) - err(-1, "%s: fstat", test); -} - -static void -samefile(const char *test, struct stat *sb1, struct stat *sb2) -{ - - if (sb1->st_dev != sb2->st_dev) - errx(-1, "%s: samefile: different device", test); - if (sb1->st_ino != sb2->st_ino) - errx(-1, "%s: samefile: different inode", test); -} - -static void -sendfd_payload(const char *test, int sockfd, int sendfd, - void *payload, size_t paylen) -{ - struct iovec iovec; - char message[CMSG_SPACE(sizeof(int))]; - struct cmsghdr *cmsghdr; - struct msghdr msghdr; - ssize_t len; - - bzero(&msghdr, sizeof(msghdr)); - bzero(&message, sizeof(message)); - - msghdr.msg_control = message; - msghdr.msg_controllen = sizeof(message); - - iovec.iov_base = payload; - iovec.iov_len = paylen; - - msghdr.msg_iov = &iovec; - msghdr.msg_iovlen = 1; - - cmsghdr = (struct cmsghdr *)message; - cmsghdr->cmsg_len = CMSG_LEN(sizeof(int)); - cmsghdr->cmsg_level = SOL_SOCKET; - cmsghdr->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA(cmsghdr) = sendfd; - - len = sendmsg(sockfd, &msghdr, 0); - if (len < 0) - err(-1, "%s: sendmsg", test); - if ((size_t)len != paylen) - errx(-1, "%s: sendmsg: %zd bytes sent", test, len); -} - -static void -sendfd(const char *test, int sockfd, int sendfd) -{ - char ch; - - return (sendfd_payload(test, sockfd, sendfd, &ch, sizeof(ch))); -} - -static void -recvfd_payload(const char *test, int sockfd, int *recvfd, - void *buf, size_t buflen) -{ - struct cmsghdr *cmsghdr; - char message[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX)) + sizeof(int)]; - struct msghdr msghdr; - struct iovec iovec; - ssize_t len; - - bzero(&msghdr, sizeof(msghdr)); - - msghdr.msg_control = message; - msghdr.msg_controllen = sizeof(message); - - iovec.iov_base = buf; - iovec.iov_len = buflen; - - msghdr.msg_iov = &iovec; - msghdr.msg_iovlen = 1; - - len = recvmsg(sockfd, &msghdr, 0); - if (len < 0) - err(-1, "%s: recvmsg", test); - if ((size_t)len != buflen) - errx(-1, "%s: recvmsg: %zd bytes received", test, len); - - cmsghdr = CMSG_FIRSTHDR(&msghdr); - if (cmsghdr == NULL) - errx(-1, "%s: recvmsg: did not receive control message", test); - *recvfd = -1; - for (; cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) { - if (cmsghdr->cmsg_level == SOL_SOCKET && - cmsghdr->cmsg_type == SCM_RIGHTS && - cmsghdr->cmsg_len == CMSG_LEN(sizeof(int))) { - *recvfd = *(int *)CMSG_DATA(cmsghdr); - if (*recvfd == -1) - errx(-1, "%s: recvmsg: received fd -1", test); - } - } - if (*recvfd == -1) - errx(-1, "%s: recvmsg: did not receive single-fd message", - test); -} - -static void -recvfd(const char *test, int sockfd, int *recvfd) -{ - char ch; - - return (recvfd_payload(test, sockfd, recvfd, &ch, sizeof(ch))); -} - -int -main(void) -{ - struct stat putfd_1_stat, putfd_2_stat, getfd_1_stat, getfd_2_stat; - int fd[2], putfd_1, putfd_2, getfd_1, getfd_2; - const char *test; - - /* - * First test: put a temporary file into a UNIX domain socket, then - * take it out and make sure it's the same file. First time around, - * don't close the reference after sending. - */ - test = "test1-simplesendfd"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - tempfile(test, &putfd_1); - dofstat(test, putfd_1, &putfd_1_stat); - sendfd(test, fd[0], putfd_1); - recvfd(test, fd[1], &getfd_1); - dofstat(test, getfd_1, &getfd_1_stat); - samefile(test, &putfd_1_stat, &getfd_1_stat); - close(putfd_1); - close(getfd_1); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Second test: same as first, only close the file reference after - * sending, so that the only reference is the descriptor in the UNIX - * domain socket buffer. - */ - test = "test2-sendandclose"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - tempfile(test, &putfd_1); - dofstat(test, putfd_1, &putfd_1_stat); - sendfd(test, fd[0], putfd_1); - close(putfd_1); - recvfd(test, fd[1], &getfd_1); - dofstat(test, getfd_1, &getfd_1_stat); - samefile(test, &putfd_1_stat, &getfd_1_stat); - close(getfd_1); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Third test: put a temporary file into a UNIX domain socket, then - * close both endpoints causing garbage collection to kick off. - */ - test = "test3-sendandcancel"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - tempfile(test, &putfd_1); - sendfd(test, fd[0], putfd_1); - close(putfd_1); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Send two files. Then receive them. Make sure they are returned - * in the right order, and both get there. - */ - - test = "test4-twofile"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - tempfile(test, &putfd_1); - tempfile(test, &putfd_2); - dofstat(test, putfd_1, &putfd_1_stat); - dofstat(test, putfd_2, &putfd_2_stat); - sendfd(test, fd[0], putfd_1); - sendfd(test, fd[0], putfd_2); - close(putfd_1); - close(putfd_2); - recvfd(test, fd[1], &getfd_1); - recvfd(test, fd[1], &getfd_2); - dofstat(test, getfd_1, &getfd_1_stat); - dofstat(test, getfd_2, &getfd_2_stat); - samefile(test, &putfd_1_stat, &getfd_1_stat); - samefile(test, &putfd_2_stat, &getfd_2_stat); - close(getfd_1); - close(getfd_2); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Big bundling test. Send an endpoint of the UNIX domain socket - * over itself, closing the door behind it. - */ - - test = "test5-bundle"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - - sendfd(test, fd[0], fd[0]); - close(fd[0]); - recvfd(test, fd[1], &getfd_1); - close(getfd_1); - close(fd[1]); - - printf("%s passed\n", test); - - /* - * Big bundling test part two: Send an endpoint of the UNIX domain - * socket over itself, close the door behind it, and never remove it - * from the other end. - */ - - test = "test6-bundlecancel"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - sendfd(test, fd[0], fd[0]); - sendfd(test, fd[1], fd[0]); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Test for PR 151758: Send an character device over the UNIX - * domain socket and then close both sockets to orphan the - * device. - */ - - test = "test7-devfsorphan"; - printf("beginning %s\n", test); - - domainsocketpair(test, fd); - devnull(test, &putfd_1); - sendfd(test, fd[0], putfd_1); - close(putfd_1); - closesocketpair(fd); - - printf("%s passed\n", test); - - /* - * Test for PR 181741. Receiver sets LOCAL_CREDS, and kernel - * prepends a control message to the data. Sender sends large - * payload. Payload + SCM_RIGHTS + LOCAL_CREDS hit socket buffer - * limit, and receiver receives truncated data. - */ - test = "test8-rights+creds+payload"; - printf("beginning %s\n", test); - - { - const int on = 1; - u_long sendspace; - size_t len; - void *buf; - - len = sizeof(sendspace); - if (sysctlbyname("net.local.stream.sendspace", &sendspace, - &len, NULL, 0) < 0) - err(-1, "%s: sysctlbyname(net.local.stream.sendspace)", - test); - - if ((buf = malloc(sendspace)) == NULL) - err(-1, "%s: malloc", test); - - domainsocketpair(test, fd); - if (setsockopt(fd[1], 0, LOCAL_CREDS, &on, sizeof(on)) < 0) - err(-1, "%s: setsockopt(LOCAL_CREDS)", test); - tempfile(test, &putfd_1); - sendfd_payload(test, fd[0], putfd_1, buf, sendspace); - recvfd_payload(test, fd[1], &getfd_1, buf, sendspace); - close(putfd_1); - close(getfd_1); - closesocketpair(fd); - } - - printf("%s passed\n", test); - - return (0); -} diff --git a/tests/sys/sockets/unix_sendtorace_test.c b/tests/sys/sockets/unix_sendtorace_test.c deleted file mode 100644 index 9fd748d..0000000 --- a/tests/sys/sockets/unix_sendtorace_test.c +++ /dev/null @@ -1,215 +0,0 @@ -/*- - * Copyright (c) 2006 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -/* - * Attempts to exercise UNIX domain socket races relating to the non-atomic - * connect-and-send properties of sendto(). As the result of such a race is - * a kernel panic, this test simply completes or doesn't. - * - * XXX: Despite implementing support for sendto() on stream sockets with - * implied connect, the appropriate flag isn't set in the FreeBSD kernel so - * it does not work. For now, don't call the stream test. - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include <err.h> -#include <signal.h> -#include <string.h> -#include <unistd.h> - -#define ITERATIONS 1000000 - -static char socket_path[] = "tmp.XXXXXX"; - -static void -stream_server(int listenfd) -{ - int acceptfd; - - while (1) { - acceptfd = accept(listenfd, NULL, NULL); - if (acceptfd < 0) { - warn("stream_server: accept"); - continue; - } - sleep(1); - close(acceptfd); - } -} - -static void -stream_client(void) -{ - struct sockaddr_un sun; - ssize_t len; - char c = 0; - int fd, i; - - bzero(&sun, sizeof(sun)); - sun.sun_len = sizeof(sun); - sun.sun_family = AF_UNIX; - strcpy(sun.sun_path, socket_path); - for (i = 0; i < ITERATIONS; i++) { - fd = socket(PF_UNIX, SOCK_STREAM, 0); - if (fd < 0) { - warn("stream_client: socket"); - return; - } - len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun, - sizeof(sun)); - if (len < 0) - warn("stream_client: sendto"); - close(fd); - } -} - -static void -stream_test(void) -{ - struct sockaddr_un sun; - pid_t childpid; - int listenfd; - - listenfd = socket(PF_UNIX, SOCK_STREAM, 0); - if (listenfd < 0) - err(-1, "stream_test: socket"); - - bzero(&sun, sizeof(sun)); - sun.sun_len = sizeof(sun); - sun.sun_family = AF_UNIX; - strcpy(sun.sun_path, socket_path); - - if (bind(listenfd, (struct sockaddr *)&sun, sizeof(sun)) < 0) - err(-1, "stream_test: bind"); - - if (listen(listenfd, -1) < 0) - err(-1, "stream_test: listen"); - - childpid = fork(); - if (childpid < 0) - err(-1, "stream_test: fork"); - - if (childpid != 0) { - sleep(1); - stream_client(); - kill(childpid, SIGTERM); - sleep(1); - } else - stream_server(listenfd); - - (void)unlink(socket_path); -} - -static void -datagram_server(int serverfd) -{ - ssize_t len; - char c; - - while (1) { - len = recv(serverfd, &c, sizeof(c), 0); - if (len < 0) - warn("datagram_server: recv"); - } -} - -static void -datagram_client(void) -{ - struct sockaddr_un sun; - ssize_t len; - char c = 0; - int fd, i; - - bzero(&sun, sizeof(sun)); - sun.sun_len = sizeof(sun); - sun.sun_family = AF_UNIX; - strcpy(sun.sun_path, socket_path); - for (i = 0; i < ITERATIONS; i++) { - fd = socket(PF_UNIX, SOCK_DGRAM, 0); - if (fd < 0) { - warn("datagram_client: socket"); - return; - } - len = sendto(fd, &c, sizeof(c), 0, (struct sockaddr *)&sun, - sizeof(sun)); - if (len < 0) - warn("datagram_client: sendto"); - close(fd); - } -} - -static void -datagram_test(void) -{ - struct sockaddr_un sun; - pid_t childpid; - int serverfd; - - serverfd = socket(PF_UNIX, SOCK_DGRAM, 0); - if (serverfd < 0) - err(-1, "datagram_test: socket"); - - bzero(&sun, sizeof(sun)); - sun.sun_len = sizeof(sun); - sun.sun_family = AF_UNIX; - strcpy(sun.sun_path, socket_path); - - if (bind(serverfd, (struct sockaddr *)&sun, sizeof(sun)) < 0) - err(-1, "datagram_test: bind"); - - childpid = fork(); - if (childpid < 0) - err(-1, "datagram_test: fork"); - - if (childpid != 0) { - sleep(1); - datagram_client(); - kill(childpid, SIGTERM); - sleep(1); - } else - datagram_server(serverfd); - - (void)unlink(socket_path); -} - -int -main(void) -{ - - if (mkstemp(socket_path) == -1) - err(1, "mkstemp failed"); - (void)unlink(socket_path); - datagram_test(); - if (0) - stream_test(); - return (0); -} diff --git a/tests/sys/sockets/unix_socket_test.c b/tests/sys/sockets/unix_socket_test.c deleted file mode 100644 index 085366f..0000000 --- a/tests/sys/sockets/unix_socket_test.c +++ /dev/null @@ -1,84 +0,0 @@ -/*- - * Copyright (c) 2006 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -/* - * Simple UNIX domain socket regression test: create and tear down various - * supported and unsupported socket types. - */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include <err.h> -#include <errno.h> -#include <unistd.h> - -int -main(void) -{ - int sock, socks[2]; - - sock = socket(PF_LOCAL, SOCK_STREAM, 0); - if (sock < 0) - err(-1, "socket(PF_LOCAL, SOCK_STREAM, 0)"); - close(sock); - - sock = socket(PF_LOCAL, SOCK_DGRAM, 0); - if (sock < 0) - err(-1, "socket(PF_LOCAL, SOCK_DGRAM, 0)"); - close(sock); - - sock = socket(PF_LOCAL, SOCK_RAW, 0); - if (sock >= 0) { - close(sock); - errx(-1, "socket(PF_LOCAL, SOCK_RAW, 0) returned %d", sock); - } - if (errno != EPROTONOSUPPORT) - err(-1, "socket(PF_LOCAL, SOCK_RAW, 0)"); - - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, socks) < 0) - err(-1, "socketpair(PF_LOCAL, SOCK_STREAM, 0, socks)"); - if (socks[0] < 0) - errx(-1, "socketpair(PF_LOCAL, SOCK_STREAM, 0, socks) [0] < 0"); - if (socks[1] < 0) - errx(-1, "socketpair(PF_LOCAL, SOCK_STREAM, 0, socks) [1] < 1"); - close(socks[0]); - close(socks[1]); - - if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, socks) < 0) - err(-1, "socketpair(PF_LOCAL, SOCK_DGRAM, 0, socks)"); - if (socks[0] < 0) - errx(-1, "socketpair(PF_LOCAL, SOCK_DGRAM, 0, socks) [0] < 0"); - if (socks[1] < 0) - errx(-1, "socketpair(PF_LOCAL, SOCK_DGRAM, 0, socks) [1] < 1"); - close(socks[0]); - close(socks[1]); - - return (0); -} diff --git a/tests/sys/sockets/unix_sorflush_test.c b/tests/sys/sockets/unix_sorflush_test.c deleted file mode 100644 index e0deb00..0000000 --- a/tests/sys/sockets/unix_sorflush_test.c +++ /dev/null @@ -1,99 +0,0 @@ -/*- - * Copyright (c) 2008 Robert N. M. Watson - * 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. - */ - -/* - * Reproduce a race in which: - * - * - Process (a) is blocked in read on a socket waiting on data. - * - Process (b) is blocked in shutdown() on a socket waiting on (a). - * - Process (c) delivers a signal to (b) interrupting its wait. - * - * This race is premised on shutdown() not interrupting (a) properly, and the - * signal to (b) causing problems in the kernel. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/socket.h> - -#include <err.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -static void -receive_and_exit(int s) -{ - ssize_t ssize; - char ch; - - ssize = recv(s, &ch, sizeof(ch), 0); - if (ssize < 0) - err(-1, "receive_and_exit: recv"); - exit(0); -} - -static void -shutdown_and_exit(int s) -{ - - if (shutdown(s, SHUT_RD) < 0) - err(-1, "shutdown_and_exit: shutdown"); - exit(0); -} - -int -main(void) -{ - pid_t pida, pidb; - int sv[2]; - - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sv) < 0) - err(-1, "socketpair"); - - pida = fork(); - if (pida < 0) - err(-1, "fork"); - if (pida == 0) - receive_and_exit(sv[1]); - sleep(1); - pidb = fork(); - if (pidb < 0) { - warn("fork"); - (void)kill(pida, SIGKILL); - exit(-1); - } - if (pidb == 0) - shutdown_and_exit(sv[1]); - sleep(1); - if (kill(pidb, SIGKILL) < 0) - err(-1, "kill"); - sleep(1); - printf("ok 1 - unix_sorflush\n"); - exit(0); -} diff --git a/tests/sys/sockets/zerosend_test.c b/tests/sys/sockets/zerosend_test.c deleted file mode 100644 index 1f3217a..0000000 --- a/tests/sys/sockets/zerosend_test.c +++ /dev/null @@ -1,290 +0,0 @@ -/*- - * Copyright (c) 2007 Robert N. M. Watson - * 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. - * - * $FreeBSD$ - */ - -#include <sys/select.h> -#include <sys/socket.h> -#include <sys/stat.h> - -#include <netinet/in.h> - -#include <arpa/inet.h> - -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -#define PORT1 10001 -#define PORT2 10002 - -static void -try_0send(const char *test, int fd) -{ - ssize_t len; - char ch; - - ch = 0; - len = send(fd, &ch, 0, 0); - if (len < 0) - err(-1, "%s: try_0send", test); - if (len != 0) - errx(-1, "%s: try_0send: returned %zd", test, len); -} - -static void -try_0write(const char *test, int fd) -{ - ssize_t len; - char ch; - - ch = 0; - len = write(fd, &ch, 0); - if (len < 0) - err(-1, "%s: try_0write", test); - if (len != 0) - errx(-1, "%s: try_0write: returned %zd", test, len); -} - -static void -setup_udp(const char *test, int *fdp) -{ - struct sockaddr_in sin; - int sock1, sock2; - - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - sin.sin_port = htons(PORT1); - sock1 = socket(PF_INET, SOCK_DGRAM, 0); - if (sock1 < 0) - err(-1, "%s: setup_udp: socket", test); - if (bind(sock1, (struct sockaddr *)&sin, sizeof(sin)) < 0) - err(-1, "%s: setup_udp: bind(%s, %d)", test, - inet_ntoa(sin.sin_addr), PORT1); - sin.sin_port = htons(PORT2); - if (connect(sock1, (struct sockaddr *)&sin, sizeof(sin)) < 0) - err(-1, "%s: setup_udp: connect(%s, %d)", test, - inet_ntoa(sin.sin_addr), PORT2); - - sock2 = socket(PF_INET, SOCK_DGRAM, 0); - if (sock2 < 0) - err(-1, "%s: setup_udp: socket", test); - if (bind(sock2, (struct sockaddr *)&sin, sizeof(sin)) < 0) - err(-1, "%s: setup_udp: bind(%s, %d)", test, - inet_ntoa(sin.sin_addr), PORT2); - sin.sin_port = htons(PORT1); - if (connect(sock2, (struct sockaddr *)&sin, sizeof(sin)) < 0) - err(-1, "%s: setup_udp: connect(%s, %d)", test, - inet_ntoa(sin.sin_addr), PORT1); - - fdp[0] = sock1; - fdp[1] = sock2; -} - -static void -setup_tcp(const char *test, int *fdp) -{ - fd_set writefds, exceptfds; - struct sockaddr_in sin; - int ret, sock1, sock2, sock3; - struct timeval tv; - - bzero(&sin, sizeof(sin)); - sin.sin_len = sizeof(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - /* - * First set up the listen socket. - */ - sin.sin_port = htons(PORT1); - sock1 = socket(PF_INET, SOCK_STREAM, 0); - if (sock1 < 0) - err(-1, "%s: setup_tcp: socket", test); - if (bind(sock1, (struct sockaddr *)&sin, sizeof(sin)) < 0) - err(-1, "%s: bind(%s, %d)", test, inet_ntoa(sin.sin_addr), - PORT1); - if (listen(sock1, -1) < 0) - err(-1, "%s: listen", test); - - /* - * Now connect to it, non-blocking so that we don't deadlock against - * ourselves. - */ - sock2 = socket(PF_INET, SOCK_STREAM, 0); - if (sock2 < 0) - err(-1, "%s: setup_tcp: socket", test); - if (fcntl(sock2, F_SETFL, O_NONBLOCK) < 0) - err(-1, "%s: setup_tcp: fcntl(O_NONBLOCK)", test); - if (connect(sock2, (struct sockaddr *)&sin, sizeof(sin)) < 0 && - errno != EINPROGRESS) - err(-1, "%s: setup_tcp: connect(%s, %d)", test, - inet_ntoa(sin.sin_addr), PORT1); - - /* - * Now pick up the connection after sleeping a moment to make sure - * there's been time for some packets to go back and forth. - */ - if (sleep(1) < 0) - err(-1, "%s: sleep(1)", test); - sock3 = accept(sock1, NULL, NULL); - if (sock3 < 0) - err(-1, "%s: accept", test); - if (sleep(1) < 0) - err(-1, "%s: sleep(1)", test); - - FD_ZERO(&writefds); - FD_SET(sock2, &writefds); - FD_ZERO(&exceptfds); - FD_SET(sock2, &exceptfds); - tv.tv_sec = 1; - tv.tv_usec = 0; - ret = select(sock2 + 1, NULL, &writefds, &exceptfds, &tv); - if (ret < 0) - err(-1, "%s: setup_tcp: select", test); - if (FD_ISSET(sock2, &exceptfds)) - errx(-1, "%s: setup_tcp: select: exception", test); - if (!FD_ISSET(sock2, &writefds)) - errx(-1, "%s: setup_tcp: select: not writable", test); - - close(sock1); - fdp[0] = sock2; - fdp[1] = sock3; -} - -static void -setup_udsstream(const char *test, int *fdp) -{ - - if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fdp) < 0) - err(-1, "%s: setup_udsstream: socketpair", test); -} - -static void -setup_udsdgram(const char *test, int *fdp) -{ - - if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fdp) < 0) - err(-1, "%s: setup_udsdgram: socketpair", test); -} - -static void -setup_pipe(const char *test, int *fdp) -{ - - if (pipe(fdp) < 0) - err(-1, "%s: setup_pipe: pipe", test); -} - -static void -setup_fifo(const char *test, int *fdp) -{ - char path[] = "0send_fifo.XXXXXXX"; - int fd1, fd2; - - if (mkstemp(path) == -1) - err(-1, "%s: setup_fifo: mktemp", test); - unlink(path); - - if (mkfifo(path, 0600) < 0) - err(-1, "%s: setup_fifo: mkfifo(%s)", test, path); - - fd1 = open(path, O_RDONLY | O_NONBLOCK); - if (fd1 < 0) - err(-1, "%s: setup_fifo: open(%s, O_RDONLY)", test, path); - - fd2 = open(path, O_WRONLY | O_NONBLOCK); - if (fd2 < 0) - err(-1, "%s: setup_fifo: open(%s, O_WRONLY)", test, path); - - fdp[0] = fd2; - fdp[1] = fd1; -} - -static void -close_both(int *fdp) -{ - - close(fdp[0]); - fdp[0] = -1; - close(fdp[1]); - fdp[1] = -1; -} - -int -main(int argc, char *argv[]) -{ - int fd[2]; - - setup_udp("udp_0send", fd); - try_0send("udp_0send", fd[0]); - close_both(fd); - - setup_udp("udp_0write", fd); - try_0write("udp_0write", fd[0]); - close_both(fd); - - setup_tcp("tcp_0send", fd); - try_0send("tcp_0send", fd[0]); - close_both(fd); - - setup_tcp("tcp_0write", fd); - try_0write("tcp_0write", fd[0]); - close_both(fd); - - setup_udsstream("udsstream_0send", fd); - try_0send("udsstream_0send", fd[0]); - close_both(fd); - - setup_udsstream("udsstream_0write", fd); - try_0write("udsstream_0write", fd[0]); - close_both(fd); - - setup_udsdgram("udsdgram_0send", fd); - try_0send("udsdgram_0send", fd[0]); - close_both(fd); - - setup_udsdgram("udsdgram_0write", fd); - try_0write("udsdgram_0write", fd[0]); - close_both(fd); - - setup_pipe("pipe_0write", fd); - try_0write("pipd_0write", fd[0]); - close_both(fd); - - setup_fifo("fifo_0write", fd); - try_0write("fifo_0write", fd[0]); - close_both(fd); - - return (0); -} diff --git a/tests/sys/vfs/Makefile b/tests/sys/vfs/Makefile deleted file mode 100644 index 7cd908b..0000000 --- a/tests/sys/vfs/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD$ - -TESTSDIR= ${TESTSBASE}/sys/vfs - -TAP_TESTS_SH+= trailing_slash_test - -.include <bsd.test.mk> diff --git a/tests/sys/vfs/trailing_slash_test.sh b/tests/sys/vfs/trailing_slash_test.sh deleted file mode 100755 index 28c7f5f..0000000 --- a/tests/sys/vfs/trailing_slash_test.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh -# -# $FreeBSD$ -# -# Tests vfs_lookup()'s handling of trailing slashes for symlinks that -# point to files. See kern/21768 for details. Fixed in r193028. -# - -testfile=$(mktemp tmp.XXXXXX) || exit -testlink="testlink-$$" - -tests=" -$testfile:$testlink:$testfile:0 -$testfile:$testlink:$testfile/:1 -$testfile:$testlink:$testlink:0 -$testfile:$testlink:$testlink/:1 -$testfile/:$testlink:$testlink:1 -$testfile/:$testlink:$testlink/:1 -" - -trap "rm $testfile $testlink" EXIT - -set $tests -echo "1..$#" -n=1 -for testspec ; do - ( - IFS=: - set $testspec - unset IFS - ln -fs "$1" "$2" || exit 1 - cat "$3" >/dev/null 2>&1 - ret=$? - if [ "$ret" -eq "$4" ] ; then - echo "ok $n" - else - echo "fail $n - expected $4, got $ret" - fi - ) - n=$((n+1)) -done |