diff --git a/distrib/sets/lists/base/mi b/distrib/sets/lists/base/mi index 4fffcd06fba3..3ccf748f0863 100644 --- a/distrib/sets/lists/base/mi +++ b/distrib/sets/lists/base/mi @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1287 2022/01/10 10:02:30 martin Exp $ +# $NetBSD: mi,v 1.1288 2022/01/22 07:53:05 pho Exp $ # # Note: Don't delete entries from here - mark them as "obsolete" instead, # unless otherwise stated below. @@ -1147,6 +1147,7 @@ ./usr/include/protocols base-c-usr ./usr/include/quota base-obsolete obsolete ./usr/include/readline base-c-usr +./usr/include/refuse base-refuse-usr ./usr/include/rpc base-c-usr ./usr/include/rpcsvc base-c-usr ./usr/include/rump base-c-usr diff --git a/distrib/sets/lists/comp/mi b/distrib/sets/lists/comp/mi index 90bbd306e94c..64a0c4136ee6 100644 --- a/distrib/sets/lists/comp/mi +++ b/distrib/sets/lists/comp/mi @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.2404 2022/01/22 07:38:45 pho Exp $ +# $NetBSD: mi,v 1.2405 2022/01/22 07:53:05 pho Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. ./etc/mtree/set.comp comp-sys-root @@ -3092,6 +3092,7 @@ ./usr/include/readline.h comp-obsolete obsolete ./usr/include/readline/history.h comp-c-include ./usr/include/readline/readline.h comp-c-include +./usr/include/refuse/session.h comp-refuse-include ./usr/include/regex.h comp-c-include ./usr/include/regexp.h comp-c-include ./usr/include/res_update.h comp-c-include diff --git a/etc/mtree/NetBSD.dist.base b/etc/mtree/NetBSD.dist.base index 3357b3ce2df2..fb10bc556d51 100644 --- a/etc/mtree/NetBSD.dist.base +++ b/etc/mtree/NetBSD.dist.base @@ -1,4 +1,4 @@ -# $NetBSD: NetBSD.dist.base,v 1.240 2021/12/13 23:59:35 maya Exp $ +# $NetBSD: NetBSD.dist.base,v 1.241 2022/01/22 07:53:06 pho Exp $ # @(#)4.4BSD.dist 8.1 (Berkeley) 6/13/93 # Do not customize this file as it may be overwritten on upgrades. @@ -326,6 +326,7 @@ ./usr/include/prop ./usr/include/protocols ./usr/include/readline +./usr/include/refuse ./usr/include/rpc ./usr/include/rpcsvc ./usr/include/rump diff --git a/lib/librefuse/Makefile b/lib/librefuse/Makefile index eb830b0bd834..3e075b8a115a 100644 --- a/lib/librefuse/Makefile +++ b/lib/librefuse/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.13 2022/01/22 07:38:45 pho Exp $ +# $NetBSD: Makefile,v 1.14 2022/01/22 07:53:06 pho Exp $ USE_FORT?= yes # data driven bugs? @@ -13,10 +13,12 @@ FUSE_OPT_DEBUG_FLAGS= -g -DFUSE_OPT_DEBUG CFLAGS+= ${FUSE_OPT_DEBUG_FLAGS} CPPFLAGS+= -I${.CURDIR} SRCS= refuse.c refuse_log.c refuse_lowlevel.c -SRCS+= refuse_opt.c +SRCS+= refuse_opt.c refuse_signals.c MAN= refuse.3 WARNS?= 5 INCS= fuse.h fuse_opt.h fuse_log.h fuse_lowlevel.h INCSDIR= /usr/include +.include "${.CURDIR}/refuse/Makefile.inc" + .include diff --git a/lib/librefuse/fuse.h b/lib/librefuse/fuse.h index 5d1aba02ef80..223ca98263f6 100644 --- a/lib/librefuse/fuse.h +++ b/lib/librefuse/fuse.h @@ -1,4 +1,4 @@ -/* $NetBSD: fuse.h,v 1.24 2021/12/04 06:42:39 pho Exp $ */ +/* $NetBSD: fuse.h,v 1.25 2022/01/22 07:53:06 pho Exp $ */ /* * Copyright © 2007 Alistair Crooks. All rights reserved. @@ -30,9 +30,11 @@ #ifndef FUSE_H_ #define FUSE_H_ 20211204 +#include +#include +#include +#include #include - -#include #include /* The latest version of FUSE API currently provided by refuse. */ diff --git a/lib/librefuse/fuse_internal.h b/lib/librefuse/fuse_internal.h index 7bdc832e330f..533bb11b7899 100644 --- a/lib/librefuse/fuse_internal.h +++ b/lib/librefuse/fuse_internal.h @@ -1,4 +1,4 @@ -/* $NetBSD: fuse_internal.h,v 1.1 2021/12/04 06:42:39 pho Exp $ */ +/* $NetBSD: fuse_internal.h,v 1.2 2022/01/22 07:53:06 pho Exp $ */ /* * Copyright (c) 2021 The NetBSD Foundation, Inc. @@ -38,5 +38,20 @@ #include #include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Internal functions, hidden from users */ +__BEGIN_HIDDEN_DECLS +int __fuse_set_signal_handlers(struct fuse* fuse); +int __fuse_remove_signal_handlers(struct fuse* fuse); +__END_HIDDEN_DECLS + +#ifdef __cplusplus +} +#endif #endif diff --git a/lib/librefuse/refuse.c b/lib/librefuse/refuse.c index 0daba6647f25..3f721b9550cc 100644 --- a/lib/librefuse/refuse.c +++ b/lib/librefuse/refuse.c @@ -1,4 +1,4 @@ -/* $NetBSD: refuse.c,v 1.103 2021/12/04 06:42:39 pho Exp $ */ +/* $NetBSD: refuse.c,v 1.104 2022/01/22 07:53:06 pho Exp $ */ /* * Copyright © 2007 Alistair Crooks. All rights reserved. @@ -31,7 +31,7 @@ #include #if !defined(lint) -__RCSID("$NetBSD: refuse.c,v 1.103 2021/12/04 06:42:39 pho Exp $"); +__RCSID("$NetBSD: refuse.c,v 1.104 2022/01/22 07:53:06 pho Exp $"); #endif /* !lint */ /* We emit a compiler warning for anyone including without @@ -47,6 +47,8 @@ __RCSID("$NetBSD: refuse.c,v 1.103 2021/12/04 06:42:39 pho Exp $"); #include #include #include +#include +#include #include #include #include diff --git a/lib/librefuse/refuse/Makefile.inc b/lib/librefuse/refuse/Makefile.inc new file mode 100644 index 000000000000..7f62861837e3 --- /dev/null +++ b/lib/librefuse/refuse/Makefile.inc @@ -0,0 +1,7 @@ +# $NetBSD: Makefile.inc,v 1.1 2022/01/22 07:53:06 pho Exp $ + +.PATH: ${.CURDIR}/refuse + +SRCS+= session.c + +INCS+= refuse/session.h diff --git a/lib/librefuse/refuse/session.c b/lib/librefuse/refuse/session.c new file mode 100644 index 000000000000..b269a1106897 --- /dev/null +++ b/lib/librefuse/refuse/session.c @@ -0,0 +1,70 @@ +/* $NetBSD: session.c,v 1.1 2022/01/22 07:53:06 pho Exp $ */ + +/* + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 +#if !defined(lint) +__RCSID("$NetBSD: session.c,v 1.1 2022/01/22 07:53:06 pho Exp $"); +#endif /* !lint */ + +#include +#include +#include + +/* The documentation for FUSE is not clear as to what "struct fuse_session" is, + * why it exists, or how it's different from "struct fuse". For now we leave it + * undefined (i.e. an incomplete type) and treat "struct fuse_session *" as + * being identical to "struct fuse *". */ + +struct fuse_session * +fuse_get_session(struct fuse *f) { + return (struct fuse_session*)f; +} + +int +fuse_session_fd(struct fuse_session *se) { + struct fuse* fuse = (struct fuse*)se; + + /* We don't want to expose this to users, but filesystems in the wild often + * wants to set FD_CLOEXEC on it. Hope they don't assume it's the real + * /dev/fuse, because it's actually /dev/puffs in our implementation. */ + return puffs_getselectable(fuse->pu); +} + +int +fuse_set_signal_handlers(struct fuse_session *se) { + return __fuse_set_signal_handlers((struct fuse*)se); +} + +void +fuse_remove_signal_handlers(struct fuse_session *se) { + if (__fuse_remove_signal_handlers((struct fuse*)se) == -1) + warn("%s: failed to remove signal handlers", __func__); +} diff --git a/lib/librefuse/refuse/session.h b/lib/librefuse/refuse/session.h new file mode 100644 index 000000000000..ee07c92aa71d --- /dev/null +++ b/lib/librefuse/refuse/session.h @@ -0,0 +1,69 @@ +/* $NetBSD: session.h,v 1.1 2022/01/22 07:53:06 pho Exp $ */ + +/* + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. + */ +#if !defined(_FUSE_SESSION_H_) +#define _FUSE_SESSION_H_ + +/* FUSE session API + */ + +#if !defined(FUSE_H_) +# error Do not include this header directly. Include instead. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct fuse; + +/* A private structure appeared on FUSE 2.4. */ +struct fuse_session; + +/* Get a session from a fuse object. Appeared on FUSE 2.6. */ +struct fuse_session *fuse_get_session(struct fuse *f); + +/* Get the file descriptor for communicaiton with kernel. Appeared on + * FUSE 3.0. */ +int fuse_session_fd(struct fuse_session *se); + +/* Exit a session on SIGHUP, SIGTERM, and SIGINT and ignore + * SIGPIPE. Appeared on FUSE 2.5. */ +int fuse_set_signal_handlers(struct fuse_session *se); + +/* Restore default signal handlers. Appeared on FUSE 2.5. */ +void fuse_remove_signal_handlers(struct fuse_session *se); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/librefuse/refuse_signals.c b/lib/librefuse/refuse_signals.c new file mode 100644 index 000000000000..dafe91ca25da --- /dev/null +++ b/lib/librefuse/refuse_signals.c @@ -0,0 +1,331 @@ +/* $NetBSD: refuse_signals.c,v 1.1 2022/01/22 07:53:06 pho Exp $ */ + +/* + * Copyright (c) 2021 The NetBSD Foundation, Inc. + * 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 +#if !defined(lint) +__RCSID("$NetBSD: refuse_signals.c,v 1.1 2022/01/22 07:53:06 pho Exp $"); +#endif /* !lint */ + +#include +#include +#if defined(MULTITHREADED_REFUSE) +# include +#endif +#include +#include +#include + +/* Signal handling routines + * + * FUSE only supports running a single filesystem per process. ReFUSE + * is going to allow a process to run a filesystem per thread. In + * order to support this, our implementation of + * fuse_set_signal_handlers() installs a set of signal handlers which, + * when invoked, terminates all the filesystems that called the + * function. This means our fuse_remove_signal_handlers() must not + * actually remove the signal handlers until the last thread calls the + * function. + * + * FUSE installs a signal handler for a signal only if its sa_handler + * is set to SIG_DFL. This obviously has a bad consequence: if the + * caller process already has a non-default signal handler for SIGINT, + * Ctrl-C will not stop the main loop of FUSE. See + * https://stackoverflow.com/q/5044375/3571336 + * + * Maybe we should do the same knowing it's bad, but it's probably + * better to call our handler along with the old one. We may change + * this behavior if this turns out to cause serious compatibility + * issues. + * + * Also note that it is tempting to use puffs_unmountonsignal(3) but + * we can't, because there is no way to revert its effect. + */ + +#if defined(MULTITHREADED_REFUSE) +/* A mutex to protect the global state regarding signal handlers. When + * a thread is going to lock this, it must block all the signals (with + * pthread_sigmask(3)) that we install a handler for, or otherwise it + * may deadlock for trying to acquire a lock that is already held by + * itself. */ +static pthread_mutex_t signal_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +/* Saved sigaction for each signal before we modify them. */ +static struct sigaction* saved_actions[NSIG]; + +/* A linked list of "struct fuse*" which should be terminated upon + * receiving a signal. */ +struct refuse_obj_elem { + struct fuse* fuse; + struct refuse_obj_elem* next; +}; +static struct refuse_obj_elem* fuse_head; + +#if defined(MULTITHREADED_REFUSE) +static int +block_signals(sigset_t* oset) { + sigset_t set; + + if (sigemptyset(&set) != 0) + return -1; + + if (sigaddset(&set, SIGHUP) != 0) + return -1; + + if (sigaddset(&set, SIGINT) != 0) + return -1; + + if (sigaddset(&set, SIGTERM) != 0) + return -1; + + return pthread_sigmask(SIG_BLOCK, &set, oset); +} + +static int +unblock_signals(const sigset_t* oset) { + return pthread_sigmask(SIG_SETMASK, oset, NULL); +} +#endif /* defined(MULTITHREADED_REFUSE) */ + +/* handler == NULL means the signal should be ignored. */ +static int +set_signal_handler(int sig, void (*handler)(int, siginfo_t*, void*)) { + struct sigaction* saved; + struct sigaction act; + + saved = malloc(sizeof(*saved)); + if (!saved) + return -1; + + if (sigaction(sig, NULL, saved) != 0) { + free(saved); + return -1; + } + + saved_actions[sig] = saved; + + memset(&act, 0, sizeof(act)); + if (handler) { + act.sa_sigaction = handler; + act.sa_flags = SA_SIGINFO; + } + else { + /* Ignore the signal only if the signal doesn't have a + * handler. */ + if (!(saved->sa_flags & SA_SIGINFO) && saved->sa_handler == SIG_DFL) + act.sa_handler = SIG_IGN; + else + return 0; + } + + if (sigemptyset(&act.sa_mask) != 0) { + free(saved); + saved_actions[sig] = NULL; + return -1; + } + + return sigaction(sig, &act, NULL); +} + +static int +restore_signal_handler(int sig, void (*handler)(int, siginfo_t*, void*)) { + struct sigaction oact; + struct sigaction* saved; + + saved = saved_actions[sig]; + assert(saved != NULL); + + if (sigaction(sig, NULL, &oact) != 0) + return -1; + + /* Has the sigaction changed since we installed our handler? Do + * nothing if so. */ + if (handler) { + if (!(oact.sa_flags & SA_SIGINFO) || oact.sa_sigaction != handler) + goto done; + } + else { + if (oact.sa_handler != SIG_IGN) + goto done; + } + + if (sigaction(sig, saved, NULL) != 0) + return -1; + + done: + free(saved); + saved_actions[sig] = NULL; + return 0; +} + +static void +exit_handler(int sig, siginfo_t* info, void* ctx) { + struct refuse_obj_elem* elem; + struct sigaction* saved; +#if defined(MULTITHREADED_REFUSE) + int rv; + + /* pthread_mutex_lock(3) is NOT an async-signal-safe function. We + * assume it's okay, as the thread running this handler shouldn't + * be locking this mutex. */ + rv = pthread_mutex_lock(&signal_mutex); + assert(rv == 0); +#endif + + for (elem = fuse_head; elem != NULL; elem = elem->next) + fuse_exit(elem->fuse); + +#if defined(MULTITHREADED_REFUSE) + rv = pthread_mutex_unlock(&signal_mutex); + assert(rv == 0); +#endif + + saved = saved_actions[sig]; + assert(saved != NULL); + + if (saved->sa_handler != SIG_DFL && saved->sa_handler != SIG_IGN) { + if (saved->sa_flags & SA_SIGINFO) + saved->sa_sigaction(sig, info, ctx); + else + saved->sa_handler(sig); + } +} + +/* The original function appeared on FUSE 2.5 takes a pointer to + * "struct fuse_session" instead of "struct fuse". We have no such + * things as fuse sessions. + */ +int +__fuse_set_signal_handlers(struct fuse* fuse) { + int ret = 0; + struct refuse_obj_elem* elem; +#if defined(MULTITHREADED_REFUSE) + int rv; + sigset_t oset; + + rv = block_signals(&oset); + assert(rv == 0); + + rv = pthread_mutex_lock(&signal_mutex); + assert(rv == 0); +#endif + + /* Have we already installed our signal handlers? If the list is + * empty, it means we have not. */ + if (fuse_head == NULL) { + if (set_signal_handler(SIGHUP, exit_handler) != 0 || + set_signal_handler(SIGINT, exit_handler) != 0 || + set_signal_handler(SIGTERM, exit_handler) != 0 || + set_signal_handler(SIGPIPE, NULL) != 0) { + + ret = -1; + goto done; + } + } + + /* Add ourselves to the list of filesystems that want to be + * terminated upon receiving a signal. But only if we aren't + * already in the list. */ + for (elem = fuse_head; elem != NULL; elem = elem->next) { + if (elem->fuse == fuse) + goto done; + } + + elem = malloc(sizeof(*elem)); + if (!elem) { + ret = -1; + goto done; + } + elem->fuse = fuse; + elem->next = fuse_head; + fuse_head = elem; + done: + +#if defined(MULTITHREADED_REFUSE) + rv = pthread_mutex_unlock(&signal_mutex); + assert(rv == 0); + + rv = unblock_signals(&oset); + assert(rv == 0); +#endif + return ret; +} + +int +__fuse_remove_signal_handlers(struct fuse* fuse) { + int ret = 0; + struct refuse_obj_elem* prev; + struct refuse_obj_elem* elem; +#if defined(MULTITHREADED_REFUSE) + int rv; + sigset_t oset; + + rv = block_signals(&oset); + assert(rv == 0); + + rv = pthread_mutex_lock(&signal_mutex); + assert(rv == 0); +#endif + + /* Remove ourselves from the list. */ + for (prev = NULL, elem = fuse_head; + elem != NULL; + prev = elem, elem = elem->next) { + + if (elem->fuse == fuse) { + if (prev) + prev->next = elem->next; + else + fuse_head = elem->next; + free(elem); + } + } + + /* Restore handlers if we were the last one. */ + if (fuse_head == NULL) { + if (restore_signal_handler(SIGHUP, exit_handler) == -1 || + restore_signal_handler(SIGINT, exit_handler) == -1 || + restore_signal_handler(SIGTERM, exit_handler) == -1 || + restore_signal_handler(SIGPIPE, NULL) == -1) { + + ret = -1; + } + } + +#if defined(MULTITHREADED_REFUSE) + rv = pthread_mutex_unlock(&signal_mutex); + assert(rv == 0); + + rv = unblock_signals(&oset); + assert(rv == 0); +#endif + return ret; +} diff --git a/sbin/mount_qemufwcfg/fwcfg.c b/sbin/mount_qemufwcfg/fwcfg.c index e70f2391fc63..6a9f255e35c1 100644 --- a/sbin/mount_qemufwcfg/fwcfg.c +++ b/sbin/mount_qemufwcfg/fwcfg.c @@ -1,4 +1,4 @@ -/* $NetBSD: fwcfg.c,v 1.6 2021/12/04 06:42:39 pho Exp $ */ +/* $NetBSD: fwcfg.c,v 1.7 2022/01/22 07:53:06 pho Exp $ */ /*- * Copyright (c) 2017 Jared McNeill @@ -27,11 +27,12 @@ */ #include -__RCSID("$NetBSD: fwcfg.c,v 1.6 2021/12/04 06:42:39 pho Exp $"); +__RCSID("$NetBSD: fwcfg.c,v 1.7 2022/01/22 07:53:06 pho Exp $"); #define FUSE_USE_VERSION FUSE_MAKE_VERSION(2, 6) #include +#include #include #include