summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/regression/fifo/fifo_create/Makefile7
-rw-r--r--tools/regression/fifo/fifo_create/fifo_create.c285
-rw-r--r--tools/regression/fifo/fifo_io/Makefile7
-rw-r--r--tools/regression/fifo/fifo_io/fifo_io.c1409
-rw-r--r--tools/regression/fifo/fifo_misc/Makefile7
-rw-r--r--tools/regression/fifo/fifo_misc/fifo_misc.c336
-rw-r--r--tools/regression/fifo/fifo_open/Makefile7
-rw-r--r--tools/regression/fifo/fifo_open/fifo_open.c476
8 files changed, 0 insertions, 2534 deletions
diff --git a/tools/regression/fifo/fifo_create/Makefile b/tools/regression/fifo/fifo_create/Makefile
deleted file mode 100644
index 10e2b14..0000000
--- a/tools/regression/fifo/fifo_create/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# $FreeBSD$
-
-PROG= fifo_create
-MAN=
-WARNS?= 3
-
-.include <bsd.prog.mk>
diff --git a/tools/regression/fifo/fifo_create/fifo_create.c b/tools/regression/fifo/fifo_create/fifo_create.c
deleted file mode 100644
index 4e8a8a4..0000000
--- a/tools/regression/fifo/fifo_create/fifo_create.c
+++ /dev/null
@@ -1,285 +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.
- */
-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[PATH_MAX];
- 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(temp_dir, &old_dirsb) < 0)
- err(-1, "basic_create_test: %s: stat: %s", testname,
- temp_dir);
-
- sleep(2);
-
- snprintf(path, PATH_MAX, "%s/testfifo", temp_dir);
-
- 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(temp_dir, &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[PATH_MAX];
- const char *testname;
- struct stat sb;
- int error, i;
-
- if (use_mkfifo)
- testname = "mkfifo";
- else
- testname = "mknod";
-
- snprintf(path, PATH_MAX, "%s/testfifo", temp_dir);
- 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(int argc, char *argv[])
-{
- int i;
-
- if (geteuid() != 0)
- errx(-1, "must be run as root");
-
- strcpy(temp_dir, "/tmp/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/tools/regression/fifo/fifo_io/Makefile b/tools/regression/fifo/fifo_io/Makefile
deleted file mode 100644
index 49bf5bd..0000000
--- a/tools/regression/fifo/fifo_io/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# $FreeBSD$
-
-PROG= fifo_io
-MAN=
-WARNS?= 3
-
-.include <bsd.prog.mk>
diff --git a/tools/regression/fifo/fifo_io/fifo_io.c b/tools/regression/fifo/fifo_io/fifo_io.c
deleted file mode 100644
index 4d3c54e..0000000
--- a/tools/regression/fifo/fifo_io/fifo_io.c
+++ /dev/null
@@ -1,1409 +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.
- */
-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, const char *testname, 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, const char *testname, 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", "test_simpleio", &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 int alarm_fired;
-/*
- * Non-destructive SIGALRM handler.
- */
-static void
-sigalarm(int signum)
-{
-
- 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", __func__, &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", __func__, &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", __func__, &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", __func__, &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", __func__, &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", __func__, &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", __func__, &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", __func__, &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", __func__, &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", __func__, &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", __func__, &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(int argc, char *argv[])
-{
-
- strcpy(temp_dir, "/tmp/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/tools/regression/fifo/fifo_misc/Makefile b/tools/regression/fifo/fifo_misc/Makefile
deleted file mode 100644
index 97f85ec..0000000
--- a/tools/regression/fifo/fifo_misc/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# $FreeBSD$
-
-PROG= fifo_misc
-MAN=
-WARNS?= 3
-
-.include <bsd.prog.mk>
diff --git a/tools/regression/fifo/fifo_misc/fifo_misc.c b/tools/regression/fifo/fifo_misc/fifo_misc.c
deleted file mode 100644
index 4215212..0000000
--- a/tools/regression/fifo/fifo_misc/fifo_misc.c
+++ /dev/null
@@ -1,336 +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.
- */
-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, const char *testname, 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", __func__, &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", __func__, &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", __func__, &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(int argc, char *argv[])
-{
-
- strcpy(temp_dir, "/tmp/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/tools/regression/fifo/fifo_open/Makefile b/tools/regression/fifo/fifo_open/Makefile
deleted file mode 100644
index d90811c..0000000
--- a/tools/regression/fifo/fifo_open/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# $FreeBSD$
-
-PROG= fifo_open
-MAN=
-WARNS?= 3
-
-.include <bsd.prog.mk>
diff --git a/tools/regression/fifo/fifo_open/fifo_open.c b/tools/regression/fifo/fifo_open/fifo_open.c
deleted file mode 100644
index 6899a3a..0000000
--- a/tools/regression/fifo/fifo_open/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.
- */
-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(int argc, char *argv[])
-{
-
- if (geteuid() != 0)
- errx(-1, "must be run as root");
-
- strcpy(temp_dir, "/tmp/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);
-}
OpenPOWER on IntegriCloud