Home | History | Annotate | Line # | Download | only in common
kern_time_50.c revision 1.19
      1 /*	$NetBSD: kern_time_50.c,v 1.19 2011/03/04 01:36:56 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2008, 2009 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  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 #include <sys/cdefs.h>
     32 __KERNEL_RCSID(0, "$NetBSD: kern_time_50.c,v 1.19 2011/03/04 01:36:56 christos Exp $");
     33 
     34 #ifdef _KERNEL_OPT
     35 #include "opt_aio.h"
     36 #include "opt_ntp.h"
     37 #include "opt_mqueue.h"
     38 #endif
     39 
     40 #include <sys/param.h>
     41 #include <sys/systm.h>
     42 #include <sys/namei.h>
     43 #include <sys/filedesc.h>
     44 #include <sys/kernel.h>
     45 #include <sys/file.h>
     46 #include <sys/stat.h>
     47 #include <sys/socketvar.h>
     48 #include <sys/vnode.h>
     49 #include <sys/proc.h>
     50 #include <sys/uio.h>
     51 #include <sys/dirent.h>
     52 #include <sys/malloc.h>
     53 #include <sys/kauth.h>
     54 #include <sys/time.h>
     55 #include <sys/timex.h>
     56 #include <sys/aio.h>
     57 #include <sys/poll.h>
     58 #include <sys/syscallargs.h>
     59 #include <sys/resource.h>
     60 
     61 #include <compat/common/compat_util.h>
     62 #include <compat/sys/time.h>
     63 #include <compat/sys/timex.h>
     64 #include <compat/sys/resource.h>
     65 #include <compat/sys/clockctl.h>
     66 
     67 int
     68 compat_50_sys_clock_gettime(struct lwp *l,
     69     const struct compat_50_sys_clock_gettime_args *uap, register_t *retval)
     70 {
     71 	/* {
     72 		syscallarg(clockid_t) clock_id;
     73 		syscallarg(struct timespec50 *) tp;
     74 	} */
     75 	int error;
     76 	struct timespec ats;
     77 	struct timespec50 ats50;
     78 
     79 	error = clock_gettime1(SCARG(uap, clock_id), &ats);
     80 	if (error != 0)
     81 		return error;
     82 
     83 	timespec_to_timespec50(&ats, &ats50);
     84 
     85 	return copyout(&ats50, SCARG(uap, tp), sizeof(ats50));
     86 }
     87 
     88 /* ARGSUSED */
     89 int
     90 compat_50_sys_clock_settime(struct lwp *l,
     91     const struct compat_50_sys_clock_settime_args *uap, register_t *retval)
     92 {
     93 	/* {
     94 		syscallarg(clockid_t) clock_id;
     95 		syscallarg(const struct timespec50 *) tp;
     96 	} */
     97 	int error;
     98 	struct timespec ats;
     99 	struct timespec50 ats50;
    100 
    101 	error = copyin(SCARG(uap, tp), &ats50, sizeof(ats50));
    102 	if (error)
    103 		return error;
    104 	timespec50_to_timespec(&ats50, &ats);
    105 
    106 	return clock_settime1(l->l_proc, SCARG(uap, clock_id), &ats,
    107 	    true);
    108 }
    109 
    110 
    111 int
    112 compat_50_sys_clock_getres(struct lwp *l,
    113     const struct compat_50_sys_clock_getres_args *uap, register_t *retval)
    114 {
    115 	/* {
    116 		syscallarg(clockid_t) clock_id;
    117 		syscallarg(struct timespec50 *) tp;
    118 	} */
    119 	struct timespec50 ats50;
    120 	struct timespec ats;
    121 	int error = 0;
    122 
    123 	error = clock_getres1(SCARG(uap, clock_id), &ats);
    124 	if (error != 0)
    125 		return error;
    126 
    127 	if (SCARG(uap, tp)) {
    128 		timespec_to_timespec50(&ats, &ats50);
    129 		error = copyout(&ats50, SCARG(uap, tp), sizeof(ats50));
    130 	}
    131 
    132 	return error;
    133 }
    134 
    135 /* ARGSUSED */
    136 int
    137 compat_50_sys_nanosleep(struct lwp *l,
    138     const struct compat_50_sys_nanosleep_args *uap, register_t *retval)
    139 {
    140 	/* {
    141 		syscallarg(struct timespec50 *) rqtp;
    142 		syscallarg(struct timespec50 *) rmtp;
    143 	} */
    144 	struct timespec rmt, rqt;
    145 	struct timespec50 rmt50, rqt50;
    146 	int error, error1;
    147 
    148 	error = copyin(SCARG(uap, rqtp), &rqt50, sizeof(rqt50));
    149 	if (error)
    150 		return error;
    151 	timespec50_to_timespec(&rqt50, &rqt);
    152 
    153 	error = nanosleep1(l, &rqt, SCARG(uap, rmtp) ? &rmt : NULL);
    154 	if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR))
    155 		return error;
    156 
    157 	timespec_to_timespec50(&rmt, &rmt50);
    158 	error1 = copyout(&rmt50, SCARG(uap, rmtp), sizeof(*SCARG(uap, rmtp)));
    159 	return error1 ? error1 : error;
    160 }
    161 
    162 /* ARGSUSED */
    163 int
    164 compat_50_sys_gettimeofday(struct lwp *l,
    165     const struct compat_50_sys_gettimeofday_args *uap, register_t *retval)
    166 {
    167 	/* {
    168 		syscallarg(struct timeval50 *) tp;
    169 		syscallarg(void *) tzp;		really "struct timezone *";
    170 	} */
    171 	struct timeval atv;
    172 	struct timeval50 atv50;
    173 	int error = 0;
    174 	struct timezone tzfake;
    175 
    176 	if (SCARG(uap, tp)) {
    177 		microtime(&atv);
    178 		timeval_to_timeval50(&atv, &atv50);
    179 		error = copyout(&atv50, SCARG(uap, tp), sizeof(*SCARG(uap, tp)));
    180 		if (error)
    181 			return error;
    182 	}
    183 	if (SCARG(uap, tzp)) {
    184 		/*
    185 		 * NetBSD has no kernel notion of time zone, so we just
    186 		 * fake up a timezone struct and return it if demanded.
    187 		 */
    188 		tzfake.tz_minuteswest = 0;
    189 		tzfake.tz_dsttime = 0;
    190 		error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake));
    191 	}
    192 	return error;
    193 }
    194 
    195 /* ARGSUSED */
    196 int
    197 compat_50_sys_settimeofday(struct lwp *l,
    198     const struct compat_50_sys_settimeofday_args *uap, register_t *retval)
    199 {
    200 	/* {
    201 		syscallarg(const struct timeval50 *) tv;
    202 		syscallarg(const void *) tzp; really "const struct timezone *";
    203 	} */
    204 	struct timeval50 atv50;
    205 	struct timeval atv;
    206 	int error = copyin(SCARG(uap, tv), &atv50, sizeof(atv50));
    207 	if (error)
    208 		return error;
    209 	timeval50_to_timeval(&atv50, &atv);
    210 	return settimeofday1(&atv, false, SCARG(uap, tzp), l, true);
    211 }
    212 
    213 /* ARGSUSED */
    214 int
    215 compat_50_sys_adjtime(struct lwp *l,
    216     const struct compat_50_sys_adjtime_args *uap, register_t *retval)
    217 {
    218 	/* {
    219 		syscallarg(const struct timeval50 *) delta;
    220 		syscallarg(struct timeval50 *) olddelta;
    221 	} */
    222 	int error;
    223 	struct timeval50 delta50, olddelta50;
    224 	struct timeval delta, olddelta;
    225 
    226 	if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME,
    227 	    KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL, NULL)) != 0)
    228 		return error;
    229 
    230 	if (SCARG(uap, delta)) {
    231 		error = copyin(SCARG(uap, delta), &delta50,
    232 		    sizeof(*SCARG(uap, delta)));
    233 		if (error)
    234 			return (error);
    235 		timeval50_to_timeval(&delta50, &delta);
    236 	}
    237 	adjtime1(SCARG(uap, delta) ? &delta : NULL,
    238 	    SCARG(uap, olddelta) ? &olddelta : NULL, l->l_proc);
    239 	if (SCARG(uap, olddelta)) {
    240 		timeval_to_timeval50(&olddelta, &olddelta50);
    241 		error = copyout(&olddelta50, SCARG(uap, olddelta),
    242 		    sizeof(*SCARG(uap, olddelta)));
    243 	}
    244 	return error;
    245 }
    246 
    247 /* BSD routine to set/arm an interval timer. */
    248 /* ARGSUSED */
    249 int
    250 compat_50_sys_getitimer(struct lwp *l,
    251     const struct compat_50_sys_getitimer_args *uap, register_t *retval)
    252 {
    253 	/* {
    254 		syscallarg(int) which;
    255 		syscallarg(struct itimerval50 *) itv;
    256 	} */
    257 	struct proc *p = l->l_proc;
    258 	struct itimerval aitv;
    259 	struct itimerval50 aitv50;
    260 	int error;
    261 
    262 	error = dogetitimer(p, SCARG(uap, which), &aitv);
    263 	if (error)
    264 		return error;
    265 	itimerval_to_itimerval50(&aitv, &aitv50);
    266 	return copyout(&aitv50, SCARG(uap, itv), sizeof(*SCARG(uap, itv)));
    267 }
    268 
    269 int
    270 compat_50_sys_setitimer(struct lwp *l,
    271     const struct compat_50_sys_setitimer_args *uap, register_t *retval)
    272 {
    273 	/* {
    274 		syscallarg(int) which;
    275 		syscallarg(const struct itimerval50 *) itv;
    276 		syscallarg(struct itimerval50 *) oitv;
    277 	} */
    278 	struct proc *p = l->l_proc;
    279 	int which = SCARG(uap, which);
    280 	struct compat_50_sys_getitimer_args getargs;
    281 	const struct itimerval50 *itvp;
    282 	struct itimerval50 aitv50;
    283 	struct itimerval aitv;
    284 	int error;
    285 
    286 	if ((u_int)which > ITIMER_PROF)
    287 		return (EINVAL);
    288 	itvp = SCARG(uap, itv);
    289 	if (itvp &&
    290 	    (error = copyin(itvp, &aitv50, sizeof(aitv50)) != 0))
    291 		return (error);
    292 	itimerval50_to_itimerval(&aitv50, &aitv);
    293 	if (SCARG(uap, oitv) != NULL) {
    294 		SCARG(&getargs, which) = which;
    295 		SCARG(&getargs, itv) = SCARG(uap, oitv);
    296 		if ((error = compat_50_sys_getitimer(l, &getargs, retval)) != 0)
    297 			return (error);
    298 	}
    299 	if (itvp == 0)
    300 		return (0);
    301 
    302 	return dosetitimer(p, which, &aitv);
    303 }
    304 
    305 int
    306 compat_50_sys_aio_suspend(struct lwp *l,
    307     const struct compat_50_sys_aio_suspend_args *uap, register_t *retval)
    308 {
    309 	/* {
    310 		syscallarg(const struct aiocb *const[]) list;
    311 		syscallarg(int) nent;
    312 		syscallarg(const struct timespec50 *) timeout;
    313 	} */
    314 #ifdef AIO
    315 	struct aiocb **list;
    316 	struct timespec ts;
    317 	struct timespec50 ts50;
    318 	int error, nent;
    319 
    320 	nent = SCARG(uap, nent);
    321 	if (nent <= 0 || nent > aio_listio_max)
    322 		return EAGAIN;
    323 
    324 	if (SCARG(uap, timeout)) {
    325 		/* Convert timespec to ticks */
    326 		error = copyin(SCARG(uap, timeout), &ts50,
    327 		    sizeof(*SCARG(uap, timeout)));
    328 		if (error)
    329 			return error;
    330 		timespec50_to_timespec(&ts50, &ts);
    331 	}
    332 	list = kmem_alloc(nent * sizeof(*list), KM_SLEEP);
    333 	error = copyin(SCARG(uap, list), list, nent * sizeof(*list));
    334 	if (error)
    335 		goto out;
    336 	error = aio_suspend1(l, list, nent, SCARG(uap, timeout) ? &ts : NULL);
    337 out:
    338 	kmem_free(list, nent * sizeof(*list));
    339 	return error;
    340 #else
    341 	return ENOSYS;
    342 #endif
    343 }
    344 
    345 int
    346 compat_50_sys__lwp_park(struct lwp *l,
    347     const struct compat_50_sys__lwp_park_args *uap, register_t *retval)
    348 {
    349 	/* {
    350 		syscallarg(const struct timespec50 *)	ts;
    351 		syscallarg(lwpid_t)			unpark;
    352 		syscallarg(const void *)		hint;
    353 		syscallarg(const void *)		unparkhint;
    354 	} */
    355 	struct timespec ts, *tsp;
    356 	struct timespec50 ts50;
    357 	int error;
    358 
    359 	if (SCARG(uap, ts) == NULL)
    360 		tsp = NULL;
    361 	else {
    362 		error = copyin(SCARG(uap, ts), &ts50, sizeof(ts50));
    363 		if (error != 0)
    364 			return error;
    365 		timespec50_to_timespec(&ts50, &ts);
    366 		tsp = &ts;
    367 	}
    368 
    369 	if (SCARG(uap, unpark) != 0) {
    370 		error = lwp_unpark(SCARG(uap, unpark), SCARG(uap, unparkhint));
    371 		if (error != 0)
    372 			return error;
    373 	}
    374 
    375 	return lwp_park(tsp, SCARG(uap, hint));
    376 }
    377 
    378 int
    379 compat_50_sys_mq_timedsend(struct lwp *l,
    380     const struct compat_50_sys_mq_timedsend_args *uap, register_t *retval)
    381 {
    382 	/* {
    383 		syscallarg(mqd_t) mqdes;
    384 		syscallarg(const char *) msg_ptr;
    385 		syscallarg(size_t) msg_len;
    386 		syscallarg(unsigned) msg_prio;
    387 		syscallarg(const struct timespec50 *) abs_timeout;
    388 	} */
    389 #ifdef MQUEUE
    390 	struct timespec50 ts50;
    391 	struct timespec ts, *tsp;
    392 	int error;
    393 
    394 	/* Get and convert time value */
    395 	if (SCARG(uap, abs_timeout)) {
    396 		error = copyin(SCARG(uap, abs_timeout), &ts50, sizeof(ts50));
    397 		if (error)
    398 			return error;
    399 		timespec50_to_timespec(&ts50, &ts);
    400 		tsp = &ts;
    401 	} else {
    402 		tsp = NULL;
    403 	}
    404 
    405 	return mq_send1(SCARG(uap, mqdes), SCARG(uap, msg_ptr),
    406 	    SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp);
    407 #else
    408 	return ENOSYS;
    409 #endif
    410 }
    411 
    412 int
    413 compat_50_sys_mq_timedreceive(struct lwp *l,
    414     const struct compat_50_sys_mq_timedreceive_args *uap, register_t *retval)
    415 {
    416 	/* {
    417 		syscallarg(mqd_t) mqdes;
    418 		syscallarg(char *) msg_ptr;
    419 		syscallarg(size_t) msg_len;
    420 		syscallarg(unsigned *) msg_prio;
    421 		syscallarg(const struct timespec50 *) abs_timeout;
    422 	} */
    423 #ifdef MQUEUE
    424 	struct timespec ts, *tsp;
    425 	struct timespec50 ts50;
    426 	ssize_t mlen;
    427 	int error;
    428 
    429 	/* Get and convert time value */
    430 	if (SCARG(uap, abs_timeout)) {
    431 		error = copyin(SCARG(uap, abs_timeout), &ts50, sizeof(ts50));
    432 		if (error)
    433 			return error;
    434 
    435 		timespec50_to_timespec(&ts50, &ts);
    436 		tsp = &ts;
    437 	} else {
    438 		tsp = NULL;
    439 	}
    440 
    441 	error = mq_recv1(SCARG(uap, mqdes), SCARG(uap, msg_ptr),
    442 	    SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp, &mlen);
    443 	if (error == 0)
    444 		*retval = mlen;
    445 
    446 	return error;
    447 #else
    448 	return ENOSYS;
    449 #endif
    450 }
    451 
    452 static int
    453 tscopyin(const void *u, void *s, size_t len)
    454 {
    455 	struct timespec50 ts50;
    456 	int error;
    457 
    458 	KASSERT(len == sizeof(struct timespec));
    459 	error = copyin(u, &ts50, sizeof(ts50));
    460 	if (error)
    461 		return error;
    462 	timespec50_to_timespec(&ts50, s);
    463 	return 0;
    464 }
    465 
    466 static int
    467 tscopyout(const void *s, void *u, size_t len)
    468 {
    469 	struct timespec50 ts50;
    470 
    471 	KASSERT(len == sizeof(struct timespec));
    472 	timespec_to_timespec50(s, &ts50);
    473 	return copyout(&ts50, u, sizeof(ts50));
    474 }
    475 
    476 int
    477 compat_50_sys___sigtimedwait(struct lwp *l,
    478     const struct compat_50_sys___sigtimedwait_args *uap, register_t *retval)
    479 {
    480 	int res;
    481 
    482 	res = sigtimedwait1(l,
    483 	    (const struct sys_____sigtimedwait50_args *)uap, retval, copyout,
    484 	    tscopyin, tscopyout);
    485 	if (!res)
    486 		*retval = 0; /* XXX NetBSD<=5 was not POSIX compliant */
    487 	return res;
    488 }
    489 
    490 void
    491 rusage_to_rusage50(const struct rusage *ru, struct rusage50 *ru50)
    492 {
    493 	(void)memcpy(&ru50->ru_first, &ru->ru_first,
    494 	    (char *)&ru50->ru_last - (char *)&ru50->ru_first +
    495 	    sizeof(ru50->ru_last));
    496 	ru50->ru_maxrss = ru->ru_maxrss;
    497 	timeval_to_timeval50(&ru->ru_utime, &ru50->ru_utime);
    498 	timeval_to_timeval50(&ru->ru_stime, &ru50->ru_stime);
    499 }
    500 
    501 int
    502 compat_50_sys_getrusage(struct lwp *l,
    503     const struct compat_50_sys_getrusage_args *uap, register_t *retval)
    504 {
    505 	/* {
    506 		syscallarg(int) who;
    507 		syscallarg(struct rusage50 *) rusage;
    508 	} */
    509 	struct rusage ru;
    510 	struct rusage50 ru50;
    511 	struct proc *p = l->l_proc;
    512 
    513 	switch (SCARG(uap, who)) {
    514 	case RUSAGE_SELF:
    515 		mutex_enter(p->p_lock);
    516 		memcpy(&ru, &p->p_stats->p_ru, sizeof(ru));
    517 		calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL);
    518 		mutex_exit(p->p_lock);
    519 		break;
    520 
    521 	case RUSAGE_CHILDREN:
    522 		mutex_enter(p->p_lock);
    523 		memcpy(&ru, &p->p_stats->p_cru, sizeof(ru));
    524 		mutex_exit(p->p_lock);
    525 		break;
    526 
    527 	default:
    528 		return EINVAL;
    529 	}
    530 	rusage_to_rusage50(&ru, &ru50);
    531 	return copyout(&ru50, SCARG(uap, rusage), sizeof(ru50));
    532 }
    533 
    534 
    535 /* Return the time remaining until a POSIX timer fires. */
    536 int
    537 compat_50_sys_timer_gettime(struct lwp *l,
    538     const struct compat_50_sys_timer_gettime_args *uap, register_t *retval)
    539 {
    540 	/* {
    541 		syscallarg(timer_t) timerid;
    542 		syscallarg(struct itimerspec50 *) value;
    543 	} */
    544 	struct itimerspec its;
    545 	struct itimerspec50 its50;
    546 	int error;
    547 
    548 	if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
    549 	    &its)) != 0)
    550 		return error;
    551 	itimerspec_to_itimerspec50(&its, &its50);
    552 
    553 	return copyout(&its50, SCARG(uap, value), sizeof(its50));
    554 }
    555 
    556 /* Set and arm a POSIX realtime timer */
    557 int
    558 compat_50_sys_timer_settime(struct lwp *l,
    559     const struct compat_50_sys_timer_settime_args *uap, register_t *retval)
    560 {
    561 	/* {
    562 		syscallarg(timer_t) timerid;
    563 		syscallarg(int) flags;
    564 		syscallarg(const struct itimerspec50 *) value;
    565 		syscallarg(struct itimerspec50 *) ovalue;
    566 	} */
    567 	int error;
    568 	struct itimerspec value, ovalue, *ovp = NULL;
    569 	struct itimerspec50 value50, ovalue50;
    570 
    571 	if ((error = copyin(SCARG(uap, value), &value50, sizeof(value50))) != 0)
    572 		return error;
    573 
    574 	itimerspec50_to_itimerspec(&value50, &value);
    575 	if (SCARG(uap, ovalue))
    576 		ovp = &ovalue;
    577 
    578 	if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
    579 	    SCARG(uap, flags), l->l_proc)) != 0)
    580 		return error;
    581 
    582 	if (ovp) {
    583 		itimerspec_to_itimerspec50(&ovalue, &ovalue50);
    584 		return copyout(&ovalue50, SCARG(uap, ovalue), sizeof(ovalue50));
    585 	}
    586 	return 0;
    587 }
    588 
    589 /*
    590  * ntp_gettime() - NTP user application interface
    591  */
    592 int
    593 compat_50_sys___ntp_gettime30(struct lwp *l,
    594     const struct compat_50_sys___ntp_gettime30_args *uap, register_t *retval)
    595 {
    596 #ifdef NTP
    597 	/* {
    598 		syscallarg(struct ntptimeval *) ntvp;
    599 	} */
    600 	struct ntptimeval ntv;
    601 	struct ntptimeval50 ntv50;
    602 	int error;
    603 
    604 	if (SCARG(uap, ntvp)) {
    605 		ntp_gettime(&ntv);
    606 		timespec_to_timespec50(&ntv.time, &ntv50.time);
    607 		ntv50.maxerror = ntv.maxerror;
    608 		ntv50.esterror = ntv.esterror;
    609 		ntv50.tai = ntv.tai;
    610 		ntv50.time_state = ntv.time_state;
    611 
    612 		error = copyout(&ntv50, SCARG(uap, ntvp), sizeof(ntv50));
    613 		if (error)
    614 			return error;
    615 	}
    616 	*retval = ntp_timestatus();
    617 	return 0;
    618 #else
    619 	return ENOSYS;
    620 #endif
    621 }
    622 int
    623 compat50_clockctlioctl(dev_t dev, u_long cmd, void *data, int flags,
    624     struct lwp *l)
    625 {
    626 	int error = 0;
    627 
    628 	switch (cmd) {
    629 	case CLOCKCTL_OSETTIMEOFDAY: {
    630 		struct timeval50 tv50;
    631 		struct timeval tv;
    632 		struct clockctl50_settimeofday *args = data;
    633 
    634 		error = copyin(args->tv, &tv50, sizeof(tv50));
    635 		if (error)
    636 			return (error);
    637 		timeval50_to_timeval(&tv50, &tv);
    638 		error = settimeofday1(&tv, false, args->tzp, l, false);
    639 		break;
    640 	}
    641 	case CLOCKCTL_OADJTIME: {
    642 		struct timeval atv, oldatv;
    643 		struct timeval50 atv50;
    644 		struct clockctl50_adjtime *args = data;
    645 
    646 		if (args->delta) {
    647 			error = copyin(args->delta, &atv50, sizeof(atv50));
    648 			if (error)
    649 				return (error);
    650 			timeval50_to_timeval(&atv50, &atv);
    651 		}
    652 		adjtime1(args->delta ? &atv : NULL,
    653 		    args->olddelta ? &oldatv : NULL, l->l_proc);
    654 		if (args->olddelta) {
    655 			timeval_to_timeval50(&oldatv, &atv50);
    656 			error = copyout(&atv50, args->olddelta, sizeof(atv50));
    657 		}
    658 		break;
    659 	}
    660 	case CLOCKCTL_OCLOCK_SETTIME: {
    661 		struct timespec50 tp50;
    662 		struct timespec tp;
    663 		struct clockctl50_clock_settime *args = data;
    664 
    665 		error = copyin(args->tp, &tp50, sizeof(tp50));
    666 		if (error)
    667 			return (error);
    668 		timespec50_to_timespec(&tp50, &tp);
    669 		error = clock_settime1(l->l_proc, args->clock_id, &tp, true);
    670 		break;
    671 	}
    672 	default:
    673 		error = EINVAL;
    674 	}
    675 
    676 	return (error);
    677 }
    678 int
    679 compat_50_sys_wait4(struct lwp *l, const struct compat_50_sys_wait4_args *uap,
    680     register_t *retval)
    681 {
    682 	/* {
    683 		syscallarg(int)			pid;
    684 		syscallarg(int *)		status;
    685 		syscallarg(int)			options;
    686 		syscallarg(struct rusage50 *)	rusage;
    687 	} */
    688 	int status, error, pid = SCARG(uap, pid);
    689 	struct rusage50 ru50;
    690 	struct rusage ru;
    691 
    692 	error = do_sys_wait(&pid, &status, SCARG(uap, options),
    693 	    SCARG(uap, rusage) != NULL ? &ru : NULL);
    694 
    695 	retval[0] = pid;
    696 	if (pid == 0)
    697 		return error;
    698 
    699 	if (SCARG(uap, rusage)) {
    700 		rusage_to_rusage50(&ru, &ru50);
    701 		error = copyout(&ru50, SCARG(uap, rusage), sizeof(ru50));
    702 	}
    703 
    704 	if (error == 0 && SCARG(uap, status))
    705 		error = copyout(&status, SCARG(uap, status), sizeof(status));
    706 
    707 	return error;
    708 }
    709