From d4f159fda3ce5662f64210fd896dd2d55113f3e5 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Mon, 18 Mar 2024 19:23:29 -0400 Subject: [PATCH] Determine behaviour of EVFILT_WRITE for regular files on FreeBSD --- test/CMakeLists.txt | 3 +- test/common.h | 1 + test/main.c | 4 +++ test/write.c | 73 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 test/write.c diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6d8c11e4..2409cd2b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -25,7 +25,8 @@ set(LIBKQUEUE_TEST_SOURCES test.c timer.c user.c - vnode.c) + vnode.c + write.c) if(UNIX) list(APPEND LIBKQUEUE_TEST_SOURCES proc.c diff --git a/test/common.h b/test/common.h index 69e20431..fbf16fb4 100644 --- a/test/common.h +++ b/test/common.h @@ -112,6 +112,7 @@ void test_kqueue(struct test_context *); void test_evfilt_read(struct test_context *); void test_evfilt_signal(struct test_context *); void test_evfilt_vnode(struct test_context *); +void test_evfilt_write(struct test_context *); void test_evfilt_timer(struct test_context *); void test_evfilt_proc(struct test_context *); #ifdef EVFILT_USER diff --git a/test/main.c b/test/main.c index e5c0dece..da80eb4e 100644 --- a/test/main.c +++ b/test/main.c @@ -169,6 +169,10 @@ main(int argc, char **argv) .ut_func = test_evfilt_vnode, .ut_end = INT_MAX }, #endif + { .ut_name = "write", + .ut_enabled = 1, + .ut_func = test_evfilt_write, + .ut_end = INT_MAX }, #ifdef EVFILT_USER { .ut_name = "user", .ut_enabled = 1, diff --git a/test/write.c b/test/write.c new file mode 100644 index 00000000..46224a1b --- /dev/null +++ b/test/write.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 Arran Cudbard-Bell + * + * 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. + */ + +#include "common.h" + + +/** Test if we can setup an event to write to a regular file + * + * Setting up a write event on a regular file doesn't make much sense + * but it is allowed by kqueue, so check we exhibit similar behaviour. + */ +void +test_kevent_write_regular_file(struct test_context *ctx) +{ + struct kevent kev, ret[1]; + int fd; + + fd = open(ctx->testfile, O_CREAT | O_WRONLY); + if (fd < 0) + abort(); + + EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, &fd); + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); + kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1); + + /* File should appear immediately writable */ + kevent_get(NULL, 0, ctx->kqfd, 1); + kevent_cmp(&kev, ret); + if (write(fd, "test", 4) != 4) { + printf("failed writing to set file: %s", strerror(errno)); + abort(); + } + + /* ...should still be writable */ + kevent_get(NULL, 0, ctx->kqfd, 1); + kevent_cmp(&kev, ret); + + kev.flags = EV_DELETE; + kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL)); + + close(fd); + unlink(ctx->testfile); +} + +void +test_evfilt_write(struct test_context *ctx) +{ + char *tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL) +#ifdef __ANDROID__ + tmpdir = "/data/local/tmp"; +#else + tmpdir = "/tmp"; +#endif + + snprintf(ctx->testfile, sizeof(ctx->testfile), "%s/kqueue-test%d.tmp", + tmpdir, testing_make_uid()); + + test(kevent_write_regular_file, ctx); +}