1*d02810a4Smartin /* $NetBSD: netbsd32_mqueue.c,v 1.4 2015/06/30 06:01:04 martin Exp $ */ 29cec043eSmartin 39cec043eSmartin /*- 49cec043eSmartin * Copyright (c) 2008 The NetBSD Foundation, Inc. 59cec043eSmartin * All rights reserved. 69cec043eSmartin * 79cec043eSmartin * This code is derived from software developed for The NetBSD Foundation. 89cec043eSmartin * 99cec043eSmartin * Redistribution and use in source and binary forms, with or without 109cec043eSmartin * modification, are permitted provided that the following conditions 119cec043eSmartin * are met: 129cec043eSmartin * 1. Redistributions of source code must retain the above copyright 139cec043eSmartin * notice, this list of conditions and the following disclaimer. 149cec043eSmartin * 2. Redistributions in binary form must reproduce the above copyright 159cec043eSmartin * notice, this list of conditions and the following disclaimer in the 169cec043eSmartin * documentation and/or other materials provided with the distribution. 179cec043eSmartin * 189cec043eSmartin * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 199cec043eSmartin * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 209cec043eSmartin * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 219cec043eSmartin * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 229cec043eSmartin * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 239cec043eSmartin * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 249cec043eSmartin * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 259cec043eSmartin * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 269cec043eSmartin * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 279cec043eSmartin * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 289cec043eSmartin * POSSIBILITY OF SUCH DAMAGE. 299cec043eSmartin */ 309cec043eSmartin 319cec043eSmartin #include <sys/cdefs.h> 32*d02810a4Smartin __KERNEL_RCSID(0, "$NetBSD: netbsd32_mqueue.c,v 1.4 2015/06/30 06:01:04 martin Exp $"); 339cec043eSmartin 349cec043eSmartin #if defined(_KERNEL_OPT) 359cec043eSmartin #include "opt_compat_netbsd.h" 369cec043eSmartin #endif 379cec043eSmartin 389cec043eSmartin #include <sys/param.h> 399cec043eSmartin #include <sys/dirent.h> 409cec043eSmartin #include <sys/filedesc.h> 419cec043eSmartin #include <sys/fcntl.h> 429cec043eSmartin #include <sys/module.h> 439cec043eSmartin 449cec043eSmartin #include <compat/netbsd32/netbsd32.h> 459cec043eSmartin #include <compat/netbsd32/netbsd32_syscall.h> 469cec043eSmartin #include <compat/netbsd32/netbsd32_syscallargs.h> 479cec043eSmartin #include <compat/netbsd32/netbsd32_conv.h> 489cec043eSmartin 499cec043eSmartin 509cec043eSmartin int 519cec043eSmartin netbsd32_mq_open(struct lwp *l, const struct netbsd32_mq_open_args *uap, 529cec043eSmartin register_t *retval) 539cec043eSmartin { 549cec043eSmartin /* { 559cec043eSmartin syscallarg(const netbsd32_charp) name; 569cec043eSmartin syscallarg(int) oflag; 579cec043eSmartin syscallarg(mode_t) mode; 589cec043eSmartin syscallarg(struct netbsd32_mq_attrp_t) attr; 599cec043eSmartin } */ 609cec043eSmartin struct netbsd32_mq_attr attr32; 619cec043eSmartin struct mq_attr *attr = NULL, a; 629cec043eSmartin int error; 639cec043eSmartin 649cec043eSmartin if ((SCARG(uap, oflag) & O_CREAT) && (SCARG_P32(uap,attr) != NULL)) { 65*d02810a4Smartin error = copyin(SCARG_P32(uap,attr), &attr32, sizeof(attr32)); 669cec043eSmartin if (error) 679cec043eSmartin return error; 689cec043eSmartin netbsd32_to_mq_attr(&attr32, &a); 699cec043eSmartin attr = &a; 709cec043eSmartin } 719cec043eSmartin 729cec043eSmartin return mq_handle_open(l, SCARG_P32(uap, name), SCARG(uap, oflag), 739cec043eSmartin SCARG(uap, mode), attr, retval); 749cec043eSmartin } 759cec043eSmartin 769cec043eSmartin int 779cec043eSmartin netbsd32_mq_close(struct lwp *l, const struct netbsd32_mq_close_args *uap, 789cec043eSmartin register_t *retval) 799cec043eSmartin { 809cec043eSmartin /* { 819cec043eSmartin syscallarg(mqd_t) mqdes; 829cec043eSmartin } */ 839cec043eSmartin 849cec043eSmartin return netbsd32_close(l, (const void*)uap, retval); 859cec043eSmartin } 869cec043eSmartin 879cec043eSmartin int 889cec043eSmartin netbsd32_mq_unlink(struct lwp *l, const struct netbsd32_mq_unlink_args *uap, 899cec043eSmartin register_t *retval) 909cec043eSmartin { 919cec043eSmartin /* { 929cec043eSmartin syscallarg(const netbsd32_charp) name; 939cec043eSmartin } */ 949cec043eSmartin struct sys_mq_unlink_args ua; 959cec043eSmartin 969cec043eSmartin NETBSD32TOP_UAP(name, const char); 979cec043eSmartin return sys_mq_unlink(l, &ua, retval); 989cec043eSmartin } 999cec043eSmartin 1009cec043eSmartin int 1019cec043eSmartin netbsd32_mq_getattr(struct lwp *l, const struct netbsd32_mq_getattr_args *uap, 1029cec043eSmartin register_t *retval) 1039cec043eSmartin { 1049cec043eSmartin /* { 1059cec043eSmartin syscallarg(mqd_t) mqdes; 1069cec043eSmartin syscallarg(netbsd32_mq_attrp_t) mqstat; 1079cec043eSmartin } */ 1089cec043eSmartin struct mqueue *mq; 1099cec043eSmartin struct mq_attr attr; 1109cec043eSmartin struct netbsd32_mq_attr a32; 1119cec043eSmartin int error; 1129cec043eSmartin 1139cec043eSmartin error = mqueue_get(SCARG(uap, mqdes), 0, &mq); 1149cec043eSmartin if (error) 1159cec043eSmartin return error; 1169cec043eSmartin 1179cec043eSmartin memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr)); 1189cec043eSmartin mutex_exit(&mq->mq_mtx); 1199cec043eSmartin fd_putfile((int)SCARG(uap, mqdes)); 1209cec043eSmartin netbsd32_from_mq_attr(&attr, &a32); 1219cec043eSmartin return copyout(&a32, SCARG_P32(uap,mqstat), sizeof(a32)); 1229cec043eSmartin } 1239cec043eSmartin 1249cec043eSmartin int 1259cec043eSmartin netbsd32_mq_setattr(struct lwp *l, const struct netbsd32_mq_setattr_args *uap, 1269cec043eSmartin register_t *retval) 1279cec043eSmartin { 1289cec043eSmartin /* { 1299cec043eSmartin syscallarg(mqd_t) mqdes; 1309cec043eSmartin syscallarg(const netbsd32_mq_attrp_t) mqstat; 1319cec043eSmartin syscallarg(netbsd32_mq_attrp_t) omqstat; 1329cec043eSmartin } */ 1339cec043eSmartin struct mqueue *mq; 1349cec043eSmartin struct netbsd32_mq_attr attr32; 1359cec043eSmartin struct mq_attr attr; 1369cec043eSmartin int error, nonblock; 1379cec043eSmartin 1389cec043eSmartin error = copyin(SCARG_P32(uap, mqstat), &attr32, sizeof(attr32)); 1399cec043eSmartin if (error) 1409cec043eSmartin return error; 1419cec043eSmartin netbsd32_to_mq_attr(&attr32, &attr); 1429cec043eSmartin nonblock = (attr.mq_flags & O_NONBLOCK); 1439cec043eSmartin 1449cec043eSmartin error = mqueue_get(SCARG(uap, mqdes), 0, &mq); 1459cec043eSmartin if (error) 1469cec043eSmartin return error; 1479cec043eSmartin 1489cec043eSmartin /* Copy the old attributes, if needed */ 1499cec043eSmartin if (SCARG_P32(uap, omqstat)) 1509cec043eSmartin memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr)); 1519cec043eSmartin 1529cec043eSmartin /* Ignore everything, except O_NONBLOCK */ 1539cec043eSmartin if (nonblock) 1549cec043eSmartin mq->mq_attrib.mq_flags |= O_NONBLOCK; 1559cec043eSmartin else 1569cec043eSmartin mq->mq_attrib.mq_flags &= ~O_NONBLOCK; 1579cec043eSmartin 1589cec043eSmartin mutex_exit(&mq->mq_mtx); 1599cec043eSmartin fd_putfile((int)SCARG(uap, mqdes)); 1609cec043eSmartin 1619cec043eSmartin /* 1629cec043eSmartin * Copy the data to the user-space. 1639cec043eSmartin * Note: According to POSIX, the new attributes should not be set in 1649cec043eSmartin * case of fail - this would be violated. 1659cec043eSmartin */ 1669cec043eSmartin if (SCARG_P32(uap, omqstat)) { 1679cec043eSmartin netbsd32_from_mq_attr(&attr, &attr32); 1689cec043eSmartin error = copyout(&attr32, SCARG_P32(uap, omqstat), 1699cec043eSmartin sizeof(attr32)); 1709cec043eSmartin } 1719cec043eSmartin 1729cec043eSmartin return error; 1739cec043eSmartin } 1749cec043eSmartin 1759cec043eSmartin int 1769cec043eSmartin netbsd32_mq_notify(struct lwp *l, const struct netbsd32_mq_notify_args *uap, 1779cec043eSmartin register_t *result) 1789cec043eSmartin { 1799cec043eSmartin /* { 1809cec043eSmartin syscallarg(mqd_t) mqdes; 1819cec043eSmartin syscallarg(const netbsd32_sigeventp_t) notification; 1829cec043eSmartin } */ 1839cec043eSmartin struct mqueue *mq; 1849cec043eSmartin struct netbsd32_sigevent sig32; 1859cec043eSmartin int error; 1869cec043eSmartin 1879cec043eSmartin if (SCARG_P32(uap, notification)) { 1889cec043eSmartin /* Get the signal from user-space */ 1899cec043eSmartin error = copyin(SCARG_P32(uap, notification), &sig32, 1909cec043eSmartin sizeof(sig32)); 1919cec043eSmartin if (error) 1929cec043eSmartin return error; 1939cec043eSmartin if (sig32.sigev_notify == SIGEV_SIGNAL && 1949cec043eSmartin (sig32.sigev_signo <=0 || sig32.sigev_signo >= NSIG)) 1959cec043eSmartin return EINVAL; 1969cec043eSmartin } 1979cec043eSmartin 1989cec043eSmartin error = mqueue_get(SCARG(uap, mqdes), 0, &mq); 1999cec043eSmartin if (error) { 2009cec043eSmartin return error; 2019cec043eSmartin } 2029cec043eSmartin if (SCARG_P32(uap, notification)) { 2039cec043eSmartin /* Register notification: set the signal and target process */ 2049cec043eSmartin if (mq->mq_notify_proc == NULL) { 2059cec043eSmartin netbsd32_to_sigevent(&sig32, &mq->mq_sig_notify); 2069cec043eSmartin mq->mq_notify_proc = l->l_proc; 2079cec043eSmartin } else { 2089cec043eSmartin /* Fail if someone else already registered */ 2099cec043eSmartin error = EBUSY; 2109cec043eSmartin } 2119cec043eSmartin } else { 2129cec043eSmartin /* Unregister the notification */ 2139cec043eSmartin mq->mq_notify_proc = NULL; 2149cec043eSmartin } 2159cec043eSmartin mutex_exit(&mq->mq_mtx); 2169cec043eSmartin fd_putfile((int)SCARG(uap, mqdes)); 2179cec043eSmartin 2189cec043eSmartin return error; 2199cec043eSmartin } 2209cec043eSmartin 2219cec043eSmartin int 2229cec043eSmartin netbsd32_mq_send(struct lwp *l, const struct netbsd32_mq_send_args *uap, 2239cec043eSmartin register_t *result) 2249cec043eSmartin { 2259cec043eSmartin /* { 2269cec043eSmartin syscallarg(mqd_t) mqdes; 2279cec043eSmartin syscallarg(const netbsd32_charp) msg_ptr; 2289cec043eSmartin syscallarg(netbsd32_size_t) msg_len; 2299cec043eSmartin syscallarg(unsigned) msg_prio; 2309cec043eSmartin } */ 2319cec043eSmartin 2329cec043eSmartin 2339cec043eSmartin return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr), 2349cec043eSmartin SCARG(uap, msg_len), SCARG(uap, msg_prio), NULL); 2359cec043eSmartin } 2369cec043eSmartin 2379cec043eSmartin int 2389cec043eSmartin netbsd32_mq_receive(struct lwp *l, const struct netbsd32_mq_receive_args *uap, 2399cec043eSmartin register_t *retval) 2409cec043eSmartin { 2419cec043eSmartin /* { 2429cec043eSmartin syscallarg(mqd_t) mqdes; 2439cec043eSmartin syscallarg(netbsd32_charp) msg_ptr; 2449cec043eSmartin syscallarg(netbsd32_size_t) msg_len; 2459cec043eSmartin syscallarg(netbsd32_uintp) msg_prio; 2469cec043eSmartin } */ 2479cec043eSmartin ssize_t mlen; 2489cec043eSmartin int error; 2499cec043eSmartin 2509cec043eSmartin error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr), 2519cec043eSmartin SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), NULL, &mlen); 2529cec043eSmartin if (error == 0) 2539cec043eSmartin *retval = mlen; 2549cec043eSmartin 2559cec043eSmartin return error; 2569cec043eSmartin } 2579cec043eSmartin 2589cec043eSmartin int 2598e9c942dSmartin netbsd32___mq_timedsend50(struct lwp *l, 2608e9c942dSmartin const struct netbsd32___mq_timedsend50_args *uap, register_t *retval) 2619cec043eSmartin { 2629cec043eSmartin /* { 2639cec043eSmartin syscallarg(mqd_t) mqdes; 2649cec043eSmartin syscallarg(const netbsd32_charp) msg_ptr; 2659cec043eSmartin syscallarg(netbsd32_size_t) msg_len; 2669cec043eSmartin syscallarg(unsigned) msg_prio; 2678e9c942dSmartin syscallarg(const netbsd32_timespecp_t) abs_timeout; 2689cec043eSmartin } */ 2699cec043eSmartin struct timespec ts, *tsp; 2709cec043eSmartin struct netbsd32_timespec ts32; 2719cec043eSmartin int error; 2729cec043eSmartin 2739cec043eSmartin /* Get and convert time value */ 2749cec043eSmartin if (SCARG_P32(uap, abs_timeout)) { 2759cec043eSmartin error = copyin(SCARG_P32(uap, abs_timeout), &ts32, 2769cec043eSmartin sizeof(ts32)); 2779cec043eSmartin if (error) 2789cec043eSmartin return error; 2799cec043eSmartin netbsd32_to_timespec(&ts32, &ts); 2809cec043eSmartin tsp = &ts; 2819cec043eSmartin } else { 2829cec043eSmartin tsp = NULL; 2839cec043eSmartin } 2849cec043eSmartin 2859cec043eSmartin return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr), 2869cec043eSmartin SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp); 2879cec043eSmartin } 2889cec043eSmartin 2899cec043eSmartin int 2908e9c942dSmartin netbsd32___mq_timedreceive50(struct lwp *l, 2918e9c942dSmartin const struct netbsd32___mq_timedreceive50_args *uap, register_t *retval) 2929cec043eSmartin { 2939cec043eSmartin /* { 2949cec043eSmartin syscallarg(mqd_t) mqdes; 2959cec043eSmartin syscallarg(netbsd32_charp) msg_ptr; 2969cec043eSmartin syscallarg(netbsd32_size_t) msg_len; 2979cec043eSmartin syscallarg(netbsd32_uintp) msg_prio; 2988e9c942dSmartin syscallarg(const netbsd32_timespecp_t) abs_timeout; 2999cec043eSmartin } */ 3009cec043eSmartin struct timespec ts, *tsp; 3019cec043eSmartin struct netbsd32_timespec ts32; 3029cec043eSmartin ssize_t mlen; 3039cec043eSmartin int error; 3049cec043eSmartin 3059cec043eSmartin /* Get and convert time value */ 3069cec043eSmartin if (SCARG_P32(uap, abs_timeout)) { 3079cec043eSmartin error = copyin(SCARG_P32(uap, abs_timeout), &ts32, 3089cec043eSmartin sizeof(ts32)); 3099cec043eSmartin if (error) 3109cec043eSmartin return error; 3119cec043eSmartin netbsd32_to_timespec(&ts32, &ts); 3129cec043eSmartin tsp = &ts; 3139cec043eSmartin } else { 3149cec043eSmartin tsp = NULL; 3159cec043eSmartin } 3169cec043eSmartin 3179cec043eSmartin error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr), 3189cec043eSmartin SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), tsp, &mlen); 3199cec043eSmartin if (error == 0) 3209cec043eSmartin *retval = mlen; 3219cec043eSmartin 3229cec043eSmartin return error; 3239cec043eSmartin } 3248e9c942dSmartin 325