Home | History | Annotate | Line # | Download | only in netbsd32
netbsd32_mqueue.c revision 1.1
      1 /*	$NetBSD: netbsd32_mqueue.c,v 1.1 2015/06/20 19:58:40 martin Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software developed for The NetBSD Foundation.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     21  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     28  * POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_mqueue.c,v 1.1 2015/06/20 19:58:40 martin Exp $");
     33 
     34 #if defined(_KERNEL_OPT)
     35 #include "opt_compat_netbsd.h"
     36 #endif
     37 
     38 #include <sys/param.h>
     39 #include <sys/dirent.h>
     40 #include <sys/filedesc.h>
     41 #include <sys/fcntl.h>
     42 #include <sys/module.h>
     43 
     44 #include <compat/netbsd32/netbsd32.h>
     45 #include <compat/netbsd32/netbsd32_syscall.h>
     46 #include <compat/netbsd32/netbsd32_syscallargs.h>
     47 #include <compat/netbsd32/netbsd32_conv.h>
     48 
     49 
     50 int
     51 netbsd32_mq_open(struct lwp *l, const struct netbsd32_mq_open_args *uap,
     52     register_t *retval)
     53 {
     54 	/* {
     55 		syscallarg(const netbsd32_charp) name;
     56 		syscallarg(int) oflag;
     57 		syscallarg(mode_t) mode;
     58 		syscallarg(struct netbsd32_mq_attrp_t) attr;
     59 	} */
     60 	struct netbsd32_mq_attr attr32;
     61 	struct mq_attr *attr = NULL, a;
     62 	int error;
     63 
     64 	if ((SCARG(uap, oflag) & O_CREAT) && (SCARG_P32(uap,attr) != NULL)) {
     65 		error = copyin(&attr32, SCARG_P32(uap,attr), sizeof(attr32));
     66 		if (error)
     67 			return error;
     68 		netbsd32_to_mq_attr(&attr32, &a);
     69 		attr = &a;
     70 	}
     71 
     72 	return mq_handle_open(l, SCARG_P32(uap, name), SCARG(uap, oflag),
     73 	    SCARG(uap, mode), attr, retval);
     74 }
     75 
     76 int
     77 netbsd32_mq_close(struct lwp *l, const struct netbsd32_mq_close_args *uap,
     78     register_t *retval)
     79 {
     80 	/* {
     81 		syscallarg(mqd_t) mqdes;
     82 	} */
     83 
     84 	return netbsd32_close(l, (const void*)uap, retval);
     85 }
     86 
     87 int
     88 netbsd32_mq_unlink(struct lwp *l, const struct netbsd32_mq_unlink_args *uap,
     89     register_t *retval)
     90 {
     91 	/* {
     92 		syscallarg(const netbsd32_charp) name;
     93 	} */
     94 	struct sys_mq_unlink_args ua;
     95 
     96 	NETBSD32TOP_UAP(name, const char);
     97 	return sys_mq_unlink(l, &ua, retval);
     98 }
     99 
    100 int
    101 netbsd32_mq_getattr(struct lwp *l, const struct netbsd32_mq_getattr_args *uap,
    102     register_t *retval)
    103 {
    104 	/* {
    105 		syscallarg(mqd_t) mqdes;
    106 		syscallarg(netbsd32_mq_attrp_t) mqstat;
    107 	} */
    108 	struct mqueue *mq;
    109 	struct mq_attr attr;
    110 	struct netbsd32_mq_attr a32;
    111 	int error;
    112 
    113 	error = mqueue_get(SCARG(uap, mqdes), 0, &mq);
    114 	if (error)
    115 		return error;
    116 
    117 	memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr));
    118 	mutex_exit(&mq->mq_mtx);
    119 	fd_putfile((int)SCARG(uap, mqdes));
    120 	netbsd32_from_mq_attr(&attr, &a32);
    121 	return copyout(&a32, SCARG_P32(uap,mqstat), sizeof(a32));
    122 }
    123 
    124 int
    125 netbsd32_mq_setattr(struct lwp *l, const struct netbsd32_mq_setattr_args *uap,
    126     register_t *retval)
    127 {
    128 	/* {
    129 		syscallarg(mqd_t) mqdes;
    130 		syscallarg(const netbsd32_mq_attrp_t) mqstat;
    131 		syscallarg(netbsd32_mq_attrp_t) omqstat;
    132 	} */
    133 	struct mqueue *mq;
    134 	struct netbsd32_mq_attr attr32;
    135 	struct mq_attr attr;
    136 	int error, nonblock;
    137 
    138 	error = copyin(SCARG_P32(uap, mqstat), &attr32, sizeof(attr32));
    139 	if (error)
    140 		return error;
    141 	netbsd32_to_mq_attr(&attr32, &attr);
    142 	nonblock = (attr.mq_flags & O_NONBLOCK);
    143 
    144 	error = mqueue_get(SCARG(uap, mqdes), 0, &mq);
    145 	if (error)
    146 		return error;
    147 
    148 	/* Copy the old attributes, if needed */
    149 	if (SCARG_P32(uap, omqstat))
    150 		memcpy(&attr, &mq->mq_attrib, sizeof(struct mq_attr));
    151 
    152 	/* Ignore everything, except O_NONBLOCK */
    153 	if (nonblock)
    154 		mq->mq_attrib.mq_flags |= O_NONBLOCK;
    155 	else
    156 		mq->mq_attrib.mq_flags &= ~O_NONBLOCK;
    157 
    158 	mutex_exit(&mq->mq_mtx);
    159 	fd_putfile((int)SCARG(uap, mqdes));
    160 
    161 	/*
    162 	 * Copy the data to the user-space.
    163 	 * Note: According to POSIX, the new attributes should not be set in
    164 	 * case of fail - this would be violated.
    165 	 */
    166 	if (SCARG_P32(uap, omqstat)) {
    167 		netbsd32_from_mq_attr(&attr, &attr32);
    168 		error = copyout(&attr32, SCARG_P32(uap, omqstat),
    169 		    sizeof(attr32));
    170 	}
    171 
    172 	return error;
    173 }
    174 
    175 int
    176 netbsd32_mq_notify(struct lwp *l, const struct netbsd32_mq_notify_args *uap,
    177     register_t *result)
    178 {
    179 	/* {
    180 		syscallarg(mqd_t) mqdes;
    181 		syscallarg(const netbsd32_sigeventp_t) notification;
    182 	} */
    183 	struct mqueue *mq;
    184 	struct netbsd32_sigevent sig32;
    185 	int error;
    186 
    187 	if (SCARG_P32(uap, notification)) {
    188 		/* Get the signal from user-space */
    189 		error = copyin(SCARG_P32(uap, notification), &sig32,
    190 		    sizeof(sig32));
    191 		if (error)
    192 			return error;
    193 		if (sig32.sigev_notify == SIGEV_SIGNAL &&
    194 		    (sig32.sigev_signo <=0 || sig32.sigev_signo >= NSIG))
    195 			return EINVAL;
    196 	}
    197 
    198 	error = mqueue_get(SCARG(uap, mqdes), 0, &mq);
    199 	if (error) {
    200 		return error;
    201 	}
    202 	if (SCARG_P32(uap, notification)) {
    203 		/* Register notification: set the signal and target process */
    204 		if (mq->mq_notify_proc == NULL) {
    205 			netbsd32_to_sigevent(&sig32, &mq->mq_sig_notify);
    206 			mq->mq_notify_proc = l->l_proc;
    207 		} else {
    208 			/* Fail if someone else already registered */
    209 			error = EBUSY;
    210 		}
    211 	} else {
    212 		/* Unregister the notification */
    213 		mq->mq_notify_proc = NULL;
    214 	}
    215 	mutex_exit(&mq->mq_mtx);
    216 	fd_putfile((int)SCARG(uap, mqdes));
    217 
    218 	return error;
    219 }
    220 
    221 int
    222 netbsd32_mq_send(struct lwp *l, const struct netbsd32_mq_send_args *uap,
    223     register_t *result)
    224 {
    225 	/* {
    226 		syscallarg(mqd_t) mqdes;
    227 		syscallarg(const netbsd32_charp) msg_ptr;
    228 		syscallarg(netbsd32_size_t) msg_len;
    229 		syscallarg(unsigned) msg_prio;
    230 	} */
    231 
    232 
    233 	return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
    234 	    SCARG(uap, msg_len), SCARG(uap, msg_prio), NULL);
    235 }
    236 
    237 int
    238 netbsd32_mq_receive(struct lwp *l, const struct netbsd32_mq_receive_args *uap,
    239     register_t *retval)
    240 {
    241 	/* {
    242 		syscallarg(mqd_t) mqdes;
    243 		syscallarg(netbsd32_charp) msg_ptr;
    244 		syscallarg(netbsd32_size_t) msg_len;
    245 		syscallarg(netbsd32_uintp) msg_prio;
    246 	} */
    247 	ssize_t mlen;
    248 	int error;
    249 
    250 	error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
    251 	    SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), NULL, &mlen);
    252 	if (error == 0)
    253 		*retval = mlen;
    254 
    255 	return error;
    256 }
    257 
    258 #ifdef COMPAT_50
    259 
    260 int
    261 compat_50_netbsd32_mq_timedsend(struct lwp *l,
    262     const struct compat_50_netbsd32_mq_timedsend_args *uap,
    263     register_t *retval)
    264 {
    265 	/* {
    266 		syscallarg(mqd_t) mqdes;
    267 		syscallarg(const netbsd32_charp) msg_ptr;
    268 		syscallarg(netbsd32_size_t) msg_len;
    269 		syscallarg(unsigned) msg_prio;
    270 		syscallarg(const netbsd32_timespec50p_t) abs_timeout;
    271 	} */
    272 	struct timespec ts, *tsp;
    273 	struct netbsd32_timespec ts32;
    274 	int error;
    275 
    276 	/* Get and convert time value */
    277 	if (SCARG_P32(uap, abs_timeout)) {
    278 		error = copyin(SCARG_P32(uap, abs_timeout), &ts32,
    279 		     sizeof(ts32));
    280 		if (error)
    281 			return error;
    282 		netbsd32_to_timespec(&ts32, &ts);
    283 		tsp = &ts;
    284 	} else {
    285 		tsp = NULL;
    286 	}
    287 
    288 	return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
    289 	    SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp);
    290 }
    291 
    292 int
    293 compat_50_netbsd32_mq_timedreceive(struct lwp *l,
    294     const struct compat_50_netbsd32_mq_timedreceive_args *uap,
    295     register_t *retval)
    296 {
    297 	/* {
    298 		syscallarg(mqd_t) mqdes;
    299 		syscallarg(netbsd32_charp) msg_ptr;
    300 		syscallarg(netbsd32_size_t) msg_len;
    301 		syscallarg(netbsd32_uintp) msg_prio;
    302 		syscallarg(const netbsd32_timespec50p_t) abs_timeout;
    303 	} */
    304 	struct timespec ts, *tsp;
    305 	struct netbsd32_timespec ts32;
    306 	ssize_t mlen;
    307 	int error;
    308 
    309 	/* Get and convert time value */
    310 	if (SCARG_P32(uap, abs_timeout)) {
    311 		error = copyin(SCARG_P32(uap, abs_timeout), &ts32,
    312 		    sizeof(ts32));
    313 		if (error)
    314 			return error;
    315 		netbsd32_to_timespec(&ts32, &ts);
    316 		tsp = &ts;
    317 	} else {
    318 		tsp = NULL;
    319 	}
    320 
    321 	error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
    322 	    SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), tsp, &mlen);
    323 	if (error == 0)
    324 		*retval = mlen;
    325 
    326 	return error;
    327 }
    328 #endif
    329