aboutsummaryrefslogtreecommitdiff
path: root/compat/linux
diff options
context:
space:
mode:
Diffstat (limited to 'compat/linux')
-rw-r--r--compat/linux/Makefile61
-rw-r--r--compat/linux/arch/x86_64/h_syscall.c55
-rw-r--r--compat/linux/h_common.sh34
-rw-r--r--compat/linux/h_inotify_directory.c108
-rw-r--r--compat/linux/h_inotify_init.c65
-rw-r--r--compat/linux/h_inotify_single_file.c87
-rw-r--r--compat/linux/h_inotify_watch_change.c88
-rw-r--r--compat/linux/h_linux.c36
-rw-r--r--compat/linux/h_linux.h76
-rw-r--r--compat/linux/h_not_supported.sh33
-rw-r--r--compat/linux/t_inotify.sh79
11 files changed, 722 insertions, 0 deletions
diff --git a/compat/linux/Makefile b/compat/linux/Makefile
new file mode 100644
index 000000000000..cd3b1a91bf21
--- /dev/null
+++ b/compat/linux/Makefile
@@ -0,0 +1,61 @@
+# $NetBSD: Makefile,v 1.1 2023/08/19 22:56:44 christos Exp $
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/compat/linux
+TESTS_SH= t_inotify
+
+TC_PROGS= h_inotify_init
+TC_PROGS+= h_inotify_directory
+TC_PROGS+= h_inotify_single_file
+TC_PROGS+= h_inotify_watch_change
+
+.PATH: ${.CURDIR}/arch/${MACHINE_ARCH}
+
+LDFLAGS+= -nostartfiles -static
+CFLAGS+= -I${.CURDIR}/../../../sys
+CFLAGS+= -I${.CURDIR}
+CFLAGS+= -D_STANDALONE
+
+FILESDIR= ${TESTSDIR}
+
+.for _P in ${TESTS_SH}
+.if ${MACHINE_ARCH} == "x86_64"
+TESTS_SH_SRC_${_P}= h_common.sh
+.else
+TESTS_SH_SRC_${_P}= h_not_supported.sh
+.endif
+TESTS_SH_SRC_${_P}+= ${_P}.sh
+.endfor
+
+.for _P in ${TC_PROGS}
+CLEANFILES+= ${_P}
+FILES+= ${_P}
+
+.if ${MACHINE_ARCH} == "x86_64"
+PROGS+= ${_P}.out
+SRCS.${_P}.out= ${_P}.c
+SRCS.${_P}.out+= h_linux.c
+SRCS.${_P}.out+= h_syscall.c
+MAN.${_P}.out= # empty
+FILESMODE_${_P}= ${BINMODE}
+
+proginstall-${_P}.out:
+ # Do not install
+
+${_P}: ${_P}.out
+ ${_MKTARGET_CREATE}
+ cp ${.ALLSRC} ${.TARGET}
+ ${ELFEDIT} --output-osabi Linux ${.TARGET}
+.else
+${_P}:
+ echo '' > ${.TARGET}
+.endif
+
+realall: ${_P}
+.endfor
+
+CLEANFILES+= ${TESTS_SH}
+CLEANFILES+= Atffile
+
+.include <bsd.test.mk>
diff --git a/compat/linux/arch/x86_64/h_syscall.c b/compat/linux/arch/x86_64/h_syscall.c
new file mode 100644
index 000000000000..32485c121a47
--- /dev/null
+++ b/compat/linux/arch/x86_64/h_syscall.c
@@ -0,0 +1,55 @@
+/* $NetBSD: h_syscall.c,v 1.1 2023/08/19 22:56:44 christos Exp $ */
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Theodore Preduta.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: h_syscall.c,v 1.1 2023/08/19 22:56:44 christos Exp $");
+#include "h_linux.h"
+
+long
+syscall6(long number, register_t arg1, register_t arg2, register_t arg3,
+ register_t arg4, register_t arg5, register_t arg6, ...)
+{
+ long retval;
+ register register_t r10 __asm__ ("r10") = arg4;
+ register register_t r8 __asm__ ("r8") = arg5;
+ register register_t r9 __asm__ ("r9") = arg6;
+
+ __asm__ __volatile__ ("syscall"
+ : "=a"(retval)
+ : "a"(number), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
+ : "rcx", "r11", "memory");
+
+ if (retval < 0) {
+ errno = -retval;
+ return -1;
+ }
+
+ return retval;
+}
diff --git a/compat/linux/h_common.sh b/compat/linux/h_common.sh
new file mode 100644
index 000000000000..79e4d700566c
--- /dev/null
+++ b/compat/linux/h_common.sh
@@ -0,0 +1,34 @@
+# $NetBSD: h_common.sh,v 1.1 2023/08/19 22:56:44 christos Exp $
+#
+# Copyright (c) 2023 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by Theodore Preduta.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#/
+
+h_ensure_emul_exists() {
+ modstat | grep -q '^compat_linux\W' \
+ || atf_skip "Linux emulation not loaded"
+}
diff --git a/compat/linux/h_inotify_directory.c b/compat/linux/h_inotify_directory.c
new file mode 100644
index 000000000000..3fc8d91e7674
--- /dev/null
+++ b/compat/linux/h_inotify_directory.c
@@ -0,0 +1,108 @@
+/* $NetBSD: h_inotify_directory.c,v 1.1 2023/08/19 22:56:44 christos Exp $ */
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Theodore Preduta.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: h_inotify_directory.c,v 1.1 2023/08/19 22:56:44 christos Exp $");
+
+#include "h_linux.h"
+
+#include <sys/null.h>
+
+#include <compat/linux/linux_syscall.h>
+#include <compat/linux/common/linux_inotify.h>
+
+#define INOTIFY_ALL_DIRECTORY (LINUX_IN_ATTRIB|LINUX_IN_CREATE \
+ |LINUX_IN_MOVE_SELF|LINUX_IN_MOVED_FROM \
+ |LINUX_IN_MOVED_TO|LINUX_IN_DELETE \
+ |LINUX_IN_DELETE_SELF)
+
+char buf[8192];
+
+struct {
+ uint32_t mask;
+ bool cookie;
+ char name[16];
+} target_events[] = {
+ { .mask = LINUX_IN_CREATE, .cookie = 0, .name = "test", },
+ { .mask = LINUX_IN_MOVED_FROM, .cookie = 1, .name = "test", },
+ { .mask = LINUX_IN_MOVED_TO, .cookie = 1, .name = "test2", },
+ { .mask = LINUX_IN_DELETE, .cookie = 0, .name = "test2", },
+ { .mask = LINUX_IN_MOVE_SELF, .cookie = 0, .name = "", },
+ { .mask = LINUX_IN_DELETE_SELF, .cookie = 0, .name = "", },
+ { .mask = LINUX_IN_IGNORED, .cookie = 0, .name = "", },
+};
+
+void
+_start(void)
+{
+ int fd, wd, targetfd;
+ char *cur_buf;
+ struct linux_inotify_event *cur_ie;
+
+ RS(mkdir("test", 0644));
+
+ RS(fd = syscall(LINUX_SYS_inotify_init));
+ RS(wd = syscall(LINUX_SYS_inotify_add_watch, fd, (register_t)"test",
+ INOTIFY_ALL_DIRECTORY));
+
+ /* Create some events. */
+ RS(targetfd = open("test/test", LINUX_O_RDWR|LINUX_O_CREAT, 0644));
+ RS(write(targetfd, &targetfd, sizeof(targetfd)));
+ RS(close(targetfd));
+ RS(rename("test/test", "test/test2"));
+ RS(unlink("test/test2"));
+ RS(rename("test", "test2"));
+ RS(rmdir("test2"));
+
+ /* Check the events. */
+ RS(read(fd, buf, sizeof(buf)));
+ cur_buf = buf;
+ for (size_t i = 0; i < __arraycount(target_events); i++) {
+ cur_ie = (struct linux_inotify_event *)cur_buf;
+
+ REQUIRE(cur_ie->wd == wd);
+ REQUIRE(cur_ie->mask == target_events[i].mask);
+
+ if (target_events[i].cookie)
+ REQUIRE(cur_ie->cookie != 0);
+ else
+ REQUIRE(cur_ie->cookie == 0);
+
+ if (target_events[i].name[0] != '\0') {
+ REQUIRE(cur_ie->len > strlen(target_events[i].name));
+ REQUIRE(strcmp(cur_ie->name, target_events[i].name) == 0);
+ } else
+ REQUIRE(cur_ie->len == 0);
+
+ cur_buf += sizeof(struct linux_inotify_event) + cur_ie->len;
+ }
+
+ exit(0);
+}
diff --git a/compat/linux/h_inotify_init.c b/compat/linux/h_inotify_init.c
new file mode 100644
index 000000000000..c1a45d9ad570
--- /dev/null
+++ b/compat/linux/h_inotify_init.c
@@ -0,0 +1,65 @@
+/* $NetBSD: h_inotify_init.c,v 1.1 2023/08/19 22:56:44 christos Exp $ */
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Theodore Preduta.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: h_inotify_init.c,v 1.1 2023/08/19 22:56:44 christos Exp $");
+
+#include "h_linux.h"
+
+#include <compat/linux/linux_syscall.h>
+#include <compat/linux/common/linux_errno.h>
+#include <compat/linux/common/linux_fcntl.h>
+#include <compat/linux/common/linux_inotify.h>
+
+void
+_start(void)
+{
+ int fd;
+
+ /* Check that none of CLOEXEC or NONBLOCK are set. */
+ RS(fd = syscall(LINUX_SYS_inotify_init));
+ REQUIRE(fcntl(fd, LINUX_F_GETFD) == 0);
+ REQUIRE((fcntl(fd, LINUX_F_GETFL) & LINUX_O_NONBLOCK) == 0);
+ RS(close(fd));
+
+ /* Check that only NONBLOCK is set. */
+ RS(fd = syscall(LINUX_SYS_inotify_init1, LINUX_IN_NONBLOCK));
+ REQUIRE(fcntl(fd, LINUX_F_GETFD) == 0);
+ REQUIRE((fcntl(fd, LINUX_F_GETFL) & LINUX_O_NONBLOCK) != 0);
+ RS(close(fd));
+
+ /* Check that only CLOEXEC is set. */
+ RS(fd = syscall(LINUX_SYS_inotify_init1, LINUX_IN_CLOEXEC));
+ REQUIRE(fcntl(fd, LINUX_F_GETFD) != 0);
+ REQUIRE((fcntl(fd, LINUX_F_GETFL) & LINUX_O_NONBLOCK) == 0);
+ RS(close(fd));
+
+ exit(0);
+}
diff --git a/compat/linux/h_inotify_single_file.c b/compat/linux/h_inotify_single_file.c
new file mode 100644
index 000000000000..6e2f7125b120
--- /dev/null
+++ b/compat/linux/h_inotify_single_file.c
@@ -0,0 +1,87 @@
+/* $NetBSD: h_inotify_single_file.c,v 1.1 2023/08/19 22:56:44 christos Exp $ */
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Theodore Preduta.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: h_inotify_single_file.c,v 1.1 2023/08/19 22:56:44 christos Exp $");
+
+#include "h_linux.h"
+
+#include <compat/linux/linux_syscall.h>
+#include <compat/linux/common/linux_inotify.h>
+
+#define INOTIFY_ALL_FILE (LINUX_IN_ATTRIB|LINUX_IN_CLOSE_NOWRITE \
+ |LINUX_IN_OPEN|LINUX_IN_MOVE_SELF \
+ |LINUX_IN_ACCESS|LINUX_IN_CLOSE_WRITE \
+ |LINUX_IN_MODIFY|LINUX_IN_DELETE_SELF)
+
+struct linux_inotify_event events[10];
+
+void
+_start(void)
+{
+ int fd, wd, targetfd, buf;
+
+ RS(targetfd = open("test", LINUX_O_RDWR|LINUX_O_CREAT, 0644));
+ RS(close(targetfd));
+
+ RS(fd = syscall(LINUX_SYS_inotify_init));
+ RS(wd = syscall(LINUX_SYS_inotify_add_watch, fd, (register_t)"test",
+ INOTIFY_ALL_FILE));
+
+ /* Create some events. */
+ RS(targetfd = open("test", LINUX_O_RDWR|LINUX_O_CREAT, 0644));
+ RS(write(targetfd, &buf, sizeof(buf)));
+ RS(read(targetfd, &buf, sizeof(buf)));
+ RS(close(targetfd));
+ RS(targetfd = open("test", LINUX_O_RDONLY|LINUX_O_CREAT, 0644));
+ RS(close(targetfd));
+ RS(rename("test", "test2"));
+ RS(unlink("test2"));
+
+ /* Get and check the events. */
+ RS(read(fd, events, sizeof(events)));
+
+ for (size_t i = 0; i < __arraycount(events); i++)
+ REQUIRE(events[i].wd == wd && events[i].cookie == 0
+ && events[i].len == 0);
+
+ REQUIRE(events[0].mask == LINUX_IN_OPEN);
+ REQUIRE(events[1].mask == LINUX_IN_MODIFY);
+ REQUIRE(events[2].mask == LINUX_IN_ACCESS);
+ REQUIRE(events[3].mask == LINUX_IN_CLOSE_WRITE);
+ REQUIRE(events[4].mask == LINUX_IN_OPEN);
+ REQUIRE(events[5].mask == LINUX_IN_CLOSE_NOWRITE);
+ REQUIRE(events[6].mask == LINUX_IN_MOVE_SELF);
+ REQUIRE(events[7].mask == LINUX_IN_ATTRIB);
+ REQUIRE(events[8].mask == LINUX_IN_DELETE_SELF);
+ REQUIRE(events[9].mask == LINUX_IN_IGNORED);
+
+ exit(0);
+}
diff --git a/compat/linux/h_inotify_watch_change.c b/compat/linux/h_inotify_watch_change.c
new file mode 100644
index 000000000000..99075bd59940
--- /dev/null
+++ b/compat/linux/h_inotify_watch_change.c
@@ -0,0 +1,88 @@
+/* $NetBSD: h_inotify_watch_change.c,v 1.1 2023/08/19 22:56:44 christos Exp $ */
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Theodore Preduta.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: h_inotify_watch_change.c,v 1.1 2023/08/19 22:56:44 christos Exp $");
+
+#include "h_linux.h"
+
+#include <compat/linux/linux_syscall.h>
+#include <compat/linux/common/linux_inotify.h>
+
+struct linux_inotify_event events[2];
+
+void
+_start(void)
+{
+ int fd, wd, targetfd;
+ ssize_t nread;
+
+ RS(targetfd = open("test", LINUX_O_RDWR|LINUX_O_CREAT, 0644));
+ RS(close(targetfd));
+
+ RS(fd = syscall(LINUX_SYS_inotify_init));
+ RS(wd = syscall(LINUX_SYS_inotify_add_watch, fd, (register_t)"test",
+ LINUX_IN_CLOSE_NOWRITE));
+
+ /* We should only get the close event. */
+ RS(targetfd = open("test", LINUX_O_RDONLY|LINUX_O_CREAT, 0644));
+ RS(close(targetfd));
+
+ RS(nread = read(fd, events, sizeof(events)));
+ REQUIRE(nread == sizeof(events[0]));
+ REQUIRE(events[0].mask == LINUX_IN_CLOSE_NOWRITE);
+
+ /* Change the watch descriptor. */
+ RS(wd = syscall(LINUX_SYS_inotify_add_watch, fd, (register_t)"test",
+ LINUX_IN_OPEN));
+
+ /* We should only get the open event. */
+ RS(targetfd = open("test", LINUX_O_RDONLY|LINUX_O_CREAT, 0644));
+ RS(close(targetfd));
+
+ RS(nread = read(fd, events, sizeof(events)));
+ REQUIRE(nread == sizeof(events[0]));
+ REQUIRE(events[0].mask == LINUX_IN_OPEN);
+
+ /* Add to the watch descriptor. */
+ RS(wd = syscall(LINUX_SYS_inotify_add_watch, fd, (register_t)"test",
+ LINUX_IN_CLOSE_NOWRITE|LINUX_IN_MASK_ADD));
+
+ /* Now we should get both the open and the close. */
+ RS(targetfd = open("test", LINUX_O_RDONLY|LINUX_O_CREAT, 0644));
+ RS(close(targetfd));
+
+ RS(nread = read(fd, events, sizeof(events)));
+ REQUIRE(nread == 2 * sizeof(events[0]));
+ REQUIRE(events[0].mask == LINUX_IN_OPEN);
+ REQUIRE(events[1].mask == LINUX_IN_CLOSE_NOWRITE);
+
+ exit(0);
+}
diff --git a/compat/linux/h_linux.c b/compat/linux/h_linux.c
new file mode 100644
index 000000000000..4acbb051626d
--- /dev/null
+++ b/compat/linux/h_linux.c
@@ -0,0 +1,36 @@
+/* $NetBSD: h_linux.c,v 1.1 2023/08/19 22:56:44 christos Exp $ */
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Theodore Preduta.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: h_linux.c,v 1.1 2023/08/19 22:56:44 christos Exp $");
+
+#include "h_linux.h"
+
+int errno = 0;
diff --git a/compat/linux/h_linux.h b/compat/linux/h_linux.h
new file mode 100644
index 000000000000..1b21fa6d39fc
--- /dev/null
+++ b/compat/linux/h_linux.h
@@ -0,0 +1,76 @@
+/* $NetBSD: h_linux.h,v 1.2 2023/08/23 20:05:05 rillig Exp $ */
+
+/*-
+ * Copyright (c) 2023 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Theodore Preduta.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef SRC_TESTS_COMPAT_LINUX_H_LINUX_H_
+#define SRC_TESTS_COMPAT_LINUX_H_LINUX_H_
+
+#include <sys/types.h> /* For register_t. */
+
+#define FAIL (-1)
+
+#define syscall(number, ...) syscall6(number, ## __VA_ARGS__, \
+ 0, 0, 0, 0, 0, 0)
+
+#define RS(x) do { if ((x) == -1) exit(errno); } while (0)
+#define REQUIRE(x) do { if (!(x)) exit(FAIL); } while (0)
+
+/* Convenience wrappers for common syscalls. */
+#define close(fd) (int)syscall(LINUX_SYS_close, fd)
+#define exit(status) (void)syscall(LINUX_SYS_exit_group, status)
+#define fcntl(fd, cmd, ...) (int)syscall(LINUX_SYS_fcntl, fd, cmd, \
+ ## __VA_ARGS__)
+#define lseek(fd, off, whence) (off_t)syscall(LINUX_SYS_lseek, fd, \
+ (register_t)off, whence)
+#define mkdir(path, mode) (int)syscall(LINUX_SYS_mkdir, \
+ (register_t)path, mode)
+#define open(path, flags, ...) (int)syscall(LINUX_SYS_open, \
+ (register_t)path, flags, \
+ ## __VA_ARGS__)
+#define read(fd, buf, count) (ssize_t)syscall(LINUX_SYS_read, fd, \
+ (register_t)buf, count)
+#define rename(from, to) (int)syscall(LINUX_SYS___posix_rename, \
+ (register_t)from, (register_t)to)
+#define rmdir(path) (int)syscall(LINUX_SYS_rmdir, \
+ (register_t)path)
+#define unlink(path) (int)syscall(LINUX_SYS_unlink, \
+ (register_t)path)
+#define write(fd, buf, count) (ssize_t)syscall(LINUX_SYS_write, fd, \
+ (register_t)buf, count)
+
+/* GCC builtins. */
+#define strcmp(s1, s2) __builtin_strcmp(s1, s2)
+#define strlen(s) __builtin_strlen(s)
+
+long syscall6(long number, register_t, register_t, register_t, register_t,
+ register_t, register_t, ...);
+
+extern int errno;
+
+#endif /* !SRC_TESTS_COMPAT_LINUX_H_LINUX_H_ */
diff --git a/compat/linux/h_not_supported.sh b/compat/linux/h_not_supported.sh
new file mode 100644
index 000000000000..97a8f58e75c1
--- /dev/null
+++ b/compat/linux/h_not_supported.sh
@@ -0,0 +1,33 @@
+# $NetBSD: h_not_supported.sh,v 1.1 2023/08/19 22:56:44 christos Exp $
+#
+# Copyright (c) 2023 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by Theodore Preduta.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#/
+
+h_ensure_emul_exists() {
+ atf_skip "Linux emulation tests are not supported on this architecture"
+}
diff --git a/compat/linux/t_inotify.sh b/compat/linux/t_inotify.sh
new file mode 100644
index 000000000000..a25931a3b56d
--- /dev/null
+++ b/compat/linux/t_inotify.sh
@@ -0,0 +1,79 @@
+# $NetBSD: t_inotify.sh,v 1.1 2023/08/19 22:56:44 christos Exp $
+#
+# Copyright (c) 2023 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by Theodore Preduta.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#/
+
+atf_test_case init
+init_head() {
+ atf_set "descr" "Tests inotify_init applies its flags correctly"
+}
+
+init_body() {
+ h_ensure_emul_exists
+ atf_check -s exit:0 "$(atf_get_srcdir)/h_inotify_init"
+}
+
+atf_test_case single_file
+single_file_head() {
+ atf_set "descr" \
+ "Tests correct events are generated when a single file is watched"
+}
+
+single_file_body() {
+ h_ensure_emul_exists
+ atf_check -s exit:0 "$(atf_get_srcdir)/h_inotify_single_file"
+}
+
+atf_test_case directory
+directory_head() {
+ atf_set "descr" \
+ "Tests correct events are generated when a directory is watched"
+}
+
+directory_body() {
+ h_ensure_emul_exists
+ atf_check -s exit:0 "$(atf_get_srcdir)/h_inotify_directory"
+}
+
+atf_test_case watch_change
+watch_change_head() {
+ atf_set "descr" \
+ "Tests the watch descriptor can be modified"
+}
+
+watch_change_body() {
+ h_ensure_emul_exists
+ atf_check -s exit:0 "$(atf_get_srcdir)/h_inotify_watch_change"
+}
+
+atf_init_test_cases() {
+ atf_add_test_case init
+ atf_add_test_case directory
+ atf_add_test_case single_file
+ atf_add_test_case watch_change
+}