Home | History | Annotate | Line # | Download | only in netbsd32
netbsd32_mqueue.c revision 1.2
      1 /*	$NetBSD: netbsd32_mqueue.c,v 1.2 2015/06/21 08:32:36 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.2 2015/06/21 08:32:36 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 int
    259 netbsd32___mq_timedsend50(struct lwp *l,
    260      const struct netbsd32___mq_timedsend50_args *uap, register_t *retval)
    261 {
    262 	/* {
    263 		syscallarg(mqd_t) mqdes;
    264 		syscallarg(const netbsd32_charp) msg_ptr;
    265 		syscallarg(netbsd32_size_t) msg_len;
    266 		syscallarg(unsigned) msg_prio;
    267 		syscallarg(const netbsd32_timespecp_t) abs_timeout;
    268 	} */
    269 	struct timespec ts, *tsp;
    270 	struct netbsd32_timespec ts32;
    271 	int error;
    272 
    273 	/* Get and convert time value */
    274 	if (SCARG_P32(uap, abs_timeout)) {
    275 		error = copyin(SCARG_P32(uap, abs_timeout), &ts32,
    276 		     sizeof(ts32));
    277 		if (error)
    278 			return error;
    279 		netbsd32_to_timespec(&ts32, &ts);
    280 		tsp = &ts;
    281 	} else {
    282 		tsp = NULL;
    283 	}
    284 
    285 	return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
    286 	    SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp);
    287 }
    288 
    289 int
    290 netbsd32___mq_timedreceive50(struct lwp *l,
    291     const struct netbsd32___mq_timedreceive50_args *uap, register_t *retval)
    292 {
    293 	/* {
    294 		syscallarg(mqd_t) mqdes;
    295 		syscallarg(netbsd32_charp) msg_ptr;
    296 		syscallarg(netbsd32_size_t) msg_len;
    297 		syscallarg(netbsd32_uintp) msg_prio;
    298 		syscallarg(const netbsd32_timespecp_t) abs_timeout;
    299 	} */
    300 	struct timespec ts, *tsp;
    301 	struct netbsd32_timespec ts32;
    302 	ssize_t mlen;
    303 	int error;
    304 
    305 	/* Get and convert time value */
    306 	if (SCARG_P32(uap, abs_timeout)) {
    307 		error = copyin(SCARG_P32(uap, abs_timeout), &ts32,
    308 		    sizeof(ts32));
    309 		if (error)
    310 			return error;
    311 		netbsd32_to_timespec(&ts32, &ts);
    312 		tsp = &ts;
    313 	} else {
    314 		tsp = NULL;
    315 	}
    316 
    317 	error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
    318 	    SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), tsp, &mlen);
    319 	if (error == 0)
    320 		*retval = mlen;
    321 
    322 	return error;
    323 }
    324 
    325 #ifdef COMPAT_50
    326 int
    327 compat_50_netbsd32_mq_timedsend(struct lwp *l,
    328     const struct compat_50_netbsd32_mq_timedsend_args *uap,
    329     register_t *retval)
    330 {
    331 	/* {
    332 		syscallarg(mqd_t) mqdes;
    333 		syscallarg(const netbsd32_charp) msg_ptr;
    334 		syscallarg(netbsd32_size_t) msg_len;
    335 		syscallarg(unsigned) msg_prio;
    336 		syscallarg(const netbsd32_timespec50p_t) abs_timeout;
    337 	} */
    338 	struct timespec ts, *tsp;
    339 	struct netbsd32_timespec50 ts32;
    340 	int error;
    341 
    342 	/* Get and convert time value */
    343 	if (SCARG_P32(uap, abs_timeout)) {
    344 		error = copyin(SCARG_P32(uap, abs_timeout), &ts32,
    345 		     sizeof(ts32));
    346 		if (error)
    347 			return error;
    348 		netbsd32_to_timespec50(&ts32, &ts);
    349 		tsp = &ts;
    350 	} else {
    351 		tsp = NULL;
    352 	}
    353 
    354 	return mq_send1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
    355 	    SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp);
    356 }
    357 
    358 int
    359 compat_50_netbsd32_mq_timedreceive(struct lwp *l,
    360     const struct compat_50_netbsd32_mq_timedreceive_args *uap,
    361     register_t *retval)
    362 {
    363 	/* {
    364 		syscallarg(mqd_t) mqdes;
    365 		syscallarg(netbsd32_charp) msg_ptr;
    366 		syscallarg(netbsd32_size_t) msg_len;
    367 		syscallarg(netbsd32_uintp) msg_prio;
    368 		syscallarg(const netbsd32_timespec50p_t) abs_timeout;
    369 	} */
    370 	struct timespec ts, *tsp;
    371 	struct netbsd32_timespec50 ts32;
    372 	ssize_t mlen;
    373 	int error;
    374 
    375 	/* Get and convert time value */
    376 	if (SCARG_P32(uap, abs_timeout)) {
    377 		error = copyin(SCARG_P32(uap, abs_timeout), &ts32,
    378 		    sizeof(ts32));
    379 		if (error)
    380 			return error;
    381 		netbsd32_to_timespec50(&ts32, &ts);
    382 		tsp = &ts;
    383 	} else {
    384 		tsp = NULL;
    385 	}
    386 
    387 	error = mq_recv1(SCARG(uap, mqdes), SCARG_P32(uap, msg_ptr),
    388 	    SCARG(uap, msg_len), SCARG_P32(uap, msg_prio), tsp, &mlen);
    389 	if (error == 0)
    390 		*retval = mlen;
    391 
    392 	return error;
    393 }
    394 #endif
    395