/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
/* * Setup standard FHS 2.3 structure in /var, and * write runlevel to UTMP, needed by, e.g., printerdrake. */ static void setup(void *UNUSED(arg)) { #ifdef RUNLEVEL struct utmp entry; #endif _d("Setting up FHS structure in /var ..."); makedir("/var/cache", 0755); makedir("/var/games", 0755); makedir("/var/lib", 0755); makedir("/var/lib/misc", 0755); makedir("/var/lib/alarm", 0755); makedir("/var/lock", 0755); makedir("/var/log", 0755); makedir("/var/mail", 0755); makedir("/var/opt", 0755); makedir("/var/run", 0755); makedir("/var/spool", 0755); makedir("/var/spool/cron", 0755); makedir("/var/tmp", 0755); makedir("/var/empty", 0755); _d("Setting up necessary UTMP files ..."); touch("/var/run/utmp"); chown("/var/run/utmp", 0, getgroup("utmp")); #ifdef RUNLEVEL memset(&entry, 0, sizeof(struct utmp)); entry.ut_type = RUN_LVL; entry.ut_pid = '0' + RUNLEVEL; setutent(); pututline(&entry); endutent(); #endif #ifdef TOUCH_ETC_NETWORK_RUN_IFSTATE touch("/etc/network/run/ifstate"); #else erase("/etc/network/run/ifstate"); #endif _d("Setting up misc files ..."); makedir("/var/run/lldpd", 0755); /* Needed by lldpd */ makedir("/var/run/pluto", 0755); /* Needed by Openswan */ makedir("/var/run/quagga", 0755); /* Needed by Quagga */ makedir("/var/log/quagga", 0755); /* Needed by Quagga */ makedir("/var/run/sshd", 01755); /* OpenSSH */ makefifo("/dev/xconsole", 0640); /* sysklogd */ chown("/dev/xconsole", 0, getgroup("tty")); }
/* * 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); }
int ask_passwd_cli(const char *manufacturer, const char *product, const char *devnode) { int i = 0; int ttys_notified = 0; int MAX_PWD_ATTEMPTS = 0; int passwd_match = 0; char *tty = NULL; char *username = NULL; char *plain_txt_passwd = NULL; char *fifo_path = NULL; FILE *fp = NULL; struct auth_len lengths; MAX_PWD_ATTEMPTS = get_sield_attr_int("max password tries"); if (MAX_PWD_ATTEMPTS == -1) MAX_PWD_ATTEMPTS = 3; ttys_notified = notify_all_ttys(manufacturer, product, devnode); if (ttys_notified == 0) { log_fn("No users are logged in. Ignoring %s (%s %s).", devnode, manufacturer, product); return 0; } log_fn("Wrote to %d tty(s) about device %s (%s %s). Awaiting response.", ttys_notified, devnode, manufacturer, product); fifo_path = makefifo(manufacturer, product, devnode); if (fifo_path == NULL) return 0; for (i = 0; (i < MAX_PWD_ATTEMPTS) && (passwd_match != 1); i++) { /* Open the named pipe for reading. */ fp = fopen(fifo_path, "r"); if (fp == NULL) { log_fn("fopen: %s: %s", fifo_path, strerror(errno)); free(fifo_path); continue; } /* Lengths */ if (fread(&lengths, sizeof(struct auth_len), 1, fp) != 1) { log_fn("Unable to read data (strlens) sent from CLI app."); continue; } tty = malloc((lengths.tty_len + 1) * sizeof(char)); username = malloc((lengths.user_len + 1) * sizeof(char)); plain_txt_passwd = malloc((lengths.pwd_len + 1) * sizeof(char)); if ((fread(tty, sizeof(char), lengths.tty_len + 1, fp) != lengths.tty_len + 1) || (fread(username, sizeof(char), lengths.user_len + 1, fp) != lengths.user_len + 1) || (fread(plain_txt_passwd, sizeof(char), lengths.pwd_len + 1, fp) != lengths.pwd_len + 1)) { log_fn("Unable to read data sent from CLI app."); if (tty) free(tty); if (username) free(username); if (plain_txt_passwd) free(plain_txt_passwd); fclose(fp); continue; } if (is_passwd_correct(plain_txt_passwd)) { log_fn("%s (@%s) provided correct password.", username, tty); write_to_tty(tty, "Password accepted.\n"); passwd_match = 1; } else { log_fn("%s (@%s) entered incorrect password. Attempt #%d", username, tty, i+1); write_to_tty(tty, "Incorrect password given.\n"); passwd_match = 0; } if (tty) free(tty); if (username) free(username); if (plain_txt_passwd) free(plain_txt_passwd); fclose(fp); } if (passwd_match == 0) { log_fn("Used all password attempts."); } /* Delete the associated named pipe. */ if (remove(fifo_path) == -1) { log_fn("Unable to delete named pipe %s", fifo_path); } if (remove(FIFO_DIR) == -1) { log_fn("Couldn't delete directory %s", FIFO_DIR); } if (fifo_path) free(fifo_path); return passwd_match; }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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); }
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); }