Home | History | Annotate | Line # | Download | only in netbsd32
netbsd32_compat_50.c revision 1.3
      1 /*	$NetBSD: netbsd32_compat_50.c,v 1.3 2009/01/26 13:00:04 njoly Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Christos Zoulas.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 #include <sys/cdefs.h>
     39 __KERNEL_RCSID(0, "$NetBSD: netbsd32_compat_50.c,v 1.3 2009/01/26 13:00:04 njoly Exp $");
     40 
     41 #if defined(_KERNEL_OPT)
     42 #include "opt_sysv.h"
     43 #endif
     44 
     45 #include "fs_lfs.h"
     46 
     47 #include <sys/param.h>
     48 #include <sys/systm.h>
     49 #include <sys/malloc.h>
     50 #include <sys/mount.h>
     51 #include <sys/socket.h>
     52 #include <sys/socketvar.h>
     53 #include <sys/stat.h>
     54 #include <sys/time.h>
     55 #include <sys/ktrace.h>
     56 #include <sys/eventvar.h>
     57 #include <sys/resourcevar.h>
     58 #include <sys/vnode.h>
     59 #include <sys/file.h>
     60 #include <sys/filedesc.h>
     61 #include <sys/poll.h>
     62 #include <sys/namei.h>
     63 #include <sys/statvfs.h>
     64 #include <sys/syscallargs.h>
     65 #include <sys/proc.h>
     66 #include <sys/dirent.h>
     67 #include <sys/kauth.h>
     68 #include <sys/vfs_syscalls.h>
     69 #include <sys/ipc.h>
     70 #include <sys/msg.h>
     71 #include <sys/sem.h>
     72 #include <sys/shm.h>
     73 
     74 #include <compat/netbsd32/netbsd32.h>
     75 #include <compat/netbsd32/netbsd32_syscallargs.h>
     76 #include <compat/netbsd32/netbsd32_conv.h>
     77 #include <compat/sys/mount.h>
     78 #include <compat/sys/time.h>
     79 
     80 
     81 /*
     82  * Common routine to set access and modification times given a vnode.
     83  */
     84 static int
     85 get_utimes32(const netbsd32_timeval50p_t *tptr, struct timeval *tv,
     86     struct timeval **tvp)
     87 {
     88 	int error;
     89 	struct netbsd32_timeval50 tv32[2];
     90 
     91 	if (tptr == NULL) {
     92 		*tvp = NULL;
     93 		return 0;
     94 	}
     95 
     96 	error = copyin(tptr, tv32, sizeof(tv32));
     97 	if (error)
     98 		return error;
     99 	netbsd32_to_timeval50(&tv32[0], &tv[0]);
    100 	netbsd32_to_timeval50(&tv32[1], &tv[1]);
    101 
    102 	*tvp = tv;
    103 	return 0;
    104 }
    105 
    106 int
    107 compat_50_netbsd32_mknod(struct lwp *l,
    108     const struct compat_50_netbsd32_mknod_args *uap, register_t *retval)
    109 {
    110 	/* {
    111 		syscallarg(netbsd32_charp) path;
    112 		syscallarg(mode_t) mode;
    113 		syscallarg(uint32_t) dev;
    114 	} */
    115 	return do_sys_mknod(l, SCARG_P32(uap, path), SCARG(uap, mode),
    116 	    SCARG(uap, dev), retval);
    117 }
    118 
    119 int
    120 compat_50_netbsd32_select(struct lwp *l,
    121     const struct compat_50_netbsd32_select_args *uap, register_t *retval)
    122 {
    123 	/* {
    124 		syscallarg(int) nd;
    125 		syscallarg(netbsd32_fd_setp_t) in;
    126 		syscallarg(netbsd32_fd_setp_t) ou;
    127 		syscallarg(netbsd32_fd_setp_t) ex;
    128 		syscallarg(netbsd32_timeval50p_t) tv;
    129 	} */
    130 	int error;
    131 	struct netbsd32_timeval50 tv32;
    132 	struct timeval atv, *tv = NULL;
    133 
    134 	if (SCARG_P32(uap, tv)) {
    135 		error = copyin(SCARG_P32(uap, tv), &tv32, sizeof(tv32));
    136 		if (error != 0)
    137 			return error;
    138 		netbsd32_to_timeval50(&tv32, &atv);
    139 		tv = &atv;
    140 	}
    141 
    142 	return selcommon(l, retval, SCARG(uap, nd), SCARG_P32(uap, in),
    143 	    SCARG_P32(uap, ou), SCARG_P32(uap, ex), tv, NULL);
    144 	return 0;
    145 }
    146 
    147 int
    148 compat_50_netbsd32_gettimeofday(struct lwp *l,
    149     const struct compat_50_netbsd32_gettimeofday_args *uap, register_t *retval)
    150 {
    151 	/* {
    152 		syscallarg(netbsd32_timeval50p_t) tp;
    153 		syscallarg(netbsd32_timezonep_t) tzp;
    154 	} */
    155 	struct timeval atv;
    156 	struct netbsd32_timeval50 tv32;
    157 	int error = 0;
    158 	struct netbsd32_timezone tzfake;
    159 
    160 	if (SCARG_P32(uap, tp)) {
    161 		microtime(&atv);
    162 		netbsd32_from_timeval50(&atv, &tv32);
    163 		error = copyout(&tv32, SCARG_P32(uap, tp), sizeof(tv32));
    164 		if (error)
    165 			return error;
    166 	}
    167 	if (SCARG_P32(uap, tzp)) {
    168 		/*
    169 		 * NetBSD has no kernel notion of time zone, so we just
    170 		 * fake up a timezone struct and return it if demanded.
    171 		 */
    172 		tzfake.tz_minuteswest = 0;
    173 		tzfake.tz_dsttime = 0;
    174 		error = copyout(&tzfake, SCARG_P32(uap, tzp), sizeof(tzfake));
    175 	}
    176 	return error;
    177 }
    178 
    179 int
    180 compat_50_netbsd32_settimeofday(struct lwp *l,
    181     const struct compat_50_netbsd32_settimeofday_args *uap, register_t *retval)
    182 {
    183 	/* {
    184 		syscallarg(const netbsd32_timeval50p_t) tv;
    185 		syscallarg(const netbsd32_timezonep_t) tzp;
    186 	} */
    187 	struct netbsd32_timeval50 atv32;
    188 	struct timeval atv;
    189 	struct timespec ats;
    190 	int error;
    191 	struct proc *p = l->l_proc;
    192 
    193 	/* Verify all parameters before changing time. */
    194 
    195 	/*
    196 	 * NetBSD has no kernel notion of time zone, and only an
    197 	 * obsolete program would try to set it, so we log a warning.
    198 	 */
    199 	if (SCARG_P32(uap, tzp))
    200 		printf("pid %d attempted to set the "
    201 		    "(obsolete) kernel time zone\n", p->p_pid);
    202 
    203 	if (SCARG_P32(uap, tv) == 0)
    204 		return 0;
    205 
    206 	if ((error = copyin(SCARG_P32(uap, tv), &atv32, sizeof(atv32))) != 0)
    207 		return error;
    208 
    209 	netbsd32_to_timeval50(&atv32, &atv);
    210 	TIMEVAL_TO_TIMESPEC(&atv, &ats);
    211 	return settime(p, &ats);
    212 }
    213 
    214 int
    215 compat_50_netbsd32_utimes(struct lwp *l,
    216     const struct compat_50_netbsd32_utimes_args *uap, register_t *retval)
    217 {
    218 	/* {
    219 		syscallarg(const netbsd32_charp) path;
    220 		syscallarg(const netbsd32_timeval50p_t) tptr;
    221 	} */
    222 	int error;
    223 	struct timeval tv[2], *tvp;
    224 
    225 	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
    226 	if (error != 0)
    227 		return error;
    228 
    229 	return do_sys_utimes(l, NULL, SCARG_P32(uap, path), FOLLOW,
    230 	    tvp, UIO_SYSSPACE);
    231 }
    232 
    233 int
    234 compat_50_netbsd32_adjtime(struct lwp *l,
    235     const struct compat_50_netbsd32_adjtime_args *uap, register_t *retval)
    236 {
    237 	/* {
    238 		syscallarg(const netbsd32_timeval50p_t) delta;
    239 		syscallarg(netbsd32_timeval50p_t) olddelta;
    240 	} */
    241 	struct netbsd32_timeval50 atv;
    242 	int error;
    243 
    244 	extern int time_adjusted;     /* in kern_ntptime.c */
    245 	extern int64_t time_adjtime;  /* in kern_ntptime.c */
    246 
    247 	if ((error = kauth_authorize_system(l->l_cred,
    248 	    KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL,
    249 	    NULL)) != 0)
    250 		return (error);
    251 
    252 	if (SCARG_P32(uap, olddelta)) {
    253 		atv.tv_sec = time_adjtime / 1000000;
    254 		atv.tv_usec = time_adjtime % 1000000;
    255 		if (atv.tv_usec < 0) {
    256 			atv.tv_usec += 1000000;
    257 			atv.tv_sec--;
    258 		}
    259 		(void) copyout(&atv,
    260 			       SCARG_P32(uap, olddelta),
    261 			       sizeof(atv));
    262 		if (error)
    263 			return (error);
    264 	}
    265 
    266 	if (SCARG_P32(uap, delta)) {
    267 		error = copyin(SCARG_P32(uap, delta), &atv,
    268 			       sizeof(struct timeval));
    269 		if (error)
    270 			return (error);
    271 
    272 		time_adjtime = (int64_t)atv.tv_sec * 1000000 + atv.tv_usec;
    273 
    274 		if (time_adjtime)
    275 			/* We need to save the system time during shutdown */
    276 			time_adjusted |= 1;
    277 	}
    278 
    279 	return 0;
    280 }
    281 
    282 #if defined(LFS) || !defined(_KERNEL)
    283 int
    284 compat_50_netbsd32_lfs_segwait(struct lwp *l,
    285     const struct compat_50_netbsd32_lfs_segwait_args *uap, register_t *retval)
    286 {
    287 	return 0;
    288 }
    289 #endif
    290 
    291 int
    292 compat_50_netbsd32_futimes(struct lwp *l,
    293     const struct compat_50_netbsd32_futimes_args *uap, register_t *retval)
    294 {
    295 	/* {
    296 		syscallarg(int) fd;
    297 		syscallarg(const netbsd32_timeval50p_t) tptr;
    298 	} */
    299 	int error;
    300 	file_t *fp;
    301 	struct timeval tv[2], *tvp;
    302 
    303 	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
    304 	if (error != 0)
    305 		return error;
    306 
    307 	/* fd_getvnode() will use the descriptor for us */
    308 	if ((error = fd_getvnode(SCARG(uap, fd), &fp)) != 0)
    309 		return error;
    310 
    311 	error = do_sys_utimes(l, fp->f_data, NULL, 0, tvp, UIO_SYSSPACE);
    312 
    313 	fd_putfile(SCARG(uap, fd));
    314 	return error;
    315 }
    316 
    317 int
    318 compat_50_netbsd32_clock_gettime(struct lwp *l,
    319     const struct compat_50_netbsd32_clock_gettime_args *uap, register_t *retval)
    320 {
    321 	/* {
    322 		syscallarg(netbsd32_clockid_t) clock_id;
    323 		syscallarg(netbsd32_timespec50p_t) tp;
    324 	} */
    325 	clockid_t clock_id;
    326 	struct timespec ats;
    327 	struct netbsd32_timespec50 ts32;
    328 
    329 	clock_id = SCARG(uap, clock_id);
    330 	if (clock_id != CLOCK_REALTIME)
    331 		return (EINVAL);
    332 
    333 	nanotime(&ats);
    334 	netbsd32_from_timespec50(&ats, &ts32);
    335 
    336 	return copyout(&ts32, SCARG_P32(uap, tp), sizeof(ts32));
    337 }
    338 
    339 int
    340 compat_50_netbsd32_clock_settime(struct lwp *l,
    341     const struct compat_50_netbsd32_clock_settime_args *uap, register_t *retval)
    342 {
    343 	/* {
    344 		syscallarg(netbsd32_clockid_t) clock_id;
    345 		syscallarg(const netbsd32_timespec50p_t) tp;
    346 	} */
    347 	struct netbsd32_timespec50 ts32;
    348 	clockid_t clock_id;
    349 	struct timespec ats;
    350 	int error;
    351 
    352 	clock_id = SCARG(uap, clock_id);
    353 	if (clock_id != CLOCK_REALTIME)
    354 		return (EINVAL);
    355 
    356 	if ((error = copyin(SCARG_P32(uap, tp), &ts32, sizeof(ts32))) != 0)
    357 		return (error);
    358 
    359 	netbsd32_to_timespec50(&ts32, &ats);
    360 	return settime(l->l_proc, &ats);
    361 }
    362 
    363 int
    364 compat_50_netbsd32_clock_getres(struct lwp *l,
    365     const struct compat_50_netbsd32_clock_getres_args *uap, register_t *retval)
    366 {
    367 	/* {
    368 		syscallarg(netbsd32_clockid_t) clock_id;
    369 		syscallarg(netbsd32_timespec50p_t) tp;
    370 	} */
    371 	struct netbsd32_timespec50 ts32;
    372 	clockid_t clock_id;
    373 	struct timespec ts;
    374 	int error = 0;
    375 
    376 	clock_id = SCARG(uap, clock_id);
    377 	if (clock_id != CLOCK_REALTIME)
    378 		return (EINVAL);
    379 
    380 	if (SCARG_P32(uap, tp)) {
    381 		ts.tv_sec = 0;
    382 		ts.tv_nsec = 1000000000 / hz;
    383 
    384 		netbsd32_from_timespec50(&ts, &ts32);
    385 		error = copyout(&ts, SCARG_P32(uap, tp), sizeof(ts));
    386 	}
    387 
    388 	return error;
    389 }
    390 
    391 int
    392 compat_50_netbsd32_timer_settime(struct lwp *l,
    393     const struct compat_50_netbsd32_timer_settime_args *uap, register_t *retval)
    394 {
    395 	/* {
    396 		syscallarg(netbsd32_timer_t) timerid;
    397 		syscallarg(int) flags;
    398 		syscallarg(const netbsd32_itimerspec50p_t) value;
    399 		syscallarg(netbsd32_itimerspec50p_t) ovalue;
    400 	} */
    401 	int error;
    402 	struct itimerspec value, ovalue, *ovp = NULL;
    403 	struct netbsd32_itimerspec50 its32;
    404 
    405 	if ((error = copyin(SCARG_P32(uap, value), &its32, sizeof(its32))) != 0)
    406 		return (error);
    407 	netbsd32_to_timespec50(&its32.it_interval, &value.it_interval);
    408 	netbsd32_to_timespec50(&its32.it_value, &value.it_value);
    409 
    410 	if (SCARG_P32(uap, ovalue))
    411 		ovp = &ovalue;
    412 
    413 	if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
    414 	    SCARG(uap, flags), l->l_proc)) != 0)
    415 		return error;
    416 
    417 	if (ovp) {
    418 		netbsd32_from_timespec50(&ovp->it_interval, &its32.it_interval);
    419 		netbsd32_from_timespec50(&ovp->it_value, &its32.it_value);
    420 		return copyout(&its32, SCARG_P32(uap, ovalue), sizeof(its32));
    421 	}
    422 	return 0;
    423 }
    424 
    425 int
    426 compat_50_netbsd32_timer_gettime(struct lwp *l, const struct compat_50_netbsd32_timer_gettime_args *uap, register_t *retval)
    427 {
    428 	/* {
    429 		syscallarg(netbsd32_timer_t) timerid;
    430 		syscallarg(netbsd32_itimerspec50p_t) value;
    431 	} */
    432 	int error;
    433 	struct itimerspec its;
    434 	struct netbsd32_itimerspec50 its32;
    435 
    436 	if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
    437 	    &its)) != 0)
    438 		return error;
    439 
    440 	netbsd32_from_timespec50(&its.it_interval, &its32.it_interval);
    441 	netbsd32_from_timespec50(&its.it_value, &its32.it_value);
    442 
    443 	return copyout(&its32, SCARG_P32(uap, value), sizeof(its32));
    444 }
    445 
    446 int
    447 compat_50_netbsd32_nanosleep(struct lwp *l,
    448     const struct compat_50_netbsd32_nanosleep_args *uap, register_t *retval)
    449 {
    450 	/* {
    451 		syscallarg(const netbsd32_timespec50p_t) rqtp;
    452 		syscallarg(netbsd32_timespecp_t) rmtp;
    453 	} */
    454 	static int nanowait;
    455 	struct netbsd32_timespec50 ts32;
    456 	struct timespec rqt, ctime, rmt;
    457 	int error, timo;
    458 
    459 	error = copyin(SCARG_P32(uap, rqtp), &ts32, sizeof(ts32));
    460 	if (error)
    461 		return (error);
    462 
    463 	netbsd32_to_timespec50(&ts32, &rqt);
    464 	if (itimespecfix(&rqt))
    465 		return (EINVAL);
    466 
    467 	getnanotime(&ctime);
    468 	timespecadd(&rqt, &ctime, &rqt);
    469 	timo = tshzto(&rqt);
    470 	/*
    471 	 * Avoid inadvertantly sleeping forever
    472 	 */
    473 	if (timo == 0)
    474 		timo = 1;
    475 
    476 	error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
    477 	if (error == ERESTART)
    478 		error = EINTR;
    479 	if (error == EWOULDBLOCK)
    480 		error = 0;
    481 
    482 	if (SCARG_P32(uap, rmtp)) {
    483 		int error1;
    484 
    485 		getnanotime(&rmt);
    486 
    487 		timespecsub(&rqt, &rmt, &rmt);
    488 		if (rmt.tv_sec < 0)
    489 			timespecclear(&rmt);
    490 
    491 		netbsd32_from_timespec50(&rmt, &ts32);
    492 		error1 = copyout(&ts32, SCARG_P32(uap,rmtp), sizeof(ts32));
    493 		if (error1)
    494 			return (error1);
    495 	}
    496 
    497 	return error;
    498 }
    499 
    500 static int
    501 compat_50_netbsd32_sigtimedwait_put_info(const void *src, void *dst, size_t size)
    502 {
    503 	const siginfo_t *info = src;
    504 	siginfo32_t info32;
    505 
    506 	netbsd32_si_to_si32(&info32, info);
    507 
    508 	return copyout(&info32, dst, sizeof(info32));
    509 }
    510 
    511 static int
    512 compat_50_netbsd32_sigtimedwait_fetch_timeout(const void *src, void *dst, size_t size)
    513 {
    514 	struct timespec *ts = dst;
    515 	struct netbsd32_timespec50 ts32;
    516 	int error;
    517 
    518 	error = copyin(src, &ts32, sizeof(ts32));
    519 	if (error)
    520 		return error;
    521 
    522 	netbsd32_to_timespec50(&ts32, ts);
    523 	return 0;
    524 }
    525 
    526 static int
    527 compat_50_netbsd32_sigtimedwait_put_timeout(const void *src, void *dst, size_t size)
    528 {
    529 	const struct timespec *ts = src;
    530 	struct netbsd32_timespec50 ts32;
    531 
    532 	netbsd32_from_timespec50(ts, &ts32);
    533 
    534 	return copyout(&ts32, dst, sizeof(ts32));
    535 }
    536 
    537 int
    538 compat_50_netbsd32___sigtimedwait(struct lwp *l,
    539     const struct compat_50_netbsd32___sigtimedwait_args *uap, register_t *retval)
    540 {
    541 	/* {
    542 		syscallarg(netbsd32_sigsetp_t) set;
    543 		syscallarg(netbsd32_siginfop_t) info;
    544 		syscallarg(netbsd32_timespec50p_t) timeout;
    545 	} */
    546 	struct sys_____sigtimedwait50_args ua;
    547 
    548 	NETBSD32TOP_UAP(set, const sigset_t);
    549 	NETBSD32TOP_UAP(info, siginfo_t);
    550 	NETBSD32TOP_UAP(timeout, struct timespec);
    551 
    552 	return __sigtimedwait1(l, &ua, retval,
    553 	    compat_50_netbsd32_sigtimedwait_put_info,
    554 	    compat_50_netbsd32_sigtimedwait_fetch_timeout,
    555 	    compat_50_netbsd32_sigtimedwait_put_timeout);
    556 	return 0;
    557 }
    558 
    559 int
    560 compat_50_netbsd32_lutimes(struct lwp *l,
    561     const struct compat_50_netbsd32_lutimes_args *uap, register_t *retval)
    562 {
    563 	/* {
    564 		syscallarg(const netbsd32_charp) path;
    565 		syscallarg(const netbsd32_timeval50p_t) tptr;
    566 	} */
    567 	int error;
    568 	struct timeval tv[2], *tvp;
    569 
    570 	error = get_utimes32(SCARG_P32(uap, tptr), tv, &tvp);
    571 	if (error != 0)
    572 		return error;
    573 
    574 	return do_sys_utimes(l, NULL, SCARG_P32(uap, path), NOFOLLOW,
    575 	    tvp, UIO_SYSSPACE);
    576 }
    577 
    578 int
    579 compat_50_netbsd32__lwp_park(struct lwp *l,
    580     const struct compat_50_netbsd32__lwp_park_args *uap, register_t *retval)
    581 {
    582 	/* {
    583 		syscallarg(const netbsd32_timespec50p) ts;
    584 		syscallarg(lwpid_t) unpark;
    585 		syscallarg(netbsd32_voidp) hint;
    586 		syscallarg(netbsd32_voidp) unparkhint;
    587 	} */
    588 	struct timespec ts, *tsp;
    589 	struct netbsd32_timespec50 ts32;
    590 	int error;
    591 
    592 	if (SCARG_P32(uap, ts) == NULL)
    593 		tsp = NULL;
    594 	else {
    595 		error = copyin(SCARG_P32(uap, ts), &ts32, sizeof ts32);
    596 		if (error != 0)
    597 			return error;
    598 		netbsd32_to_timespec50(&ts32, &ts);
    599 		tsp = &ts;
    600 	}
    601 
    602 	if (SCARG(uap, unpark) != 0) {
    603 		error = lwp_unpark(SCARG(uap, unpark),
    604 		    SCARG_P32(uap, unparkhint));
    605 		if (error != 0)
    606 			return error;
    607 	}
    608 
    609 	return lwp_park(tsp, SCARG_P32(uap, hint));
    610 	return 0;
    611 }
    612 
    613 static int
    614 netbsd32_kevent_fetch_timeout(const void *src, void *dest, size_t length)
    615 {
    616 	struct netbsd32_timespec50 ts32;
    617 	int error;
    618 
    619 	KASSERT(length == sizeof(struct timespec50));
    620 
    621 	error = copyin(src, &ts32, sizeof(ts32));
    622 	if (error)
    623 		return error;
    624 	netbsd32_to_timespec50(&ts32, (struct timespec *)dest);
    625 	return 0;
    626 }
    627 
    628 static int
    629 netbsd32_kevent_fetch_changes(void *private, const struct kevent *changelist,
    630     struct kevent *changes, size_t index, int n)
    631 {
    632 	const struct netbsd32_kevent *src =
    633 	    (const struct netbsd32_kevent *)changelist;
    634 	struct netbsd32_kevent *kev32, *changes32 = private;
    635 	int error, i;
    636 
    637 	error = copyin(src + index, changes32, n * sizeof(*changes32));
    638 	if (error)
    639 		return error;
    640 	for (i = 0, kev32 = changes32; i < n; i++, kev32++, changes++)
    641 		netbsd32_to_kevent(kev32, changes);
    642 	return 0;
    643 }
    644 
    645 static int
    646 netbsd32_kevent_put_events(void *private, struct kevent *events,
    647     struct kevent *eventlist, size_t index, int n)
    648 {
    649 	struct netbsd32_kevent *kev32, *events32 = private;
    650 	int i;
    651 
    652 	for (i = 0, kev32 = events32; i < n; i++, kev32++, events++)
    653 		netbsd32_from_kevent(events, kev32);
    654 	kev32 = (struct netbsd32_kevent *)eventlist;
    655 	return  copyout(events32, kev32, n * sizeof(*events32));
    656 }
    657 
    658 int
    659 compat_50_netbsd32_kevent(struct lwp *l,
    660     const struct compat_50_netbsd32_kevent_args *uap, register_t *retval)
    661 {
    662 	/* {
    663 		syscallarg(int) fd;
    664 		syscallarg(netbsd32_keventp_t) changelist;
    665 		syscallarg(netbsd32_size_t) nchanges;
    666 		syscallarg(netbsd32_keventp_t) eventlist;
    667 		syscallarg(netbsd32_size_t) nevents;
    668 		syscallarg(netbsd32_timespec50p_t) timeout;
    669 	} */
    670 	int error;
    671 	size_t maxalloc, nchanges, nevents;
    672 	struct kevent_ops netbsd32_kevent_ops = {
    673 		keo_fetch_timeout: netbsd32_kevent_fetch_timeout,
    674 		keo_fetch_changes: netbsd32_kevent_fetch_changes,
    675 		keo_put_events: netbsd32_kevent_put_events,
    676 	};
    677 
    678 	nchanges = SCARG(uap, nchanges);
    679 	nevents = SCARG(uap, nevents);
    680 	maxalloc = MIN(KQ_NEVENTS, MAX(nchanges, nevents));
    681 	netbsd32_kevent_ops.keo_private =
    682 	    malloc(maxalloc * sizeof(struct netbsd32_kevent), M_TEMP,
    683 	    M_WAITOK);
    684 
    685 	error = kevent1(retval, SCARG(uap, fd),
    686 	    NETBSD32PTR64(SCARG(uap, changelist)), nchanges,
    687 	    NETBSD32PTR64(SCARG(uap, eventlist)), nevents,
    688 	    NETBSD32PTR64(SCARG(uap, timeout)), &netbsd32_kevent_ops);
    689 
    690 	free(netbsd32_kevent_ops.keo_private, M_TEMP);
    691 	return error;
    692 	return 0;
    693 }
    694 
    695 int
    696 compat_50_netbsd32_pselect(struct lwp *l,
    697     const struct compat_50_netbsd32_pselect_args *uap, register_t *retval)
    698 {
    699 	/* {
    700 		syscallarg(int) nd;
    701 		syscallarg(netbsd32_fd_setp_t) in;
    702 		syscallarg(netbsd32_fd_setp_t) ou;
    703 		syscallarg(netbsd32_fd_setp_t) ex;
    704 		syscallarg(const netbsd32_timespec50p_t) ts;
    705 		syscallarg(const netbsd32_sigsetp_t) mask;
    706 	} */
    707 	int error;
    708 	struct netbsd32_timespec50 ts32;
    709 	struct timespec ts;
    710 	struct timeval atv, *tv = NULL;
    711 	sigset_t amask, *mask = NULL;
    712 
    713 	if (SCARG_P32(uap, ts)) {
    714 		error = copyin(SCARG_P32(uap, ts), &ts32, sizeof(ts32));
    715 		if (error != 0)
    716 			return error;
    717 		netbsd32_to_timespec50(&ts32, &ts);
    718 		atv.tv_sec = ts.tv_sec;
    719 		atv.tv_usec = ts.tv_nsec / 1000;
    720 		tv = &atv;
    721 	}
    722 	if (SCARG_P32(uap, mask)) {
    723 		error = copyin(SCARG_P32(uap, mask), &amask, sizeof(amask));
    724 		if (error != 0)
    725 			return error;
    726 		mask = &amask;
    727 	}
    728 
    729 	return selcommon(l, retval, SCARG(uap, nd), SCARG_P32(uap, in),
    730 	    SCARG_P32(uap, ou), SCARG_P32(uap, ex), tv, mask);
    731 	return 0;
    732 }
    733 
    734 int
    735 compat_50_netbsd32_pollts(struct lwp *l,
    736     const struct compat_50_netbsd32_pollts_args *uap, register_t *retval)
    737 {
    738 	/* {
    739 		syscallarg(struct netbsd32_pollfdp_t) fds;
    740 		syscallarg(u_int) nfds;
    741 		syscallarg(const netbsd32_timespec50p_t) ts;
    742 		syscallarg(const netbsd32_sigsetp_t) mask;
    743 	} */
    744 	int error;
    745 	struct netbsd32_timespec50 ts32;
    746 	struct timespec ts;
    747 	struct timeval atv, *tv = NULL;
    748 	sigset_t amask, *mask = NULL;
    749 
    750 	if (SCARG_P32(uap, ts)) {
    751 		error = copyin(SCARG_P32(uap, ts), &ts32, sizeof(ts32));
    752 		if (error != 0)
    753 			return error;
    754 		netbsd32_to_timespec50(&ts32, &ts);
    755 		atv.tv_sec = ts.tv_sec;
    756 		atv.tv_usec = ts.tv_nsec / 1000;
    757 		tv = &atv;
    758 	}
    759 	if (NETBSD32PTR64( SCARG(uap, mask))) {
    760 		error = copyin(SCARG_P32(uap, mask), &amask, sizeof(amask));
    761 		if (error != 0)
    762 			return error;
    763 		mask = &amask;
    764 	}
    765 
    766 	return pollcommon(l, retval, SCARG_P32(uap, fds),
    767 	    SCARG(uap, nfds), tv, mask);
    768 }
    769 
    770 int
    771 compat_50_netbsd32___stat30(struct lwp *l,
    772     const struct compat_50_netbsd32___stat30_args *uap, register_t *retval)
    773 {
    774 	/* {
    775 		syscallarg(const netbsd32_charp) path;
    776 		syscallarg(netbsd32_stat50p_t) ub;
    777 	} */
    778 	struct netbsd32_stat50 sb32;
    779 	struct stat sb;
    780 	int error;
    781 	const char *path;
    782 
    783 	path = SCARG_P32(uap, path);
    784 
    785 	error = do_sys_stat(path, FOLLOW, &sb);
    786 	if (error)
    787 		return error;
    788 	netbsd32_from___stat50(&sb, &sb32);
    789 	error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
    790 	return error;
    791 }
    792 
    793 int
    794 compat_50_netbsd32___fstat30(struct lwp *l,
    795     const struct compat_50_netbsd32___fstat30_args *uap, register_t *retval)
    796 {
    797 	/* {
    798 		syscallarg(int) fd;
    799 		syscallarg(netbsd32_stat50p_t) sb;
    800 	} */
    801 	struct netbsd32_stat50 sb32;
    802 	struct stat ub;
    803 	int error;
    804 
    805 	error = do_sys_fstat(SCARG(uap, fd), &ub);
    806 	if (error == 0) {
    807 		netbsd32_from___stat50(&ub, &sb32);
    808 		error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb32));
    809 	}
    810 	return error;
    811 }
    812 
    813 int
    814 compat_50_netbsd32___lstat30(struct lwp *l,
    815     const struct compat_50_netbsd32___lstat30_args *uap, register_t *retval)
    816 {
    817 	/* {
    818 		syscallarg(const netbsd32_charp) path;
    819 		syscallarg(netbsd32_stat50p_t) ub;
    820 	} */
    821 	struct netbsd32_stat50 sb32;
    822 	struct stat sb;
    823 	int error;
    824 	const char *path;
    825 
    826 	path = SCARG_P32(uap, path);
    827 
    828 	error = do_sys_stat(path, NOFOLLOW, &sb);
    829 	if (error)
    830 		return error;
    831 	netbsd32_from___stat50(&sb, &sb32);
    832 	error = copyout(&sb32, SCARG_P32(uap, ub), sizeof(sb32));
    833 	return error;
    834 }
    835 
    836 int
    837 compat_50_netbsd32___fhstat40(struct lwp *l, const struct compat_50_netbsd32___fhstat40_args *uap, register_t *retval)
    838 {
    839 	/* {
    840 		syscallarg(const netbsd32_pointer_t) fhp;
    841 		syscallarg(netbsd32_size_t) fh_size;
    842 		syscallarg(netbsd32_stat50p_t) sb;
    843 	} */
    844 	struct stat sb;
    845 	struct netbsd32_stat50 sb32;
    846 	int error;
    847 
    848 	error = do_fhstat(l, SCARG_P32(uap, fhp), SCARG(uap, fh_size), &sb);
    849 	if (error != 0) {
    850 		netbsd32_from___stat50(&sb, &sb32);
    851 		error = copyout(&sb32, SCARG_P32(uap, sb), sizeof(sb));
    852 	}
    853 	return error;
    854 }
    855 
    856 int
    857 compat_50_netbsd32_wait4(struct lwp *l, const struct compat_50_netbsd32_wait4_args *uap, register_t *retval)
    858 {
    859 	/* {
    860 		syscallarg(int) pid;
    861 		syscallarg(netbsd32_intp) status;
    862 		syscallarg(int) options;
    863 		syscallarg(netbsd32_rusage50p_t) rusage;
    864 	} */
    865 	int		status, error;
    866 	int		was_zombie;
    867 	struct rusage	ru;
    868 	struct netbsd32_rusage50	ru32;
    869 	int pid = SCARG(uap, pid);
    870 
    871 	error = do_sys_wait(l, &pid, &status, SCARG(uap, options),
    872 	    SCARG_P32(uap, rusage) != NULL ? &ru : NULL, &was_zombie);
    873 
    874 	retval[0] = pid;
    875 	if (pid == 0)
    876 		return error;
    877 
    878 	if (SCARG_P32(uap, rusage)) {
    879 		netbsd32_from_rusage50(&ru, &ru32);
    880 		error = copyout(&ru32, SCARG_P32(uap, rusage), sizeof(ru32));
    881 	}
    882 
    883 	if (error == 0 && SCARG_P32(uap, status))
    884 		error = copyout(&status, SCARG_P32(uap, status), sizeof(status));
    885 
    886 	return error;
    887 }
    888 
    889 
    890 int
    891 compat_50_netbsd32_getrusage(struct lwp *l, const struct compat_50_netbsd32_getrusage_args *uap, register_t *retval)
    892 {
    893 	/* {
    894 		syscallarg(int) who;
    895 		syscallarg(netbsd32_rusage50p_t) rusage;
    896 	} */
    897 	struct proc *p = l->l_proc;
    898 	struct rusage *rup;
    899 	struct netbsd32_rusage50 ru;
    900 
    901 	switch (SCARG(uap, who)) {
    902 
    903 	case RUSAGE_SELF:
    904 		rup = &p->p_stats->p_ru;
    905 		mutex_enter(p->p_lock);
    906 		calcru(p, &rup->ru_utime, &rup->ru_stime, NULL, NULL);
    907 		mutex_exit(p->p_lock);
    908 		break;
    909 
    910 	case RUSAGE_CHILDREN:
    911 		rup = &p->p_stats->p_cru;
    912 		break;
    913 
    914 	default:
    915 		return (EINVAL);
    916 	}
    917 	netbsd32_from_rusage50(rup, &ru);
    918 	return copyout(&ru, SCARG_P32(uap, rusage), sizeof(ru));
    919 }
    920 
    921 int
    922 compat_50_netbsd32_setitimer(struct lwp *l,
    923     const struct compat_50_netbsd32_setitimer_args *uap, register_t *retval)
    924 {
    925 	/* {
    926 		syscallarg(int) which;
    927 		syscallarg(const netbsd32_itimerval50p_t) itv;
    928 		syscallarg(netbsd32_itimerval50p_t) oitv;
    929 	} */
    930 	struct proc *p = l->l_proc;
    931 	struct netbsd32_itimerval50 s32it, *itv32;
    932 	int which = SCARG(uap, which);
    933 	struct compat_50_netbsd32_getitimer_args getargs;
    934 	struct itimerval aitv;
    935 	int error;
    936 
    937 	if ((u_int)which > ITIMER_PROF)
    938 		return (EINVAL);
    939 	itv32 = SCARG_P32(uap, itv);
    940 	if (itv32) {
    941 		if ((error = copyin(itv32, &s32it, sizeof(s32it))))
    942 			return (error);
    943 		netbsd32_to_itimerval50(&s32it, &aitv);
    944 	}
    945 	if (SCARG_P32(uap, oitv) != 0) {
    946 		SCARG(&getargs, which) = which;
    947 		SCARG(&getargs, itv) = SCARG(uap, oitv);
    948 		if ((error = compat_50_netbsd32_getitimer(l, &getargs, retval)) != 0)
    949 			return (error);
    950 	}
    951 	if (itv32 == 0)
    952 		return 0;
    953 
    954 	return dosetitimer(p, which, &aitv);
    955 }
    956 
    957 int
    958 compat_50_netbsd32_getitimer(struct lwp *l, const struct compat_50_netbsd32_getitimer_args *uap, register_t *retval)
    959 {
    960 	/* {
    961 		syscallarg(int) which;
    962 		syscallarg(netbsd32_itimerval50p_t) itv;
    963 	} */
    964 	struct proc *p = l->l_proc;
    965 	struct netbsd32_itimerval50 s32it;
    966 	struct itimerval aitv;
    967 	int error;
    968 
    969 	error = dogetitimer(p, SCARG(uap, which), &aitv);
    970 	if (error)
    971 		return error;
    972 
    973 	netbsd32_from_itimerval50(&aitv, &s32it);
    974 	return copyout(&s32it, SCARG_P32(uap, itv), sizeof(s32it));
    975 }
    976 
    977 #if defined(SYSVSEM)
    978 
    979 int
    980 compat_50_netbsd32___semctl14(struct lwp *l, const struct compat_50_netbsd32___semctl14_args *uap, register_t *retval)
    981 {
    982 	return do_netbsd32___semctl14(l, uap, retval, NULL);
    983 }
    984 
    985 int
    986 do_netbsd32___semctl14(struct lwp *l, const struct compat_50_netbsd32___semctl14_args *uap, register_t *retval, void *vkarg)
    987 {
    988 	/* {
    989 		syscallarg(int) semid;
    990 		syscallarg(int) semnum;
    991 		syscallarg(int) cmd;
    992 		syscallarg(netbsd32_semun50p_t) arg;
    993 	} */
    994 	struct semid_ds sembuf;
    995 	struct netbsd32_semid_ds50 sembuf32;
    996 	int cmd, error;
    997 	void *pass_arg;
    998 	union __semun karg;
    999 	union netbsd32_semun50 karg32;
   1000 
   1001 	cmd = SCARG(uap, cmd);
   1002 
   1003 	switch (cmd) {
   1004 	case IPC_SET:
   1005 	case IPC_STAT:
   1006 		pass_arg = &sembuf;
   1007 		break;
   1008 
   1009 	case GETALL:
   1010 	case SETVAL:
   1011 	case SETALL:
   1012 		pass_arg = &karg;
   1013 		break;
   1014 	default:
   1015 		pass_arg = NULL;
   1016 		break;
   1017 	}
   1018 
   1019 	if (pass_arg) {
   1020 		if (vkarg != NULL)
   1021 			karg32 = *(union netbsd32_semun50 *)vkarg;
   1022 		else {
   1023 			error = copyin(SCARG_P32(uap, arg), &karg32,
   1024 					sizeof(karg32));
   1025 			if (error)
   1026 				return error;
   1027 		}
   1028 		if (pass_arg == &karg) {
   1029 			switch (cmd) {
   1030 			case GETALL:
   1031 			case SETALL:
   1032 				karg.array = NETBSD32PTR64(karg32.array);
   1033 				break;
   1034 			case SETVAL:
   1035 				karg.val = karg32.val;
   1036 				break;
   1037 			}
   1038 		}
   1039 		if (cmd == IPC_SET) {
   1040 			error = copyin(NETBSD32PTR64(karg32.buf), &sembuf32,
   1041 			    sizeof(sembuf32));
   1042 			if (error)
   1043 				return (error);
   1044 			netbsd32_to_semid_ds50(&sembuf32, &sembuf);
   1045 		}
   1046 	}
   1047 
   1048 	error = semctl1(l, SCARG(uap, semid), SCARG(uap, semnum), cmd,
   1049 	    pass_arg, retval);
   1050 
   1051 	if (error == 0 && cmd == IPC_STAT) {
   1052 		netbsd32_from_semid_ds50(&sembuf, &sembuf32);
   1053 		error = copyout(&sembuf32, NETBSD32PTR64(karg32.buf),
   1054 		    sizeof(sembuf32));
   1055 	}
   1056 
   1057 	return (error);
   1058 }
   1059 #endif
   1060 
   1061 #if defined(SYSVMSG)
   1062 
   1063 int
   1064 compat_50_netbsd32___msgctl13(struct lwp *l, const struct compat_50_netbsd32___msgctl13_args *uap, register_t *retval)
   1065 {
   1066 	/* {
   1067 		syscallarg(int) msqid;
   1068 		syscallarg(int) cmd;
   1069 		syscallarg(netbsd32_msqid_ds50p_t) buf;
   1070 	} */
   1071 	struct msqid_ds ds;
   1072 	struct netbsd32_msqid_ds50 ds32;
   1073 	int error, cmd;
   1074 
   1075 	cmd = SCARG(uap, cmd);
   1076 	if (cmd == IPC_SET) {
   1077 		error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32));
   1078 		if (error)
   1079 			return error;
   1080 		netbsd32_to_msqid_ds50(&ds32, &ds);
   1081 	}
   1082 
   1083 	error = msgctl1(l, SCARG(uap, msqid), cmd,
   1084 	    (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL);
   1085 
   1086 	if (error == 0 && cmd == IPC_STAT) {
   1087 		netbsd32_from_msqid_ds50(&ds, &ds32);
   1088 		error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32));
   1089 	}
   1090 
   1091 	return error;
   1092 }
   1093 #endif
   1094 
   1095 #if defined(SYSVSHM)
   1096 
   1097 int
   1098 compat_50_netbsd32___shmctl13(struct lwp *l, const struct compat_50_netbsd32___shmctl13_args *uap, register_t *retval)
   1099 {
   1100 	/* {
   1101 		syscallarg(int) shmid;
   1102 		syscallarg(int) cmd;
   1103 		syscallarg(netbsd32_shmid_ds50p_t) buf;
   1104 	} */
   1105 	struct shmid_ds ds;
   1106 	struct netbsd32_shmid_ds50 ds32;
   1107 	int error, cmd;
   1108 
   1109 	cmd = SCARG(uap, cmd);
   1110 	if (cmd == IPC_SET) {
   1111 		error = copyin(SCARG_P32(uap, buf), &ds32, sizeof(ds32));
   1112 		if (error)
   1113 			return error;
   1114 		netbsd32_to_shmid_ds50(&ds32, &ds);
   1115 	}
   1116 
   1117 	error = shmctl1(l, SCARG(uap, shmid), cmd,
   1118 	    (cmd == IPC_SET || cmd == IPC_STAT) ? &ds : NULL);
   1119 
   1120 	if (error == 0 && cmd == IPC_STAT) {
   1121 		netbsd32_from_shmid_ds50(&ds, &ds32);
   1122 		error = copyout(&ds32, SCARG_P32(uap, buf), sizeof(ds32));
   1123 	}
   1124 
   1125 	return error;
   1126 }
   1127 #endif
   1128