Module Name: src Committed By: martin Date: Sat Jun 20 19:58:41 UTC 2015
Modified Files: src/sys/compat/netbsd32: files.netbsd32 netbsd32.h netbsd32_conv.h netbsd32_signal.c Added Files: src/sys/compat/netbsd32: netbsd32_module.c netbsd32_mqueue.c Log Message: Implement modctl, sigqueinfo and mq_* To generate a diff of this commit: cvs rdiff -u -r1.34 -r1.35 src/sys/compat/netbsd32/files.netbsd32 cvs rdiff -u -r1.103 -r1.104 src/sys/compat/netbsd32/netbsd32.h cvs rdiff -u -r1.28 -r1.29 src/sys/compat/netbsd32/netbsd32_conv.h cvs rdiff -u -r0 -r1.1 src/sys/compat/netbsd32/netbsd32_module.c \ src/sys/compat/netbsd32/netbsd32_mqueue.c cvs rdiff -u -r1.38 -r1.39 src/sys/compat/netbsd32/netbsd32_signal.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/compat/netbsd32/files.netbsd32 diff -u src/sys/compat/netbsd32/files.netbsd32:1.34 src/sys/compat/netbsd32/files.netbsd32:1.35 --- src/sys/compat/netbsd32/files.netbsd32:1.34 Mon Nov 17 01:01:57 2014 +++ src/sys/compat/netbsd32/files.netbsd32 Sat Jun 20 19:58:40 2015 @@ -1,4 +1,4 @@ -# $NetBSD: files.netbsd32,v 1.34 2014/11/17 01:01:57 uebayasi Exp $ +# $NetBSD: files.netbsd32,v 1.35 2015/06/20 19:58:40 martin Exp $ # # config file description for machine-independent netbsd32 compat code. # included by ports that need it. @@ -17,7 +17,9 @@ file compat/netbsd32/netbsd32_fs.c comp file compat/netbsd32/netbsd32_ioctl.c compat_netbsd32 file compat/netbsd32/netbsd32_ipc.c compat_netbsd32 file compat/netbsd32/netbsd32_lwp.c compat_netbsd32 +file compat/netbsd32/netbsd32_module.c compat_netbsd32 file compat/netbsd32/netbsd32_mod.c compat_netbsd32 +file compat/netbsd32/netbsd32_mqueue.c compat_netbsd32 file compat/netbsd32/netbsd32_select.c compat_netbsd32 file compat/netbsd32/netbsd32_sem.c compat_netbsd32 file compat/netbsd32/netbsd32_signal.c compat_netbsd32 Index: src/sys/compat/netbsd32/netbsd32.h diff -u src/sys/compat/netbsd32/netbsd32.h:1.103 src/sys/compat/netbsd32/netbsd32.h:1.104 --- src/sys/compat/netbsd32/netbsd32.h:1.103 Sun Oct 5 20:17:28 2014 +++ src/sys/compat/netbsd32/netbsd32.h Sat Jun 20 19:58:40 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32.h,v 1.103 2014/10/05 20:17:28 christos Exp $ */ +/* $NetBSD: netbsd32.h,v 1.104 2015/06/20 19:58:40 martin Exp $ */ /* * Copyright (c) 1998, 2001, 2008 Matthew R. Green @@ -143,6 +143,7 @@ typedef netbsd32_pointer_t netbsd32_u_ch typedef netbsd32_pointer_t netbsd32_charpp; typedef netbsd32_pointer_t netbsd32_size_tp; typedef netbsd32_pointer_t netbsd32_intp; +typedef netbsd32_pointer_t netbsd32_uintp; typedef netbsd32_pointer_t netbsd32_longp; typedef netbsd32_pointer_t netbsd32_caddrp; typedef netbsd32_pointer_t netbsd32_caddr; @@ -1000,6 +1001,21 @@ struct netbsd32_posix_spawn_file_actions netbsd32_posix_spawn_file_actions_entryp fae; }; +struct netbsd32_modctl_load { + netbsd32_charp ml_filename; + int ml_flags; + netbsd32_charp ml_props; + netbsd32_size_t ml_propslen; +}; + +struct netbsd32_mq_attr { + netbsd32_long mq_flags; + netbsd32_long mq_maxmsg; + netbsd32_long mq_msgsize; + netbsd32_long mq_curmsgs; +}; +typedef netbsd32_pointer_t netbsd32_mq_attrp_t; + #if 0 int netbsd32_kevent(struct lwp *, void *, register_t *); #endif @@ -1039,7 +1055,8 @@ vaddr_t netbsd32_vm_default_addr(struct void netbsd32_adjust_limits(struct proc *); void netbsd32_si_to_si32(siginfo32_t *, const siginfo_t *); -void netbsd32_si32_to_si(siginfo_t *, const siginfo32_t *); +void netbsd32_ksi32_to_ksi(struct _ksiginfo *si, const struct __ksiginfo32 *si32); + void startlwp32(void *); struct compat_50_netbsd32___semctl14_args; Index: src/sys/compat/netbsd32/netbsd32_conv.h diff -u src/sys/compat/netbsd32/netbsd32_conv.h:1.28 src/sys/compat/netbsd32/netbsd32_conv.h:1.29 --- src/sys/compat/netbsd32/netbsd32_conv.h:1.28 Tue Mar 18 18:20:41 2014 +++ src/sys/compat/netbsd32/netbsd32_conv.h Sat Jun 20 19:58:40 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_conv.h,v 1.28 2014/03/18 18:20:41 riastradh Exp $ */ +/* $NetBSD: netbsd32_conv.h,v 1.29 2015/06/20 19:58:40 martin Exp $ */ /* * Copyright (c) 1998, 2001 Matthew R. Green @@ -786,4 +786,24 @@ netbsd32_copyout_plistref(netbsd32_point sizeof(struct netbsd32_plistref)); } +static __inline void +netbsd32_to_mq_attr(const struct netbsd32_mq_attr *a32, + struct mq_attr *attr) +{ + attr->mq_flags = a32->mq_flags; + attr->mq_maxmsg = a32->mq_maxmsg; + attr->mq_msgsize = a32->mq_msgsize; + attr->mq_curmsgs = a32->mq_curmsgs; +} + +static __inline void +netbsd32_from_mq_attr(const struct mq_attr *attr, + struct netbsd32_mq_attr *a32) +{ + a32->mq_flags = attr->mq_flags; + a32->mq_maxmsg = attr->mq_maxmsg; + a32->mq_msgsize = attr->mq_msgsize; + a32->mq_curmsgs = attr->mq_curmsgs; +} + #endif /* _COMPAT_NETBSD32_NETBSD32_CONV_H_ */ Index: src/sys/compat/netbsd32/netbsd32_signal.c diff -u src/sys/compat/netbsd32/netbsd32_signal.c:1.38 src/sys/compat/netbsd32/netbsd32_signal.c:1.39 --- src/sys/compat/netbsd32/netbsd32_signal.c:1.38 Fri Jan 24 22:10:47 2014 +++ src/sys/compat/netbsd32/netbsd32_signal.c Sat Jun 20 19:58:40 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_signal.c,v 1.38 2014/01/24 22:10:47 christos Exp $ */ +/* $NetBSD: netbsd32_signal.c,v 1.39 2015/06/20 19:58:40 martin Exp $ */ /* * Copyright (c) 1998, 2001 Matthew R. Green @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_signal.c,v 1.38 2014/01/24 22:10:47 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_signal.c,v 1.39 2015/06/20 19:58:40 martin Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -51,10 +51,6 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_sig #include <compat/sys/ucontext.h> #include <compat/common/compat_sigaltstack.h> -#ifdef unused -static void netbsd32_si32_to_si(siginfo_t *, const siginfo32_t *); -#endif - int netbsd32_sigaction(struct lwp *l, const struct netbsd32_sigaction_args *uap, register_t *retval) @@ -185,48 +181,44 @@ netbsd32___sigaction_sigtramp(struct lwp return (0); } -#ifdef unused -static void -netbsd32_si32_to_si(siginfo_t *si, const siginfo32_t *si32) +void +netbsd32_ksi32_to_ksi(struct _ksiginfo *si, const struct __ksiginfo32 *si32) { memset(si, 0, sizeof (*si)); - si->si_signo = si32->si_signo; - si->si_code = si32->si_code; - si->si_errno = si32->si_errno; + si->_signo = si32->_signo; + si->_code = si32->_code; + si->_errno = si32->_errno; - switch (si32->si_signo) { + switch (si32->_signo) { case SIGILL: case SIGBUS: case SIGSEGV: case SIGFPE: case SIGTRAP: - si->si_addr = NETBSD32PTR64(si32->si_addr); - si->si_trap = si32->si_trap; + si->_reason._fault._addr = NETBSD32IPTR64(si32->_reason._fault._addr); + si->_reason._fault._trap = si32->_reason._fault._trap; break; case SIGALRM: case SIGVTALRM: case SIGPROF: - si->si_pid = si32->si_pid; - si->si_uid = si32->si_uid; - /* - * XXX sival_ptr is currently unused. - */ - si->si_value.sival_int = si32->si_value.sival_int; + default: /* see sigqueue() and kill1() */ + si->_reason._rt._pid = si32->_reason._rt._pid; + si->_reason._rt._uid = si32->_reason._rt._uid; + si->_reason._rt._value.sival_int = si32->_reason._rt._value.sival_int; break; case SIGCHLD: - si->si_pid = si32->si_pid; - si->si_uid = si32->si_uid; - si->si_utime = si32->si_utime; - si->si_stime = si32->si_stime; + si->_reason._child._pid = si32->_reason._child._pid; + si->_reason._child._uid = si32->_reason._child._uid; + si->_reason._child._utime = si32->_reason._child._utime; + si->_reason._child._stime = si32->_reason._child._stime; break; case SIGURG: case SIGIO: - si->si_band = si32->si_band; - si->si_fd = si32->si_fd; + si->_reason._poll._band = si32->_reason._poll._band; + si->_reason._poll._fd = si32->_reason._poll._fd; break; } } -#endif void netbsd32_si_to_si32(siginfo32_t *si32, const siginfo_t *si) @@ -251,11 +243,9 @@ netbsd32_si_to_si32(siginfo32_t *si32, c case SIGALRM: case SIGVTALRM: case SIGPROF: + default: si32->si_pid = si->si_pid; si32->si_uid = si->si_uid; - /* - * XXX sival_ptr is currently unused. - */ si32->si_value.sival_int = si->si_value.sival_int; break; case SIGCHLD: @@ -443,3 +433,25 @@ netbsd32_____sigtimedwait50(struct lwp * netbsd32_sigtimedwait_fetch_timeout, netbsd32_sigtimedwait_put_timeout); } + +int +netbsd32_sigqueueinfo(struct lwp *l, + const struct netbsd32_sigqueueinfo_args *uap, register_t *retval) +{ + /* { + syscallarg(pid_t) pid; + syscallarg(const netbsd32_siginfop_t) info; + } */ + struct __ksiginfo32 ksi32; + ksiginfo_t ksi; + int error; + + if ((error = copyin(SCARG_P32(uap, info), &ksi32, + sizeof(ksi32))) != 0) + return error; + + KSI_INIT(&ksi); + netbsd32_ksi32_to_ksi(&ksi.ksi_info, &ksi32); + + return kill1(l, SCARG(uap, pid), &ksi, retval); +} Added files: Index: src/sys/compat/netbsd32/netbsd32_module.c diff -u /dev/null src/sys/compat/netbsd32/netbsd32_module.c:1.1 --- /dev/null Sat Jun 20 19:58:41 2015 +++ src/sys/compat/netbsd32/netbsd32_module.c Sat Jun 20 19:58:40 2015 @@ -0,0 +1,172 @@ +/* $NetBSD: netbsd32_module.c,v 1.1 2015/06/20 19:58:40 martin Exp $ */ + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software developed for The NetBSD Foundation. + * + * 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> +__KERNEL_RCSID(0, "$NetBSD: netbsd32_module.c,v 1.1 2015/06/20 19:58:40 martin Exp $"); + +#include <sys/param.h> +#include <sys/dirent.h> +#include <sys/module.h> +#include <sys/kobj.h> + +#include <compat/netbsd32/netbsd32.h> +#include <compat/netbsd32/netbsd32_syscall.h> +#include <compat/netbsd32/netbsd32_syscallargs.h> +#include <compat/netbsd32/netbsd32_conv.h> + +int +netbsd32_modctl(struct lwp *lwp, const struct netbsd32_modctl_args *uap, + register_t *result) +{ + /* { + syscallarg(int) cmd; + syscallarg(netbsd32_voidp) arg; + } */ + char buf[MAXMODNAME]; + size_t mslen; + module_t *mod; + modinfo_t *mi; + modstat_t *ms, *mso; + vaddr_t addr; + size_t size; + struct netbsd32_iovec iov; + struct netbsd32_modctl_load ml; + int error; + void *arg; +#ifdef MODULAR + uintptr_t loadtype; +#endif + + arg = SCARG_P32(uap, arg); + + switch (SCARG(uap, cmd)) { + case MODCTL_LOAD: + error = copyin(arg, &ml, sizeof(ml)); + if (error != 0) + break; + error = handle_modctl_load(NETBSD32PTR64(ml.ml_filename), + ml.ml_flags, NETBSD32PTR64(ml.ml_props), ml.ml_propslen); + break; + + case MODCTL_UNLOAD: + error = copyinstr(arg, buf, sizeof(buf), NULL); + if (error == 0) { + error = module_unload(buf); + } + break; + + case MODCTL_STAT: + error = copyin(arg, &iov, sizeof(iov)); + if (error != 0) { + break; + } + kernconfig_lock(); + mslen = (module_count+module_builtinlist+1) * sizeof(modstat_t); + mso = kmem_zalloc(mslen, KM_SLEEP); + if (mso == NULL) { + kernconfig_unlock(); + return ENOMEM; + } + ms = mso; + TAILQ_FOREACH(mod, &module_list, mod_chain) { + mi = mod->mod_info; + strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name)); + if (mi->mi_required != NULL) { + strlcpy(ms->ms_required, mi->mi_required, + sizeof(ms->ms_required)); + } + if (mod->mod_kobj != NULL) { + kobj_stat(mod->mod_kobj, &addr, &size); + ms->ms_addr = addr; + ms->ms_size = size; + } + ms->ms_class = mi->mi_class; + ms->ms_refcnt = mod->mod_refcnt; + ms->ms_source = mod->mod_source; + ms++; + } + TAILQ_FOREACH(mod, &module_builtins, mod_chain) { + mi = mod->mod_info; + strlcpy(ms->ms_name, mi->mi_name, sizeof(ms->ms_name)); + if (mi->mi_required != NULL) { + strlcpy(ms->ms_required, mi->mi_required, + sizeof(ms->ms_required)); + } + if (mod->mod_kobj != NULL) { + kobj_stat(mod->mod_kobj, &addr, &size); + ms->ms_addr = addr; + ms->ms_size = size; + } + ms->ms_class = mi->mi_class; + ms->ms_refcnt = -1; + KASSERT(mod->mod_source == MODULE_SOURCE_KERNEL); + ms->ms_source = mod->mod_source; + ms++; + } + kernconfig_unlock(); + error = copyout(mso, NETBSD32PTR64(iov.iov_base), + min(mslen - sizeof(modstat_t), iov.iov_len)); + kmem_free(mso, mslen); + if (error == 0) { + iov.iov_len = mslen - sizeof(modstat_t); + error = copyout(&iov, arg, sizeof(iov)); + } + break; + + case MODCTL_EXISTS: +#ifndef MODULAR + error = ENOSYS; +#else + loadtype = (uintptr_t)arg; + switch (loadtype) { /* 0 = modload, 1 = autoload */ + case 0: /* FALLTHROUGH */ + case 1: + error = kauth_authorize_system(kauth_cred_get(), + KAUTH_SYSTEM_MODULE, 0, + (void *)(uintptr_t)MODCTL_LOAD, + (void *)loadtype, NULL); + break; + + default: + error = EINVAL; + break; + } +#endif + break; + + default: + error = EINVAL; + break; + } + + return error; +} + + Index: src/sys/compat/netbsd32/netbsd32_mqueue.c diff -u /dev/null src/sys/compat/netbsd32/netbsd32_mqueue.c:1.1 --- /dev/null Sat Jun 20 19:58:41 2015 +++ src/sys/compat/netbsd32/netbsd32_mqueue.c Sat Jun 20 19:58:40 2015 @@ -0,0 +1,328 @@ +/* $NetBSD: netbsd32_mqueue.c,v 1.1 2015/06/20 19:58:40 martin Exp $ */ + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software developed for The NetBSD Foundation. + * + * 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> +__KERNEL_RCSID(0, "$NetBSD: netbsd32_mqueue.c,v 1.1 2015/06/20 19:58:40 martin Exp $"); + +#if defined(_KERNEL_OPT) +#include "opt_compat_netbsd.h" +#endif + +#include <sys/param.h> +#include <sys/dirent.h> +#include <sys/filedesc.h> +#include <sys/fcntl.h> +#include <sys/module.h> + +#include <compat/netbsd32/netbsd32.h> +#include <compat/netbsd32/netbsd32_syscall.h> +#include <compat/netbsd32/netbsd32_syscallargs.h> +#include <compat/netbsd32/netbsd32_conv.h> + + +int +netbsd32_mq_open(struct lwp *l, const struct netbsd32_mq_open_args *uap, + register_t *retval) +{ + /* { + syscallarg(const netbsd32_charp) name; + syscallarg(int) oflag; + syscallarg(mode_t) mode; + syscallarg(struct netbsd32_mq_attrp_t) attr; + } */ + struct netbsd32_mq_attr attr32; + struct mq_attr *attr = NULL, a; + int error; + + if ((SCARG(uap, oflag) & O_CREAT) && (SCARG_P32(uap,attr) != NULL)) { + error = copyin(&attr32, SCARG_P32(uap,attr), sizeof(attr32)); + if (error) + return error; + netbsd32_to_mq_attr(&attr32, &a); + attr = &a; + } + + return mq_handle_open(l, SCARG_P32(uap, name), SCARG(uap, oflag), + SCARG(uap, mode), attr, retval); +} + +int +netbsd32_mq_close(struct lwp *l, const struct netbsd32_mq_close_args *uap, + register_t *retval) +{ + /* { + syscallarg(mqd_t) mqdes; + } */ + + return netbsd32_close(l, (const void*)uap, retval); +} + +int +netbsd32_mq_unlink(struct lwp *l, const struct netbsd32_mq_unlink_args *uap, + register_t *retval) +{ + /* { + syscallarg(const netbsd32_charp) name; + } */ + struct sys_mq_unlink_args ua; + + NETBSD32TOP_UAP(name, const char); + return sys_mq_unlink(l, &ua, retval); +} + +int +netbsd32_mq_getattr(struct lwp *l, const struct netbsd32_mq_getattr_args *uap, + register_t *retval) +{ + /* { + syscallarg(mqd_t) mqdes; + syscallarg(netbsd32_mq_attrp_t) mqstat; + } */ + struct mqueue *mq; + struct mq_attr attr; + struct netbsd32_mq_attr a32; + int error; + + error = mqueue_get(SCARG(uap, mqdes), 0, &mq); + if (error) + return error; + + memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr)); + mutex_exit(&mq->mq_mtx); + fd_putfile((int)SCARG(uap, mqdes)); + netbsd32_from_mq_attr(&attr, &a32); + return copyout(&a32, SCARG_P32(uap,mqstat), sizeof(a32)); +} + +int +netbsd32_mq_setattr(struct lwp *l, const struct netbsd32_mq_setattr_args *uap, + register_t *retval) +{ + /* { + syscallarg(mqd_t) mqdes; + syscallarg(const netbsd32_mq_attrp_t) mqstat; + syscallarg(netbsd32_mq_attrp_t) omqstat; + } */ + struct mqueue *mq; + struct netbsd32_mq_attr attr32; + struct mq_attr attr; + int error, nonblock; + + error = copyin(SCARG_P32(uap, mqstat), &attr32, sizeof(attr32)); + if (error) + return error; + netbsd32_to_mq_attr(&attr32, &attr); + nonblock = (attr.mq_flags & O_NONBLOCK); + + error = mqueue_get(SCARG(uap, mqdes), 0, &mq); + if (error) + return error; + + /* Copy the old attributes, if needed */ + if (SCARG_P32(uap, omqstat)) + memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr)); + + /* Ignore everything, except O_NONBLOCK */ + if (nonblock) + mq->mq_attrib.mq_flags |= O_NONBLOCK; + else + mq->mq_attrib.mq_flags &= ~O_NONBLOCK; + + mutex_exit(&mq->mq_mtx); + fd_putfile((int)SCARG(uap, mqdes)); + + /* + * Copy the data to the user-space. + * Note: According to POSIX, the new attributes should not be set in + * case of fail - this would be violated. + */ + if (SCARG_P32(uap, omqstat)) { + netbsd32_from_mq_attr(&attr, &attr32); + error = copyout(&attr32, SCARG_P32(uap, omqstat), + sizeof(attr32)); + } + + return error; +} + +int +netbsd32_mq_notify(struct lwp *l, const struct netbsd32_mq_notify_args *uap, + register_t *result) +{ + /* { + syscallarg(mqd_t) mqdes; + syscallarg(const netbsd32_sigeventp_t) notification; + } */ + struct mqueue *mq; + struct netbsd32_sigevent sig32; + int error; + + if (SCARG_P32(uap, notification)) { + /* Get the signal from user-space */ + error = copyin(SCARG_P32(uap, notification), &sig32, + sizeof(sig32)); + if (error) + return error; + if (sig32.sigev_notify == SIGEV_SIGNAL && + (sig32.sigev_signo <=0 || sig32.sigev_signo >= NSIG)) + return EINVAL; + } + + error = mqueue_get(SCARG(uap, mqdes), 0, &mq); + if (error) { + return error; + } + if (SCARG_P32(uap, notification)) { + /* Register notification: set the signal and target process */ + if (mq->mq_notify_proc == NULL) { + netbsd32_to_sigevent(&sig32, &mq->mq_sig_notify); + mq->mq_notify_proc = l->l_proc; + } else { + /* Fail if someone else already registered */ + error = EBUSY; + } + } else { + /* Unregister the notification */ + mq->mq_notify_proc = NULL; + } + mutex_exit(&mq->mq_mtx); + fd_putfile((int)SCARG(uap, mqdes)); + + return error; +} + +int +netbsd32_mq_send(struct lwp *l, const struct netbsd32_mq_send_args *uap, + register_t *result) +{ + /* { + syscallarg(mqd_t) mqdes; + syscallarg(const netbsd32_charp) msg_ptr; + syscallarg(netbsd32_size_t) msg_len; + syscallarg(unsigned) msg_prio; + } */ + + + return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr), + SCARG(uap, msg_len), SCARG(uap, msg_prio), NULL); +} + +int +netbsd32_mq_receive(struct lwp *l, const struct netbsd32_mq_receive_args *uap, + register_t *retval) +{ + /* { + syscallarg(mqd_t) mqdes; + syscallarg(netbsd32_charp) msg_ptr; + syscallarg(netbsd32_size_t) msg_len; + syscallarg(netbsd32_uintp) msg_prio; + } */ + ssize_t mlen; + int error; + + error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr), + SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), NULL, &mlen); + if (error == 0) + *retval = mlen; + + return error; +} + +#ifdef COMPAT_50 + +int +compat_50_netbsd32_mq_timedsend(struct lwp *l, + const struct compat_50_netbsd32_mq_timedsend_args *uap, + register_t *retval) +{ + /* { + syscallarg(mqd_t) mqdes; + syscallarg(const netbsd32_charp) msg_ptr; + syscallarg(netbsd32_size_t) msg_len; + syscallarg(unsigned) msg_prio; + syscallarg(const netbsd32_timespec50p_t) abs_timeout; + } */ + struct timespec ts, *tsp; + struct netbsd32_timespec ts32; + int error; + + /* Get and convert time value */ + if (SCARG_P32(uap, abs_timeout)) { + error = copyin(SCARG_P32(uap, abs_timeout), &ts32, + sizeof(ts32)); + if (error) + return error; + netbsd32_to_timespec(&ts32, &ts); + tsp = &ts; + } else { + tsp = NULL; + } + + return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr), + SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp); +} + +int +compat_50_netbsd32_mq_timedreceive(struct lwp *l, + const struct compat_50_netbsd32_mq_timedreceive_args *uap, + register_t *retval) +{ + /* { + syscallarg(mqd_t) mqdes; + syscallarg(netbsd32_charp) msg_ptr; + syscallarg(netbsd32_size_t) msg_len; + syscallarg(netbsd32_uintp) msg_prio; + syscallarg(const netbsd32_timespec50p_t) abs_timeout; + } */ + struct timespec ts, *tsp; + struct netbsd32_timespec ts32; + ssize_t mlen; + int error; + + /* Get and convert time value */ + if (SCARG_P32(uap, abs_timeout)) { + error = copyin(SCARG_P32(uap, abs_timeout), &ts32, + sizeof(ts32)); + if (error) + return error; + netbsd32_to_timespec(&ts32, &ts); + tsp = &ts; + } else { + tsp = NULL; + } + + error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr), + SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), tsp, &mlen); + if (error == 0) + *retval = mlen; + + return error; +} +#endif